diff --git a/Buildings/Applications/DataCenters/ChillerCooled/Examples/BaseClasses/PartialDataCenter.mo b/Buildings/Applications/DataCenters/ChillerCooled/Examples/BaseClasses/PartialDataCenter.mo index a40a96bec26..a06f2cd1fed 100644 --- a/Buildings/Applications/DataCenters/ChillerCooled/Examples/BaseClasses/PartialDataCenter.mo +++ b/Buildings/Applications/DataCenters/ChillerCooled/Examples/BaseClasses/PartialDataCenter.mo @@ -171,18 +171,15 @@ partial model PartialDataCenter annotation (Placement(transformation(extent={{10,-10},{-10,10}}, rotation=90, origin={-50,-150}))); - Buildings.Examples.ChillerPlant.BaseClasses.SimplifiedRoom roo( + Buildings.Examples.ChillerPlants.DataCenter.BaseClasses.SimplifiedRoom roo( redeclare replaceable package Medium = MediumA, rooLen=50, rooWid=30, rooHei=3, m_flow_nominal=mAir_flow_nominal, QRoo_flow=500000, - nPorts=2) - "Room model" - annotation (Placement(transformation( - extent={{10,-10},{-10,10}}, - origin={4,-180}))); + nPorts=2) "Room model" annotation (Placement(transformation(extent={{10,-10}, + {-10,10}}, origin={4,-180}))); Buildings.Fluid.Actuators.Valves.TwoWayLinear val[numChi]( redeclare each package Medium = MediumW, each m_flow_nominal=m1_flow_chi_nominal, diff --git a/Buildings/Applications/DataCenters/DXCooled/Examples/DXCooledAirsideEconomizer.mo b/Buildings/Applications/DataCenters/DXCooled/Examples/DXCooledAirsideEconomizer.mo index f08fad4918e..1708fd2a64d 100644 --- a/Buildings/Applications/DataCenters/DXCooled/Examples/DXCooledAirsideEconomizer.mo +++ b/Buildings/Applications/DataCenters/DXCooled/Examples/DXCooledAirsideEconomizer.mo @@ -39,7 +39,7 @@ model DXCooledAirsideEconomizer parameter Real minSpeFan = 0.2 "Minimum fan speed ratio required by variable speed fans"; - Buildings.Examples.ChillerPlant.BaseClasses.SimplifiedRoom roo( + Buildings.Examples.ChillerPlants.DataCenter.BaseClasses.SimplifiedRoom roo( redeclare package Medium = Medium, rooLen=50, rooHei=3, diff --git a/Buildings/Controls/OBC/ASHRAE/G36/AHUs/SingleZone/VAV/Controller.mo b/Buildings/Controls/OBC/ASHRAE/G36/AHUs/SingleZone/VAV/Controller.mo index 849271ea396..4a0ecf167b6 100644 --- a/Buildings/Controls/OBC/ASHRAE/G36/AHUs/SingleZone/VAV/Controller.mo +++ b/Buildings/Controls/OBC/ASHRAE/G36/AHUs/SingleZone/VAV/Controller.mo @@ -1264,8 +1264,7 @@ equation annotation (Dialog(enable=have_frePro), defaultComponentName="conVAV", Icon(coordinateSystem(preserveAspectRatio=false, extent={{-200,-400},{200,400}}), - graphics={ - Rectangle( + graphics={Rectangle( extent={{-200,-400},{200,400}}, lineColor={0,0,127}, fillColor={255,255,255}, diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Controller.mo new file mode 100644 index 00000000000..2a2b558ff69 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Controller.mo @@ -0,0 +1,2735 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +block Controller "Chiller plant controller" + + parameter Boolean closeCoupledPlant=false + "True: the plant is close coupled, i.e. the pipe length from the chillers to cooling towers does not exceed approximately 100 feet" + annotation (Dialog(tab="General")); + + // ---- General: Chiller configuration ---- + + parameter Integer nChi=2 + "Total number of chillers" + annotation(Dialog(tab="General", group="Chillers configuration")); + + parameter Boolean have_parChi=true + "Flag: true means that the plant has parallel chillers" + annotation(Dialog(tab="General", group="Chillers configuration")); + + parameter Boolean have_ponyChiller=false + "True: have pony chiller" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Boolean need_reduceChillerDemand=false + "True: need limit chiller demand when chiller staging" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real desCap(unit="W")=1e6 + "Plant design capacity" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Integer chiTyp[nChi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal} + "Chiller type. Recommended staging order: positive displacement, variable speed centrifugal, constant speed centrifugal" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real chiDesCap[nChi](unit=fill("W", nChi)) + "Design chiller capacities vector" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real chiMinCap[nChi](unit=fill("W", nChi)) + "Chiller minimum cycling loads vector" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real TChiWatSupMin[nChi]( + unit=fill("K", nChi), + displayUnit=fill("degC",nChi))={278.15,278.15} + "Minimum chilled water supply temperature" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real minChiLif( + unit="K", + displayUnit="K")=10 + "Minimum allowable lift at minimum load for chiller" + annotation(Dialog(tab="General", group="Chillers configuration", enable=not have_heaPreConSig)); + + parameter Boolean have_heaPreConSig=false + "True: if there is head pressure control signal from chiller controller" + annotation(Dialog(tab="General", group="Chillers configuration")); + + parameter Boolean anyVsdCen = false + "True: the plant contains at least one variable speed centrifugal chiller" + annotation (Dialog(tab="General", group="Chillers configuration")); + + // ---- General: Waterside economizer ---- + + parameter Boolean have_WSE=false + "True if the plant has waterside economizer. When the plant has waterside economizer, the condenser water pump speed must be variable" + annotation (Dialog(tab="General", group="Waterside economizer")); + + parameter Real heaExcAppDes( + unit="K", + displayUnit="K")=2 + "Design heat exchanger approach" + annotation(Evaluate=true, Dialog(tab="General", group="Waterside economizer", enable=have_WSE)); + + parameter Boolean have_byPasValCon=false + "True: chilled water flow through economizer is controlled using heat exchanger bypass valve" + annotation (Dialog(group="Waterside economizer", enable=have_WSE)); + + // ----- General: Chilled water pump --- + + parameter Integer nChiWatPum = 2 + "Total number of chilled water pumps" + annotation (Dialog(tab="General", group="Chilled water pump")); + + parameter Boolean have_heaChiWatPum=true + "Flag of headered chilled water pumps design: true=headered, false=dedicated" + annotation (Dialog(tab="General", group="Chilled water pump")); + + parameter Boolean have_locSenChiWatPum=false + "True: there is local differential pressure sensor hardwired to the plant controller" + annotation (Dialog(tab="General", group="Chilled water pump")); + + parameter Integer nSenChiWatPum=2 + "Total number of remote differential pressure sensors" + annotation (Dialog(tab="General", group="Chilled water pump")); + + // ---- General: Condenser water pump ---- + + parameter Integer nConWatPum=2 + "Total number of condenser water pumps" + annotation (Dialog(tab="General", group="Condenser water pump")); + + parameter Boolean have_fixSpeConWatPum = false + "True: the plant has fixed speed condenser water pumps. When the plant has waterside economizer, it must be false" + annotation(Dialog(tab="General", group="Condenser water pump", enable=not have_WSE)); + + parameter Real fixConWatPumSpe = 0.9 + "Fixed speed of the constant speed condenser water pump" + annotation(Dialog(tab="General", group="Condenser water pump", enable=not have_WSE and have_fixSpeConWatPum)); + + parameter Boolean have_heaConWatPum=true + "True: headered condenser water pumps" + annotation (Dialog(tab="General", group="Condenser water pump")); + + // ---- General: Chiller staging settings ---- + + parameter Integer nSta = 2 + "Number of chiller stages, neither zero stage nor the stages with enabled waterside economizer is included" + annotation (Dialog(tab="General", group="Staging configuration")); + + parameter Integer totSta=6 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable" + annotation (Dialog(tab="General", group="Staging configuration")); + + parameter Integer staMat[nSta, nChi] = {{1,0},{1,1}} + "Staging matrix with chiller stage as row index and chiller as column index" + annotation (Dialog(tab="General", group="Staging configuration")); + + parameter Real desChiNum[nSta+1]={0,1,2} + "Design number of chiller that should be ON at each chiller stage, including the zero stage" + annotation (Dialog(tab="General", group="Staging configuration", enable=have_fixSpeConWatPum)); + + parameter Real staVec[totSta]={0,0.5,1,1.5,2,2.5} + "Plant stage vector, element value like x.5 means chiller stage x plus WSE" + annotation (Dialog(tab="General", group="Staging configuration")); + + parameter Real desConWatPumSpe[totSta]( + max=fill(1, totSta), + min=fill(0, totSta))={0,0.5,0.75,0.6,0.75,0.9} + "Design condenser water pump speed setpoints, according to current chiller stage and WSE status" + annotation (Dialog(tab="General", group="Staging configuration")); + + parameter Real desConWatPumNum[totSta]={0,1,1,2,2,2} + "Design number of condenser water pumps that should be ON, according to current chiller stage and WSE status" + annotation (Dialog(tab="General", group="Staging configuration")); + + parameter Real towCelOnSet[totSta]={0,2,2,4,4,4} + "Design number of tower fan cells that should be ON, according to current chiller stage and WSE status" + annotation(Dialog(tab="General", group="Staging configuration")); + + // ---- General: Cooling tower ---- + + parameter Integer nTowCel=4 + "Total number of cooling tower cells" + annotation (Dialog(tab="General", group="Cooling tower")); + + parameter Real cooTowAppDes( + unit="K", + displayUnit="K")=2 + "Design cooling tower approach" + annotation(Evaluate=true, Dialog(tab="General", group="Cooling tower")); + + // ---- Plant enable ---- + + parameter Real schTab[4,2] = [0,1; 6*3600,1; 19*3600,1; 24*3600,1] + "Plant enabling schedule allowing operators to lock out the plant during off-hour" + annotation(Dialog(tab="Plant enable")); + + parameter Real TChiLocOut( + unit="K", + displayUnit="degC")=277.5 + "Outdoor air lockout temperature below which the chiller plant should be disabled" + annotation(Dialog(tab="Plant enable")); + + parameter Real plaThrTim(unit="s")=900 + "Threshold time to check status of chiller plant" + annotation(Dialog(tab="Plant enable")); + + parameter Real reqThrTim(unit="s")=180 + "Threshold time to check current chiller plant request" + annotation(Dialog(tab="Plant enable")); + + parameter Integer ignReq = 0 + "Ignorable chiller plant requests" + annotation(Dialog(tab="Plant enable")); + + parameter Real iniPumDel(unit="s")=5 + "Time to delay pump operation when the plant is just initiated" + annotation(Dialog(tab="Plant enable")); + + // ---- Waterside economizer ---- + + parameter Real holdPeriod(unit="s")=1200 + "WSE minimum on or off time" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Enable parameters", enable=have_WSE)); + + parameter Real delDis(unit="s")=120 + "Delay disable time period" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Enable parameters", enable=have_WSE)); + + parameter Real TOffsetEna(unit="K")=2 + "Temperature offset between the chilled water return upstream of WSE and the predicted WSE output" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Enable parameters", enable=have_WSE)); + + parameter Real TOffsetDis(unit="K")=1 + "Temperature offset between the chilled water return upstream and downstream WSE" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Enable parameters", enable=have_WSE)); + + parameter Real TOutWetDes( + unit="K", + displayUnit="degC")=288.15 + "Design outdoor air wet bulb temperature" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Design parameters", enable=have_WSE)); + + parameter Real VHeaExcDes_flow(unit="m3/s")=0.015 + "Desing heat exchanger chilled water volume flow rate" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Design parameters", enable=have_WSE)); + + parameter Real step=0.02 "Tuning step" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Tuning", enable=have_WSE)); + + parameter Real wseOnTimDec(unit="s")=3600 + "Economizer enable time needed to allow decrease of the tuning parameter" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Tuning", enable=have_WSE)); + + parameter Real wseOnTimInc(unit="s")=1800 + "Economizer enable time needed to allow increase of the tuning parameter" + annotation(Evaluate=true, Dialog(tab="Waterside economizer", group="Tuning", enable=have_WSE)); + + parameter Real dpDes=6000 + "Design pressure difference across the chilled water side economizer" + annotation (Dialog(tab="Waterside economizer", group="Valve or pump control", + enable=have_WSE and have_byPasValCon)); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController ecoValCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Waterside economizer",group="Valve or pump control", + enable=have_WSE and have_byPasValCon)); + + parameter Real kEcoVal=0.1 "Gain of controller" + annotation (Dialog(tab="Waterside economizer",group="Valve or pump control", + enable=have_WSE and have_byPasValCon)); + + parameter Real TiEcoVal=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Waterside economizer", group="Valve or pump control", + enable=have_WSE and have_byPasValCon + and (ecoValCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or ecoValCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdEcoVal=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Waterside economizer",group="Valve or pump control", + enable=have_WSE and have_byPasValCon + and (ecoValCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or ecoValCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real minEcoSpe=0.1 + "Minimum economizer chilled water pump speed" + annotation (Dialog(tab="Waterside economizer",group="Valve or pump control", + enable=have_WSE and not have_byPasValCon)); + + parameter Real desEcoSpe=0.9 + "Design economizer pump speed" + annotation (Dialog(tab="Waterside economizer",group="Valve or pump control", + enable=have_WSE and not have_byPasValCon)); + + // ---- Head pressure ---- + + parameter Real minConWatPumSpe(unit="1")=0.1 + "Minimum condenser water pump speed" + annotation(Dialog(enable= not ((not have_WSE) and have_fixSpeConWatPum), tab="Head pressure", group="Limits")); + + parameter Real minHeaPreValPos(unit="1")=0.1 + "Minimum head pressure control valve position" + annotation(Dialog(enable= (not ((not have_WSE) and (not have_fixSpeConWatPum))), tab="Head pressure", group="Limits")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeHeaPre= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="Head pressure", group="Loop signal", enable=not have_heaPreConSig)); + + parameter Real kHeaPreCon=0.1 + "Gain of controller" + annotation(Dialog(tab="Head pressure", group="Loop signal", enable=not have_heaPreConSig)); + + parameter Real TiHeaPreCon(unit="s")=10 + "Time constant of integrator block" + annotation(Dialog(tab="Head pressure", group="Loop signal", enable=not have_heaPreConSig)); + + // ---- Minimum flow bypass ---- + + parameter Real byPasSetTim(unit="s")=300 + "Time constant for resetting minimum bypass flow" + annotation(Dialog(tab="Minimum flow bypass", group="Time parameters")); + + parameter Real minFloSet[nChi](unit=fill("m3/s", nChi))={0.0089,0.0089} + "Minimum chilled water flow through each chiller" + annotation(Dialog(tab="Minimum flow bypass", group="Flow limits")); + + parameter Real maxFloSet[nChi](unit=fill("m3/s", nChi))={0.025,0.025} + "Maximum chilled water flow through each chiller" + annotation(Dialog(tab="Minimum flow bypass", group="Flow limits")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeMinFloByp= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Minimum flow bypass", group="Controller")); + + parameter Real kMinFloBypCon=0.1 + "Gain of controller" + annotation (Dialog(tab="Minimum flow bypass", group="Controller")); + + parameter Real TiMinFloBypCon(unit="s")=10 + "Time constant of integrator block" + annotation (Dialog(tab="Minimum flow bypass", + group="Controller", enable=controllerTypeMinFloByp==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + controllerTypeMinFloByp==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + parameter Real TdMinFloBypCon(unit="s")=0 + "Time constant of derivative block" + annotation (Dialog(tab="Minimum flow bypass", + group="Controller", enable=controllerTypeMinFloByp==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerTypeMinFloByp==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + parameter Real yMaxFloBypCon(unit="1")=1 + "Upper limit of output" + annotation (Dialog(tab="Minimum flow bypass", group="Controller")); + + parameter Real yMinFloBypCon(unit="1")=0.1 + "Lower limit of output" + annotation (Dialog(tab="Minimum flow bypass", group="Controller")); + + // ---- Chilled water pumps ---- + + parameter Real minChiWatPumSpe(unit="1")=0.1 + "Minimum pump speed" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller")); + + parameter Real maxChiWatPumSpe(unit="1")=1 + "Maximum pump speed" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller")); + + parameter Integer nPum_nominal( + max=nChiWatPum, + min=1)=nChiWatPum + "Total number of pumps that operate at design conditions" + annotation (Dialog(tab="Chilled water pumps", group="Nominal conditions")); + + parameter Real VChiWat_flow_nominal(unit="m3/s")=0.5 + "Total plant design chilled water flow rate" + annotation (Dialog(tab="Chilled water pumps", group="Nominal conditions")); + + parameter Real maxLocDp(unit="Pa")=15*6894.75 + "Maximum chilled water loop local differential pressure setpoint" + annotation (Dialog(tab="Chilled water pumps", group="Pump speed control when there is local DP sensor", enable=have_locSenChiWatPum)); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeChiWatPum= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller")); + + parameter Real kChiWatPum=0.1 "Gain of controller" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller")); + + parameter Real TiChiWatPum(unit="s")=10 + "Time constant of integrator block" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller")); + + parameter Real TdChiWatPum(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller", + enable=controllerTypeChiWatPum == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerTypeChiWatPum == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + // ---- Plant reset ---- + + parameter Real holTim(unit="s")=900 + "Time to fix plant reset value" + annotation(Dialog(tab="Plant Reset")); + + parameter Real iniSet(unit="1")=0 + "Initial setpoint" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real minSet(unit="1")=0 + "Minimum plant reset value" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real maxSet(unit="1")=1 + "Maximum plant reset value" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real delTim(unit="s")=900 + "Delay time after which trim and respond is activated" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real samplePeriod(unit="s")=300 + "Sample period time" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Integer numIgnReq = 2 + "Number of ignored requests" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real triAmo = -0.02 "Trim amount" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real resAmo = 0.03 + "Respond amount (must be opposite in to triAmo)" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real maxRes = 0.07 + "Maximum response per time interval (same sign as resAmo)" + annotation (Dialog(tab="Plant Reset", group="Trim and respond")); + + parameter Real dpChiWatPumMin( + unit="Pa", + displayUnit="Pa")=34473.8 + "Minimum chilled water pump differential static pressure, default 5 psi" + annotation (Dialog(tab="Plant Reset", group="Chilled water supply")); + + parameter Real dpChiWatPumMax[nSenChiWatPum]( + unit=fill("Pa", nSenChiWatPum), + displayUnit=fill("Pa",nSenChiWatPum)) + "Maximum chilled water pump differential static pressure, the array size equals to the number of remote pressure sensor" + annotation (Dialog(tab="Plant Reset", group="Chilled water supply")); + + parameter Real TChiWatSupMax( + unit="K", + displayUnit="degC")=288.706 + "Maximum chilled water supply temperature, default 60 degF" + annotation (Dialog(tab="Plant Reset", group="Chilled water supply")); + + parameter Real halSet = 0.5 + "Half plant reset value" + annotation (Dialog(tab="Plant Reset", group="Chilled water supply")); + + // ---- Staging setpoints ---- + + parameter Real avePer(unit="s")=300 + "Time period for the capacity requirement rolling average" + annotation (Dialog(tab="Staging", group="Hold and delay")); + + parameter Real delayStaCha(unit="s")=900 + "Hold period for each stage change" + annotation (Dialog(tab="Staging", group="Hold and delay")); + + parameter Real parLoaRatDelay(unit="s")=900 + "Enable delay for operating and staging part load ratio condition" + annotation (Dialog(tab="Staging", group="Hold and delay")); + + parameter Real faiSafTruDelay(unit="s")=900 + "Enable delay for failsafe condition" + annotation (Dialog(tab="Staging", group="Hold and delay")); + + parameter Real effConTruDelay(unit="s")=900 + "Enable delay for efficiency condition" + annotation (Dialog(tab="Staging", group="Hold and delay")); + + parameter Real shortTDelay(unit="s")=600 + "Short enable delay for staging from zero to first available stage up" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Staging", group="Hold and delay")); + + parameter Real longTDelay(unit="s")=1200 + "Long enable delay for staging from zero to first available stage up" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Staging", group="Hold and delay")); + + parameter Real posDisMult(unit="1")=0.8 + "Positive displacement chiller type staging multiplier" + annotation (Dialog(tab="Staging", group="Staging part load ratio")); + + parameter Real conSpeCenMult(unit="1")=0.9 + "Constant speed centrifugal chiller type staging multiplier" + annotation (Dialog(tab="Staging", group="Staging part load ratio")); + + parameter Real anyOutOfScoMult(unit="1")=0.9 + "Outside of G36 recommended staging order chiller type SPLR multiplier" + annotation(Evaluate=true, __cdl(ValueInReference=False), Dialog(tab="Staging", group="Staging part load ratio")); + + parameter Real varSpeStaMin(unit="1")=0.45 + "Minimum stage up or down part load ratio for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen, tab="Staging", group="Staging part load ratio")); + + parameter Real varSpeStaMax(unit="1")=0.9 + "Maximum stage up or down part load ratio for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen, tab="Staging", group="Staging part load ratio")); + + parameter Real smallTDif(unit="K")=1 + "Offset between the chilled water supply temperature and its setpoint for the long condition" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Staging", group="Value comparison")); + + parameter Real largeTDif(unit="K")=2 + "Offset between the chilled water supply temperature and its setpoint for the short condition" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Staging", group="Value comparison")); + + parameter Real faiSafTDif(unit="K")=1 + "Offset between the chilled water supply temperature and its setpoint for the failsafe condition" + annotation (Dialog(tab="Staging", group="Value comparison")); + + parameter Real dpDif( + unit="Pa", + displayUnit="Pa")=2*6895 + "Offset between the chilled water pump diferential static pressure and its setpoint" + annotation (Dialog(tab="Staging", group="Value comparison")); + + parameter Real TDif(unit="K")=1 + "Offset between the chilled water supply temperature and its setpoint for staging down to WSE only" + annotation (Dialog(tab="Staging", group="Value comparison")); + + parameter Real faiSafDpDif( + unit="Pa", + displayUnit="Pa")=2*6895 + "Offset between the chilled water differential pressure and its setpoint" + annotation (Dialog(tab="Staging", group="Value comparison")); + + parameter Real effConSigDif( + max=1, + min=0)=0.05 + "Signal hysteresis deadband" + annotation (Dialog(tab="Staging", group="Value comparison")); + + // ---- Staging up and down process ---- + + parameter Real chiDemRedFac(unit="1")=0.75 + "Demand reducing factor of current operating chillers" + annotation (Dialog(tab="Staging", group="Up and down process", enable=need_reduceChillerDemand)); + + parameter Real holChiDemTim(unit="s")=300 + "Maximum time to wait for the actual demand less than percentage of current load" + annotation (Dialog(tab="Staging", group="Up and down process", enable=need_reduceChillerDemand)); + + parameter Real aftByPasSetTim(unit="s")=60 + "Time to allow loop to stabilize after resetting minimum chilled water flow setpoint" + annotation (Dialog(tab="Staging", group="Up and down process")); + + parameter Real waiTim(unit="s")=30 + "Waiting time after enabling next head pressure control" + annotation (Dialog(tab="Staging", group="Up and down process")); + + parameter Real chaChiWatIsoTim(unit="s")=300 + "Time to slowly change isolation valve, should be determined in the field" + annotation (Dialog(tab="Staging", group="Up and down process")); + + parameter Real proOnTim(unit="s")=300 + "Threshold time to check after newly enabled chiller being operated" + annotation (Dialog(tab="Staging", group="Up and down process", enable=have_ponyChiller)); + + parameter Real thrTimEnb(unit="s")=10 + "Threshold time to enable head pressure control after condenser water pump being reset" + annotation (Dialog(tab="Staging", group="Up and down process")); + + // ---- Cooling tower: fan speed ---- + + parameter Real fanSpeMin(unit="1")=0.1 + "Minimum tower fan speed" + annotation (Dialog(tab="Cooling Towers", group="Fan speed")); + + parameter Real fanSpeMax(unit="1")=1 + "Maximum tower fan speed" + annotation (Dialog(tab="Cooling Towers", group="Fan speed")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController intOpeCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Controller in the mode when WSE and chillers are enabled" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE)); + + parameter Real kIntOpeTowFan=0.1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE)); + + parameter Real TiIntOpeTowFan(unit="s")=10 + "Time constant of integrator block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE and (intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdIntOpeTowFan(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE and (intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController chiWatConTowFan= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Controller in the mode when only WSE is enabled" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", enable=have_WSE)); + + parameter Real kWSETowFan=0.1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", enable=have_WSE)); + + parameter Real TiWSETowFan(unit="s")=10 + "Time constant of integrator block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE and (chiWatConTowFan==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + chiWatConTowFan==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdWSETowFan(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE and (chiWatConTowFan==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + chiWatConTowFan==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + // Fan speed control: controlling condenser return water temperature when WSE is not enabled + parameter Real LIFT_min[nChi](unit=fill("K", nChi))={12,12} + "Minimum LIFT of each chiller" + annotation (Evaluate=true, Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control")); + + parameter Real TConWatSup_nominal[nChi]( + unit=fill("K", nChi), + displayUnit=fill("degC",nChi))={293.15,293.15} + "Condenser water supply temperature (condenser entering) of each chiller" + annotation (Evaluate=true, Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control")); + + parameter Real TConWatRet_nominal[nChi]( + unit=fill("K", nChi), + displayUnit=fill("degC",nChi))={303.15,303.15} + "Condenser water return temperature (condenser leaving) of each chiller" + annotation (Evaluate=true, Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController couPlaCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of coupled plant controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=closeCoupledPlant)); + + parameter Real kCouPla=1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=closeCoupledPlant)); + + parameter Real TiCouPla(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=closeCoupledPlant and (couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdCouPla(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=closeCoupledPlant and (couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real yCouPlaMax(unit="1")=1 + "Upper limit of output" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=closeCoupledPlant)); + + parameter Real yCouPlaMin(unit="1")=0 + "Lower limit of output" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=closeCoupledPlant)); + + parameter Real samplePeriodConTDiff(unit="s")=30 + "Period of sampling condenser water supply and return temperature difference" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant)); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController supWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Condenser supply water temperature controller for less coupled plant" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant)); + + parameter Real kSupCon=0.1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant)); + + parameter Real TiSupCon(unit="s")=10 + "Time constant of integrator block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant and (supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdSupCon(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant and (supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real ySupConMax=1 "Upper limit of output" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant)); + + parameter Real ySupConMin=0 "Lower limit of output" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant)); + + parameter Real iniPlaTim(unit="s")=600 + "Time to hold return temperature at initial setpoint after plant being enabled" + annotation (Dialog(tab="Cooling Towers", group="Advanced")); + + parameter Real ramTim(unit="s")=180 + "Time to ramp return water temperature from initial value to setpoint" + annotation (Dialog(tab="Cooling Towers", group="Advanced")); + + parameter Real cheMinFanSpe(unit="s")=300 + "Threshold time for checking duration when tower fan equals to the minimum tower fan speed" + annotation (Dialog(tab="Cooling Towers", group="Advanced")); + + parameter Real cheMaxTowSpe(unit="s")=300 + "Threshold time for checking duration when any enabled chiller maximum cooling speed equals to the minimum tower fan speed" + annotation (Dialog(tab="Cooling Towers", group="Advanced")); + + parameter Real cheTowOff(unit="s")=60 + "Threshold time for checking duration when there is no enabled tower fan" + annotation (Dialog(tab="Cooling Towers", group="Advanced")); + + // ---- Cooling tower: staging ---- + parameter Real chaTowCelIsoTim(unit="s")=300 + "Time to slowly change isolation valve" + annotation (Dialog(tab="Cooling Towers", group="Enable isolation valve")); + + // ---- Cooling tower: Water level control ---- + parameter Real watLevMin(unit="1")=0.7 + "Minimum cooling tower water level recommended by manufacturer" + annotation (Dialog(tab="Cooling Towers", group="Makeup water")); + + parameter Real watLevMax(unit="1")=1 + "Maximum cooling tower water level recommended by manufacturer" + annotation (Dialog(tab="Cooling Towers", group="Makeup water")); + + // ---- Advanced ---- + parameter Real locDt(unit="K")=1 + "Offset temperature for lockout chiller" + annotation(Evaluate=true, Dialog(tab="Advanced", group="Plant enable")); + + parameter Real hysDt( + unit="K", + displayUnit="K")=1 + "Deadband temperature used in hysteresis block" + annotation(Evaluate=true, Dialog(tab="Advanced", group="Waterside economizer")); + + parameter Real dpDifHys( + unit="Pa", + displayUnit="Pa")=0.5*6895 + "Pressure difference hysteresis deadband" + annotation (Dialog(tab="Advanced", group="Staging")); + + parameter Real relFloDif=0.05 + "Relative error to the setpoint for checking if it has achieved flow rate setpoint" + annotation (Dialog(tab="Advanced", group="Staging")); + + parameter Real speChe=0.005 + "Lower threshold value to check fan or pump speed" + annotation (Dialog(tab="Advanced", group="Cooling towers")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiConIsoVal[nChi] + "Chiller condenser water isolation valve status" + annotation (Placement(transformation(extent={{-940,644},{-900,684}}), + iconTransformation(extent={{-140,360},{-100,400}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatReq[nChi] + "Chilled water requst status for each chiller" + annotation (Placement(transformation(extent={{-940,614},{-900,654}}), + iconTransformation(extent={{-140,340},{-100,380}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatReq[nChi] + "Condenser water requst status for each chiller" + annotation (Placement(transformation(extent={{-940,584},{-900,624}}), + iconTransformation(extent={{-140,320},{-100,360}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nChiWatPum] + "Chilled water pump status" + annotation(Placement(transformation(extent={{-940,554},{-900,594}}), + iconTransformation(extent={{-140,300},{-100,340}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiIsoVal[nChi] if have_heaChiWatPum + "Chilled water isolation valve status" + annotation(Placement(transformation(extent={{-940,520},{-900,560}}), + iconTransformation(extent={{-140,280},{-100,320}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_local( + final quantity="PressureDifference", + final displayUnit="Pa") if have_locSenChiWatPum + "Chilled water differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-940,490},{-900,530}}), + iconTransformation(extent={{-140,240},{-100,280}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_remote[nSenChiWatPum]( + final unit=fill("Pa", nSenChiWatPum), + final quantity=fill("PressureDifference", nSenChiWatPum)) + "Chilled water differential static pressure from remote sensor" + annotation(Placement(transformation(extent={{-940,450},{-900,490}}), + iconTransformation(extent={{-140,220},{-100,260}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s") + "Measured chilled water volume flow rate" + annotation(Placement(transformation(extent={{-940,420},{-900,460}}), + iconTransformation(extent={{-140,200},{-100,240}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Vector of chiller proven on status: true=ON" + annotation(Placement(transformation(extent={{-940,380},{-900,420}}), + iconTransformation(extent={{-140,180},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutWet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if have_WSE + "Outdoor air wet bulb temperature" + annotation(Placement(transformation(extent={{-940,340},{-900,380}}), + iconTransformation(extent={{-140,140},{-100,180}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRetDow( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if have_WSE + "Chiller water return temperature downstream of the WSE" + annotation(Placement(transformation(extent={{-940,300},{-900,340}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chiller water return temperature upstream of the WSE" + annotation(Placement(transformation(extent={{-940,260},{-900,300}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured condenser water return temperature (condenser leaving)" + annotation(Placement(transformation(extent={{-940,220},{-900,260}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured chilled water supply temperature" + annotation(Placement(transformation(extent={{-940,190},{-900,230}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHeaPreCon[nChi] if have_heaPreConSig + "Chiller head pressure control loop signal from chiller controller" + annotation (Placement(transformation(extent={{-940,160},{-900,200}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiLoa[nChi]( + final quantity=fill("ElectricCurrent",nChi), + final unit=fill("A", nChi)) if need_reduceChillerDemand + "Current chiller load, in amperage" + annotation(Placement(transformation(extent={{-940,120},{-900,160}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat( + final unit="Pa", + final quantity="PressureDifference") + if have_WSE and have_byPasValCon + "Differential static pressure across economizer in the chilled water side" + annotation (Placement(transformation(extent={{-940,90},{-900,130}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiAva[nChi] + "Chiller availability status vector" + annotation(Placement(transformation(extent={{-940,60},{-900,100}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEcoPum + if have_WSE and not have_byPasValCon + "True: economizer heat exchanger pump is proven on" + annotation (Placement(transformation(extent={{-940,30},{-900,70}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TEntHex( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + if have_WSE and not have_byPasValCon + "Chilled water temperature entering economizer heat exchanger" + annotation (Placement(transformation(extent={{-940,0},{-900,40}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-940,-100},{-900,-60}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chilled water isolation valve position" + annotation(Placement(transformation(extent={{-940,-248},{-900,-208}}), + iconTransformation(extent={{-140,-140},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput TChiWatSupResReq + "Chilled water supply temperature setpoint reset request" + annotation (Placement(transformation(extent={{-940,-320},{-900,-280}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput chiPlaReq + "Number of chiller plant cooling requests" + annotation (Placement(transformation(extent={{-940,-360},{-900,-320}}), + iconTransformation(extent={{-140,-180},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum), + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation(Placement(transformation(extent={{-940,-400},{-900,-360}}), + iconTransformation(extent={{-140,-220},{-100,-180}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatPum[nConWatPum] + "Condenser water pump status" + annotation (Placement(transformation(extent={{-940,-430},{-900,-390}}), + iconTransformation(extent={{-140,-240},{-100,-200}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Outdoor air dry bulb temperature" + annotation (Placement(transformation(extent={{-940,-540},{-900,-500}}), + iconTransformation(extent={{-140,-260},{-100,-220}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiCooLoa[nChi]( + final quantity=fill("HeatFlowRate",nChi), + final unit=fill("W", nChi)) if have_WSE + "Current chiller cooling load" + annotation (Placement(transformation(extent={{-940,-580},{-900,-540}}), + iconTransformation(extent={{-140,-280},{-100,-240}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final quantity="1", + final min=0, + final max=1) "Tower fan speed" + annotation (Placement(transformation(extent={{-940,-608},{-900,-568}}), + iconTransformation(extent={{-140,-320},{-100,-280}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not closeCoupledPlant + "Condenser water supply temperature (condenser entering)" + annotation(Placement(transformation(extent={{-940,-680},{-900,-640}}), + iconTransformation(extent={{-140,-340},{-100,-300}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uIsoVal[nTowCel]( + final min=fill(0, nTowCel), + final max=fill(1, nTowCel), + final unit=fill("1", nTowCel)) + "Vector of tower cells isolation valve position" + annotation(Placement(transformation(extent={{-940,-728},{-900,-688}}), + iconTransformation(extent={{-140,-360},{-100,-320}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput watLev + "Measured water level" + annotation (Placement(transformation(extent={{-940,-760},{-900,-720}}), + iconTransformation(extent={{-140,-380},{-100,-340}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowSta[nTowCel] + "Vector of tower cell proven on status: true=running tower cell" + annotation(Placement(transformation(extent={{-940,-800},{-900,-760}}), + iconTransformation(extent={{-140,-400},{-100,-360}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yEcoConWatIsoVal if have_WSE + "Economizer condensing water isolation valve position" + annotation (Placement(transformation(extent={{920,760},{960,800}}), + iconTransformation(extent={{100,370},{140,410}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yWseRetVal( + final min=0, + final max=1, + final unit="1") if have_byPasValCon and have_WSE + "WSE in-line CHW return line valve position" + annotation (Placement(transformation(extent={{920,730},{960,770}}), + iconTransformation(extent={{100,338},{140,378}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yWsePumOn + if have_WSE and not have_byPasValCon + "Heat exchanger pump command on" + annotation (Placement(transformation(extent={{920,700},{960,740}}), + iconTransformation(extent={{100,310},{140,350}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yWsePumSpe( + final min=0, + final unit="1", + final max=1) if have_WSE and not have_byPasValCon + "Heat exchanger pump speed setpoint" + annotation (Placement(transformation(extent={{920,670},{960,710}}), + iconTransformation(extent={{100,290},{140,330}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{920,630},{960,670}}), + iconTransformation(extent={{100,260},{140,300}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiWatPum[nChiWatPum] + if have_heaChiWatPum + "Chilled water pump status setpoint" + annotation(Placement(transformation(extent={{920,500},{960,540}}), + iconTransformation(extent={{100,230},{140,270}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiPumSpe[nChiWatPum]( + final min=fill(0,nChiWatPum), + final max=fill(1,nChiWatPum), + final unit=fill("1",nChiWatPum)) "Chilled water pump speed setpoint" + annotation (Placement(transformation(extent={{920,460},{960,500}}), + iconTransformation(extent={{100,200},{140,240}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiDem[nChi]( + final quantity=fill("ElectricCurrent",nChi), + final unit=fill("A", nChi)) if need_reduceChillerDemand + "Chiller demand setpoint to set through BACnet or similar " + annotation(Placement(transformation(extent={{920,400},{960,440}}), + iconTransformation(extent={{100,170},{140,210}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status setpoint" + annotation(Placement(transformation(extent={{920,330},{960,370}}), + iconTransformation(extent={{100,140},{140,180}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yHeaPreConValSta[nChi] + "Chiller head pressure control status setpoint" + annotation (Placement(transformation(extent={{920,260},{960,300}}), + iconTransformation(extent={{100,110},{140,150}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaPreConVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Head pressure control valve position" + annotation (Placement(transformation(extent={{920,220},{960,260}}), + iconTransformation(extent={{100,70},{140,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatPumSpe[nConWatPum]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{920,130},{960,170}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatMinFloSet( + final quantity="VolumeFlowRate", + final unit="m3/s", + final min=0) "Chilled water minimum flow setpoint" + annotation (Placement(transformation(extent={{920,100},{960,140}}), + iconTransformation(extent={{100,12},{140,52}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yConWatPum[nConWatPum] + "Status setpoint of condenser water pump" + annotation (Placement(transformation(extent={{920,70},{960,110}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) + "Chiller isolation valve position setpoints" + annotation (Placement(transformation(extent={{920,-20},{960,20}}), + iconTransformation(extent={{100,-90},{140,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yReaChiDemLim + if need_reduceChillerDemand + "Release chiller demand limit, normally true" + annotation (Placement(transformation(extent={{920,-230},{960,-190}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinValPosSet( + final min=0, + final max=1, + final unit="1") "Chilled water minimum flow bypass valve position setpoint" + annotation (Placement(transformation(extent={{920,-340},{960,-300}}), + iconTransformation(extent={{100,-120},{140,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yTowCelIsoVal[nTowCel]( + final min=fill(0, nTowCel), + final max=fill(1, nTowCel), + final unit=fill("1", nTowCel)) + "Cooling tower cells isolation valve position" + annotation (Placement(transformation(extent={{920,-640},{960,-600}}), + iconTransformation(extent={{100,-200},{140,-160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowCel[nTowCel] + "Vector of tower cells status setpoint" + annotation(Placement(transformation(extent={{920,-680},{960,-640}}), + iconTransformation(extent={{100,-230},{140,-190}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yTowFanSpe[nTowCel]( + final min=fill(0, nTowCel), + final max=fill(1, nTowCel), + final unit=fill("1", nTowCel)) + "Fan speed setpoint of each cooling tower cell" + annotation (Placement(transformation(extent={{920,-720},{960,-680}}), + iconTransformation(extent={{100,-260},{140,-220}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yMakUp + "Makeup water valve On-Off status" + annotation(Placement(transformation(extent={{920,-780},{960,-740}}), + iconTransformation(extent={{100,-290},{140,-250}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Controller wseSta( + final have_byPasValCon=have_byPasValCon, + final nSta=nSta, + final holdPeriod=holdPeriod, + final delDis=delDis, + final TOffsetEna=TOffsetEna, + final TOffsetDis=TOffsetDis, + final heaExcAppDes=heaExcAppDes, + final cooTowAppDes=cooTowAppDes, + final TOutWetDes=TOutWetDes, + final VHeaExcDes_flow=VHeaExcDes_flow, + final hysDt=hysDt, + final step=step, + final wseOnTimDec=wseOnTimDec, + final wseOnTimInc=wseOnTimInc, + final dpDes=dpDes, + final valCon=ecoValCon, + final k=kEcoVal, + final Ti=TiEcoVal, + final Td=TdEcoVal, + final minSpe=minEcoSpe, + final desSpe=desEcoSpe) if have_WSE + "Waterside economizer (WSE) enable/disable status" + annotation(Placement(transformation(extent={{-700,300},{-660,340}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Enable plaEna( + final schTab=schTab, + final TChiLocOut=TChiLocOut, + final plaThrTim=plaThrTim, + final reqThrTim=reqThrTim, + final ignReq=ignReq, + final locDt=locDt) "Sequence to enable and disable plant" + annotation (Placement(transformation(extent={{-700,-540},{-660,-500}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller + heaPreCon[nChi]( + final have_fixSpeConWatPum=fill(have_fixSpeConWatPum, nChi), + final have_heaPreConSig=fill(have_heaPreConSig, nChi), + final have_WSE=fill(have_WSE, nChi), + final minTowSpe=fill(fanSpeMin, nChi), + final minConWatPumSpe=fill(minConWatPumSpe, nChi), + final minHeaPreValPos=fill(minHeaPreValPos, nChi), + final controllerType=fill(controllerTypeHeaPre, nChi), + final minChiLif=fill(minChiLif, nChi), + final k=fill(kHeaPreCon, nChi), + final Ti=fill(TiHeaPreCon, nChi)) "Chiller head pressure controller" + annotation (Placement(transformation(extent={{-520,180},{-480,220}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Controller minBypValCon( + final nChi=nChi, + final minFloSet=minFloSet, + final controllerType=controllerTypeMinFloByp, + final k=kMinFloBypCon, + final Ti=TiMinFloBypCon, + final Td=TdMinFloBypCon, + final yMax=yMaxFloBypCon, + final yMin=yMinFloBypCon) + "Controller for chilled water minimum flow bypass valve" + annotation (Placement(transformation(extent={{-680,-160},{-640,-120}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Controller chiWatPumCon( + final have_heaPum=have_heaChiWatPum, + final have_locSen=have_locSenChiWatPum, + final have_WSE=have_WSE, + final nChi=nChi, + final nPum=nChiWatPum, + final nSen=nSenChiWatPum, + final minPumSpe=minChiWatPumSpe, + final maxPumSpe=maxChiWatPumSpe, + final nPum_nominal=nPum_nominal, + final VChiWat_flow_nominal=VChiWat_flow_nominal, + final maxLocDp=maxLocDp, + final controllerType=controllerTypeChiWatPum, + final k=kChiWatPum, + final Ti=TiChiWatPum, + final Td=TdChiWatPum) + "Sequences to control chilled water pumps in primary-only plant system" + annotation(Placement(transformation(extent={{440,480},{500,540}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterPlantReset chiWatPlaRes( + final nPum=nChiWatPum, + final holTim=holTim, + final iniSet=iniSet, + final minSet=minSet, + final maxSet=maxSet, + final delTim=delTim, + final samplePeriod=samplePeriod, + final numIgnReq=numIgnReq, + final triAmo=triAmo, + final resAmo=resAmo, + final maxRes=maxRes) + "Sequences to generate chilled water plant reset" + annotation(Placement(transformation(extent={{-700,-320},{-660,-280}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterSupply chiWatSupSet( + final nRemDpSen=nSenChiWatPum, + final dpChiWatPumMin=dpChiWatPumMin, + final dpChiWatPumMax=dpChiWatPumMax, + final TChiWatSupMin=TChiWatSupMin_Lowest, + final TChiWatSupMax=TChiWatSupMax, + final minSet=minSet, + final maxSet=maxSet, + final halSet=halSet) + "Sequences to generate setpoints of chilled water supply temperature and the pump differential static pressure" + annotation(Placement(transformation(extent={{-520,420},{-480,460}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController staSetCon( + final have_WSE=have_WSE, + final have_serChi=have_serChi, + final have_locSen=have_locSenChiWatPum, + final nRemSen=nSenChiWatPum, + final anyVsdCen=anyVsdCen, + final nChi=nChi, + final chiDesCap=chiDesCap, + final chiMinCap=chiMinCap, + final chiTyp=chiTyp, + final nSta=nSta, + final staMat=staMat, + final avePer=avePer, + final delayStaCha=delayStaCha, + final parLoaRatDelay=parLoaRatDelay, + final faiSafTruDelay=faiSafTruDelay, + final effConTruDelay=effConTruDelay, + final shortTDelay=shortTDelay, + final longTDelay=longTDelay, + final posDisMult=posDisMult, + final conSpeCenMult=conSpeCenMult, + final anyOutOfScoMult=anyOutOfScoMult, + final varSpeStaMin=varSpeStaMin, + final varSpeStaMax=varSpeStaMax, + final smallTDif=smallTDif, + final largeTDif=largeTDif, + final faiSafTDif=faiSafTDif, + final dpDif=dpDif, + final TDif=TDif, + final TDifHys=hysDt, + final faiSafDpDif=faiSafDpDif, + final dpDifHys=dpDifHys, + final effConSigDif=effConSigDif) + "Calculates the chiller stage status setpoint signal" + annotation(Placement(transformation(extent={{-260,-68},{-180,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller towCon( + final nChi=nChi, + final totSta=totSta, + final nTowCel=nTowCel, + final nConWatPum=nConWatPum, + final closeCoupledPlant=closeCoupledPlant, + final have_WSE=have_WSE, + final desCap=desCap, + final fanSpeMin=fanSpeMin, + final fanSpeMax=fanSpeMax, + final chiMinCap=chiMinCap, + final intOpeCon=intOpeCon, + final kIntOpe=kIntOpeTowFan, + final TiIntOpe=TiIntOpeTowFan, + final TdIntOpe=TdIntOpeTowFan, + final chiWatCon=chiWatConTowFan, + final kWSE=kWSETowFan, + final TiWSE=TiWSETowFan, + final TdWSE=TdWSETowFan, + final LIFT_min=LIFT_min, + final TConWatSup_nominal=TConWatSup_nominal, + final TConWatRet_nominal=TConWatRet_nominal, + final TChiWatSupMin=TChiWatSupMin, + final couPlaCon=couPlaCon, + final kCouPla=kCouPla, + final TiCouPla=TiCouPla, + final TdCouPla=TdCouPla, + final yCouPlaMax=yCouPlaMax, + final yCouPlaMin=yCouPlaMin, + final samplePeriod=samplePeriodConTDiff, + final supWatCon=supWatCon, + final kSupCon=kSupCon, + final TiSupCon=TiSupCon, + final TdSupCon=TdSupCon, + final ySupConMax=ySupConMax, + final ySupConMin=ySupConMin, + final speChe=speChe, + final iniPlaTim=iniPlaTim, + final ramTim=ramTim, + final cheMinFanSpe=cheMinFanSpe, + final cheMaxTowSpe=cheMaxTowSpe, + final cheTowOff=cheTowOff, + final staVec=staVec, + final towCelOnSet=towCelOnSet, + final chaTowCelIsoTim=chaTowCelIsoTim, + final watLevMin=watLevMin, + final watLevMax=watLevMax) + "Cooling tower controller" + annotation(Placement(transformation(extent={{-260,-720},{-180,-560}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Down dowProCon( + final nChi=nChi, + final nConWatPum=nConWatPum, + final totSta=totSta, + final nChiSta=nSta + 1, + final have_WSE=have_WSE, + final have_ponyChiller=have_ponyChiller, + final have_parChi=have_parChi, + final have_heaConWatPum=have_heaConWatPum, + final have_fixSpeConWatPum=have_fixSpeConWatPum, + final need_reduceChillerDemand=need_reduceChillerDemand, + final chiDemRedFac=chiDemRedFac, + final holChiDemTim=holChiDemTim, + final waiTim=waiTim, + final proOnTim=proOnTim, + final chaChiWatIsoTim=chaChiWatIsoTim, + final staVec=staVec, + final desConWatPumSpe=desConWatPumSpe, + final desConWatPumNum=desConWatPumNum, + final byPasSetTim=byPasSetTim, + final minFloSet=minFloSet, + final maxFloSet=maxFloSet, + final aftByPasSetTim=aftByPasSetTim, + final pumSpeChe=speChe, + final relFloDif=relFloDif, + final desChiNum=desChiNum) + "Staging down process controller" + annotation(Placement(transformation(extent={{180,-300},{260,-140}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Up upProCon( + final nChi=nChi, + final nConWatPum=nConWatPum, + final totSta=totSta, + final nChiSta=nSta + 1, + final have_WSE=have_WSE, + final have_ponyChiller=have_ponyChiller, + final have_parChi=have_parChi, + final have_heaConWatPum=have_heaConWatPum, + final have_fixSpeConWatPum=have_fixSpeConWatPum, + final need_reduceChillerDemand=need_reduceChillerDemand, + final chiDemRedFac=chiDemRedFac, + final holChiDemTim=holChiDemTim, + final byPasSetTim=byPasSetTim, + final minFloSet=minFloSet, + final maxFloSet=maxFloSet, + final aftByPasSetTim=aftByPasSetTim, + final staVec=staVec, + final desConWatPumSpe=desConWatPumSpe, + final desConWatPumNum=desConWatPumNum, + final thrTimEnb=thrTimEnb, + final waiTim=waiTim, + final chaChiWatIsoTim=chaChiWatIsoTim, + final proOnTim=proOnTim, + final pumSpeChe=speChe, + final relFloDif=relFloDif, + final desChiNum=desChiNum) + "Staging up process controller" + annotation(Placement(transformation(extent={{180,280},{260,440}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMax mulMax( + final nin=nTowCel) if have_WSE + "All input values are the same" + annotation(Placement(transformation(extent={{-60,-590},{-40,-570}}))); + + Buildings.Controls.OBC.CDL.Logical.Or chaProUpDown + "Either in staging up or in staging down process" + annotation(Placement(transformation(extent={{380,-90},{400,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Check if stage change is finished" + annotation(Placement(transformation(extent={{480,-90},{500,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChiWatPum) + "Check if there is any chilled water pump is enabled" + annotation(Placement(transformation(extent={{-740,-134},{-720,-114}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMax conWatPumSpe( + final nin=nConWatPum) + if not have_fixSpeConWatPum + "Running condenser water pump speed" + annotation (Placement(transformation(extent={{-660,-390},{-640,-370}}))); + + Buildings.Controls.OBC.CDL.Logical.Or staCooTow + "Tower stage change status: true=stage cooling tower" + annotation (Placement(transformation(extent={{480,-130},{500,-110}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) if have_WSE + "Waterside economizer status" + annotation (Placement(transformation(extent={{-620,240},{-600,260}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator conWatRetTem( + final nout=nChi) + if not have_heaPreConSig + "Condenser water return temperature" + annotation (Placement(transformation(extent={{-680,230},{-660,250}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator chiWatSupTem( + final nout=nChi) + if not have_heaPreConSig + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-680,194},{-660,214}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch desConWatPumSpeSwi + if not have_fixSpeConWatPum + "Design condenser water pump speed" + annotation (Placement(transformation(extent={{480,190},{500,210}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator desConPumSpe( + final nout=nChi) if not have_fixSpeConWatPum + "Replicate design condenser water pump speed" + annotation (Placement(transformation(extent={{540,190},{560,210}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMax mulMax1( + final nin=nChi) + if not have_fixSpeConWatPum + "Condenser water pump speed" + annotation (Placement(transformation(extent={{-460,150},{-440,170}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch chiMinFloSet + "Chiller water minimum flow setpoint" + annotation (Placement(transformation(extent={{480,110},{500,130}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator uChiSwi( + final nout=nChi) + "In chiller stage up process" + annotation (Placement(transformation(extent={{460,340},{480,360}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch uChiStaPro[nChi] + "Chiller head pressure control status" + annotation (Placement(transformation(extent={{640,340},{660,360}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre preConPumLeaSta + "Lead condenser water pump status from previous step" + annotation (Placement(transformation(extent={{480,-260},{500,-240}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo equRot + if have_heaChiWatPum + "Rotates two pumps or groups of pumps" + annotation (Placement(transformation(extent={{260,570},{280,590}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1[nChiWatPum]( + final k={1,2}) if have_heaChiWatPum + "Two pumps or groups of pumps only" + annotation (Placement(transformation(extent={{320,600},{340,620}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2[nChiWatPum]( + final k={2,1}) if have_heaChiWatPum + "Two pumps or groups of pumps only" + annotation (Placement(transformation(extent={{320,550},{340,570}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi[2] if have_heaChiWatPum + "Two devices or groups of devices" + annotation (Placement(transformation(extent={{380,570},{400,590}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch chiStaUp + "In chiller stage up process" + annotation (Placement(transformation(extent={{380,310},{400,330}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 "Stage cooling tower" + annotation (Placement(transformation(extent={{100,-450},{120,-430}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nChiWatPum] if have_heaChiWatPum + "Convert boolean to integer" + annotation (Placement(transformation(extent={{580,550},{600,570}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum totChiPum( + final nin=nChiWatPum) if have_heaChiWatPum + "Total enabled chilled water pump" + annotation (Placement(transformation(extent={{620,550},{640,570}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr( + final t=1) + "Check if more than one pump is enabled, if yes, then it means lag pump is enabled" + annotation (Placement(transformation(extent={{580,590},{600,610}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch chiHeaCon[nChi] + "Chiller head control enabling status" + annotation (Placement(transformation(extent={{520,270},{540,290}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch conWatPumNum + "Total number of enablded condenser water pump" + annotation (Placement(transformation(extent={{440,50},{460,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo equRot1 if have_heaChiWatPum + "Rotates two pumps or groups of pumps" + annotation (Placement(transformation(extent={{540,50},{560,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch conPumLeaSta + "Pick the condenser water pump lead status" + annotation (Placement(transformation(extent={{440,-260},{460,-240}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr1( + final t=1) + "Check if more than one pump is enabled, if yes, then it means lag pump is enabled" + annotation (Placement(transformation(extent={{480,50},{500,70}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch chiIsoVal[nChi] + "Chiller isolation valve position setpoint" + annotation (Placement(transformation(extent={{540,-10},{560,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch chiDem[nChi] + if need_reduceChillerDemand + "Chiller demand" + annotation (Placement(transformation(extent={{640,410},{660,430}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch relDem if need_reduceChillerDemand + "Release chiller demand limit" + annotation (Placement(transformation(extent={{480,-220},{500,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre preChaPro + "Stage changing process status from previous step" + annotation (Placement(transformation(extent={{440,-90},{460,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre leaChiPumPre + "Lead chilled water pump status previous value" + annotation (Placement(transformation(extent={{520,590},{540,610}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre leaChiWatPum[nChiWatPum] + "Chilled water pump status previous value" + annotation (Placement(transformation(extent={{540,550},{560,570}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con( + final k=fixConWatPumSpe) + if have_fixSpeConWatPum "Speed of constant speed condenser water pump" + annotation (Placement(transformation(extent={{540,90},{560,110}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator chiWatPumSpe( + final nout=nChiWatPum) + "Chilled water pump speed" + annotation (Placement(transformation(extent={{580,450},{600,470}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChiWatPum] + "Boolean to real" + annotation (Placement(transformation(extent={{580,490},{600,510}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro[nChiWatPum] + "Chilled water pump speed setpoint" + annotation (Placement(transformation(extent={{640,470},{660,490}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro1[nChiWatPum] + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{660,140},{680,160}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator conWatPumSpe1( + final nout=nConWatPum) "Condenser water pump speed" + annotation (Placement(transformation(extent={{590,140},{610,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[nConWatPum] + "Boolean to real" + annotation (Placement(transformation(extent={{580,56},{600,76}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea3[nChi] + "Boolean to real" + annotation (Placement(transformation(extent={{580,250},{600,270}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro4[nChi] + "Head pressure control valve position" + annotation (Placement(transformation(extent={{660,230},{680,250}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpeVal[nChi]( + final k=fill(1, nChi)) + if not have_WSE and not have_fixSpeConWatPum + "Full open head pressure control valve" + annotation (Placement(transformation(extent={{240,180},{260,200}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.EnableDevices enaDev( + final nSta=nSta, + final nChiWatPum=nChiWatPum, + final nConWatPum=nConWatPum, + final iniPumDel=iniPumDel) + "Enable devices when plant is enabled" + annotation (Placement(transformation(extent={{-540,-440},{-520,-420}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch leaChiPum "Lead chilled water pump" + annotation (Placement(transformation(extent={{200,582},{220,602}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.DisableChillers disChi( + final have_WSE=have_WSE, + final nChi=nChi, + final nChiWatPum=nChiWatPum, + final nConWatPum=nConWatPum, + final nTowCel=nTowCel) "Disable devices when plant is disabled" + annotation (Placement(transformation(extent={{740,-480},{760,-460}}))); + + Buildings.Controls.OBC.CDL.Logical.And celCom[nTowCel] + "False: disable tower cell" + annotation (Placement(transformation(extent={{840,-670},{860,-650}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi[nTowCel] + "Tower cell isolation valve position setpoint" + annotation (Placement(transformation(extent={{880,-630},{900,-610}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1[nTowCel]( + final k=fill(0, nTowCel)) + "Constant zero" + annotation (Placement(transformation(extent={{700,-590},{720,-570}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nTowCel] + "Tower cell fan speed setpoint" + annotation (Placement(transformation(extent={{880,-710},{900,-690}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.IdentifyStage ideSta( + final nSta=nSta, + final nChi=nChi, + final staMat=staMat) "Identify stage index" + annotation (Placement(transformation(extent={{-520,120},{-500,140}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep3( + final nout=nTowCel) + "Replicate boolean input" + annotation (Placement(transformation(extent={{780,-590},{800,-570}}))); + +protected + final parameter Boolean have_serChi = not have_parChi + "true = series chillers plant; false = parallel chillers plant" + annotation (Dialog(tab="General", group="Chillers configuration")); + + final parameter Real TChiWatSupMin_Lowest( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=min(TChiWatSupMin) + "Minimum chilled water supply temperature. This is the lowest minimum chilled water supply temperature of chillers in the plant"; + +equation + connect(staSetCon.uPla, plaEna.yPla) annotation(Line(points={{-268,72},{-580,72}, + {-580,-520},{-658,-520}}, color={255,0,255})); + connect(TChiWatRetDow, wseSta.TChiWatRetDow) annotation(Line(points={{-920,320}, + {-840,320},{-840,332},{-704,332}}, color={0,0,127})); + connect(chiWatSupSet.TChiWatSupSet, staSetCon.TChiWatSupSet) annotation(Line( + points={{-476,428},{-380,428},{-380,48},{-268,48}}, color={0,0,127})); + connect(TChiWatSup, staSetCon.TChiWatSup) annotation(Line(points={{-920,210},{ + -840,210},{-840,40},{-268,40}}, color={0,0,127})); + connect(VChiWat_flow, minBypValCon.VChiWat_flow) annotation(Line(points={{-920, + 440},{-880,440},{-880,-140},{-684,-140}}, color={0,0,127})); + connect(TChiWatRet, staSetCon.TChiWatRet) annotation(Line(points={{-920,280},{ + -860,280},{-860,-48},{-268,-48}}, color={0,0,127})); + connect(staSetCon.TWsePre, wseSta.TWsePre) annotation(Line(points={{-268,-56}, + {-420,-56},{-420,338},{-656,338}}, color={0,0,127})); + connect(VChiWat_flow, staSetCon.VChiWat_flow) annotation(Line(points={{-920,440}, + {-880,440},{-880,-64},{-268,-64}}, color={0,0,127})); + connect(TChiWatSupResReq, chiWatPlaRes.TChiWatSupResReq) + annotation (Line(points={{-920,-300},{-704,-300}}, color={255,127,0})); + connect(chiWatPlaRes.yChiWatPlaRes, chiWatSupSet.uChiWatPlaRes) annotation ( + Line(points={{-656,-300},{-540,-300},{-540,440},{-524,440}}, color={0,0,127})); + connect(wseSta.y, staSetCon.uWseSta) annotation(Line(points={{-656,326},{-630, + 326},{-630,96},{-268,96}}, color={255,0,255})); + connect(wseSta.y, towCon.uWse) annotation(Line(points={{-656,326},{-630,326},{ + -630,-580},{-268,-580}}, color={255,0,255})); + connect(plaEna.yPla, towCon.uPla) annotation(Line(points={{-658,-520},{-580,-520}, + {-580,-636},{-268,-636}}, color={255,0,255})); + connect(TOutWet, staSetCon.TOutWet) annotation(Line(points={{-920,360},{-870,360}, + {-870,-20},{-268,-20}}, color={0,0,127})); + connect(mulMax.y, staSetCon.uTowFanSpeMax) annotation(Line(points={{-38,-580}, + {0,-580},{0,-360},{-780,-360},{-780,-36},{-268,-36}}, + color={0,0,127})); + connect(staSetCon.ySta, upProCon.uStaSet) annotation(Line(points={{-172,-24},{ + -140,-24},{-140,436},{172,436}}, color={255,127,0})); + connect(staSetCon.ySta, dowProCon.uStaSet) annotation(Line(points={{-172,-24}, + {-140,-24},{-140,-144},{172,-144}}, color={255,127,0})); + connect(staSetCon.yChiSet, upProCon.uChiSet) annotation(Line(points={{-172,4}, + {-130,4},{-130,424},{172,424}}, color={255,0,255})); + connect(staSetCon.yChiSet, dowProCon.uChiSet) annotation(Line(points={{-172,4}, + {-130,4},{-130,-152},{172,-152}}, color={255,0,255})); + connect(uChiLoa, upProCon.uChiLoa) annotation(Line(points={{-920,140},{-830,140}, + {-830,408},{172,408}}, color={0,0,127})); + connect(upProCon.yStaPro, chaProUpDown.u1) annotation(Line(points={{268,436},{ + 330,436},{330,-80},{378,-80}}, color={255,0,255})); + connect(dowProCon.yStaPro, chaProUpDown.u2) annotation(Line(points={{268,-144}, + {340,-144},{340,-88},{378,-88}}, color={255,0,255})); + connect(uChi, dowProCon.uChi) annotation(Line(points={{-920,400},{-800,400},{-800, + -184},{172,-184}}, color={255,0,255})); + connect(mulMax.y, wseSta.uTowFanSpeMax) annotation(Line(points={{-38,-580},{0, + -580},{0,-360},{-780,-360},{-780,324},{-704,324}}, color={0,0,127})); + connect(towCon.yMakUp, yMakUp) annotation(Line(points={{-172,-708},{-140,-708}, + {-140,-760},{940,-760}}, color={255,0,255})); + connect(uChiWatPum, chiWatPlaRes.uChiWatPum) annotation(Line(points={{-920,574}, + {-790,574},{-790,-288},{-704,-288}}, + color={255,0,255})); + connect(mulOr.y, minBypValCon.uChiWatPum) annotation(Line(points={{-718,-124}, + {-684,-124}}, color={255,0,255})); + connect(uChiWatPum, mulOr.u) annotation(Line(points={{-920,574},{-790,574},{-790, + -124},{-742,-124}}, color={255,0,255})); + connect(staSetCon.yOpeParLoaRatMin, dowProCon.yOpeParLoaRatMin) annotation ( + Line(points={{-172,-52.8},{-120,-52.8},{-120,-168},{172,-168}}, color= + {0,0,127})); + connect(uChi, upProCon.uChi) annotation(Line(points={{-920,400},{172,400}}, + color={255,0,255})); + connect(wseSta.y, upProCon.uWSE) annotation(Line(points={{-656,326},{-630,326}, + {-630,344},{172,344}}, color={255,0,255})); + connect(wseSta.y, dowProCon.uWSE) annotation(Line(points={{-656,326},{-630,326}, + {-630,-272},{172,-272}}, color={255,0,255})); + connect(dowProCon.VChiWat_flow, VChiWat_flow) annotation(Line(points={{172,-192}, + {-880,-192},{-880,440},{-920,440}},color={0,0,127})); + connect(VChiWat_flow, chiWatPumCon.VChiWat_flow) annotation(Line(points={{-920, + 440},{-880,440},{-880,495},{434,495}},color={0,0,127})); + connect(dpChiWat_remote, chiWatPumCon.dpChiWat_remote) annotation(Line( + points={{-920,470},{-770,470},{-770,483},{434,483}}, color={0,0,127})); + connect(TChiWatSup, towCon.TChiWatSup) annotation(Line(points={{-920,210},{-840, + 210},{-840,-596},{-268,-596}}, color={0,0,127})); + connect(chiWatSupSet.TChiWatSupSet, towCon.TChiWatSupSet) annotation(Line( + points={{-476,428},{-380,428},{-380,-604},{-268,-604}},color={0,0,127})); + connect(dowProCon.uChiLoa, uChiLoa) annotation(Line(points={{172,-176},{-830, + -176},{-830,140},{-920,140}}, + color={0,0,127})); + connect(dowProCon.uChiWatIsoVal, uChiWatIsoVal) annotation(Line(points={{172,-228}, + {-920,-228}}, color={0,0,127})); + connect(uChiWatIsoVal, upProCon.uChiWatIsoVal) annotation(Line(points={{-920,-228}, + {110,-228},{110,292},{172,292}}, color={0,0,127})); + connect(chiWatSupSet.dpChiWatPumSet, chiWatPumCon.dpChiWatSet_remote) + annotation (Line(points={{-476,452},{-370,452},{-370,477},{434,477}}, color= + {0,0,127})); + connect(uChiAva, staSetCon.uChiAva) annotation(Line(points={{-920,80},{-268,80}}, + color={255,0,255})); + connect(minBypValCon.yValPos, yMinValPosSet) annotation (Line(points={{-636,-140}, + {-480,-140},{-480,-320},{940,-320}}, color={0,0,127})); + connect(staSetCon.ySta, towCon.uChiStaSet) annotation(Line(points={{-172,-24}, + {-140,-24},{-140,-120},{-330,-120},{-330,-684},{-268,-684}}, + color={255,127,0})); + connect(TConWatSup, towCon.TConWatSup) annotation(Line(points={{-920,-660},{-268, + -660}}, color={0,0,127})); + connect(TConWatRet, towCon.TConWatRet) annotation(Line(points={{-920,240},{-850, + 240},{-850,-644},{-268,-644}}, color={0,0,127})); + connect(watLev, towCon.watLev) annotation (Line(points={{-920,-740},{-300,-740}, + {-300,-716},{-268,-716}}, color={0,0,127})); + connect(towCon.uIsoVal, uIsoVal) annotation(Line(points={{-268,-708},{-920,-708}}, + color={0,0,127})); + connect(uTowSta, towCon.uTowSta) annotation (Line(points={{-920,-780},{-440,-780}, + {-440,-628},{-268,-628}}, color={255,0,255})); + connect(uConWatPumSpe, conWatPumSpe.u) annotation (Line(points={{-920,-380},{-662, + -380}}, color={0,0,127})); + connect(uConWatPumSpe, towCon.uConWatPumSpe) annotation (Line(points={{-920,-380}, + {-820,-380},{-820,-652},{-268,-652}}, color={0,0,127})); + connect(conWatPumSpe.y, dowProCon.uConWatPumSpe) annotation (Line(points={{-638, + -380},{130,-380},{130,-288},{172,-288}}, color={0,0,127})); + connect(conWatPumSpe.y, upProCon.uConWatPumSpe) annotation (Line(points={{-638, + -380},{130,-380},{130,328},{172,328}}, color={0,0,127})); + connect(wseSta.yTunPar, staSetCon.uTunPar) annotation (Line(points={{-656,332}, + {-640,332},{-640,-28},{-268,-28}}, color={0,0,127})); + connect(TChiWatRet, wseSta.TChiWatRet) annotation (Line(points={{-920,280},{-860, + 280},{-860,336},{-704,336}}, color={0,0,127})); + connect(upProCon.yTowStaUp, staCooTow.u1) annotation (Line(points={{268,388},{ + 310,388},{310,-120},{478,-120}}, color={255,0,255})); + connect(dowProCon.yTowStaDow, staCooTow.u2) annotation (Line(points={{268,-220}, + {380,-220},{380,-128},{478,-128}}, color={255,0,255})); + connect(TOut, plaEna.TOut) annotation (Line(points={{-920,-520},{-860,-520},{-860, + -528.4},{-704,-528.4}}, color={0,0,127})); + connect(towCon.uFanSpe, uFanSpe) + annotation (Line(points={{-268,-588},{-920,-588}}, color={0,0,127})); + connect(uChiConIsoVal, dowProCon.uChiConIsoVal) annotation (Line(points={{-920, + 664},{100,664},{100,-260},{172,-260}}, color={255,0,255})); + connect(uChiConIsoVal, upProCon.uChiConIsoVal) annotation (Line(points={{-920, + 664},{100,664},{100,380},{172,380}}, color={255,0,255})); + connect(upProCon.uConWatReq, uConWatReq) annotation (Line(points={{172,352},{80, + 352},{80,604},{-920,604}}, color={255,0,255})); + connect(upProCon.uChiWatReq, uChiWatReq) annotation (Line(points={{172,284},{90, + 284},{90,634},{-920,634}}, color={255,0,255})); + connect(uChiWatReq, dowProCon.uChiWatReq) annotation (Line(points={{-920,634}, + {90,634},{90,-240},{172,-240}}, color={255,0,255})); + connect(uConWatReq, dowProCon.uConWatReq) annotation (Line(points={{-920,604}, + {80,604},{80,-248},{172,-248}}, color={255,0,255})); + connect(VChiWat_flow, upProCon.VChiWat_flow) annotation (Line(points={{-920,440}, + {-880,440},{-880,390.4},{172,390.4}}, color={0,0,127})); + connect(wseSta.y, booRep.u) annotation (Line(points={{-656,326},{-630,326},{-630, + 250},{-622,250}}, color={255,0,255})); + connect(booRep.y, heaPreCon.uWSE) annotation (Line(points={{-598,250},{-560, + 250},{-560,188},{-524,188}}, + color={255,0,255})); + connect(TConWatRet, conWatRetTem.u) annotation (Line(points={{-920,240},{-682, + 240}}, color={0,0,127})); + connect(conWatRetTem.y, heaPreCon.TConWatRet) annotation (Line(points={{-658,240}, + {-650,240},{-650,212},{-524,212}}, color={0,0,127})); + connect(TChiWatSup, chiWatSupTem.u) annotation (Line(points={{-920,210},{-840, + 210},{-840,204},{-682,204}}, color={0,0,127})); + connect(chiWatSupTem.y, heaPreCon.TChiWatSup) annotation (Line(points={{-658,204}, + {-524,204}}, color={0,0,127})); + connect(upProCon.yDesConWatPumSpe, desConWatPumSpeSwi.u1) annotation (Line( + points={{268,356},{360,356},{360,208},{478,208}}, color={0,0,127})); + connect(dowProCon.yDesConWatPumSpe, desConWatPumSpeSwi.u3) annotation (Line( + points={{268,-264},{360,-264},{360,192},{478,192}}, color={0,0,127})); + connect(desConPumSpe.y, heaPreCon.desConWatPumSpe) annotation (Line(points={{ + 562,200},{580,200},{580,240},{-532,240},{-532,196},{-524,196}}, color + ={0,0,127})); + connect(heaPreCon.uHeaPreCon, uHeaPreCon) annotation (Line(points={{-524,180}, + {-920,180}}, color={0,0,127})); + connect(heaPreCon.yMaxTowSpeSet, towCon.uMaxTowSpeSet) annotation (Line( + points={{-476,212},{-360,212},{-360,-620},{-268,-620}}, color={0,0,127})); + connect(heaPreCon.yConWatPumSpeSet, mulMax1.u) annotation (Line(points={{-476, + 188},{-470,188},{-470,160},{-462,160}}, color={0,0,127})); + connect(mulMax1.y, dowProCon.uConWatPumSpeSet) annotation (Line(points={{-438, + 160},{-400,160},{-400,-280},{172,-280}}, color={0,0,127})); + connect(mulMax1.y, upProCon.uConWatPumSpeSet) annotation (Line(points={{-438,160}, + {-400,160},{-400,336},{172,336}}, color={0,0,127})); + connect(upProCon.yChiWatMinFloSet, chiMinFloSet.u1) annotation (Line(points={{268,404}, + {350,404},{350,128},{478,128}}, color={0,0,127})); + connect(dowProCon.yChiWatMinFloSet, chiMinFloSet.u3) annotation (Line(points={{268, + -284},{350,-284},{350,112},{478,112}}, color={0,0,127})); + connect(chiMinFloSet.y, minBypValCon.VChiWatSet_flow) annotation (Line(points={{502,120}, + {640,120},{640,-100},{-700,-100},{-700,-156},{-684,-156}}, + color={0,0,127})); + connect(uChiSwi.y, uChiStaPro.u2) + annotation (Line(points={{482,350},{638,350}}, color={255,0,255})); + connect(upProCon.yChi, uChiStaPro.u1) annotation (Line(points={{268,292},{300, + 292},{300,380},{620,380},{620,358},{638,358}}, color={255,0,255})); + connect(dowProCon.yChi, uChiStaPro.u3) annotation (Line(points={{268,-172},{620, + -172},{620,342},{638,342}}, color={255,0,255})); + connect(staSetCon.yCapReq, towCon.reqPlaCap) annotation (Line(points={{-172,-64}, + {-160,-64},{-160,-500},{-370,-500},{-370,-612},{-268,-612}}, color= + {0,0,127})); + connect(equRot.yDevRol, intSwi.u2) annotation (Line(points={{282,574},{310,574}, + {310,580},{378,580}}, color={255,0,255})); + connect(conInt1.y, intSwi.u1) annotation (Line(points={{342,610},{360,610},{360, + 588},{378,588}}, color={255,127,0})); + connect(conInt2.y, intSwi.u3) annotation (Line(points={{342,560},{360,560},{360, + 572},{378,572}}, color={255,127,0})); + connect(intSwi.y, chiWatPumCon.uPumLeaLag) annotation (Line(points={{402,580}, + {420,580},{420,543},{434,543}}, color={255,127,0})); + connect(uChiWatPum, equRot.uDevSta) annotation (Line(points={{-920,574},{258,574}}, + color={255,0,255})); + connect(chiStaUp.y, chiMinFloSet.u2) annotation (Line(points={{402,320},{420,320}, + {420,120},{478,120}}, color={255,0,255})); + connect(upProCon.yStaPro, chiStaUp.u) annotation (Line(points={{268,436},{330, + 436},{330,320},{378,320}}, color={255,0,255})); + connect(dowProCon.yStaPro, chiStaUp.clr) annotation (Line(points={{268,-144},{ + 340,-144},{340,314},{378,314}}, color={255,0,255})); + connect(VChiWat_flow, wseSta.VChiWat_flow) annotation (Line(points={{-920,440}, + {-880,440},{-880,328},{-704,328}}, color={0,0,127})); + connect(TOutWet, wseSta.TOutWet) annotation (Line(points={{-920,360},{-870,360}, + {-870,340},{-704,340}}, color={0,0,127})); + connect(pre2.y, towCon.uTowStaCha) annotation (Line(points={{122,-440},{180, + -440},{180,-512},{-320,-512},{-320,-692},{-268,-692}}, color={255,0,255})); + connect(staCooTow.y, pre2.u) annotation (Line(points={{502,-120},{590,-120},{ + 590,-400},{80,-400},{80,-440},{98,-440}}, color={255,0,255})); + connect(towCon.ySpeSet, mulMax.u) annotation (Line(points={{-172,-684},{-100, + -684},{-100,-580},{-62,-580}}, color={0,0,127})); + connect(booToInt.y, totChiPum.u) + annotation (Line(points={{602,560},{618,560}}, color={255,127,0})); + connect(chiStaUp.y, desConWatPumSpeSwi.u2) annotation (Line(points={{402,320}, + {420,320},{420,200},{478,200}}, color={255,0,255})); + connect(chiStaUp.y, uChiSwi.u) annotation (Line(points={{402,320},{420,320},{420, + 350},{458,350}}, color={255,0,255})); + connect(upProCon.yChiHeaCon, chiHeaCon.u1) annotation (Line(points={{268,324}, + {320,324},{320,288},{518,288}}, color={255,0,255})); + connect(uChiSwi.y, chiHeaCon.u2) annotation (Line(points={{482,350},{510,350}, + {510,280},{518,280}}, color={255,0,255})); + connect(dowProCon.yChiHeaCon, chiHeaCon.u3) annotation (Line(points={{268,-232}, + {320,-232},{320,272},{518,272}}, color={255,0,255})); + connect(chiStaUp.y, conWatPumNum.u2) annotation (Line(points={{402,320},{420,320}, + {420,60},{438,60}}, color={255,0,255})); + connect(upProCon.yConWatPumNum, conWatPumNum.u1) annotation (Line(points={{268,340}, + {370,340},{370,68},{438,68}}, color={255,127,0})); + connect(dowProCon.yConWatPumNum, conWatPumNum.u3) annotation (Line(points={{268, + -272},{370,-272},{370,52},{438,52}}, color={255,127,0})); + connect(chiStaUp.y, conPumLeaSta.u2) annotation (Line(points={{402,320},{420,320}, + {420,-250},{438,-250}}, color={255,0,255})); + connect(dowProCon.yLeaPum, conPumLeaSta.u3) annotation (Line(points={{268,-248}, + {380,-248},{380,-258},{438,-258}}, color={255,0,255})); + connect(upProCon.yLeaPum, conPumLeaSta.u1) annotation (Line(points={{268,372}, + {290,372},{290,-242},{438,-242}}, color={255,0,255})); + connect(conPumLeaSta.y, preConPumLeaSta.u) + annotation (Line(points={{462,-250},{478,-250}}, color={255,0,255})); + connect(conWatPumNum.y, intGreThr1.u) + annotation (Line(points={{462,60},{478,60}}, color={255,127,0})); + connect(intGreThr1.y, equRot1.uLagStaSet) + annotation (Line(points={{502,60},{538,60}}, color={255,0,255})); + connect(preConPumLeaSta.y, equRot1.uLeaStaSet) annotation (Line(points={{502,-250}, + {520,-250},{520,66},{538,66}}, color={255,0,255})); + connect(uConWatPum, equRot1.uDevSta) annotation (Line(points={{-920,-410},{530, + -410},{530,54},{538,54}}, color={255,0,255})); + connect(equRot1.yDevStaSet, yConWatPum) + annotation (Line(points={{562,66},{570,66},{570,90},{940,90}}, color={255,0,255})); + connect(chiMinFloSet.y, yChiWatMinFloSet) + annotation (Line(points={{502,120},{940,120}}, color={0,0,127})); + connect(uChiSwi.y, chiIsoVal.u2) annotation (Line(points={{482,350},{510,350}, + {510,0},{538,0}}, color={255,0,255})); + connect(upProCon.yChiWatIsoVal, chiIsoVal.u1) annotation (Line(points={{268,304}, + {280,304},{280,8},{538,8}}, color={0,0,127})); + connect(dowProCon.yChiWatIsoVal, chiIsoVal.u3) annotation (Line(points={{268,-204}, + {280,-204},{280,-8},{538,-8}}, color={0,0,127})); + connect(uChiCooLoa, towCon.chiLoa) annotation (Line(points={{-920,-560},{-594, + -560},{-594,-564},{-268,-564}}, color={0,0,127})); + connect(uChiSwi.y, chiDem.u2) annotation (Line(points={{482,350},{510,350},{510, + 420},{638,420}}, color={255,0,255})); + connect(upProCon.yChiDem, chiDem.u1) annotation (Line(points={{268,420},{430,420}, + {430,428},{638,428}}, color={0,0,127})); + connect(dowProCon.yChiDem, chiDem.u3) annotation (Line(points={{268,-160},{430, + -160},{430,412},{638,412}}, color={0,0,127})); + connect(chiDem.y, yChiDem) + annotation (Line(points={{662,420},{940,420}}, color={0,0,127})); + connect(uConWatPum, upProCon.uConWatPum) annotation (Line(points={{-920,-410}, + {140,-410},{140,308},{172,308}}, color={255,0,255})); + connect(uConWatPum, dowProCon.uConWatPum) annotation (Line(points={{-920,-410}, + {140,-410},{140,-296},{172,-296}}, color={255,0,255})); + connect(desConWatPumSpeSwi.y, desConPumSpe.u) + annotation (Line(points={{502,200},{538,200}}, color={0,0,127})); + connect(dowProCon.yReaDemLim, relDem.u3) annotation (Line(points={{268,-188},{ + 390,-188},{390,-218},{478,-218}}, color={255,0,255})); + connect(upProCon.yStaPro, relDem.u1) annotation (Line(points={{268,436},{330,436}, + {330,-202},{478,-202}}, color={255,0,255})); + connect(chiStaUp.y, relDem.u2) annotation (Line(points={{402,320},{420,320},{420, + -210},{478,-210}}, color={255,0,255})); + connect(relDem.y, yReaChiDemLim) + annotation (Line(points={{502,-210},{940,-210}}, color={255,0,255})); + connect(dpChiWat_local, chiWatPumCon.dpChiWat_local) annotation (Line(points={{-920, + 510},{-820,510},{-820,489},{434,489}}, color={0,0,127})); + connect(dpChiWat_local, staSetCon.dpChiWatPum_local) annotation (Line(points={{-920, + 510},{-820,510},{-820,4},{-268,4}}, color={0,0,127})); + connect(chiWatPumCon.dpChiWatPumSet_local, staSetCon.dpChiWatPumSet_local) + annotation (Line(points={{506,483},{520,483},{520,460},{-350,460},{-350,12}, + {-268,12}}, color={0,0,127})); + connect(chiWatSupSet.dpChiWatPumSet, staSetCon.dpChiWatPumSet_remote) + annotation (Line(points={{-476,452},{-370,452},{-370,-4},{-268,-4}}, color={ + 0,0,127})); + connect(dpChiWat_remote, staSetCon.dpChiWatPum_remote) annotation (Line( + points={{-920,470},{-770,470},{-770,-12},{-268,-12}}, color={0,0,127})); + connect(falEdg.u, preChaPro.y) + annotation (Line(points={{478,-80},{462,-80}}, color={255,0,255})); + connect(chaProUpDown.y, preChaPro.u) + annotation (Line(points={{402,-80},{438,-80}}, color={255,0,255})); + connect(preChaPro.y, chiWatPlaRes.chaPro) annotation (Line(points={{462,-80},{ + 470,-80},{470,-330},{-720,-330},{-720,-312},{-704,-312}}, color={255,0, + 255})); + connect(preChaPro.y, staSetCon.chaPro) annotation (Line(points={{462,-80},{470, + -80},{470,-330},{-320,-330},{-320,88},{-268,88}}, color={255,0,255})); + connect(leaChiWatPum.y, booToInt.u) + annotation (Line(points={{562,560},{578,560}}, color={255,0,255})); + connect(chiWatPumCon.yChiWatPum, leaChiWatPum.u) annotation (Line(points={{506,510}, + {530,510},{530,560},{538,560}}, color={255,0,255})); + connect(totChiPum.y, intGreThr.u) annotation (Line(points={{642,560},{650,560}, + {650,580},{570,580},{570,600},{578,600}}, color={255,127,0})); + connect(intGreThr.y, equRot.uLagStaSet) annotation (Line(points={{602,600},{610, + 600},{610,640},{240,640},{240,580},{258,580}}, color={255,0,255})); + connect(chiWatPumCon.yLea, leaChiPumPre.u) annotation (Line(points={{506,534}, + {510,534},{510,600},{518,600}}, color={255,0,255})); + connect(uChiHeaCon, dowProCon.uChiHeaCon) annotation (Line(points={{-920,-80}, + {150,-80},{150,-216},{172,-216}}, color={255,0,255})); + connect(uChiHeaCon, upProCon.uChiHeaCon) annotation (Line(points={{-920,-80},{ + 150,-80},{150,300},{172,300}}, color={255,0,255})); + connect(chiHeaCon.y, yHeaPreConValSta) + annotation (Line(points={{542,280},{940,280}}, color={255,0,255})); + connect(chiWatPumCon.yChiWatPum, booToRea.u) annotation (Line(points={{506,510}, + {540,510},{540,500},{578,500}}, color={255,0,255})); + connect(chiWatPumCon.yPumSpe, chiWatPumSpe.u) annotation (Line(points={{506,492}, + {540,492},{540,460},{578,460}}, color={0,0,127})); + connect(chiWatPumCon.yChiWatPum, yChiWatPum) annotation (Line(points={{506,510}, + {530,510},{530,520},{940,520}}, color={255,0,255})); + connect(booToRea.y, pro.u1) annotation (Line(points={{602,500},{620,500},{620, + 486},{638,486}}, color={0,0,127})); + connect(chiWatPumSpe.y, pro.u2) annotation (Line(points={{602,460},{620,460},{ + 620,474},{638,474}}, color={0,0,127})); + connect(desConWatPumSpeSwi.y, conWatPumSpe1.u) annotation (Line(points={{502,200}, + {520,200},{520,150},{588,150}}, color={0,0,127})); + connect(equRot1.yDevStaSet, booToRea1.u) + annotation (Line(points={{562,66},{578,66}}, color={255,0,255})); + connect(booToRea1.y, pro1.u2) annotation (Line(points={{602,66},{650,66},{650, + 144},{658,144}}, color={0,0,127})); + connect(con.y, conWatPumSpe1.u) annotation (Line(points={{562,100},{570,100},{ + 570,150},{588,150}}, color={0,0,127})); + connect(conWatPumSpe1.y, pro1.u1) annotation (Line(points={{612,150},{640,150}, + {640,156},{658,156}}, color={0,0,127})); + connect(chiHeaCon.y, booToRea3.u) annotation (Line(points={{542,280},{560,280}, + {560,260},{578,260}}, color={255,0,255})); + connect(booToRea3.y, pro4.u1) annotation (Line(points={{602,260},{640,260},{640, + 246},{658,246}}, color={0,0,127})); + connect(heaPreCon.yHeaPreConVal, pro4.u2) annotation (Line(points={{-476,200}, + {-160,200},{-160,234},{658,234}}, color={0,0,127})); + connect(fulOpeVal.y, pro4.u2) annotation (Line(points={{262,190},{272,190},{272, + 234},{658,234}}, color={0,0,127})); + connect(chiWatSupSet.TChiWatSupSet, TChiWatSupSet) annotation (Line(points={{-476, + 428},{-380,428},{-380,650},{940,650}}, color={0,0,127})); + connect(plaEna.chiPlaReq, chiPlaReq) annotation (Line(points={{-704,-512},{-860, + -512},{-860,-340},{-920,-340}}, color={255,127,0})); + connect(uChi, towCon.uChi) annotation (Line(points={{-920,400},{-800,400},{-800, + -572},{-268,-572}}, color={255,0,255})); + connect(staSetCon.yIni, wseSta.uIni) annotation (Line(points={{-172,-16},{-150, + -16},{-150,272},{-750,272},{-750,316},{-704,316}}, color={255,127,0})); + connect(plaEna.yPla, wseSta.uPla) annotation (Line(points={{-658,-520},{-580,-520}, + {-580,72},{-760,72},{-760,320},{-704,320}}, color={255,0,255})); + connect(dpChiWat, wseSta.dpChiWat) annotation (Line(points={{-920,110},{-730,110}, + {-730,308},{-704,308}}, color={0,0,127})); + connect(uEcoPum, wseSta.uPum) annotation (Line(points={{-920,50},{-720,50},{-720, + 304},{-704,304}}, color={255,0,255})); + connect(TEntHex, wseSta.TEntHex) annotation (Line(points={{-920,20},{-710,20}, + {-710,300},{-704,300}}, color={0,0,127})); + connect(plaEna.yPla, enaDev.uPla) annotation (Line(points={{-658,-520},{-580,-520}, + {-580,-422},{-542,-422}}, color={255,0,255})); + connect(staSetCon.yIni, enaDev.uIni) annotation (Line(points={{-172,-16},{-150, + -16},{-150,-370},{-570,-370},{-570,-426},{-542,-426}}, color={255,127,0})); + connect(staSetCon.ySta, enaDev.uChiSta) annotation (Line(points={{-172,-24},{-140, + -24},{-140,-144},{-560,-144},{-560,-430},{-542,-430}},color={255,127,0})); + connect(uConWatPum, enaDev.uConWatPum) annotation (Line(points={{-920,-410},{-590, + -410},{-590,-438},{-542,-438}}, color={255,0,255})); + connect(uChiWatPum, enaDev.uChiWatPum) annotation (Line(points={{-920,574},{-790, + 574},{-790,-434},{-542,-434}}, color={255,0,255})); + connect(equRot.yDevStaSet, chiWatPumCon.uChiWatPum) annotation (Line(points={{282,586}, + {300,586},{300,531},{434,531}}, color={255,0,255})); + connect(plaEna.yPla, chiWatPumCon.uPla) annotation (Line(points={{-658,-520}, + {-580,-520},{-580,537},{434,537}},color={255,0,255})); + connect(leaChiPum.y, equRot.uLeaStaSet) annotation (Line(points={{222,592},{234, + 592},{234,586},{258,586}}, color={255,0,255})); + connect(leaChiPumPre.y, leaChiPum.u3) annotation (Line(points={{542,600},{550, + 600},{550,630},{190,630},{190,584},{198,584}}, color={255,0,255})); + connect(enaDev.yEnaPlaPro, leaChiPum.u2) annotation (Line(points={{-518,-421}, + {-410,-421},{-410,592},{198,592}}, color={255,0,255})); + connect(enaDev.yLeaPriChiPum, leaChiPum.u1) annotation (Line(points={{-518,-430}, + {-390,-430},{-390,600},{198,600}}, color={255,0,255})); + connect(enaDev.yLeaConPum, upProCon.uEnaPlaConPum) annotation (Line(points={{-518, + -433},{-110,-433},{-110,364},{172,364}}, color={255,0,255})); + connect(enaDev.yConWatIsoVal, upProCon.uEnaPlaConIso) annotation (Line(points={{-518, + -426},{70,-426},{70,320},{172,320}}, color={255,0,255})); + connect(enaDev.yLeaTowCel, towCon.uEnaPla) annotation (Line(points={{-518,-436}, + {-400,-436},{-400,-668},{-268,-668}}, color={255,0,255})); + connect(wseSta.yConWatIsoVal, yEcoConWatIsoVal) annotation (Line(points={{-656, + 320},{-620,320},{-620,780},{940,780}}, color={0,0,127})); + connect(wseSta.yRetVal,yWseRetVal) annotation (Line(points={{-656,313.6},{-610, + 313.6},{-610,750},{940,750}}, color={0,0,127})); + connect(wseSta.yPumOn, yWsePumOn) annotation (Line(points={{-656,308},{-600,308}, + {-600,720},{940,720}}, color={255,0,255})); + connect(wseSta.yPumSpe, yWsePumSpe) annotation (Line(points={{-656,302},{-590, + 302},{-590,690},{940,690}}, color={0,0,127})); + connect(uChiStaPro.y, disChi.uChi) annotation (Line(points={{662,350},{710, + 350},{710,-461},{738,-461}}, color={255,0,255})); + connect(chiIsoVal.y, disChi.uChiWatIsoVal) annotation (Line(points={{562,0},{ + 660,0},{660,-465},{738,-465}}, color={0,0,127})); + connect(uChiWatReq, disChi.uChiWatReq) annotation (Line(points={{-920,634},{ + -810,634},{-810,-463},{738,-463}}, color={255,0,255})); + connect(disChi.yChiWatIsoVal, yChiWatIsoVal) annotation (Line(points={{762,-465}, + {810,-465},{810,0},{940,0}}, color={0,0,127})); + connect(uChiWatPum, disChi.uConWatReq) annotation (Line(points={{-920,574},{ + -790,574},{-790,-468},{738,-468}}, color={255,0,255})); + connect(pro4.y, disChi.uConWatIsoVal) annotation (Line(points={{682,240},{700, + 240},{700,-471},{738,-471}}, color={0,0,127})); + connect(disChi.yConWatIsoVal, yHeaPreConVal) annotation (Line(points={{762,-468}, + {820,-468},{820,240},{940,240}}, color={0,0,127})); + connect(disChi.yChiWatPumSpe, yChiPumSpe) annotation (Line(points={{762,-472}, + {830,-472},{830,480},{940,480}}, color={0,0,127})); + connect(pro.y, disChi.uChiWatPumSpe) annotation (Line(points={{662,480},{720, + 480},{720,-473},{738,-473}}, color={0,0,127})); + connect(pro1.y, disChi.uConWatPumSpe) annotation (Line(points={{682,150},{730, + 150},{730,-475},{738,-475}}, color={0,0,127})); + connect(disChi.yConWatPumSpe, yConWatPumSpe) annotation (Line(points={{762,-475}, + {840,-475},{840,150},{940,150}}, color={0,0,127})); + connect(towCon.yTowSta, celCom.u1) + annotation (Line(points={{-172,-660},{838,-660}}, color={255,0,255})); + connect(celCom.y, yTowCel) + annotation (Line(points={{862,-660},{940,-660}}, color={255,0,255})); + connect(swi.y, yTowCelIsoVal) + annotation (Line(points={{902,-620},{940,-620}}, color={0,0,127})); + connect(towCon.yIsoVal, swi.u1) annotation (Line(points={{-172,-620},{720,-620}, + {720,-612},{878,-612}}, color={0,0,127})); + connect(con1.y, swi.u3) annotation (Line(points={{722,-580},{740,-580},{740,-628}, + {878,-628}}, color={0,0,127})); + connect(swi1.y, yTowFanSpe) + annotation (Line(points={{902,-700},{940,-700}}, color={0,0,127})); + connect(con1.y, swi1.u3) annotation (Line(points={{722,-580},{740,-580},{740,-708}, + {878,-708}}, color={0,0,127})); + connect(towCon.ySpeSet, swi1.u1) annotation (Line(points={{-172,-684},{-100,-684}, + {-100,-692},{878,-692}}, color={0,0,127})); + connect(uChi, ideSta.uChi) annotation (Line(points={{-920,400},{-800,400},{-800, + 130},{-522,130}}, color={255,0,255})); + connect(ideSta.ySta, staSetCon.uSta) annotation (Line(points={{-498,130},{-340, + 130},{-340,60},{-268,60}}, color={255,127,0})); + connect(ideSta.ySta, towCon.uChiSta) annotation (Line(points={{-498,130},{-340, + 130},{-340,-676},{-268,-676}}, color={255,127,0})); + connect(ideSta.ySta, dowProCon.uChiSta) annotation (Line(points={{-498,130},{-340, + 130},{-340,-204},{172,-204}}, color={255,127,0})); + connect(ideSta.ySta, upProCon.uChiSta) annotation (Line(points={{-498,130},{-340, + 130},{-340,372},{172,372}}, color={255,127,0})); + connect(staSetCon.ySta, wseSta.uChiSta) annotation (Line(points={{-172,-24},{-140, + -24},{-140,280},{-740,280},{-740,312},{-704,312}}, color={255,127,0})); + connect(chaProUpDown.y, disChi.chaPro) annotation (Line(points={{402,-80},{ + 410,-80},{410,-477},{738,-477}}, color={255,0,255})); + connect(uChiStaPro.y, yChi) + annotation (Line(points={{662,350},{940,350}}, color={255,0,255})); + connect(disChi.yTowCel, booScaRep3.u) annotation (Line(points={{762,-479},{ + 770,-479},{770,-580},{778,-580}}, color={255,0,255})); + connect(booScaRep3.y, celCom.u2) annotation (Line(points={{802,-580},{820, + -580},{820,-668},{838,-668}}, color={255,0,255})); + connect(booScaRep3.y, swi.u2) annotation (Line(points={{802,-580},{820,-580}, + {820,-620},{878,-620}}, color={255,0,255})); + connect(booScaRep3.y, swi1.u2) annotation (Line(points={{802,-580},{820,-580}, + {820,-700},{878,-700}}, color={255,0,255})); + connect(chiHeaCon.y, heaPreCon.uChiHeaCon) annotation (Line(points={{542,280}, + {560,280},{560,260},{-550,260},{-550,220},{-524,220}}, color={255,0, + 255})); + connect(uChiWatIsoVal, chiWatPumCon.uChiWatIsoVal) annotation (Line(points={{-920, + -228},{110,-228},{110,501},{434,501}}, color={0,0,127})); + connect(wseSta.y, disChi.uWSE) annotation (Line(points={{-656,326},{-630,326}, + {-630,-479},{738,-479}}, color={255,0,255})); + connect(wseSta.y, chiWatPumCon.uWse) annotation (Line(points={{-656,326},{ + -630,326},{-630,507},{434,507}}, color={255,0,255})); +annotation ( + defaultComponentName="chiPlaCon", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-400},{100,400}}), + graphics={ + Rectangle( + extent={{-100,-400},{100,400}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-100,440},{100,400}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-50,160},{50,-162}}, + lineColor={28,108,200}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Polygon( + points={{-50,160},{16,4},{-50,-162},{-50,160}}, + lineColor={175,175,175}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,388},{-50,374}}, + textColor={255,0,255}, + textString="uChiConIsoVal"), + Text( + extent={{-98,366},{-58,354}}, + textColor={255,0,255}, + textString="uChiWatReq"), + Text( + extent={{-100,326},{-56,316}}, + textColor={255,0,255}, + textString="uChiWatPum"), + Text( + extent={{-98,346},{-56,334}}, + textColor={255,0,255}, + textString="uConWatReq"), + Text( + extent={{-100,306},{-62,296}}, + textColor={255,0,255}, + textString="uChiIsoVal", + visible=have_heaChiWatPum), + Text( + extent={{-98,248},{-50,234}}, + textColor={0,0,127}, + textString="dpChiWat_remote"), + Text( + extent={{-100,228},{-58,216}}, + textColor={0,0,127}, + textString="VChiWat_flow"), + Text( + extent={{-98,206},{-80,194}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-100,166},{-68,156}}, + textColor={0,0,127}, + textString="TOutWet", + visible=have_WSE), + Text( + extent={{-98,148},{-50,134}}, + textColor={0,0,125}, + textString="TChiWatRetDow", + visible=have_WSE), + Text( + extent={{-100,126},{-60,116}}, + textColor={0,0,127}, + textString="TChiWatRet"), + Text( + extent={{-100,108},{-60,92}}, + textColor={0,0,127}, + textString="TConWatRet"), + Text( + extent={{-98,86},{-58,74}}, + textColor={0,0,127}, + textString="TChiWatSup"), + Text( + extent={{-98,58},{-60,44}}, + textColor={0,0,127}, + textString="uHeaPreCon", + visible=have_heaPreConSig), + Text( + extent={{-98,26},{-66,14}}, + textColor={0,0,127}, + textString="uChiLoa", + visible=need_reduceChillerDemand), + Text( + extent={{-100,-24},{-64,-36}}, + textColor={255,0,255}, + textString="uChiAva"), + Text( + extent={{-98,-112},{-50,-126}}, + textColor={0,0,127}, + textString="uChiWatIsoVal"), + Text( + extent={{-98,-132},{-50,-146}}, + textColor={255,127,0}, + textString="TChiWatSupResReq"), + Text( + extent={{-98,-192},{-50,-206}}, + textColor={0,0,127}, + textString="uConWatPumSpe"), + Text( + extent={{-98,-212},{-50,-226}}, + textColor={255,0,255}, + textString="uConWatPum"), + Text( + extent={{-98,-232},{-78,-246}}, + textColor={0,0,127}, + textString="TOut"), + Text( + extent={{-98,-252},{-50,-266}}, + textColor={0,0,127}, + textString="uChiCooLoa", + visible=have_WSE), + Text( + extent={{-96,-294},{-64,-306}}, + textColor={0,0,127}, + textString="uFanSpe"), + Text( + extent={{-98,-314},{-50,-328}}, + textColor={0,0,127}, + textString="TConWatSup", + visible=not closeCoupledPlant), + Text( + extent={{-100,-334},{-68,-346}}, + textColor={0,0,127}, + textString="uIsoVal"), + Text( + extent={{-98,-352},{-68,-364}}, + textColor={0,0,127}, + textString="watLev"), + Text( + extent={{-98,-372},{-62,-386}}, + textColor={255,0,255}, + textString="uTowSta"), + Text( + extent={{50,258},{98,244}}, + textColor={255,0,255}, + textString="yChiWatPum", + visible=have_heaChiWatPum), + Text( + extent={{76,168},{98,154}}, + textColor={255,0,255}, + textString="yChi"), + Text( + extent={{52,8},{100,-6}}, + textColor={255,0,255}, + textString="yConWatPum"), + Text( + extent={{62,-202},{98,-216}}, + textColor={255,0,255}, + textString="yTowCel"), + Text( + extent={{64,-264},{98,-278}}, + textColor={255,0,255}, + textString="yMakUp"), + Text( + extent={{52,228},{100,214}}, + textColor={0,0,127}, + textString="yChiPumSpe"), + Text( + extent={{52,198},{100,184}}, + textColor={0,0,127}, + textString="yChiDem", + visible=need_reduceChillerDemand), + Text( + extent={{52,98},{100,84}}, + textColor={0,0,127}, + textString="yHeaPreConVal"), + Text( + extent={{52,68},{100,54}}, + textColor={0,0,127}, + textString="yConWatPumSpe"), + Text( + extent={{52,40},{100,26}}, + textColor={0,0,127}, + textString="yChiWatMinFloSet"), + Text( + extent={{52,-62},{100,-76}}, + textColor={0,0,127}, + textString="yChiWatIsoVal"), + Text( + extent={{52,-92},{100,-106}}, + textColor={0,0,127}, + textString="yMinValPosSet"), + Text( + extent={{52,-172},{100,-186}}, + textColor={0,0,127}, + textString="yTowCelIsoVal"), + Text( + extent={{52,-232},{100,-246}}, + textColor={0,0,127}, + textString="yTwoFanSpe"), + Text( + extent={{52,-30},{100,-44}}, + textColor={255,0,255}, + textString="yReaChiDemLim", + visible=need_reduceChillerDemand), + Text( + extent={{-98,268},{-50,254}}, + textColor={0,0,127}, + visible=have_locSenChiWatPum, + textString="dpChiWat_local"), + Text( + extent={{-98,-94},{-54,-108}}, + textColor={255,0,255}, + textString="uChiHeaCon"), + Text( + extent={{50,136},{98,122}}, + textColor={255,0,255}, + visible=have_heaChiWatPum, + textString="yHeaPreConValSta"), + Text( + extent={{48,290},{96,276}}, + textColor={0,0,125}, + textString="TChiWatSupSet"), + Text( + extent={{-98,-154},{-70,-164}}, + textColor={255,127,0}, + textString="chiPlaReq"), + Text( + extent={{-98,-64},{-62,-78}}, + textColor={0,0,127}, + textString="TEntHex", + visible=have_WSE and not have_byPasValCon), + Text( + extent={{-98,-2},{-50,-16}}, + textColor={0,0,127}, + textString="dpChiWat", + visible=have_WSE and have_byPasValCon), + Text( + extent={{-98,-44},{-62,-56}}, + textColor={255,0,255}, + textString="uEcoPum", + visible=have_WSE and not have_byPasValCon), + Text( + extent={{34,398},{94,384}}, + textColor={0,0,125}, + textString="yEcoConWatIsoVal", + visible=have_WSE), + Text( + extent={{46,368},{94,354}}, + textColor={0,0,125}, + textString="yWseRetVal", + visible=have_byPasValCon and have_WSE), + Text( + extent={{46,318},{94,304}}, + textColor={0,0,125}, + textString="yWsePumSpe", + visible=have_WSE and not have_byPasValCon), + Text( + extent={{48,338},{96,324}}, + textColor={255,0,255}, + visible=have_WSE and not have_byPasValCon, + textString="yWsePumOn")}), + Diagram(coordinateSystem(extent={{-900,-800},{920,800}}), graphics={Text( + extent={{-574,-594},{-490,-614}}, + textColor={28,108,200}, + textString="might need a pre block")}), +Documentation(info=" +

+This is chiller plant control sequence implemented according to ASHRAE Guideline 36-2021. +It is composed by the subsequences in this pacakge. The applicability of some sequences +are listed in the table below. The yes means that the sequence is appliable to +the system type. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SubsequencesPrimary
only
Primary
Secondary
Parallel
chillers
Series
chillers
Headed
CHWP
Dedicated
CHWP
Headed
CWP
Dedicated
CWP
VarSpe
CWP
ConSpe
CWP
Water
cooled
Air
cooled
With
WSE
Plant
reset
yesyesyesnot
implemented
yesyesyesyesyesyesyesyesyes + + Chilled water plant reset
+ and + + Chilled water supply +
Waterside
economizers
yesyesyesyesyesyesyesyesyesyesyesyesyes + + Economizer controller +
Head pressure
control
yesyesyesyesyesyesyesyesyesyesyesnot
applicable
yes + + Head pressure controller +
Minimum
flow
yesnot
specified
yesyesyesyesyesyesyesyesyesyesyes + + Bypass valve controller
+ and + + Bypass flow setpoint +
Primary chilled
water pumps
yesnot
implemented
yesnot
implemented
yesyesyesyesyesyesyesyesyes + + Chilled water pump controller +
Condenser water
pumps
yesyesyesnot
specified
yesyesyesyesyesyesyesnot
applicable
yes + + Condenser water pump controller +
Chillers
staging
yesnot
implemented
yesnot
implemented
yesnot
implemented
yesnot
implemented
yesyesyesyesyes + + Staging up
+ and + + Staging down +
Cooling
towers
yesyesyesyesyesyesyesyesyesyesyesyesyes + + Tower controller +
+ + +

1. Plant reset

+

+In Guideline36-2021, the sequences for following types of plant have been specified. +However, they have not yet been implemented in this library. +

+ + +

2. Head pressure control

+

+If there is head pressure control signal from chiller, the sequence is not needed. +In Guideline36-2021, it assumes: +

+ + +

3. Minimum chilled water flow

+

+In Guideline36-2021, the sequences for following types of plant have not been specified. +

+ + +

4. Primary chilled water (CHW) pump control

+

+In Guideline36-2021, the sequences for following types of plant have been specified. +However, they have not yet been implemented in this library. +

+ + +

5. Secondary chilled water pumps control

+

+In Guideline36-2021, the secondary chilled water pumps control have been specified. +However, they have not yet been implemented in this library, section 5.20.7. +

+ +

6. Condenser water (CW) pumps control

+

+In Guideline36-2021, the sequences for following types of plant have not been specified. +

+ + +

7. Chiller staging control

+

+In Guideline36-2021, the sequences for following types of plant have been specified. +However, they have not yet been implemented in this library. +

+ + +

8. Cooling tower control

+

+In current implementation, the tower sequence assumes that the cells are enabled in +the order as it is labelled, meaning that it enabled the cells as cell 1, 2, 3, +etc. Note from the Guideline36-2021, +

+ +

+In Guideline36-2021, the sequences for following types of plant have been specified. +However, they have not yet been implemented in this library. +

+ + +

9. Equipment rotation

+

+The sequence Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo +rotates equipment, +such as chillers or pumps, in order to ensure equal wear and tear. It is applicable +for two identical devices or device groups. +

+", revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Controller.mo new file mode 100644 index 00000000000..de044561a69 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Controller.mo @@ -0,0 +1,590 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers; +block Controller "Waterside economizer (WSE) enable/disable status" + + parameter Boolean have_byPasValCon=true + "True: chilled water flow through economizer is controlled using heat exchanger bypass valve"; + + parameter Integer nSta = 3 + "Number of chiller stages"; + + parameter Real holdPeriod( + final unit="s", + final quantity="Time")=1200 + "WSE minimum on or off time" + annotation(Dialog(group="Enable parameters")); + + parameter Real delDis( + final unit="s", + final quantity="Time")=120 + "Delay disable time period" + annotation(Dialog(group="Enable parameters")); + + parameter Real TOffsetEna( + final unit="K", + final quantity="TemperatureDifference")=2 + "Temperature offset between the chilled water return upstream of WSE and the predicted WSE output" + annotation(Dialog(group="Enable parameters")); + + parameter Real TOffsetDis( + final unit="K", + final quantity="TemperatureDifference")=1 + "Temperature offset between the chilled water return upstream and downstream WSE" + annotation(Dialog(group="Enable parameters")); + + parameter Real heaExcAppDes( + final unit="K", + final quantity="TemperatureDifference")=2 + "Design heat exchanger approach" + annotation(Dialog(group="Design parameters")); + + parameter Real cooTowAppDes( + final unit="K", + final quantity="TemperatureDifference")=2 + "Design cooling tower approach" + annotation(Dialog(group="Design parameters")); + + parameter Real TOutWetDes( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Design outdoor air wet bulb temperature" + annotation(Dialog(group="Design parameters")); + + parameter Real hysDt( + final unit="K", + final quantity="TemperatureDifference")=1 + "Deadband temperature used in hysteresis block" + annotation (Evaluate=true, Dialog(tab="Advanced", group="Hysteresis")); + + parameter Real VHeaExcDes_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.015 + "Design heat exchanger chilled water volume flow rate" + annotation(Dialog(group="Design parameters")); + + parameter Real step( + final unit="1")=0.02 + "Incremental step used to reduce or increase the water-side economizer tuning parameter" + annotation (Evaluate=true, Dialog(tab="Advanced", group="Tuning")); + + parameter Real wseOnTimDec( + final unit="s", + final quantity="Time", + displayUnit="h") = 3600 + "Economizer enable time needed to allow decrease of the tuning parameter" + annotation (Evaluate=true,Dialog(tab="Advanced", group="Tuning")); + + parameter Real wseOnTimInc( + final unit="s", + final quantity="Time", + displayUnit="h") = 1800 + "Economizer enable time needed to allow increase of the tuning parameter" + annotation (Evaluate=true,Dialog(tab="Advanced", group="Tuning")); + + parameter Real dpDes( + final unit="Pa", + final quantity="PresureDifference")=6000 + "Design pressure difference across the chilled water side economizer" + annotation (Dialog(group="Valve or pump control", enable=have_byPasValCon)); + parameter CDL.Types.SimpleController valCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="Valve or pump control", enable=have_byPasValCon)); + parameter Real k=0.1 + "Gain of controller" + annotation (Dialog(group="Valve or pump control", enable=have_byPasValCon)); + parameter Real Ti(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(group="Valve or pump control", + enable=(valCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or valCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID) + and have_byPasValCon)); + parameter Real Td(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(group="Valve or pump control", + enable=(valCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or valCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID) + and have_byPasValCon)); + parameter Real minSpe( + final min=0, + final max=1)=0.1 + "Minimum pump speed" + annotation (Dialog(group="Valve or pump control", enable=not have_byPasValCon)); + parameter Real desSpe( + final min=0, + final max=1)=0.9 + "Design pump speed" + annotation (Dialog(group="Valve or pump control", enable=not have_byPasValCon)); + + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutWet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-220,190},{-180,230}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water return temperature upstream of the WSE" + annotation (Placement(transformation(extent={{-220,150},{-180,190}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRetDow( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water return temperature downstream of the WSE" + annotation (Placement(transformation(extent={{-220,110},{-180,150}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTowFanSpeMax( + final min=0, + final max=1, + final unit="1") + "Maximum cooling tower fan speed" + annotation (Placement(transformation(extent={{-220,0},{-180,40}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s") + "Measured chilled water volume flow rate" + annotation (Placement(transformation(extent={{-220,50},{-180,90}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-220,-40},{-180,0}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uIni( + final min=0, + final max=nSta) "Initial chiller stage (at plant enable)" + annotation (Placement(transformation(extent={{-220,-70},{-180,-30}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta( + final min=0, + final max=nSta) + "Current chiller stage" + annotation (Placement(transformation(extent={{-220,-128},{-180,-88}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat( + final unit="Pa", + final quantity="PressureDifference") if have_byPasValCon + "Differential static pressure across economizer in the chilled water side" + annotation (Placement(transformation(extent={{-220,-160},{-180,-120}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPum + if not have_byPasValCon "True: heat exchanger pump is proven on" + annotation (Placement(transformation(extent={{-220,-200},{-180,-160}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TEntHex( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not have_byPasValCon + "Chilled water temperature entering heat exchanger" + annotation (Placement(transformation(extent={{-220,-230},{-180,-190}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TWsePre( + final quantity="ThermodynamicTemperature", + displayUnit="degC", + final unit="K") + "Predicted waterside economizer outlet temperature" + annotation (Placement(transformation(extent={{180,110},{220,150}}), + iconTransformation(extent={{100,70},{140,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yTunPar + "Tuning parameter" + annotation (Placement(transformation(extent={{180,20},{220,60}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y + "WSE enable/disable status" + annotation (Placement(transformation(extent={{180,-40},{220,0}}), + iconTransformation(extent={{100,10},{140,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatIsoVal( + final min=0, + final max=1, + final unit="1") "Economizer condensing water isolation valve position" + annotation (Placement(transformation(extent={{180,-120},{220,-80}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetVal( + final min=0, + final max=1, + final unit="1") if have_byPasValCon + "WSE in-line CHW return line valve position" + annotation (Placement(transformation(extent={{180,-166},{220,-126}}), + iconTransformation(extent={{100,-52},{140,-12}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPumOn + if not have_byPasValCon "Heat exchanger pump command on" + annotation (Placement(transformation(extent={{180,-200},{220,-160}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumSpe( + final min=0, + final max=1, + final unit="1") if not have_byPasValCon + "Heat exchanger pump speed setpoint" + annotation (Placement(transformation(extent={{180,-230},{220,-190}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.CDL.Reals.LessThreshold enaTChiWatRet( + final t=delDis) + "Enable condition based on chilled water return temperature upstream and downstream WSE" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis enaTWet( + final uLow = TOffsetEna - hysDt/2, + final uHigh = TOffsetEna + hysDt/2) + "Enable condition based on the outdoor wet bulb temperature" + annotation (Placement(transformation(extent={{20,156},{40,176}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning wseTun( + final step=step, + final wseOnTimDec=wseOnTimDec, + final wseOnTimInc=wseOnTimInc) + "Tuning parameter for the WSE outlet temperature calculation" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.PredictedOutletTemperature wseTOut( + final heaExcAppDes=heaExcAppDes, + final cooTowAppDes=cooTowAppDes, + final TOutWetDes=TOutWetDes, + final VHeaExcDes_flow=VHeaExcDes_flow) + "Calculates the predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub2 "Subtract" + annotation (Placement(transformation(extent={{-20,156},{0,176}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 "Subtract" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=holdPeriod, + final falseHoldDuration=holdPeriod) + "Keeps a signal constant for a given time period" + annotation (Placement(transformation(extent={{140,156},{160,176}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 "And" + annotation (Placement(transformation(extent={{100,156},{120,176}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys( + final uLow = TOffsetDis - hysDt/2, + final uHigh = TOffsetDis + hysDt/2) + "Hysteresis comparing CHW temperatures upstream and downstream WSE" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer timer + "Measures the disable condition satisfied time " + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Falling edge to indicate the moment of disable" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truHol( + final trueHoldDuration=holdPeriod, + final falseHoldDuration=0) + "Holds a true signal for a period of time right after disable" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Nor nor + "Not either of the inputs" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.BypassValve wseVal( + final dpDes=dpDes, + final controllerType=valCon, + final k=k, + final Ti=Ti, + final Td=Td) if have_byPasValCon + "Chilled water flow through economizer is controlled using bypass valve" + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.HeatExchangerPump wsePum( + final minSpe=minSpe, + final desSpe=desSpe) + if not have_byPasValCon + "Pump control for economizer when the chilled water flow is controlled by a variable speed heat exchanger pump" + annotation (Placement(transformation(extent={{120,-190},{140,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Plant enabled with 0 initial stage, it means enabled with economizer-only operation" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) "Stage 0" + annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu + "Check if initial stage is 0" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Plant enabled with economizer-only operation" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1 + "Check if current stage is initial stage" + annotation (Placement(transformation(extent={{-100,-110},{-80,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Not in initial stage" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Or enaEco "Economizer enabled" + annotation (Placement(transformation(extent={{120,-30},{140,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Break algebric loop" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.And enaWSE + "Enable economizer if the plant is enabled" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Break algebric loop" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + +equation + connect(uTowFanSpeMax, wseTun.uTowFanSpeMax) annotation (Line(points={{-200,20}, + {-150,20},{-150,35},{-142,35}}, color={0,0,127})); + connect(TOutWet, wseTOut.TOutWet) + annotation (Line(points={{-200,210},{-120,210},{-120,168},{-102,168}}, + color={0,0,127})); + connect(VChiWat_flow, wseTOut.VChiWat_flow) + annotation (Line(points={{-200,70},{-120,70},{-120,160},{-102,160}}, + color={0,0,127})); + connect(TChiWatRet, sub1.u1) + annotation (Line(points={{-200,170},{-170,170},{-170,106},{-102,106}}, + color={0,0,127})); + connect(enaTWet.y, and2.u1) + annotation (Line(points={{42,166},{98,166}}, color={255,0,255})); + connect(truFalHol.u, and2.y) + annotation (Line(points={{138,166},{122,166}}, + color={255,0,255})); + connect(timer.y, enaTChiWatRet.u) + annotation (Line(points={{42,100},{58,100}}, color={0,0,127})); + connect(TChiWatRetDow, sub1.u2) + annotation (Line(points={{-200,130},{-160,130},{-160,94},{-102,94}}, + color={0,0,127})); + connect(sub1.y, hys.u) + annotation (Line(points={{-78,100},{-62,100}},color={0,0,127})); + connect(enaTChiWatRet.y, and2.u2) annotation (Line(points={{82,100},{90,100},{ + 90,158},{98,158}}, color={255,0,255})); + connect(wseTun.y, wseTOut.uTunPar) annotation (Line(points={{-118,40},{-110,40}, + {-110,152},{-102,152}}, color={0,0,127})); + connect(wseTOut.y, sub2.u2) annotation (Line(points={{-78,160},{-22,160}}, + color={0,0,127})); + connect(TChiWatRet, sub2.u1) annotation (Line(points={{-200,170},{-170,170},{-170, + 180},{-60,180},{-60,172},{-22,172}}, color={0,0,127})); + connect(sub2.y, enaTWet.u) + annotation (Line(points={{2,166},{18,166}}, color={0,0,127})); + connect(wseTun.y, yTunPar) + annotation (Line(points={{-118,40},{200,40}}, color={0,0,127})); + connect(nor.y, timer.u) + annotation (Line(points={{2,100},{18,100}}, color={255,0,255})); + connect(hys.y, nor.u1) + annotation (Line(points={{-38,100},{-22,100}}, color={255,0,255})); + connect(truHol.y, nor.u2) annotation (Line(points={{-38,60},{-30,60},{-30,92}, + {-22,92}}, color={255,0,255})); + connect(falEdg.y, truHol.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(wseTOut.y, TWsePre) annotation (Line(points={{-78,160},{-60,160},{-60, + 130},{200,130}}, color={0,0,127})); + connect(uIni, intEqu.u1) + annotation (Line(points={{-200,-50},{-102,-50}}, color={255,127,0})); + connect(conInt.y, intEqu.u2) annotation (Line(points={{-118,-80},{-110,-80},{-110, + -58},{-102,-58}}, color={255,127,0})); + connect(intEqu.y, and1.u2) annotation (Line(points={{-78,-50},{-70,-50},{-70,-28}, + {-62,-28}}, color={255,0,255})); + connect(uIni, intEqu1.u1) annotation (Line(points={{-200,-50},{-150,-50},{-150, + -100},{-102,-100}}, color={255,127,0})); + connect(uChiSta, intEqu1.u2) + annotation (Line(points={{-200,-108},{-102,-108}}, color={255,127,0})); + connect(intEqu1.y, not1.u) + annotation (Line(points={{-78,-100},{-62,-100}}, color={255,0,255})); + connect(enaEco.y, y) + annotation (Line(points={{142,-20},{200,-20}}, color={255,0,255})); + connect(dpChiWat, wseVal.dpChiWat) annotation (Line(points={{-200,-140},{-60,-140}, + {-60,-146},{118,-146}}, color={0,0,127})); + connect(uPum, wsePum.uPum) annotation (Line(points={{-200,-180},{118,-180}}, + color={255,0,255})); + connect(TEntHex, wsePum.TEntHex) annotation (Line(points={{-200,-210},{100, + -210},{100,-188},{118,-188}}, color={0,0,127})); + connect(wseVal.yConWatIsoVal, yConWatIsoVal) annotation (Line(points={{142,-134}, + {160,-134},{160,-100},{200,-100}}, color={0,0,127})); + connect(wseVal.yRetVal, yRetVal) + annotation (Line(points={{142,-146},{200,-146}}, color={0,0,127})); + connect(wsePum.yPumOn, yPumOn) + annotation (Line(points={{142,-180},{200,-180}}, color={255,0,255})); + connect(wsePum.yPumSpe, yPumSpe) annotation (Line(points={{142,-186},{160,-186}, + {160,-210},{200,-210}}, color={0,0,127})); + connect(wsePum.yConWatIsoVal, yConWatIsoVal) annotation (Line(points={{142,-174}, + {160,-174},{160,-100},{200,-100}}, color={0,0,127})); + connect(TChiWatRet, wsePum.TEntWSE) annotation (Line(points={{-200,170},{-170, + 170},{-170,-184},{118,-184}}, color={0,0,127})); + connect(uPla, wseVal.uPla) annotation (Line(points={{-200,-20},{-154,-20},{ + -154,-134},{118,-134}}, color={255,0,255})); + connect(uPla, wsePum.uPla) annotation (Line(points={{-200,-20},{-154,-20},{ + -154,-172},{118,-172}}, color={255,0,255})); + connect(uPla, and1.u1) + annotation (Line(points={{-200,-20},{-62,-20}}, color={255,0,255})); + connect(lat.y, pre2.u) + annotation (Line(points={{42,-20},{58,-20}}, color={255,0,255})); + connect(enaEco.y, wseVal.uWSE) annotation (Line(points={{142,-20},{150,-20},{150, + -40},{110,-40},{110,-140},{118,-140}}, color={255,0,255})); + connect(enaEco.y, wsePum.uWSE) annotation (Line(points={{142,-20},{150,-20},{150, + -40},{110,-40},{110,-176},{118,-176}}, color={255,0,255})); + connect(enaEco.y, falEdg.u) annotation (Line(points={{142,-20},{150,-20},{150, + 0},{-160,0},{-160,60},{-102,60}}, color={255,0,255})); + connect(enaEco.y, wseTun.uWseSta) annotation (Line(points={{142,-20},{150,-20}, + {150,0},{-160,0},{-160,45},{-142,45}}, color={255,0,255})); + connect(pre2.y, enaEco.u2) annotation (Line(points={{82,-20},{100,-20},{100, + -28},{118,-28}}, color={255,0,255})); + connect(not1.y, lat.clr) annotation (Line(points={{-38,-100},{0,-100},{0,-26}, + {18,-26}}, color={255,0,255})); + connect(and1.y, lat.u) + annotation (Line(points={{-38,-20},{18,-20}}, color={255,0,255})); + connect(uPla, enaWSE.u2) annotation (Line(points={{-200,-20},{-154,-20},{-154, + 12},{18,12}}, color={255,0,255})); + connect(enaWSE.y, pre1.u) + annotation (Line(points={{42,20},{58,20}}, color={255,0,255})); + connect(pre1.y, enaEco.u1) annotation (Line(points={{82,20},{110,20},{110,-20}, + {118,-20}}, color={255,0,255})); + connect(truFalHol.y, enaWSE.u1) annotation (Line(points={{162,166},{168,166},{ + 168,60},{0,60},{0,20},{18,20}}, color={255,0,255})); + annotation (defaultComponentName = "wseSta", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-82,64},{80,-56}}, + lineColor={28,108,200}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Polygon( + points={{-82,64},{-16,8},{-82,-56},{-82,64}}, + lineColor={175,175,175}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{6,60},{72,-52}}, + lineColor={28,108,200}, + lineThickness=0.5), + Line( + points={{6,-52},{72,60}}, + color={28,108,200}, + thickness=0.5)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-180,-220},{180,220}}), graphics={ + Rectangle( + extent={{-178,-2},{58,-118}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), Text( + extent={{-92,-64},{52,-78}}, + textColor={0,0,127}, + textString="Plant enabled in water side economizer mode")}), +Documentation(info=" +

+Waterside economizer (WSE) control sequence per ASHRAE Guideline36-2021, section 5.20.3. +

+

Enable and disable WSE

+

+The sequence controls the WSE status as follows: +

+ +

+The following state machine chart illustrates the transitions between WSE enabled and disabled state: +

+

+\"Image +

+

+The WSE enabling sequence uses the following subsequences: +

+ + +

Chilled water flow through the WSE

+ + + + +", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/BypassValve.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/BypassValve.mo new file mode 100644 index 00000000000..64e8770ec9c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/BypassValve.mo @@ -0,0 +1,158 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences; +block BypassValve + "Valves control when chilled water flow through economizer is controlled using bypass valve" + + parameter Real dpDes( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=0)=6000 + "Design pressure difference across the chilled water side economizer"; + parameter CDL.Types.SimpleController controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="Valve controller")); + parameter Real k=0.1 + "Gain of controller" + annotation (Dialog(group="Valve controller")); + parameter Real Ti(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(group="Valve controller", + enable=controllerType == CDL.Types.SimpleController.PI or controllerType == CDL.Types.SimpleController.PID)); + parameter Real Td(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(group="Valve controller", + enable=controllerType == CDL.Types.SimpleController.PD or controllerType == CDL.Types.SimpleController.PID)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-140,60},{-100,100}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE + "True: waterside economizer is enabled" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat( + final unit="Pa", + final quantity="PressureDifference") + "Differential static pressure across economizer in the chilled water side" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatIsoVal( + final min=0, + final max=1, + final unit="1") + "Economizer condensing water isolation valve position" + annotation (Placement(transformation(extent={{100,20},{140,60}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetVal( + final min=0, + final max=1, + final unit="1") + "WSE in-line CHW return line valve position" + annotation (Placement(transformation(extent={{100,-40},{140,0}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal conWatIso + "Condensing water valve position" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPID( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final reverseActing=false, + final y_reset=1) "Chilled water return line valve controller" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con( + final k=1) "Constant one" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1( + final k=dpDes) + "Design static pressure difference across waterside economizer in chilled water side" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div1 + "Normalize the measured value" + annotation (Placement(transformation(extent={{-40,-56},{-20,-36}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Return line valve position" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Waterside economizer commanded on" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); +equation + connect(dpChiWat, div1.u1) + annotation (Line(points={{-120,-40},{-42,-40}}, color={0,0,127})); + connect(con1.y, div1.u2) annotation (Line(points={{-58,-80},{-50,-80},{-50,-52}, + {-42,-52}}, color={0,0,127})); + connect(con.y, conPID.u_s) + annotation (Line(points={{-58,0},{-12,0}}, color={0,0,127})); + connect(div1.y, conPID.u_m) + annotation (Line(points={{-18,-46},{0,-46},{0,-12}}, color={0,0,127})); + connect(conPID.y, swi.u1) annotation (Line(points={{12,0},{20,0},{20,-12},{58, + -12}},color={0,0,127})); + connect(con.y, swi.u3) annotation (Line(points={{-58,0},{-50,0},{-50,-28},{58, + -28}},color={0,0,127})); + connect(swi.y, yRetVal) annotation (Line(points={{82,-20},{120,-20}}, + color={0,0,127})); + connect(conWatIso.y, yConWatIsoVal) + annotation (Line(points={{82,40},{120,40}}, color={0,0,127})); + connect(uWSE, and1.u1) + annotation (Line(points={{-120,40},{-82,40}}, color={255,0,255})); + connect(uPla, and1.u2) annotation (Line(points={{-120,80},{-90,80},{-90,32},{-82, + 32}}, color={255,0,255})); + connect(and1.y, conWatIso.u) + annotation (Line(points={{-58,40},{58,40}}, color={255,0,255})); + connect(and1.y, conPID.trigger) annotation (Line(points={{-58,40},{-40,40},{-40, + -20},{-6,-20},{-6,-12}}, color={255,0,255})); + connect(and1.y, swi.u2) annotation (Line(points={{-58,40},{-40,40},{-40,-20},{ + 58,-20}}, color={255,0,255})); +annotation (defaultComponentName = "wseVal", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Waterside economizer valves control when the chilled water flow through the economizer +is controlled using a modulating heat exchanger bypass valve. It is implemented +according to ASHRAE Guideline36-2021, section 5.20.3.4-6. +

+

+When economizer is enabled, start next condenser pump and (or) adjust the pump +speed (see +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller), +open the condenser water isolation valve to the heat exchanger (yConWatIsoVal=1), +and enable the economizer in-line chilled water return line valve (yRetVal=1). +

+

+When the in-line valve is enabled, it shall be modulated by a direct-acting PID +loop to maintain the static pressure difference across the chilled water side +of the heat exchanger at the design value (dpDes). Map the loop output from 0% open +at 0% output to 100% open at 100% output. Bias the loop to launce from 100% +output. The valve shall be fully open when the loop is disabled. +

+

+When the economizer is disabled, the economizer in-line chilled water return line +valve shall be disabled (fully open), the heat exchanger condensing water isolation +valve fully closed (yConWatIsoVal=0), and the last lag condenser water +pump disabled and (or) change the pump speed +(see +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller). +

+", +revisions=" + +")); +end BypassValve; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/HeatExchangerPump.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/HeatExchangerPump.mo new file mode 100644 index 00000000000..f29e009a55c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/HeatExchangerPump.mo @@ -0,0 +1,221 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences; +block HeatExchangerPump + "Pump control for economizer when the chilled water flow is controlled by a variable speed heat exchanger pump" + parameter Real minSpe = 0.1 "Minimum pump speed"; + parameter Real desSpe = 0.9 "Design pump speed"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-200,120},{-160,160}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE + "True: waterside economizer is enabled" + annotation (Placement(transformation(extent={{-200,90},{-160,130}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPum + "True: heat exchanger pump is proven on" + annotation (Placement(transformation(extent={{-200,40},{-160,80}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TEntWSE( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water return temperature upstream of the economizer" + annotation (Placement(transformation(extent={{-200,0},{-160,40}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TEntHex( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water temperature entering heat exchanger" + annotation (Placement(transformation(extent={{-200,-60},{-160,-20}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatIsoVal( + final min=0, + final max=1, + final unit="1") "Economizer condensing water isolation valve position" + annotation (Placement(transformation(extent={{160,90},{200,130}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPumOn + "Heat exchanger pump command on" + annotation (Placement(transformation(extent={{160,50},{200,90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumSpe( + final min=0, + final max=1, + final unit="1") "Heat exchanger pump speed setpoint" + annotation (Placement(transformation(extent={{160,10},{200,50}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal conWatIso + "Condensing water isolation valve position" + annotation (Placement(transformation(extent={{40,100},{60,120}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub "Temperature difference" + annotation (Placement(transformation(extent={{-140,-20},{-120,0}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr( + final t=1.11, + final h=0.44) + "Check if the temperature difference is greater than 2 degF (1.11 degK)" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=0.56, + final h=0.45) + "Check if the temperature difference is greater than 1 degF (0.56 degK)" + annotation (Placement(transformation(extent={{-100,-100},{-80,-80}}))); + Buildings.Controls.OBC.CDL.Integers.Switch resSpeReq1 + "Pump speed reset request" + annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant two( + final k=2) "Constant two" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant one( + final k=1) "Constant one" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-100,-140},{-80,-120}}))); + Buildings.Controls.OBC.CDL.Integers.Switch resSpeReq + "Pump speed reset request" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond resSpe( + final iniSet=desSpe, + final minSet=minSpe, + final maxSet=desSpe, + final delTim=900, + final samplePeriod=120, + final numIgnReq=0, + final triAmo=0.02, + final resAmo=-0.03, + final maxRes=-0.06) + "Reset pump speed" + annotation (Placement(transformation(extent={{60,-20},{80,0}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul "Pump Speed" + annotation (Placement(transformation(extent={{120,20},{140,40}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Waterside economizer commanded on" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); +equation + connect(conWatIso.y, yConWatIsoVal) + annotation (Line(points={{62,110},{180,110}}, color={0,0,127})); + connect(TEntWSE, sub.u1) annotation (Line(points={{-180,20},{-150,20},{-150,-4}, + {-142,-4}}, color={0,0,127})); + connect(TEntHex, sub.u2) annotation (Line(points={{-180,-40},{-150,-40},{-150, + -16},{-142,-16}}, color={0,0,127})); + connect(sub.y, greThr.u) + annotation (Line(points={{-118,-10},{-102,-10}}, color={0,0,127})); + connect(sub.y, greThr1.u) annotation (Line(points={{-118,-10},{-110,-10},{-110, + -90},{-102,-90}}, color={0,0,127})); + connect(greThr1.y, resSpeReq1.u2) + annotation (Line(points={{-78,-90},{-42,-90}}, color={255,0,255})); + connect(zer.y, resSpeReq1.u3) annotation (Line(points={{-78,-130},{-60,-130},{ + -60,-98},{-42,-98}}, color={255,127,0})); + connect(greThr.y, resSpeReq.u2) + annotation (Line(points={{-78,-10},{18,-10}},color={255,0,255})); + connect(two.y, resSpeReq.u1) annotation (Line(points={{-78,30},{0,30},{0,-2},{ + 18,-2}}, color={255,127,0})); + connect(resSpeReq1.y, resSpeReq.u3) annotation (Line(points={{-18,-90},{0,-90}, + {0,-18},{18,-18}}, color={255,127,0})); + connect(one.y, resSpeReq1.u1) annotation (Line(points={{-78,-50},{-60,-50},{-60, + -82},{-42,-82}}, color={255,127,0})); + connect(resSpeReq.y,resSpe. numOfReq) annotation (Line(points={{42,-10},{50,-10}, + {50,-18},{58,-18}}, color={255,127,0})); + connect(uPum,resSpe. uDevSta) annotation (Line(points={{-180,60},{50,60},{50,-2}, + {58,-2}}, color={255,0,255})); + connect(resSpe.y, mul.u2) annotation (Line(points={{82,-10},{100,-10},{100,24}, + {118,24}},color={0,0,127})); + connect(conWatIso.y, mul.u1) annotation (Line(points={{62,110},{100,110},{100, + 36},{118,36}}, color={0,0,127})); + connect(mul.y, yPumSpe) + annotation (Line(points={{142,30},{180,30}}, color={0,0,127})); + connect(uWSE, and1.u1) + annotation (Line(points={{-180,110},{-102,110}}, color={255,0,255})); + connect(and1.y, conWatIso.u) + annotation (Line(points={{-78,110},{38,110}}, color={255,0,255})); + connect(and1.y, yPumOn) annotation (Line(points={{-78,110},{20,110},{20,70},{180, + 70}}, color={255,0,255})); + connect(uPla, and1.u2) annotation (Line(points={{-180,140},{-120,140},{-120,102}, + {-102,102}}, color={255,0,255})); +annotation (defaultComponentName = "wsePum", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-160,-160},{160,160}})), + Documentation(info=" +

+It implements the control of the waterside economizer valves when the chilled water +flow through the economizer is controlled by variable speed heat exchanger pump. +It is implemented according to ASHRAE Guideline36-2021, section 5.20.3.7-10. +

+

+When economizer is enabled (uWSE=true), start next condenser water +pump and (or) adjust the pump speed +(see +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller), +open the condenser water isolation valve to the heat exchanger (yConWatIsoVal=1), +and enable the chilled water heat exchanger pump. +

+

+The economizer heat exchanger pump speed reset requests shall be generated based +on the difference between chilled water return temperature upstream of the economizer +and economizer heat exchanger entering chilled water temperature. +

+
    +
  1. +If the temperature difference exceeeds 2 °F (1.11 °K), send 2 requests +until the difference is less than 1.2 °F (0.67 °F). +
  2. +
  3. +Else if the temperature difference exceeds 1 °F (0.56 °K), send 1 request +until the difference is less than 0.2 °F (0.11 °K). +
  4. +
  5. +Else send 0 requests. +
  6. +
+

+When the heat exchanger pump is proven on, the pump speed shall be reset using +Trim and Respond logic with the following parameters: +

+ + + + + + + + + + + + + + +
Variable Value Definition
DeviceEconomizer heat exchanger pump proven on Associated device
SP0Pump design speed (desSpe)Initial setpoint
SPminPump minimum speed (minSpe)Minimum setpoint
SPmaxPump design speed (desSpe)Maximum setpoint
Td15 minutesDelay timer
T2 minutesTime step
I0Number of ignored requests
RPump speed reset requestsNumber of requests
SPtrim2%Trim amount
SPres-3%Respond amount
SPres_max-6%Maximum response per time interval
+
+ +

+When economizer is disabled (uWSE=false), the chilled water heat +exchanger pump shall be disabled, the heat exchanger condenser water isolation +valve fully closed (yConWatIsoVal=0), and the last lag condenser water pump disabled +and (or) change the pump speed +see +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller). +

+", +revisions=" + +")); +end HeatExchangerPump; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/PredictedOutletTemperature.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/PredictedOutletTemperature.mo new file mode 100644 index 00000000000..e5b3e2fcf9d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/PredictedOutletTemperature.mo @@ -0,0 +1,197 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences; +block PredictedOutletTemperature + "Waterside economizer predicted outlet temperature" + + parameter Real heaExcAppDes( + final unit="K", + final quantity="TemperatureDifference")=2 + "Design heat exchanger approach"; + + parameter Real cooTowAppDes( + final unit="K", + final quantity="TemperatureDifference")=2 + "Design cooling tower approach"; + + parameter Real TOutWetDes( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Design outdoor air wet bulb temperature"; + + parameter Real VHeaExcDes_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.01 + "Desing heat exchanger chilled water flow rate"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTunPar( + final min=-0.2, + final max=0.5) "Tuning parameter" + annotation (Placement(transformation(extent={{-200,-160},{-160,-120}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutWet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") "Outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-200,120},{-160,160}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s") + "Measured (secondary for primary-secondary plants) chilled water flow rate" + annotation (Placement(transformation(extent={{-200,-20},{-160,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput y( + final quantity="ThermodynamicTemperature", + final unit="K") + "Predicted waterside economizer outlet temperature" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Divide heaExcPlr + "Heat exchanger flow part load ratio" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant heaExcDes_flow( + final k= VHeaExcDes_flow) "Heat exchanger design flow" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant heaAppDes( + final k=heaExcAppDes) + "Heat exchanger design approach" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro "Product" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 "Subtraction" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TWetDes( + final k=TOutWetDes) + "Design outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro1 "Product" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towAppDes( + final k=cooTowAppDes) + "Cooling tower design approach" + annotation (Placement(transformation(extent={{40,-120},{60,-100}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum( + final nin=4) + "Sum of multiple inputs" + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Min min1 + "Lesser of the input" + annotation (Placement(transformation(extent={{0,60},{20,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con( + final k=1) "Constant one" + annotation (Placement(transformation(extent={{-60,100},{-40,120}}))); + +equation + connect(heaExcPlr.u2, heaExcDes_flow.y) annotation (Line(points={{-62,44},{ + -80,44},{-80,20},{-98,20}}, color={0,0,127})); + connect(VChiWat_flow, heaExcPlr.u1) annotation (Line(points={{-180,0},{-140,0}, + {-140,56},{-62,56}}, color={0,0,127})); + connect(heaAppDes.y, pro.u2) annotation (Line(points={{22,30},{40,30},{40,44}, + {58,44}}, color={0,0,127})); + connect(sub1.y, pro1.u1) annotation (Line(points={{-38,-50},{0,-50},{0,-64},{ + 58,-64}}, color={0,0,127})); + connect(uTunPar, pro1.u2) annotation (Line(points={{-180,-140},{20,-140},{20, + -76},{58,-76}}, color={0,0,127})); + connect(TOutWet, mulSum.u[1]) annotation (Line(points={{-180,140},{100,140},{ + 100,-0.75},{118,-0.75}}, + color={0,0,127})); + connect(pro.y, mulSum.u[2]) annotation (Line(points={{82,50},{90,50},{90, + -0.25},{118,-0.25}}, + color={0,0,127})); + connect(pro1.y, mulSum.u[3]) annotation (Line(points={{82,-70},{90,-70},{90, + 0.25},{118,0.25}},color={0,0,127})); + connect(towAppDes.y, mulSum.u[4]) annotation (Line(points={{62,-110},{100, + -110},{100,-2},{118,-2},{118,0.75}}, + color={0,0,127})); + connect(mulSum.y, y) + annotation (Line(points={{142,0},{180,0}}, color={0,0,127})); + connect(TOutWet, sub1.u2) annotation (Line(points={{-180,140},{-150,140},{-150, + -56},{-62,-56}}, color={0,0,127})); + connect(TWetDes.y, sub1.u1) annotation (Line(points={{-98,-30},{-80,-30},{-80, + -44},{-62,-44}}, color={0,0,127})); + connect(heaExcPlr.y, min1.u2) annotation (Line(points={{-38,50},{-20,50},{-20, + 64},{-2,64}}, color={0,0,127})); + connect(con.y, min1.u1) annotation (Line(points={{-38,110},{-20,110},{-20,76}, + {-2,76}}, color={0,0,127})); + connect(min1.y, pro.u1) annotation (Line(points={{22,70},{40,70},{40,56},{58, + 56}}, color={0,0,127})); + annotation (defaultComponentName = "wseTOut", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-160,-180},{160,180}})), +Documentation(info=" +

+The waterside economizer (WSE) is enabled or disabled based on the predicted WSE +heat exchanger (HX) leaving water temperature, y. +This block predicts y based on current plant load +and ambient wet bulb temperature with resepect to the design conditions, as described in +ASHRAE Guideline36-2021, section 5.20.3.1. +

+

+The block calculates the predicted WSE output temperature y as a sum of these +three components: +

+ +", +revisions=" + +")); +end PredictedOutletTemperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Tuning.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Tuning.mo new file mode 100644 index 00000000000..bfa13b24bb7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Tuning.mo @@ -0,0 +1,317 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences; +block Tuning + "Defines a tuning parameter for the temperature prediction downstream of WSE" + + parameter Real step( + final unit="1")=0.02 + "Incremental step used to reduce or increase the water-side economizer tuning parameter"; + + parameter Real wseOnTimDec( + final unit="s", + final quantity="Time", + displayUnit="h")=3600 + "Economizer enable time needed to allow decrease of the tuning parameter"; + + parameter Real wseOnTimInc( + final unit="s", + final quantity="Time", + displayUnit="h")=1800 + "Economizer enable time needed to allow increase of the tuning parameter"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWseSta "WSE enable disable status" + annotation (Placement(transformation(extent={{-360,100},{-320,140}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTowFanSpeMax( + final unit="1") + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation( + extent={{-360,-100},{-320,-60}}), iconTransformation(extent={{-140,-70}, + {-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput y( + final max=maxTunPar, + final min=minTunPar, + final start=initTunPar) + "Tuning parameter for the waterside economizer outlet temperature prediction" + annotation (Placement(transformation(extent={{320,50},{360,90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + final parameter Integer larInt=65535 "Large integer used to reset counters"; + + final parameter Real antWinGai=1 "Anti-windup gain"; + + final parameter Real initTunPar = 0 + "Initial value of the tuning parameter"; + + final parameter Real minTunPar( + final unit="1") = -0.2 + "Tuning parameter minimum limit"; + + final parameter Real maxTunPar( + final unit="1") = 0.5 + "Tuning parameter maximum limit"; + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant resVal( + final k=0) "Reset value" + annotation (Placement(transformation(extent={{120,0},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum( + final k={-1*step,step,1}, nin=3) "Multiple input sum" + annotation (Placement(transformation(extent={{120,60},{140,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 "Anti-windup adder" + annotation (Placement(transformation(extent={{200,20},{220,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim(final t=wseOnTimDec) "Timer" + annotation (Placement(transformation(extent={{-260,140},{-240,160}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg "Falling edge" + annotation (Placement(transformation(extent={{-220,90},{-200,110}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 "And" + annotation (Placement(transformation(extent={{-140,140},{-120,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim1 "Timer" + annotation (Placement(transformation(extent={{-260,40},{-240,60}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg1 "Falling edge" + annotation (Placement(transformation(extent={{-220,-10},{-200,10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 "And" + annotation (Placement(transformation(extent={{-140,0},{-120,20}}))); + + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr( + final t=wseOnTimInc) "Less than" + annotation (Placement(transformation(extent={{-220,40},{-200,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys( + final uHigh=0.99, + final uLow=0.98) "Checks if the signal is at its maximum" + annotation (Placement(transformation(extent={{-280,-90},{-260,-70}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam2( + final y_start=0) "Sampler" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr( + final t=0.5) "Greater or equal than" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea "Conversion" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 "Not" + annotation (Placement(transformation(extent={{-260,-30},{-240,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 "Not" + annotation (Placement(transformation(extent={{-240,-150},{-220,-130}}))); + + Buildings.Controls.OBC.CDL.Logical.And and5 "And" + annotation (Placement(transformation(extent={{-200,-160},{-180,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.And and6 "And" + annotation (Placement(transformation(extent={{-200,-120},{-180,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Or and4 "And" + annotation (Placement(transformation(extent={{-80,-120},{-60,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat "Latch" + annotation (Placement(transformation(extent={{-140,-140},{-120,-120}}))); + + Buildings.Controls.OBC.CDL.Integers.OnCounter disCou + "Counts the number of times the WSE got disabled" + annotation (Placement(transformation(extent={{-100,140},{-80,160}}))); + + Buildings.Controls.OBC.CDL.Integers.OnCounter disCou1 + "Counts the number of times the WSE got disabled" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Type converter" + annotation (Placement(transformation(extent={{60,140},{80,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Type converter" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxInt + "Greater or equal a threshold" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr1( + final t=larInt) "Greater or equal a threshold" + annotation (Placement(transformation(extent={{-10,70},{10,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Limiter lim( + final uMax=maxTunPar, + final uMin=minTunPar) "Limiter" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + + Buildings.Controls.OBC.CDL.Reals.IntegratorWithReset intWitRes( + final k=antWinGai) + "Integrator with reset" + annotation (Placement(transformation(extent={{240,0},{260,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre preRes + "Breaks algebraic loop for the counter and integrator reset" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical and" + annotation (Placement(transformation(extent={{-108,0},{-88,20}}))); + +equation + connect(uWseSta, tim.u) + annotation (Line(points={{-340,120},{-280,120},{-280,150},{-262,150}}, + color={255,0,255})); + connect(uWseSta, tim1.u) annotation (Line(points={{-340,120},{-280,120},{-280, + 50},{-262,50}},color={255,0,255})); + connect(uTowFanSpeMax, hys.u) + annotation (Line(points={{-340,-80},{-282,-80}}, color={0,0,127})); + connect(triSam2.y, greThr.u) + annotation (Line(points={{-38,-80},{-22,-80}}, color={0,0,127})); + connect(booToRea.y, triSam2.u) annotation (Line(points={{-78,-80},{-62,-80}}, + color={0,0,127})); + connect(uWseSta, falEdg.u) annotation (Line(points={{-340,120},{-280,120},{-280, + 100},{-222,100}}, color={255,0,255})); + connect(falEdg.y, and2.u2) annotation (Line(points={{-198,100},{-150,100},{-150, + 142},{-142,142}},color={255,0,255})); + connect(uWseSta, falEdg1.u) annotation (Line(points={{-340,120},{-280,120},{-280, + 0},{-222,0}}, color={255,0,255})); + connect(and1.u2, falEdg1.y) annotation (Line(points={{-142,2},{-160,2},{-160,0}, + {-198,0}}, color={255,0,255})); + connect(hys.y, booToRea.u) + annotation (Line(points={{-258,-80},{-102,-80}},color={255,0,255})); + connect(and4.y, triSam2.trigger) annotation (Line(points={{-58,-110},{-50,-110}, + {-50,-92}}, color={255,0,255})); + connect(uWseSta, not1.u) annotation (Line(points={{-340,120},{-280,120},{-280, + -20},{-262,-20}},color={255,0,255})); + connect(hys.y, and6.u1) annotation (Line(points={{-258,-80},{-244,-80},{-244,-110}, + {-202,-110}}, color={255,0,255})); + connect(not1.y, and6.u2) annotation (Line(points={{-238,-20},{-210,-20},{-210, + -118},{-202,-118}},color={255,0,255})); + connect(and4.u1, and6.y) annotation (Line(points={{-82,-110},{-178,-110}}, + color={255,0,255})); + connect(uWseSta, and5.u2) annotation (Line(points={{-340,120},{-300,120},{-300, + -158},{-202,-158}}, color={255,0,255})); + connect(hys.y, not2.u) annotation (Line(points={{-258,-80},{-252,-80},{-252,-140}, + {-242,-140}}, color={255,0,255})); + connect(and5.u1, not2.y) + annotation (Line(points={{-202,-150},{-210,-150},{-210,-140},{-218,-140}}, + color={255,0,255})); + connect(and5.y, lat.u) annotation (Line(points={{-178,-150},{-172,-150},{-172, + -130},{-142,-130}}, color={255,0,255})); + connect(lat.y, and4.u2) annotation (Line(points={{-118,-130},{-90,-130},{-90, + -118},{-82,-118}}, + color={255,0,255})); + connect(not1.y, lat.clr) annotation (Line(points={{-238,-20},{-160,-20},{-160, + -136},{-142,-136}}, color={255,0,255})); + connect(tim1.y, lesThr.u) + annotation (Line(points={{-238,50},{-222,50}}, color={0,0,127})); + connect(intToRea.u, disCou.y) + annotation (Line(points={{58,150},{-78,150}},color={255,127,0})); + connect(and2.y, disCou.trigger) + annotation (Line(points={{-118,150},{-102,150}}, color={255,0,255})); + connect(disCou1.y, intToRea1.u) + annotation (Line(points={{-58,10},{-2,10}}, color={255,127,0})); + connect(lim.y, y) + annotation (Line(points={{182,70},{340,70}}, color={0,0,127})); + connect(mulSum.y, lim.u) + annotation (Line(points={{142,70},{158,70}}, color={0,0,127})); + connect(lim.y, sub1.u1) annotation (Line(points={{182,70},{190,70},{190,36},{198, + 36}}, color={0,0,127})); + connect(mulSum.y, sub1.u2) annotation (Line(points={{142,70},{152,70},{152,24}, + {198,24}}, color={0,0,127})); + connect(sub1.y, intWitRes.u) annotation (Line(points={{222,30},{230,30},{230,10}, + {238,10}}, color={0,0,127})); + connect(maxInt.y, intGreEquThr1.u) + annotation (Line(points={{-18,80},{-12,80}},color={255,127,0})); + connect(disCou.y, maxInt.u1) annotation (Line(points={{-78,150},{-50,150},{-50, + 86},{-42,86}}, color={255,127,0})); + connect(disCou1.y, maxInt.u2) annotation (Line(points={{-58,10},{-50,10},{-50, + 74},{-42,74}}, color={255,127,0})); + connect(intToRea.y, mulSum.u[1]) annotation (Line(points={{82,150},{100,150}, + {100,69.3333},{118,69.3333}},color={0,0,127})); + connect(intToRea1.y, mulSum.u[2]) annotation (Line(points={{22,10},{80,10},{ + 80,70},{118,70}}, + color={0,0,127})); + connect(intWitRes.y, mulSum.u[3]) annotation (Line(points={{262,10},{280,10}, + {280,-40},{110,-40},{110,70.6667},{118,70.6667}},color={0,0,127})); + connect(intGreEquThr1.y, preRes.u) + annotation (Line(points={{12,80},{18,80}}, color={255,0,255})); + connect(preRes.y, disCou.reset) annotation (Line(points={{42,80},{50,80},{50, + 120},{-90,120},{-90,138}}, color={255,0,255})); + connect(preRes.y, disCou1.reset) annotation (Line(points={{42,80},{50,80},{50, + -10},{-70,-10},{-70,-2}}, color={255,0,255})); + connect(preRes.y, intWitRes.trigger) annotation (Line(points={{42,80},{50,80}, + {50,-10},{250,-10},{250,-2}}, color={255,0,255})); + connect(resVal.y, intWitRes.y_reset_in) annotation (Line(points={{142,10},{182, + 10},{182,2},{238,2}}, color={0,0,127})); + connect(disCou1.trigger, and3.y) + annotation (Line(points={{-82,10},{-86,10}}, color={255,0,255})); + connect(and1.y, and3.u1) + annotation (Line(points={{-118,10},{-110,10}}, color={255,0,255})); + connect(greThr.y, and3.u2) annotation (Line(points={{2,-80},{20,-80},{20,-20}, + {-116,-20},{-116,2},{-110,2}}, color={255,0,255})); + connect(tim.passed, and2.u1) annotation (Line(points={{-238,142},{-220,142},{ + -220,150},{-142,150}}, color={255,0,255})); + connect(lesThr.y, and1.u1) annotation (Line(points={{-198,50},{-180,50},{-180, + 10},{-142,10}}, color={255,0,255})); + annotation (defaultComponentName = "wseTun", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-320,-200},{320,200}})), +Documentation(info=" +

+Waterside economizer outlet temperature prediction tuning parameter subsequence +per ASHRAE Guideline36-2021, section 5.20.3.3. +

+

+The subsequence calculates the tuning parameter y as follows: +

+ +

+y initializes at 0 upon first plant start up, +it holds its value when the plant is disabled and tuning resumes from that value when the plant is re-enabled. +It is limited between -0.2 and 0.5. +

+

+In order to avoid large integer values above larInt, the counters +get reset to 0 each time any of them reaches that value. +

+", +revisions=" + +")); +end Tuning; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/BypassValve.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/BypassValve.mo new file mode 100644 index 00000000000..662d1e8b095 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/BypassValve.mo @@ -0,0 +1,86 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Validation; +model BypassValve "Validate the control of inline valve" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.BypassValve wseVal( + final Ti=10) + "Chilled water return line in-line valve control" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta( + final width=0.8, + final period=3600) "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse dpWSE( + final amplitude=3000, + final period=3600, + final offset=4500) + "Static pressure difference across chilled water side economizer" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Plant enable" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPla( + final width=0.2, final period=3600) + "Enabled plant" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); +equation + connect(ecoSta.y, wseVal.uWSE) annotation (Line(points={{-38,0},{18,0}}, + color={255,0,255})); + connect(dpWSE.y, wseVal.dpChiWat) annotation (Line(points={{-38,-40},{-20,-40}, + {-20,-6},{18,-6}}, color={0,0,127})); + connect(enaPla.y, not2.u) + annotation (Line(points={{-58,50},{-42,50}}, color={255,0,255})); + connect(not2.y, wseVal.uPla) annotation (Line(points={{-18,50},{0,50},{0,6},{18, + 6}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/BypassValve.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.BypassValve. +

+

+The validation shows that when the plant is enabled in waterside mode +(uPla=true and uWSE=true): +

+ +

+If the econimizer is disabled (uWSE=false), the condenser water +isolation valve to the heat exchanger should be fully closed and the return +line valve should be disabled in fully open position. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false))); +end BypassValve; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/HeatExchangerPump.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/HeatExchangerPump.mo new file mode 100644 index 00000000000..ea98b5bf167 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/HeatExchangerPump.mo @@ -0,0 +1,94 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Validation; +model HeatExchangerPump "Validate the control of heat exchanger pump" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.HeatExchangerPump wsePum + "Economizer heat exchanger pump control" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta( + final width=0.8, + final period=3600) "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp entWSETem( + final height=6, + final duration=3600, + final offset=285.15) + "Economizer upstream chilled water temperature" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumOn( + final width=0.8, + final period=3600) + "Pump proven on" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp entHexTem( + final height=8, + final duration=3600, + final offset=283.15) + "Entering heat exchanger return chilled water temperature" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Plant enable" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPla( + final width=0.2, final period=3600) + "Enabled plant" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); +equation + connect(ecoSta.y,wsePum. uWSE) annotation (Line(points={{-38,50},{0,50},{0,4}, + {18,4}}, color={255,0,255})); + connect(pumOn.y, wsePum.uPum) annotation (Line(points={{-38,10},{-10,10},{-10, + 0},{18,0}}, color={255,0,255})); + connect(entWSETem.y, wsePum.TEntWSE) annotation (Line(points={{-38,-30},{-10,-30}, + {-10,-4},{18,-4}}, color={0,0,127})); + connect(entHexTem.y, wsePum.TEntHex) annotation (Line(points={{-38,-70},{0,-70}, + {0,-8},{18,-8}}, color={0,0,127})); + connect(enaPla.y, not2.u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + connect(not2.y, wsePum.uPla) annotation (Line(points={{-18,80},{8,80},{8,8},{18, + 8}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/HeatExchangerPump.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.HeatExchangerPump. +It demonstrates the process of controlling the heat exhcnager pump in following scenarios: +

+ +", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false))); +end HeatExchangerPump; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/PredictedOutletTemperature.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/PredictedOutletTemperature.mo new file mode 100644 index 00000000000..5966971f78c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/PredictedOutletTemperature.mo @@ -0,0 +1,84 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Validation; +model PredictedOutletTemperature + "Validate water side economizer outlet temperature prediction" + + parameter Real aveTWetBul( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Chilled water supply set temperature"; + + parameter Real aveVChiWat_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.01 + "Average measured chilled water return temperature"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.PredictedOutletTemperature + wseTOut "Waterside economizer outlet temperature prediction" + annotation (Placement(transformation(extent={{40,0},{60,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TOutWetSig( + final amplitude=2, + final freqHz=1/600, + final offset=aveTWetBul) + "Measured outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow( + final freqHz=1/600, + final offset=aveVChiWat_flow, + final amplitude=0.002) "Chilled water flow" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.CDL.Discrete.Sampler sam1( + final samplePeriod=60) "Sampler" + annotation (Placement(transformation(extent={{-20,-60},{0,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram( + final offset=-0.2, + final height=0.7, + final duration=2100) "Ramp" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + +equation + connect(ram.y, sam1.u) + annotation (Line(points={{-38,-50},{-22,-50}}, color={0,0,127})); + connect(sam1.y, wseTOut.uTunPar) annotation (Line(points={{2,-50},{20,-50},{20, + 2},{38,2}}, color={0,0,127})); + connect(TOutWetSig.y, wseTOut.TOutWet) annotation (Line(points={{-38,50},{20,50}, + {20,18},{38,18}},color={0,0,127})); + connect(chiWatFlow.y, wseTOut.VChiWat_flow) + annotation (Line(points={{-38,10},{38,10}}, color={0,0,127})); + +annotation ( + experiment(StopTime=2100.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/PredictedOutletTemperature.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.PredictedOutletTemperature. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false))); +end PredictedOutletTemperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/Tuning_uEcoSta_uTowFanSpeMax.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/Tuning_uEcoSta_uTowFanSpeMax.mo new file mode 100644 index 00000000000..7cdcc4079ef --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/Tuning_uEcoSta_uTowFanSpeMax.mo @@ -0,0 +1,197 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Validation; +model Tuning_uEcoSta_uTowFanSpeMax + "Validate water side economizer tuning parameter sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning wseTun + "Tests tuning parameter increase due to a dip in tower fan speed" + annotation (Placement(transformation(extent={{-40,160},{-20,180}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning wseTun1 + "Tests tuning parameter remains constant inspite of a dip in tower fan speed due to the prolonged WSE on status" + annotation (Placement(transformation(extent={{100,160},{120,180}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning wseTun2 + "Tests tuning parameter decrease due to WSE being on for a long time before disable" + annotation (Placement(transformation(extent={{-40,60},{-20,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning wseTun3 + "Tests tuning parameter remains constant despite of a dip in tower fan speed due to the prolonged WSE on status" + annotation (Placement(transformation(extent={{100,40},{120,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning wseTun4 + "Tests anti-windup" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Timer tim + "Timer" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=7e4) "Greater than" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) "Constant" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi "Logical switch" + annotation (Placement(transformation(extent={{60,-90},{80,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta( + final width=0.5, + final period=2*55*60) + "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{-120,200},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowFanSpeSig0( + final k=1) + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation(extent={{-120,140},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowFanSpeSig2( + final k=1) + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation(extent={{-120,40},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowFanSig1( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{20,160},{40,180}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta1( + final width=0.5, + final period=2*16*60) + "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{20,200},{40,220}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin cooTowFanSta1( + final amplitude=0.2, + final offset=1.1, + final freqHz=1/(80*60), + final phase=3.1415926535898) "Cooling tower fan speed status signal" + annotation (Placement(transformation(extent={{20,118},{40,138}}))); + + Buildings.Controls.OBC.CDL.Reals.Min min1 "Minimum" + annotation (Placement(transformation(extent={{60,140},{80,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta2( + final width=0.5, + final period=2*65*60) + "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{-120,100},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta3( + final width=0.5, + final period=2*20*60) + "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{20,80},{40,100}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowFanSpeSig3( + final k=1) + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta4( + final width=0.5, + final period=2*20*60) + "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{20,-120},{40,-100}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowFanSpeSig1( + final k=1) + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation(extent={{20,-180},{40,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ecoSta5( + final width=0.5, + final period=2*65*60) + "Water side economizer enable/disable status" + annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + +equation + connect(ecoSta.y,wseTun.uWseSta) annotation (Line(points={{-98,210},{-70,210}, + {-70,175},{-42,175}}, color={255,0,255})); + connect(maxTowFanSig1.y, min1.u1) annotation (Line(points={{42,170},{50,170},{ + 50,156},{58,156}}, color={0,0,127})); + connect(cooTowFanSta1.y, min1.u2) annotation (Line(points={{42,128},{48,128},{ + 48,144},{58,144}}, color={0,0,127})); + connect(min1.y, wseTun1.uTowFanSpeMax) annotation (Line(points={{82,150},{90,150}, + {90,165},{98,165}}, color={0,0,127})); + connect(ecoSta1.y,wseTun1.uWseSta) annotation (Line(points={{42,210},{70,210}, + {70,175},{98,175}}, color={255,0,255})); + connect(ecoSta2.y,wseTun2.uWseSta) annotation (Line(points={{-98,110},{-70,110}, + {-70,75},{-42,75}}, color={255,0,255})); + connect(maxTowFanSpeSig2.y, wseTun2.uTowFanSpeMax) annotation (Line(points={{-98,50}, + {-70,50},{-70,65},{-42,65}}, color={0,0,127})); + connect(maxTowFanSpeSig0.y, wseTun.uTowFanSpeMax) annotation (Line(points={{-98,150}, + {-70,150},{-70,165},{-42,165}}, color={0,0,127})); + connect(ecoSta3.y,wseTun3.uWseSta) annotation (Line(points={{42,90},{70,90},{ + 70,55},{98,55}}, color={255,0,255})); + connect(wseTun3.uTowFanSpeMax, maxTowFanSpeSig3.y) annotation (Line(points={{98,45}, + {70,45},{70,40},{42,40}}, color={0,0,127})); + connect(maxTowFanSpeSig1.y, wseTun4.uTowFanSpeMax) annotation (Line(points={{42,-170}, + {80,-170},{80,-95},{98,-95}}, color={0,0,127})); + connect(con.y, tim.u) + annotation (Line(points={{-98,-80},{-82,-80}}, color={255,0,255})); + connect(tim.y, greThr1.u) + annotation (Line(points={{-58,-80},{-42,-80}}, color={0,0,127})); + connect(greThr1.y, logSwi.u2) + annotation (Line(points={{-18,-80},{58,-80}}, color={255,0,255})); + connect(ecoSta5.y, logSwi.u1) annotation (Line(points={{42,-50},{50,-50},{50, + -72},{58,-72}}, + color={255,0,255})); + connect(ecoSta4.y, logSwi.u3) annotation (Line(points={{42,-110},{50,-110},{50, + -88},{58,-88}}, color={255,0,255})); + connect(logSwi.y, wseTun4.uWseSta) annotation (Line(points={{82,-80},{90,-80}, + {90,-85},{98,-85}}, color={255,0,255})); +annotation ( + experiment( + StopTime=150000, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/Tuning_uEcoSta_uTowFanSpeMax.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.Tuning. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-140,-240},{140,240}}), + graphics={ + Text( + extent={{-126,6},{-20,-6}}, + textColor={0,0,127}, + textString="Tests tuning parameter decrease +based on WSE enable duration +prior to disable"), + Text( + extent={{-10,14},{154,-18}}, + textColor={0,0,127}, + textString="Tests tuning parameter increase +based on WSE enable duration +prior to disable and cooling tower +fan speed during WSE enable."), + Text( + extent={{-46,-208},{48,-214}}, + textColor={0,0,127}, + textString="Tests anti-windup")})); +end Tuning_uEcoSta_uTowFanSpeMax; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..a831498af37 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/package.order new file mode 100644 index 00000000000..9314cb28bf0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/package.order @@ -0,0 +1,4 @@ +BypassValve +HeatExchangerPump +PredictedOutletTemperature +Tuning_uEcoSta_uTowFanSpeMax diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/package.mo new file mode 100644 index 00000000000..22f19d76e81 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers; +package Subsequences "Waterside economizer control subsequences" + +annotation (preferredView="info", Documentation(info=" +

+This package contains waterside economizer control subsequences. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/package.order new file mode 100644 index 00000000000..51698baf81d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/package.order @@ -0,0 +1,5 @@ +BypassValve +HeatExchangerPump +PredictedOutletTemperature +Tuning +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/Controller.mo new file mode 100644 index 00000000000..7ed73a3306f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/Controller.mo @@ -0,0 +1,315 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Validation; +model Controller + "Validates the waterside economizer enable-disable controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Controller + wseSta(TOutWetDes(displayUnit="degC")) + "Waterside economizer enable status sequence" + annotation (Placement(transformation(extent={{-190,40},{-170,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Controller + wseSta1 "Waterside economizer enable status sequence" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Controller + wseSta2 "Waterside economizer enable status sequence" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Controller + wseSta3( + final have_byPasValCon=false, + TOutWetDes(displayUnit="degC")) + "Waterside economizer enable status sequence" + annotation (Placement(transformation(extent={{240,40},{260,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin dpWSE( + final amplitude=3000, + freqHz=1/3600, + final offset=4500) + "Static pressure difference across chilled water side economizer" + annotation (Placement(transformation(extent={{-260,-80},{-240,-60}}))); + +protected + parameter Real TOutWetBul( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=283.15 + "Average outdoor air wet bulb temperature"; + + parameter Real TChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=293.15 + "Chilled water retun temperature upstream of the WSE"; + + parameter Real TWseOut( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=290.15 + "Chilled water retun temperature downstream of the WSE"; + + parameter Real VChiWat_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.01 + "Measured chilled water return temperature"; + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlow( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{-260,0},{-240,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse TOutWetSig( + final amplitude=5, + final period=2*15*60, + final offset=TOutWetBul) "Measured outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-260,100},{-240,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant constTowFanSig( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{-260,-40},{-240,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRetSig( + final k=TChiWatRet) + "Chilled water return temperature upstream of WSE" + annotation (Placement(transformation(extent={{-260,70},{-240,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRetDow( + final k=TWseOut) + "Chilled water return temperature downstream of WSE" + annotation (Placement(transformation(extent={{-260,40},{-240,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlow1( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{-150,0},{-130,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TOutWetSig1( + final k=TOutWetBul) + "Measured outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-150,100},{-130,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant constTowFanSig1( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{-150,-40},{-130,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRetSig1( + final k=TChiWatRet) + "Chilled water return temperature upstream of WSE" + annotation (Placement(transformation(extent={{-150,70},{-130,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRetDow1( + final offset=TWseOut, + final freqHz=1/1800, + final amplitude=4) + "Chilled water return temperature downstream of WSE" + annotation (Placement(transformation(extent={{-150,40},{-130,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlow2( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{-30,0},{-10,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse TOutWetSig2( + final amplitude=5, + final period=2*15*60, + final offset=TOutWetBul) "Measured outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-30,100},{-10,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant constTowFanSig2( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{-30,-40},{-10,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRetSig2( + final k=TChiWatRet) + "Chilled water return temperature upstream of WSE" + annotation (Placement(transformation(extent={{-30,70},{-10,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRetDow3( + final offset=TWseOut, + final freqHz=1/1800, + final amplitude=4) + "Chilled water return temperature downstream of WSE" + annotation (Placement(transformation(extent={{-30,40},{-10,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) + "Stage 0" + annotation (Placement(transformation(extent={{-300,-20},{-280,0}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=2) + "Stage 0" + annotation (Placement(transformation(extent={{-300,-60},{-280,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) "Enabled plant" + annotation (Placement(transformation(extent={{-300,22},{-280,42}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlow3( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{160,0},{180,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant constTowFanSig3( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{160,-40},{180,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRetSig3( + final k=TChiWatRet) + "Chilled water return temperature upstream of WSE" + annotation (Placement(transformation(extent={{160,70},{180,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRetDow2( + final k=TWseOut) + "Chilled water return temperature downstream of WSE" + annotation (Placement(transformation(extent={{160,40},{180,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TOutWetSig3( + final k=292.15) + "Measured outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{160,100},{180,120}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.1, + final period=3600) "Enabled plant" + annotation (Placement(transformation(extent={{80,20},{100,40}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2( + final k=0) + "Stage 0" + annotation (Placement(transformation(extent={{120,-20},{140,0}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TEntHex( + final height=3, + final duration=3600, + final offset=290.15) + "Return chilled water temperature entering heat exchanger" + annotation (Placement(transformation(extent={{160,-80},{180,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{120,20},{140,40}}))); +equation + connect(constTowFanSig.y, wseSta.uTowFanSpeMax) annotation (Line(points={{-238, + -30},{-200,-30},{-200,52},{-192,52}}, color={0,0,127})); + connect(TOutWetSig.y, wseSta.TOutWet) annotation (Line(points={{-238,110},{-200, + 110},{-200,60},{-192,60}}, color={0,0,127})); + connect(TChiWatRetSig.y, wseSta.TChiWatRet) annotation (Line(points={{-238,80}, + {-220,80},{-220,58},{-192,58}}, color={0,0,127})); + connect(chiWatFlow.y, wseSta.VChiWat_flow) annotation (Line(points={{-238,10}, + {-210,10},{-210,54},{-192,54}}, color={0,0,127})); + connect(TChiWatRetDow.y,wseSta.TChiWatRetDow) + annotation (Line(points={{-238,50},{-230,50},{-230,56},{-192,56}}, color={0,0,127})); + connect(constTowFanSig1.y, wseSta1.uTowFanSpeMax) annotation (Line(points={{-128, + -30},{-90,-30},{-90,52},{-82,52}}, color={0,0,127})); + connect(TOutWetSig1.y, wseSta1.TOutWet) annotation (Line(points={{-128,110},{-90, + 110},{-90,60},{-82,60}}, color={0,0,127})); + connect(TChiWatRetSig1.y, wseSta1.TChiWatRet) annotation (Line(points={{-128,80}, + {-110,80},{-110,58},{-82,58}}, color={0,0,127})); + connect(chiWatFlow1.y, wseSta1.VChiWat_flow) annotation (Line(points={{-128,10}, + {-100,10},{-100,54},{-82,54}}, color={0,0,127})); + connect(TChiWatRetDow1.y,wseSta1.TChiWatRetDow) + annotation (Line(points={{-128,50},{-120,50},{-120,56},{-82,56}}, color={0,0,127})); + connect(constTowFanSig2.y, wseSta2.uTowFanSpeMax) annotation (Line(points={{-8,-30}, + {30,-30},{30,52},{38,52}}, color={0,0,127})); + connect(TOutWetSig2.y,wseSta2. TOutWet) annotation (Line(points={{-8,110},{30, + 110},{30,60},{38,60}}, color={0,0,127})); + connect(TChiWatRetSig2.y,wseSta2. TChiWatRet) annotation (Line(points={{-8,80}, + {10,80},{10,58},{38,58}}, color={0,0,127})); + connect(chiWatFlow2.y,wseSta2. VChiWat_flow) annotation (Line(points={{-8,10}, + {20,10},{20,54},{38,54}}, color={0,0,127})); + connect(wseSta2.TChiWatRetDow, TChiWatRetDow3.y) + annotation (Line(points={{38,56},{0,56},{0,50},{-8,50}}, color={0,0,127})); + connect(con.y, wseSta.uPla) annotation (Line(points={{-278,32},{-220,32},{-220, + 50},{-192,50}}, color={255,0,255})); + connect(con.y, wseSta1.uPla) annotation (Line(points={{-278,32},{-110,32},{-110, + 50},{-82,50}}, color={255,0,255})); + connect(con.y, wseSta2.uPla) annotation (Line(points={{-278,32},{10,32},{10,50}, + {38,50}}, color={255,0,255})); + connect(conInt.y, wseSta.uIni) annotation (Line(points={{-278,-10},{-216,-10}, + {-216,48},{-192,48}}, color={255,127,0})); + connect(conInt.y, wseSta1.uIni) annotation (Line(points={{-278,-10},{-106,-10}, + {-106,48},{-82,48}}, color={255,127,0})); + connect(conInt.y, wseSta2.uIni) annotation (Line(points={{-278,-10},{14,-10},{ + 14,48},{38,48}}, color={255,127,0})); + connect(conInt1.y, wseSta.uChiSta) annotation (Line(points={{-278,-50},{-206,-50}, + {-206,46},{-192,46}}, color={255,127,0})); + connect(conInt1.y, wseSta1.uChiSta) annotation (Line(points={{-278,-50},{-96,-50}, + {-96,46},{-82,46}}, color={255,127,0})); + connect(conInt1.y, wseSta2.uChiSta) annotation (Line(points={{-278,-50},{24,-50}, + {24,46},{38,46}}, color={255,127,0})); + connect(dpWSE.y, wseSta.dpChiWat) annotation (Line(points={{-238,-70},{-226,-70}, + {-226,44},{-192,44}}, color={0,0,127})); + connect(dpWSE.y, wseSta1.dpChiWat) annotation (Line(points={{-238,-70},{-116,-70}, + {-116,44},{-82,44}}, color={0,0,127})); + connect(dpWSE.y, wseSta2.dpChiWat) annotation (Line(points={{-238,-70},{4,-70}, + {4,44},{38,44}}, color={0,0,127})); + connect(TOutWetSig3.y, wseSta3.TOutWet) annotation (Line(points={{182,110},{220, + 110},{220,60},{238,60}}, color={0,0,127})); + connect(TChiWatRetSig3.y, wseSta3.TChiWatRet) annotation (Line(points={{182,80}, + {214,80},{214,58},{238,58}}, color={0,0,127})); + connect(TChiWatRetDow2.y, wseSta3.TChiWatRetDow) annotation (Line(points={{182, + 50},{196,50},{196,56},{238,56}}, color={0,0,127})); + connect(chiWatFlow3.y, wseSta3.VChiWat_flow) annotation (Line(points={{182,10}, + {204,10},{204,54},{238,54}}, color={0,0,127})); + connect(constTowFanSig3.y, wseSta3.uTowFanSpeMax) annotation (Line(points={{182, + -30},{208,-30},{208,52},{238,52}}, color={0,0,127})); + connect(conInt2.y, wseSta3.uIni) annotation (Line(points={{142,-10},{212,-10}, + {212,48},{238,48}}, color={255,127,0})); + connect(booPul.y, not1.u) + annotation (Line(points={{102,30},{118,30}}, color={255,0,255})); + connect(not1.y, wseSta3.uPla) annotation (Line(points={{142,30},{200,30},{200, + 50},{238,50}}, color={255,0,255})); + connect(not1.y, wseSta3.uPum) annotation (Line(points={{142,30},{200,30},{200, + 42},{238,42}}, color={255,0,255})); + connect(TEntHex.y, wseSta3.TEntHex) annotation (Line(points={{182,-70},{220,-70}, + {220,40},{238,40}}, color={0,0,127})); + connect(conInt2.y, wseSta3.uChiSta) annotation (Line(points={{142,-10},{212,-10}, + {212,46},{238,46}}, color={255,127,0})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Controller. +

+", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-320,-140},{320,140}}), + graphics={ + Text( + extent={{-276,-88},{-194,-112}}, + textColor={0,0,127}, + textString="Tests enable conditions +based on the outdoor air +wetbulb temperature"), + Text( + extent={{-166,-84},{-78,-114}}, + textColor={0,0,127}, + textString="Tests disable conditions +based on the chilled water +temperature downstream of WSE"), + Text( + extent={{-34,-88},{40,-108}}, + textColor={0,0,127}, + textString="Combines conditions from +the first two tests"), + Text( + extent={{164,-86},{254,-98}}, + textColor={0,0,127}, + textString="Plant enabled in economizer mode")})); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/package.mo new file mode 100644 index 00000000000..d9a4a2fa203 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.mo new file mode 100644 index 00000000000..9f075b9fe8c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Economizers "Waterside economizer (WSE) sequences" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains waterside economizer (WSE) control sequences. +The implementation is based on section 5.20.3. in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Economizers; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/ControllerTwo.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/ControllerTwo.mo new file mode 100644 index 00000000000..50c5234b7f8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/ControllerTwo.mo @@ -0,0 +1,333 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation; +block ControllerTwo + "Lead/lag or lead/standby equipment rotation controller for two devices or two groups of devices" + + parameter Boolean lag = true + "true = lead/lag; false = lead/standby"; + + parameter Boolean continuous = false + "Continuous lead device operation" + annotation (Evaluate=true, Dialog(enable=not lag)); + + parameter Boolean minLim = false + "Utilize minimum runtime period for a current lead device before rotation may occur" + annotation (Evaluate=true, Dialog(enable=not continuous)); + + parameter Boolean initRoles[nDev] = {true, false} + "Initial roles: true = lead, false = lag/standby" + annotation (Evaluate=true, Dialog(tab="Advanced", group="Initiation")); + + parameter Boolean simTimSta = true + "Measure rotation time from the simulation start" + annotation(Evaluate=true, Dialog(group="Scheduler", enable=continuous)); + + parameter Boolean weeInt = true + "Rotation is scheduled in: true = weekly intervals; false = daily intervals" + annotation(Evaluate=true, Dialog(group="Scheduler", enable=not simTimSta)); + + parameter Real rotationPeriod( + final unit="s", + final quantity="Time", + displayUnit="h") = 1209600 + "Rotation time period measured from simulation start" + annotation(Dialog(group="Scheduler", enable=simTimSta)); + + parameter Real minLeaRuntime( + final unit="s", + final quantity="Time", + displayUnit="h") = 43200 + "Minimum cumulative runtime period for a current lead device before rotation may occur" + annotation (Evaluate=true, Dialog(enable=(not continuous and minLim))); + + parameter Real offset( + final unit="s", + final quantity="Time") = 0 + "Offset that is added to 'time', may be used for computing time in a different time zone" + annotation(Evaluate=true, Dialog(group="Calendar", enable=(continuous and not simTimSta))); + + parameter Buildings.Controls.OBC.CDL.Types.ZeroTime zerTim = Buildings.Controls.OBC.CDL.Types.ZeroTime.NY2019 + "Enumeration for choosing how reference time (time = 0) should be defined" + annotation(Evaluate=true, Dialog(group="Calendar", enable=(continuous and not simTimSta))); + + parameter Integer yearRef(min=firstYear, max=lastYear) = 2019 + "Year when time = 0, used if zerTim=Custom" + annotation(Evaluate=true, Dialog(group="Calendar", enable=zerTim==Buildings.Controls.OBC.CDL.Types.ZeroTime.Custom and continuous)); + + parameter Integer houOfDay = 2 + "Rotation hour of the day: 0 = midnight; 23 = 11pm" + annotation(Evaluate=true, Dialog(group="Scheduler", enable=not simTimSta)); + + parameter Integer weeCou = 1 "Number of weeks" + annotation (Evaluate=true, Dialog(enable=weeInt and not simTimSta, group="Scheduler")); + + parameter Integer weekday = 1 + "Rotation weekday, 1 = Monday, 7 = Sunday" + annotation (Evaluate=true, Dialog(enable=weeInt and not simTimSta, group="Scheduler")); + + parameter Integer dayCou = 1 "Number of days" + annotation (Evaluate=true, Dialog(enable=not weeInt and not simTimSta, group="Scheduler")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaStaSet if not continuous + "Lead device status setpoint" + annotation (Placement(transformation(extent={{-200,-20},{-160,20}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLagStaSet if lag + "Lag device status setpoint" + annotation (Placement(transformation(extent={{-200,-100},{-160,-60}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevSta[nDev] + "Device proven ON status, where each index represents a physical device/group of devices" + annotation (Placement(transformation(extent={{-200,60},{-160,100}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDevStaSet[nDev] + "Device status setpoint, where each index represents a physical device/group of devices" + annotation (Placement(transformation(extent={{160,10},{180,30}}), iconTransformation( + extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDevRol[nDev] + "Device role: true = lead, false = lag or standby" annotation (Placement( + transformation(extent={{160,-30},{180,-10}}), iconTransformation(extent={{100,-80}, + {140,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler + rotSch( + final rotationPeriod=rotationPeriod, + final simTimSta=simTimSta, + final weeInt=weeInt, + final houOfDay=houOfDay, + final weeCou=weeCou, + final weekday=weekday, + final dayCou=dayCou, + final zerTim=zerTim, + final yearRef=yearRef, + final offset=offset) if continuous + "Generates equipment rotation trigger based on a schedule" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.MinimumLeadRuntime + minLeaTim(final minLeaRuntime=minLeaRuntime) if (minLim and not continuous) + "Rotation signal generator with a minimum leading device runtime limiter" + annotation (Placement(transformation(extent={{40,-40},{60,-20}}))); + +protected + final parameter Integer nDev = 2 + "Total number of devices, such as chillers, isolation valves, CW pumps, or CHW pumps"; + + final constant Integer firstYear = 2010 + "First year that is supported, i.e. the first year in timeStampsNewYear[:]" + annotation (Evaluate=true, Dialog(enable=not continuous)); + + final constant Integer lastYear = firstYear + 20 + "Last year that is currently supported" + annotation (Evaluate=true, Dialog(enable=not continuous)); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.LeastRuntime + leaRunTim(final lag=lag) if (not minLim and not continuous) + "Rotation signal generator based on least runtime, at device enable" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.ContinuousLeadSwapTwo + leaSwa if continuous + "Ensures no old lead device is switched off until the new lead device is proven on" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwoCon if continuous + "Based on a rotation trigger sets device roles according to equipment rotation" + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo if not continuous + "Based on a rotation trigger sets device roles according to equipment rotation" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLea( + final nout=nDev) if not continuous "Replicates lead signal" + annotation (Placement(transformation(extent={{-120,-20},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLag( + final nout=nDev) if lag "Replicates lag signal" + annotation (Placement(transformation(extent={{-120,-50},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nDev] if not continuous + "Switch" + annotation (Placement(transformation(extent={{-60,-42},{-40,-22}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staBySta[nDev]( + final k=fill(false, nDev)) if not lag and not continuous "Standby status" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + +equation + connect(logSwi1.u1, repLea.y) annotation (Line(points={{-62,-24},{-80,-24},{-80, + -10},{-98,-10}}, color={255,0,255})); + connect(logSwi1.u3,repLag. y) annotation (Line(points={{-62,-40},{-98,-40}}, + color={255,0,255})); + connect(uLeaStaSet, repLea.u) + annotation (Line(points={{-180,0},{-140,0},{-140,-10},{-122,-10}}, + color={255,0,255})); + connect(uLagStaSet, repLag.u) + annotation (Line(points={{-180,-80},{-140,-80},{-140,-40},{-122,-40}}, + color={255,0,255})); + connect(logSwi1.y, yDevStaSet) annotation (Line(points={{-38,-32},{-30,-32},{-30, + 60},{140,60},{140,20},{170,20}}, color={255,0,255})); + connect(staBySta.y,logSwi1. u3) annotation (Line(points={{-98,-80},{-90,-80},{ + -90,-40},{-62,-40}}, color={255,0,255})); + connect(leaSwa.yDevStaSet, yDevStaSet) annotation (Line(points={{122,30},{140, + 30},{140,20},{170,20}}, + color={255,0,255})); + connect(minLeaTim.yRot, rotTwo.uRot) + annotation (Line(points={{62,-30},{98,-30}}, color={255,0,255})); + connect(rotTwo.yDevRol, yDevRol) annotation (Line(points={{122,-30},{140,-30}, + {140,-20},{170,-20}},color={255,0,255})); + connect(rotTwo.yPreDevRolSig, minLeaTim.uPreDevRolSig) annotation (Line( + points={{122,-36},{140,-36},{140,-60},{20,-60},{20,-38},{38,-38}}, + color={255,0,255})); + connect(rotTwo.yPreDevRolSig, logSwi1.u2) annotation (Line(points={{122,-36},{ + 140,-36},{140,-60},{-80,-60},{-80,-32},{-62,-32}}, color={255,0,255})); + connect(rotSch.yRot, rotTwoCon.uRot) + annotation (Line(points={{22,30},{38,30}}, color={255,0,255})); + connect(uDevSta, leaSwa.uDevSta) annotation (Line(points={{-180,80},{90,80},{90, + 26},{98,26}}, color={255,0,255})); + connect(rotTwoCon.yDevRol, leaSwa.uDevRolSet) annotation (Line(points={{62,30}, + {80,30},{80,34},{98,34}}, + color={255,0,255})); + connect(rotTwoCon.yDevRol, yDevRol) annotation (Line(points={{62,30},{80,30},{ + 80,0},{140,0},{140,-20},{170,-20}}, color={255,0,255})); + connect(uDevSta, minLeaTim.uDevSta) annotation (Line(points={{-180,80},{-20,80}, + {-20,-30},{38,-30}}, color={255,0,255})); + connect(rotTwo.yPreDevRolSig, leaRunTim.uPreDevRolSig) annotation (Line( + points={{122,-36},{140,-36},{140,-94},{30,-94},{30,-88},{38,-88}}, + color={255,0,255})); + connect(uDevSta, leaRunTim.uDevSta) annotation (Line(points={{-180,80},{-20,80}, + {-20,-80},{38,-80}}, color={255,0,255})); + connect(leaRunTim.yRot, rotTwo.uRot) annotation (Line(points={{62,-80},{80,-80}, + {80,-30},{98,-30}}, color={255,0,255})); + +annotation(Diagram(coordinateSystem(extent={{-160,-100},{160,100}})), + defaultComponentName="equRot", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{71,7},{85,-7}}, + lineColor={235,235,235}, + fillColor={235,235,235}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor={235,235,235}, + fillColor={235,235,235}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Ellipse( + origin={-26.6667,38.6207}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={93.3333,-81.3793}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={-26.6667,-81.3793}, + lineColor={128,128,128}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={93.333,38.6207}, + lineColor={128,128,128}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Line(points={{-40,60},{0,60},{0,-60},{40,-60}}, color={128,128,128}), + Line(points={{-40,-60},{0,-60},{0,60},{40,60}}, color={128,128,128})}), + Documentation(info=" +

+This controller block rotates equipment, such as chillers, pumps or valves, in order +to ensure equal wear and tear. It is intended to be used for lead/lag and +lead/standby operation of two devices or groups of devices. The implementation is +based on the specification from ASHRAE Guideline36-2021, section 5.1.15.1.-4. +

+

+The controller takes as inputs the current device proven ON/OFF status vector uDevSta, +lead device status setpoint uLeaStaSet and lag device status setpoint uLagStaSet. +The controller features the following rotation subsequences to generate the device status setpoints yDevStaSet +and device roles yDevRol outputs: +

+ +

+The +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two subsequence allocates +the status setpoints yDevStaSet to devices based on the rotation signal. +

+

+The output vector yDevRol indicates the role of each device, where true +represents a lead role and false represents a lag or a standby role. +

+

+The indices of both output vectors and the uDevSta input vector represent physical devices. +

+

+In addition to the specification in Guideline36, this model allows the user to: +

+ +", revisions=" + +")); +end ControllerTwo; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/ContinuousLeadSwapTwo.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/ContinuousLeadSwapTwo.mo new file mode 100644 index 00000000000..b420c767069 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/ContinuousLeadSwapTwo.mo @@ -0,0 +1,69 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences; +block ContinuousLeadSwapTwo + "Ensures that the previous lead device remains enabled until the new lead device is proven on" + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevRolSet[nDev] + "Device role setpoint: true = lead, false = standby" + annotation (Placement(transformation(extent={{-100,0},{-60,40}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevSta[nDev] + "Device status: true = proven ON; false = proven OFF" + annotation (Placement(transformation(extent={{-100,-40},{-60,0}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDevStaSet[nDev] + "Device status setpoint" + annotation (Placement(transformation(extent={{60,0},{100,40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + final parameter Integer nDev = 2 + "Total number of devices, such as chillers, isolation valves, CW pumps, or CHW pumps"; + + Buildings.Controls.OBC.CDL.Logical.Or or1[nDev] "Logical or" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1[nDev] "Logical not" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + +equation + connect(uDevSta, not1.u) + annotation (Line(points={{-80,-20},{-42,-20}}, color={255,0,255})); + connect(uDevRolSet, or1.u1) + annotation (Line(points={{-80,20},{18,20}},color={255,0,255})); + connect(not1[1].y, or1[2].u2) + annotation (Line(points={{-18,-20},{0,-20},{0,12},{18,12}}, color={255,0,255})); + connect(not1[2].y, or1[1].u2) + annotation (Line(points={{-18,-20},{-10,-20},{-10,12},{18,12}}, color={255,0,255})); + connect(or1.y, yDevStaSet) + annotation (Line(points={{42,20},{80,20}}, color={255,0,255})); + annotation (defaultComponentName="leaSwa", + Icon(graphics={Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Ellipse( extent={{71,7},{85,-7}}, + lineColor={235,235,235}, + fillColor={235,235,235}, + fillPattern=FillPattern.Solid), Ellipse( extent={{-75,-6},{-89,8}}, + lineColor={235,235,235}, + fillColor={235,235,235}, + fillPattern=FillPattern.Solid), Text( extent={{-120,146},{100,108}}, + textColor={0,0,255}, textString="%name")}), + Documentation(info=" +

+This block ensures that the new lead device is started and proven on before the old +lead device is switched to standby and shut off. The implementation is +according to ASHRAE Guideline36-2021, section 5.1.15.4.b. +

+", revisions=" + +"), + Diagram(coordinateSystem(extent={{-60,-40},{60,40}}))); +end ContinuousLeadSwapTwo; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo new file mode 100644 index 00000000000..c5e989eeb1a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo @@ -0,0 +1,175 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences; +block LeastRuntime + "Generates equipment rotation signal at each device enable if that device has a least total runtime" + + parameter Boolean lag = true + "true = lead/lag; false = lead/standby"; + + parameter Boolean initRoles[nDev] = {true, false} + "Initial roles: true = lead, false = lag/standby" + annotation (Evaluate=true, Dialog(tab="Advanced", group="Initiation")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevSta[nDev] + "Device status: true = proven ON, false = proven OFF" + annotation (Placement(transformation(extent={{-200,40},{-160,80}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPreDevRolSig[nDev] + "Device roles in the previous time instance: true = lead; false = lag or standby" + annotation (Placement(transformation(extent={{-200,-60},{-160,-20}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yRot + "Rotation trigger signal" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Logical.TimerAccumulating accTim[nDev] + "Measures time spent loaded at the current role (lead or lag)" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + + CDL.Logical.MultiOr mulOr(nin=nDev) "Multiple or" + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); +protected + final parameter Integer nDev = 2 + "Total number of devices, such as chillers, isolation valves, CW pumps, or CHW pumps"; + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nDev]( + final k=fill(false, nDev)) "Constant" + annotation (Placement(transformation(extent={{-120,20},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Greater longer1 + "Runtime of the first device is longer than runtime of the second device" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + + Buildings.Controls.OBC.CDL.Reals.Greater longer2 + "Runtime of the second device is longer than the runtime of the first device" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 if lag "Logical not" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 if lag "Logical not" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3[nDev] if lag "Logical not" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3[nDev] if lag "Logical not" + annotation (Placement(transformation(extent={{40,10},{60,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg [nDev]( + final pre_u_start=fill(false, nDev)) if lag "Rising edge" + annotation (Placement(transformation(extent={{-120,-20},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1[nDev] if not lag "Logical and" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg [nDev]( + final pre_u_start=fill(false, nDev)) if not lag "Falling edge" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2[nDev] if lag + "Logical and" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + +equation + connect(uDevSta, accTim.u) + annotation (Line(points={{-180,60},{-82,60}}, color={255,0,255})); + connect(accTim[1].y, longer1.u1) + annotation (Line(points={{-58,60},{-42,60}}, color={0,0,127})); + connect(accTim[2].y, longer1.u2) annotation (Line(points={{-58,60},{-50,60},{-50, + 52},{-42,52}}, color={0,0,127})); + connect(accTim[1].y, longer2.u2) annotation (Line(points={{-58,60},{-50,60},{-50, + 22},{-42,22}}, color={0,0,127})); + connect(accTim[2].y, longer2.u1) annotation (Line(points={{-58,60},{-50,60},{-50, + 30},{-42,30}}, color={0,0,127})); + connect(longer2.y, not2.u) + annotation (Line(points={{-18,30},{-2,30}}, color={255,0,255})); + connect(longer1.y, not1.u) + annotation (Line(points={{-18,60},{-2,60}}, color={255,0,255})); + connect(uPreDevRolSig, not3.u) + annotation (Line(points={{-180,-40},{-62,-40}},color={255,0,255})); + connect(edg.y, and3.u2) annotation (Line(points={{-98,-10},{20,-10},{20,12},{38, + 12}}, color={255,0,255})); + connect(not1.y, and3[1].u1) annotation (Line(points={{22,60},{30,60},{30,20},{ + 38,20}}, color={255,0,255})); + connect(not2.y, and3[2].u1) annotation (Line(points={{22,30},{30,30},{30,20},{ + 38,20}}, color={255,0,255})); + connect(longer1.y, and1[1].u1) annotation (Line(points={{-18,60},{-10,60},{-10, + -60},{58,-60}}, color={255,0,255})); + connect(longer2.y, and1[2].u1) annotation (Line(points={{-18,30},{-10,30},{-10, + -60},{58,-60}}, color={255,0,255})); + connect(falEdg.y, and1.u2) annotation (Line(points={{-98,-60},{-60,-60},{-60,-68}, + {58,-68}}, color={255,0,255})); + connect(con.y, accTim.reset) annotation (Line(points={{-98,30},{-90,30},{-90,52}, + {-82,52}}, color={255,0,255})); + connect(uDevSta, falEdg.u) annotation (Line(points={{-180,60},{-140,60},{-140, + -60},{-122,-60}}, color={255,0,255})); + connect(uDevSta, edg.u) annotation (Line(points={{-180,60},{-140,60},{-140,-10}, + {-122,-10}}, color={255,0,255})); + connect(and3.y, and2.u1) + annotation (Line(points={{62,20},{78,20}}, color={255,0,255})); + connect(not3.y, and2.u2) annotation (Line(points={{-38,-40},{70,-40},{70,12},{ + 78,12}}, color={255,0,255})); + connect(and2.y, mulOr.u) annotation (Line(points={{102,20},{110,20},{110,0},{118, + 0}}, color={255,0,255})); + connect(and1.y, mulOr.u) annotation (Line(points={{82,-60},{110,-60},{110,0},{ + 118,0}}, color={255,0,255})); + connect(mulOr.y, yRot) + annotation (Line(points={{142,0},{180,0}}, color={255,0,255})); + + annotation (Diagram(coordinateSystem(extent={{-160,-80},{160,80}})), + defaultComponentName="leaRunTim", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Line(points={{-66,-70},{82,-70}}, + color={192,192,192}), + Line(points={{-58,68},{-58,-80}}, + color={192,192,192}), + Polygon(lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid, + points={{90.0,-70.0},{68.0,-62.0},{68.0,-78.0},{90.0,-70.0}}), + Polygon(lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid, + points={{-58,90},{-66,68},{-50,68},{-58,90}}), + Line(points={{-56,-70},{-38,-70},{-38,-26},{40,-26},{40,-70},{68,-70}}, + color={255,0,255}), + Line(points={{-58,0},{-40,0},{40,90},{40,0},{68,0}}, + color={0,0,127})}), + Documentation(info=" +

+This subsequence generates a rotation trigger signal yRot based on measuring the time each of the devices/groups of devices +has spent in its current role. The rotation trigger output yRot is generated: +

+ +

+The implementation corresponts sections 5.1.15.3. and 5.1.15.4.a. of Guideline36-2021 when applied to +two devices or groups of devices. +

+", revisions=" + +")); +end LeastRuntime; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/MinimumLeadRuntime.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/MinimumLeadRuntime.mo new file mode 100644 index 00000000000..a39e657b5ff --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/MinimumLeadRuntime.mo @@ -0,0 +1,148 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences; +block MinimumLeadRuntime + "Generates equipment rotation signal when a lead device/group of devices exceeds a miminum cumulative runtime" + + parameter Boolean initRoles[nDev] = {true, false} + "Initial roles: true = lead, false = lag/standby" + annotation (Evaluate=true, Dialog(tab="Advanced", group="Initiation")); + + parameter Real minLeaRuntime( + final unit="s", + final quantity="Time", + displayUnit="h") = 864000 + "Minimum cumulative runtime period for a current lead device before rotation may occur"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevSta[nDev] + "Device status: true = proven ON, false = proven OFF" + annotation (Placement(transformation(extent={{-200,40},{-160,80}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPreDevRolSig[nDev] + "Device roles in the previous time instance: true = lead; false = lag or standby" + annotation (Placement(transformation(extent={{-200,-80},{-160,-40}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yRot "Rotation trigger signal" + annotation (Placement(transformation(extent={{160,0},{200,40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Logical.TimerAccumulating accTim[nDev]( + final t=fill(minLeaRuntime, nDev)) + "Measures time spent loaded at the current role (lead or lag)" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + +protected + final parameter Integer nDev = 2 + "Total number of devices, such as chillers, isolation valves, CW pumps, or CHW pumps"; + + final parameter Real minLeaRuntimes[nDev]( + final unit=fill("s",nDev), + final quantity=fill("Time",nDev)) = fill(minLeaRuntime, nDev) + "Staging runtimes array"; + + Buildings.Controls.OBC.CDL.Logical.And and2[nDev] "Logical and" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nDev) "Array or" + annotation (Placement(transformation(extent={{120,10},{140,30}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd allOn( + final nin=nDev) "Outputs true if all devices are enabled" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr anyOn( + final nin=nDev) "Checks if any device is disabled" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Not allOff + "Returns true if all devices are disabled" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nDev) "Booolean replicator" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Or equSig + "Outputs true if either all devices are enabled or all devices are disabled" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg1[nDev] "Falling Edge" + annotation (Placement(transformation(extent={{-140,-70},{-120,-50}}))); + +equation + connect(mulOr.u, and2.y) + annotation (Line(points={{118,20},{102,20}}, color={255,0,255})); + + connect(booRep1.y, and2.u2) + annotation (Line(points={{42,20},{50,20},{50,12},{78,12}}, color={255,0,255})); + connect(anyOn.y, allOff.u) + annotation (Line(points={{-78,-10},{-62,-10}}, color={255,0,255})); + connect(booRep1.u, equSig.y) + annotation (Line(points={{18,20},{2,20}}, color={255,0,255})); + connect(allOff.y, equSig.u2) annotation (Line(points={{-38,-10},{-30,-10},{-30, + 12},{-22,12}}, color={255,0,255})); + connect(allOn.y, equSig.u1) annotation (Line(points={{-38,30},{-30,30},{-30,20}, + {-22,20}},color={255,0,255})); + connect(uDevSta, accTim.u) + annotation (Line(points={{-180,60},{-62,60}}, color={255,0,255})); + connect(uDevSta, allOn.u) annotation (Line(points={{-180,60},{-80,60},{-80, + 30},{-62,30}}, color={255,0,255})); + connect(uDevSta, anyOn.u) annotation (Line(points={{-180,60},{-120,60},{-120, + -10},{-102,-10}}, color={255,0,255})); + connect(mulOr.y, yRot) + annotation (Line(points={{142,20},{180,20}}, color={255,0,255})); + connect(uPreDevRolSig, falEdg1.u) + annotation (Line(points={{-180,-60},{-142,-60}}, color={255,0,255})); + connect(falEdg1.y, accTim.reset) annotation (Line(points={{-118,-60},{-110,-60}, + {-110,52},{-62,52}}, color={255,0,255})); + connect(accTim.passed, and2.u1) annotation (Line(points={{-38,52},{60,52},{60, + 20},{78,20}}, color={255,0,255})); + annotation (Diagram(coordinateSystem(extent={{-160,-80},{160,80}})), + defaultComponentName="minLeaTim", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Line(points={{-66,-70},{82,-70}}, + color={192,192,192}), + Line(points={{-58,68},{-58,-80}}, + color={192,192,192}), + Polygon(lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid, + points={{90.0,-70.0},{68.0,-62.0},{68.0,-78.0},{90.0,-70.0}}), + Polygon(lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid, + points={{-58,90},{-66,68},{-50,68},{-58,90}}), + Line(points={{-56,-70},{-38,-70},{-38,-26},{40,-26},{40,-70},{68,-70}}, + color={255,0,255}), + Line(points={{-58,0},{-40,0},{40,90},{40,0},{68,0}}, + color={0,0,127})}), + Documentation(info=" +

+This subsequence generates a rotation trigger based on measuring time each of the devices enable time. +The rotation trigger output yRot is generated as the current lead device runtime +exceeds minLeaRuntime and the conditions are met such that the devices are not hot swapped. To +avoid hot swapping the lead and lag/standby device need to be either both ON or both OFF for the rotation to occur. +As the rotation trigger output yRot signal is generated, the runtime for the previous lead device +or group of devices is reset to zero. +

+This is an OBC custom implementation. +

+", revisions=" + +")); +end MinimumLeadRuntime; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo new file mode 100644 index 00000000000..7962ab2aed2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo @@ -0,0 +1,249 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences; +block Scheduler + "Equipment rotation signal based on a scheduler for equipment that runs continuously" + + parameter Buildings.Controls.OBC.CDL.Types.ZeroTime zerTim = Buildings.Controls.OBC.CDL.Types.ZeroTime.NY2019 + "Enumeration for choosing how reference time (time = 0) should be defined" + annotation(Dialog(group="Calendar", enable=not simTimSta)); + + parameter Integer yearRef( + final min=firstYear, + final max=lastYear) = 2019 + "Year when time = 0, used if zerTim=Custom" + annotation(Dialog(group="Calendar", enable=zerTim==Buildings.Controls.OBC.CDL.Types.ZeroTime.Custom)); + + parameter Real offset( + final unit="s", + final quantity="Time") = 0 + "Offset that is added to 'time', may be used for computing time in different time zone" + annotation(Dialog(group="Calendar", enable=not simTimSta)); + + parameter Real rotationPeriod( + final unit="s", + final quantity="Time", + displayUnit="h") = 1209600 + "Rotation time period measured from simulation start" + annotation(Dialog(group="Calendar", enable=simTimSta)); + + parameter Real iniRotDel( + final unit="s", + final quantity="Time", + displayUnit="s") = 1 + "Delay before the first rotation measured from simulation start" + annotation(Dialog(group="Calendar", enable=simTimSta)); + + parameter Boolean simTimSta = true + "Measure rotation time from the simulation start"; + + parameter Boolean weeInt = false + "Rotation is scheduled in: true = weekly intervals; false = daily intervals" + annotation (Evaluate=true, Dialog(enable=not simTimSta)); + + parameter Integer houOfDay = 2 "Rotation hour of the day: 0 = midnight; 23 = 11pm" + annotation (Evaluate=true, Dialog(enable=not simTimSta)); + + parameter Integer weeCou = 1 "Number of weeks" + annotation (Evaluate=true, Dialog(enable=weeInt and not simTimSta)); + + parameter Integer weekday = 1 + "Rotation weekday, 1 = Monday, 7 = Sunday" + annotation (Evaluate=true, Dialog(enable=weeInt and not simTimSta)); + + parameter Integer dayCou = 1 "Number of days" + annotation (Evaluate=true, Dialog(enable=not weeInt and not simTimSta)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yRot + "Rotation trigger signal" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.CalendarTime calTim( + final zerTim=zerTim, + final yearRef=yearRef, + final offset=offset) if not simTimSta + "Calendar time" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Integers.OnCounter onCouInt if not simTimSta + "Integer counter" + annotation (Placement(transformation(extent={{0,10},{20,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger rotTri(final period= + rotationPeriod, final shift=0) if simTimSta "Sample trigger" + annotation (Placement(transformation(extent={{-140,-120},{-120,-100}}))); + +protected + final constant Integer firstYear = 2010 + "First year that is supported, i.e. the first year in timeStampsNewYear[:]"; + + final constant Integer lastYear = firstYear + 11 + "Last year that is supported (actual building automation system need to support a larger range)"; + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant houOfDay1( + final k=houOfDay) if not simTimSta + "Hour of the day for rotating devices that run continuously" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant weeDay( + final k=weekday) if (weeInt and not simTimSta) "Weekday for the rotation" + annotation (Placement(transformation(extent={{-140,20},{-120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant weeCou1( + final k=weeCou) if (weeInt and not simTimSta) "Number of weeks for scheduled rotation" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant dayCou1( + final k=dayCou) if (not weeInt and not simTimSta) "Number of days for scheduled rotation" + annotation (Placement(transformation(extent={{-140,-70},{-120,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal isWee if (weeInt and not simTimSta) + "Checks if current weekday is the rotation weekday" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu if not simTimSta + "Checks equality" + annotation (Placement(transformation(extent={{-80,80},{-60,100}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if not simTimSta + "Logical and" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu2 if not simTimSta + "Logical equal" + annotation (Placement(transformation(extent={{40,10},{60,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre if not simTimSta + "Logical pre" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg if not simTimSta + "Rising edge" + annotation (Placement(transformation(extent={{120,10},{140,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant truSig( + final k=true) if (not weeInt and not simTimSta) "True signal" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=iniRotDel) if simTimSta + "Timer" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 if simTimSta + "Logical And" + annotation (Placement(transformation(extent={{20,-120},{40,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) if simTimSta "True constant for the timer" + annotation (Placement(transformation(extent={{-100,-100},{-80,-80}}))); + +equation + connect(dayCou1.y, intEqu2.u2) annotation (Line(points={{-118,-60},{30,-60},{30, + 12},{38,12}}, color={255,127,0})); + connect(calTim.hour, intEqu.u1) annotation (Line(points={{-119,116},{-100,116}, + {-100,90},{-82,90}},color={255,127,0})); + connect(houOfDay1.y, intEqu.u2) annotation (Line(points={{-118,70},{-100,70},{ + -100,82},{-82,82}}, color={255,127,0})); + connect(calTim.weekDay, isWee.u1) annotation (Line(points={{-119,104},{-110,104}, + {-110,40},{-102,40}}, color={255,127,0})); + connect(weeDay.y, isWee.u2) annotation (Line(points={{-118,30},{-110,30},{-110, + 32},{-102,32}}, color={255,127,0})); + connect(intEqu.y, and2.u1) annotation (Line(points={{-58,90},{-50,90},{-50,20}, + {-42,20}},color={255,0,255})); + connect(intEqu2.y, pre.u) + annotation (Line(points={{62,20},{78,20}}, color={255,0,255})); + connect(pre.y, edg.u) + annotation (Line(points={{102,20},{118,20}}, color={255,0,255})); + connect(and2.y, onCouInt.trigger) + annotation (Line(points={{-18,20},{-2,20}},color={255,0,255})); + connect(onCouInt.y, intEqu2.u1) + annotation (Line(points={{22,20},{38,20}}, color={255,127,0})); + connect(pre.y, onCouInt.reset) annotation (Line(points={{102,20},{110,20},{110, + -8},{10,-8},{10,8}},color={255,0,255})); + connect(edg.y, yRot) + annotation (Line(points={{142,20},{150,20},{150,0},{180,0}}, color={255,0,255})); + connect(weeCou1.y, intEqu2.u2) annotation (Line(points={{-118,-20},{30,-20},{30, + 12},{38,12}}, color={255,127,0})); + connect(isWee.y, and2.u2) annotation (Line(points={{-78,40},{-60,40},{-60,12}, + {-42,12}}, color={255,0,255})); + connect(truSig.y, and2.u2) annotation (Line(points={{-78,10},{-60,10},{-60,12}, + {-42,12}}, color={255,0,255})); + connect(rotTri.y, and1.u2) annotation (Line(points={{-118,-110},{-70,-110},{-70, + -118},{18,-118}}, color={255,0,255})); + connect(and1.y, yRot) annotation (Line(points={{42,-110},{150,-110},{150,0},{180, + 0}}, color={255,0,255})); + connect(con.y, tim.u) + annotation (Line(points={{-78,-90},{-62,-90}}, color={255,0,255})); + connect(tim.passed, and1.u1) annotation (Line(points={{-38,-98},{0,-98},{0, + -110},{18,-110}}, color={255,0,255})); + annotation (Diagram(coordinateSystem(extent={{-160,-140},{160,140}})), + defaultComponentName="rotSch", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{71,7},{85,-7}}, + lineColor=DynamicSelect({235,235,235}, if yRot then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if yRot then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor={235,235,235}, + fillColor={235,235,235}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Ellipse( + extent={{-52,56},{58,-54}}, + lineColor={160,160,164}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid), + Line( + points={{4,0},{-20,24}}, + thickness=0.5), + Line( + points={{4,0},{30,0}}, + thickness=0.5)}), + Documentation(info=" +

+This block outputs generates a rotation trigger at +chosen time intervals for lead/standby configurations where a lead device runs continuously. +The implementation is based on Guideline36-2021 5.1.15.4.b, except 5.1.15.4.b 1. +

+

+The user may chose to start counting time from simulation start to generate the +rotation signal at regular intervals rotationPeriod by setting a +flag sinTimSta to true, or to use a calendar. +

+

+If a calender is used the user needs to select the time of the day as an hour between 0 and 23 at which the rotation shall occur. +Hour 0 is midnight. +The block implements two options to select the time interval for the equipment rotation: +

+ +

+To enable weekly intervals set the weeInt to true, otherwise a number of days can be used. +

+", revisions=" + +")); +end Scheduler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Two.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Two.mo new file mode 100644 index 00000000000..aa373381d96 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Two.mo @@ -0,0 +1,115 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences; +block Two + "Updates device roles based on the equipment rotation signal" + + parameter Boolean initRoles[nDev] = {true, false} + "Initial roles: true = lead, false = lag/standby" + annotation (Evaluate=true,Dialog(tab="Advanced", group="Initiation")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uRot + "Rising edge to rotate the equipment" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDevRol[nDev] + "Device role: true = lead, false = lag or standby" + annotation (Placement( + transformation(extent={{100,10},{120,30}}), iconTransformation(extent={{100,-20}, + {140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPreDevRolSig[nDev] + "Device roles in the previous time instance: true = lead; false = lag or standby" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + final parameter Integer nDev = 2 + "Total number of devices, such as chillers, isolation valves, CW pumps, or CHW pumps"; + + Buildings.Controls.OBC.CDL.Logical.Not not0[nDev] "Logical not" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nDev] "Switch" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre[nDev]( + final pre_u_start=initRoles) "Previous timestep" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nDev) "Signal replicator" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + +equation + connect(logSwi.u1,not0. y) annotation (Line(points={{-2,8},{-30,8},{-30,-10},{ + -38,-10}}, color={255,0,255})); + connect(logSwi.y,pre. u) annotation (Line(points={{22,0},{30,0},{30,-20},{38,-20}}, + color={255,0,255})); + connect(pre.y,not0. u) annotation (Line(points={{62,-20},{80,-20},{80,-40},{-70, + -40},{-70,-10},{-62,-10}}, color={255,0,255})); + connect(pre.y,logSwi. u3) annotation (Line(points={{62,-20},{72,-20},{72,-34}, + {-14,-34},{-14,-8},{-2,-8}}, color={255,0,255})); + connect(logSwi.y, yDevRol) annotation (Line(points={{22,0},{66,0},{66,20},{110, + 20}}, color={255,0,255})); + connect(uRot, booRep.u) + annotation (Line(points={{-120,0},{-80,0},{-80,30},{-62,30}},color={255,0,255})); + connect(booRep.y, logSwi.u2) annotation (Line(points={{-38,30},{-20,30},{-20,0}, + {-2,0}}, color={255,0,255})); + connect(pre.y, yPreDevRolSig) annotation (Line(points={{62,-20},{110,-20}}, + color={255,0,255})); + annotation (Diagram(coordinateSystem(extent={{-100,-60},{100,60}})), + defaultComponentName="rotTwo", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Line(points={{-40,60},{0,60},{0,-60},{40,-60}}, color={128,128,128}), + Ellipse( + origin={-26.6667,38.6207}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={93.333,38.6207}, + lineColor={128,128,128}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={93.3333,-81.3793}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={-26.6667,-81.3793}, + lineColor={128,128,128}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Line(points={{-40,-60},{0,-60},{0,60},{40,60}}, color={128,128,128})}), + Documentation(info=" +

+This subsequence takes a rotation trigger signal uRot as input to +rotate the device roles for two devices or groups of devices. It outputs the current device roles yDevRol +vector and its previous time instance value yPreDevRolSig, which is used +as an input signal to any upstream subsequences in the + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo. +

+", revisions=" + +")); +end Two; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mo new file mode 100644 index 00000000000..e2c90186e18 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mo @@ -0,0 +1,177 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model ContinuousLeadSwapTwo_uDevSta + "Validation sequence for lead device swap at continuous lead operation" + + parameter Real aveTWetBul( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Chilled water supply set temperature"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.ContinuousLeadSwapTwo leaSwa + "Makes sure the new lead device is proven on before passing on the lead role" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.ContinuousLeadSwapTwo leaSwa1 + "A way to switch two signals and invert their values" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.ContinuousLeadSwapTwo leaSwa2 + "Makes sure the new lead device is proven on before passing on the lead role" + annotation (Placement(transformation(extent={{180,40},{200,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.ContinuousLeadSwapTwo leaSwa3 + "Makes sure the new lead device is proven on before passing on the lead role" + annotation (Placement(transformation(extent={{180,-80},{200,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.5, + final period=10) "Pulse signal" + annotation (Placement(transformation(extent={{-200,80},{-180,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.5, + final period=15, + final shift=0) "Pulse signal" + annotation (Placement(transformation(extent={{-200,20},{-180,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.5, + final period=10) "Pulse signal" + annotation (Placement(transformation(extent={{-200,-20},{-180,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul4( + final width=0.5, + final period=11) "Pulse signal" + annotation (Placement(transformation(extent={{20,80},{40,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul5( + final width=0.5, + final period=7, + final shift=0) "Pulse signal" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul6( + final width=0.5, + final period=10) "Pulse signal" + annotation (Placement(transformation(extent={{20,-40},{40,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul7( + final width=0.5, + final period=10, + final shift=1) "Pulse signal" + annotation (Placement(transformation(extent={{20,-100},{40,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 "Not" + annotation (Placement(transformation(extent={{-160,60},{-140,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 "Not" + annotation (Placement(transformation(extent={{-160,20},{-140,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4 "Not" + annotation (Placement(transformation(extent={{-160,-40},{-140,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not5 "Not" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not6 "Not" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not7 "Not" + annotation (Placement(transformation(extent={{60,-100},{80,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not8 "Not" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=0, + final falseHoldDuration=6) "Holds false signal" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=0, + final falseHoldDuration=6) "Holds false signal" + annotation (Placement(transformation(extent={{-100,-100},{-80,-80}}))); + +equation + connect(booPul.y, not1.u) annotation ( + Line(points={{-178,90},{-170,90},{-170,70},{-162,70}}, color={255,0,255})); + connect(booPul.y,leaSwa. uDevSta[1]) annotation ( + Line(points={{-178,90},{-90,90},{-90,46},{-42,46}}, color={255,0,255})); + connect(booPul1.y, not2.u) + annotation (Line(points={{-178,30},{-162,30}},color={255,0,255})); + connect(not2.y,leaSwa. uDevSta[2]) annotation ( + Line(points={{-138,30},{-120,30},{-120,46},{-42,46}},color={255,0,255})); + + connect(booPul.y, leaSwa.uDevRolSet[1]) annotation (Line(points={{-178,90},{-60, + 90},{-60,54},{-42,54}}, color={255,0,255})); + connect(not1.y, leaSwa.uDevRolSet[2]) annotation (Line(points={{-138,70},{-60, + 70},{-60,54},{-42,54}}, color={255,0,255})); + connect(booPul2.y, not4.u) annotation (Line(points={{-178,-10},{-170,-10},{-170, + -30},{-162,-30}}, color={255,0,255})); + connect(booPul4.y, not6.u) annotation (Line(points={{42,90},{50,90},{50,70},{58, + 70}}, color={255,0,255})); + connect(booPul4.y, leaSwa2.uDevSta[1]) annotation (Line(points={{42,90},{130,90}, + {130,46},{178,46}}, color={255,0,255})); + connect(booPul5.y,not5. u) + annotation (Line(points={{42,30},{58,30}}, color={255,0,255})); + connect(not5.y, leaSwa2.uDevSta[2]) annotation (Line(points={{82,30},{100,30}, + {100,46},{178,46}}, color={255,0,255})); + connect(booPul4.y, leaSwa2.uDevRolSet[1]) annotation (Line(points={{42,90},{160, + 90},{160,54},{178,54}}, color={255,0,255})); + connect(not6.y, leaSwa2.uDevRolSet[2]) annotation (Line(points={{82,70},{160,70}, + {160,54},{178,54}}, color={255,0,255})); + connect(booPul6.y,not8. u) annotation (Line(points={{42,-30},{50,-30},{50,-50}, + {58,-50}}, color={255,0,255})); + connect(booPul6.y,leaSwa3. uDevSta[1]) annotation (Line(points={{42,-30},{130, + -30},{130,-74},{178,-74}}, color={255,0,255})); + connect(booPul7.y,not7. u) + annotation (Line(points={{42,-90},{58,-90}}, color={255,0,255})); + connect(not7.y,leaSwa3. uDevSta[2]) annotation (Line(points={{82,-90},{100,-90}, + {100,-74},{178,-74}}, color={255,0,255})); + connect(booPul6.y,leaSwa3. uDevRolSet[1]) annotation (Line(points={{42,-30},{160, + -30},{160,-66},{178,-66}}, color={255,0,255})); + connect(not8.y,leaSwa3. uDevRolSet[2]) annotation (Line(points={{82,-50},{160, + -50},{160,-66},{178,-66}}, color={255,0,255})); + connect(booPul2.y, truFalHol.u) annotation (Line(points={{-178,-10},{-120,-10}, + {-120,-50},{-102,-50}}, color={255,0,255})); + connect(not4.y, truFalHol1.u) annotation (Line(points={{-138,-30},{-130,-30},{ + -130,-90},{-102,-90}}, color={255,0,255})); + connect(truFalHol.y, leaSwa1.uDevSta[1]) annotation (Line(points={{-78,-50},{-60, + -50},{-60,-24},{-42,-24}}, color={255,0,255})); + connect(truFalHol1.y, leaSwa1.uDevSta[2]) annotation (Line(points={{-78,-90},{ + -60,-90},{-60,-24},{-42,-24}}, color={255,0,255})); + connect(booPul2.y, leaSwa1.uDevRolSet[1]) annotation (Line(points={{-178,-10}, + {-60,-10},{-60,-16},{-42,-16}}, color={255,0,255})); + connect(not4.y, leaSwa1.uDevRolSet[2]) annotation (Line(points={{-138,-30},{-110, + -30},{-110,-16},{-42,-16}}, color={255,0,255})); +annotation ( + experiment(StopTime=180, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.ContinuousLeadSwapTwo. +

+", revisions=" + +"), + Icon(graphics={Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-220,-120},{220,120}}))); +end ContinuousLeadSwapTwo_uDevSta; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mo new file mode 100644 index 00000000000..5dc24677abc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mo @@ -0,0 +1,154 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model LeastRuntime_uDevRol + "Validate lead/lag and lead/standby switching signal based on least device runtime" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.LeastRuntime + leaRunTim(final lag=true) + "Equipment rotation signal based on device runtime and current device status" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.LeastRuntime + leaRunTim1(final lag=false) + "Equipment rotation signal based on device runtime and current device status" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.LeastRuntime + leaRunTim2(final lag=true) + "Equipment rotation signal based on device runtime and current device status" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo "Updates device roles based on the equipment rotation signal" + annotation (Placement(transformation(extent={{80,40},{100,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo1 "Updates device roles based on the equipment rotation signal" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo2 "Updates device roles based on the equipment rotation signal" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + +protected + parameter Boolean initRoles[2] = {true, false} + "Sets initial roles: true = lead, false = lag or standby"; + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[2] "Switch" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[2] "Switch" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[2] "Switch" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staSta[2]( + final k=fill(false, 2)) "Standby status" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLag1(final nout=2) + "Replicates lag signal" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLag(final nout=2) + "Replicates lag signal" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLead(final nout=2) + "Replicates lead signal" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leadLoad( + final width=0.8, + final period=7200) "Lead device enable status" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad( + final width=0.2, final period=3600) "Lag device enable status" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad1( + final width=0.2, final period=5400) "Lag device enable status" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + +equation + connect(leadLoad.y, repLead.u) annotation (Line(points={{-78,80},{-70,80},{-70, + 70},{-62,70}}, color={255,0,255})); + connect(lagLoad.y, repLag.u) annotation (Line(points={{-78,30},{-70,30},{-70,40}, + {-62,40}}, color={255,0,255})); + connect(repLead.y, logSwi.u1) annotation (Line(points={{-38,70},{-20,70},{-20, + 58},{-2,58}},color={255,0,255})); + connect(repLag.y, logSwi.u3) annotation (Line(points={{-38,40},{-10,40},{-10,42}, + {-2,42}}, color={255,0,255})); + connect(logSwi.y,leaRunTim. uDevSta) + annotation (Line(points={{22,50},{38,50}}, color={255,0,255})); + connect(logSwi1.y,leaRunTim1. uDevSta) + annotation (Line(points={{22,0},{38,0}}, color={255,0,255})); + connect(staSta.y,logSwi1. u3) annotation (Line(points={{-78,-10},{-40,-10},{-40, + -8},{-2,-8}}, color={255,0,255})); + connect(repLead.y,logSwi1. u1) annotation (Line(points={{-38,70},{-30,70},{-30, + 8},{-2,8}}, color={255,0,255})); + connect(lagLoad1.y, repLag1.u) + annotation (Line(points={{-78,-70},{-62,-70}}, color={255,0,255})); + connect(repLead.y,logSwi2. u1) annotation (Line(points={{-38,70},{-30,70},{-30, + -42},{-2,-42}}, color={255,0,255})); + connect(repLag1.y,logSwi2. u3) annotation (Line(points={{-38,-70},{-30,-70},{-30, + -58},{-2,-58}}, color={255,0,255})); + connect(logSwi2.y,leaRunTim2. uDevSta) + annotation (Line(points={{22,-50},{38,-50}}, color={255,0,255})); + connect(leaRunTim.yRot, rotTwo.uRot) + annotation (Line(points={{62,50},{78,50}}, color={255,0,255})); + connect(rotTwo.yPreDevRolSig,leaRunTim. uPreDevRolSig) annotation (Line(points={{102,44}, + {108,44},{108,30},{30,30},{30,42},{38,42}}, color={255,0,255})); + connect(rotTwo.yPreDevRolSig, logSwi.u2) annotation (Line(points={{102,44},{108, + 44},{108,30},{-20,30},{-20,50},{-2,50}}, color={255,0,255})); + connect(leaRunTim1.yRot, rotTwo1.uRot) + annotation (Line(points={{62,0},{78,0}}, color={255,0,255})); + connect(leaRunTim2.yRot, rotTwo2.uRot) + annotation (Line(points={{62,-50},{78,-50}}, color={255,0,255})); + connect(rotTwo2.yPreDevRolSig,leaRunTim2. uPreDevRolSig) annotation (Line(points={{102,-56}, + {110,-56},{110,-70},{30,-70},{30,-58},{38,-58}}, color={255, + 0,255})); + connect(rotTwo2.yPreDevRolSig, logSwi2.u2) annotation (Line(points={{102,-56}, + {110,-56},{110,-70},{-20,-70},{-20,-50},{-2,-50}}, color={255,0,255})); + connect(rotTwo1.yPreDevRolSig,leaRunTim1. uPreDevRolSig) annotation (Line(points={{102,-6}, + {110,-6},{110,-20},{30,-20},{30,-8},{38,-8}}, color={255,0, + 255})); + connect(rotTwo1.yPreDevRolSig, logSwi1.u2) annotation (Line(points={{102,-6},{ + 110,-6},{110,-20},{-20,-20},{-20,0},{-2,0}}, color={255,0,255})); + annotation ( + experiment(StopTime=100000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.LeastRuntime. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}}), + graphics={Text( + extent={{-52,-104},{46,-114}}, + textColor={0,0,127}, + textString="For simplicity this test assumes +the device ON/OFF status equals its setpoint +(there is no delay in starting or stopping devices).")})); +end LeastRuntime_uDevRol; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mo new file mode 100644 index 00000000000..d06d037dd71 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mo @@ -0,0 +1,155 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model MinimumLeadRuntime_uDevRol + "Validate lead/lag and lead/standby switching signal based on device runtime" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.MinimumLeadRuntime + minLeaTim(final minLeaRuntime=43200) + "Equipment rotation signal based on device runtime and current device status" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.MinimumLeadRuntime + minLeaTim1(final minLeaRuntime=18000) + "Equipment rotation signal based on device runtime and current device status" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.MinimumLeadRuntime + minLeaTim2(final minLeaRuntime=14400) + "Equipment rotation signal based on device runtime and current device status" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo "Updates device roles based on the equipment rotation signal" + annotation (Placement(transformation(extent={{80,40},{100,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo1 "Updates device roles based on the equipment rotation signal" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two + rotTwo2 "Updates device roles based on the equipment rotation signal" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + +protected + parameter Boolean initRoles[2] = {true, false} + "Sets initial roles: true = lead, false = lag or standby"; + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[2] "Switch" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[2] "Switch" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[2] "Switch" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staSta[2]( + final k=fill(false, 2)) "Standby status" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLag1(final nout=2) + "Replicates lag signal" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLag(final nout=2) + "Replicates lag signal" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repLead(final nout=2) + "Replicates lead signal" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leadLoad( + final width=0.8, + final period=7200) "Lead device enable status" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad( + final width=0.2, final period=3600) "Lag device enable status" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad1( + final width=0.2, final period=5400) "Lag device enable status" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + +equation + connect(leadLoad.y, repLead.u) annotation (Line(points={{-78,80},{-70,80},{-70, + 70},{-62,70}}, color={255,0,255})); + connect(lagLoad.y, repLag.u) annotation (Line(points={{-78,30},{-70,30},{-70,40}, + {-62,40}}, color={255,0,255})); + connect(repLead.y, logSwi.u1) annotation (Line(points={{-38,70},{-20,70},{-20, + 58},{-2,58}},color={255,0,255})); + connect(repLag.y, logSwi.u3) annotation (Line(points={{-38,40},{-10,40},{-10,42}, + {-2,42}}, color={255,0,255})); + connect(logSwi.y, minLeaTim.uDevSta) + annotation (Line(points={{22,50},{38,50}}, color={255,0,255})); + connect(logSwi1.y, minLeaTim1.uDevSta) + annotation (Line(points={{22,0},{38,0}}, color={255,0,255})); + connect(staSta.y,logSwi1. u3) annotation (Line(points={{-78,-10},{-40,-10},{-40, + -8},{-2,-8}}, color={255,0,255})); + connect(repLead.y,logSwi1. u1) annotation (Line(points={{-38,70},{-30,70},{-30, + 8},{-2,8}}, color={255,0,255})); + connect(lagLoad1.y, repLag1.u) + annotation (Line(points={{-78,-70},{-62,-70}}, color={255,0,255})); + connect(repLead.y,logSwi2. u1) annotation (Line(points={{-38,70},{-30,70},{-30, + -42},{-2,-42}}, color={255,0,255})); + connect(repLag1.y,logSwi2. u3) annotation (Line(points={{-38,-70},{-30,-70},{-30, + -58},{-2,-58}}, color={255,0,255})); + connect(logSwi2.y, minLeaTim2.uDevSta) + annotation (Line(points={{22,-50},{38,-50}}, color={255,0,255})); + connect(minLeaTim.yRot, rotTwo.uRot) + annotation (Line(points={{62,50},{78,50}}, color={255,0,255})); + connect(rotTwo.yPreDevRolSig, minLeaTim.uPreDevRolSig) annotation (Line(points={{102,44}, + {108,44},{108,30},{30,30},{30,42},{38,42}}, color={255,0,255})); + connect(rotTwo.yPreDevRolSig, logSwi.u2) annotation (Line(points={{102,44},{108, + 44},{108,30},{-20,30},{-20,50},{-2,50}}, color={255,0,255})); + connect(minLeaTim1.yRot, rotTwo1.uRot) + annotation (Line(points={{62,0},{78,0}}, color={255,0,255})); + connect(minLeaTim2.yRot, rotTwo2.uRot) + annotation (Line(points={{62,-50},{78,-50}}, color={255,0,255})); + connect(rotTwo2.yPreDevRolSig, minLeaTim2.uPreDevRolSig) annotation (Line(points={{102,-56}, + {110,-56},{110,-70},{30,-70},{30,-58},{38,-58}}, color={255, + 0,255})); + connect(rotTwo2.yPreDevRolSig, logSwi2.u2) annotation (Line(points={{102,-56}, + {110,-56},{110,-70},{-20,-70},{-20,-50},{-2,-50}}, color={255,0,255})); + connect(rotTwo1.yPreDevRolSig, minLeaTim1.uPreDevRolSig) annotation (Line(points={{102,-6}, + {110,-6},{110,-20},{30,-20},{30,-8},{38,-8}}, color={255,0, + 255})); + connect(rotTwo1.yPreDevRolSig, logSwi1.u2) annotation (Line(points={{102,-6},{ + 110,-6},{110,-20},{-20,-20},{-20,0},{-2,0}}, color={255,0,255})); + +annotation ( + experiment(StopTime=100000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.MinimumLeadRuntime. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}}), + graphics={Text( + extent={{-52,-104},{46,-114}}, + textColor={0,0,127}, + textString="For simplicity this test assumes +the device ON/OFF status equals its setpoint +(there is no delay in starting or stopping devices).")})); +end MinimumLeadRuntime_uDevRol; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mo new file mode 100644 index 00000000000..0dd09b843e5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mo @@ -0,0 +1,118 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model Scheduler + "Validation sequence for the device swap scheduler in case of continuous lead device operation" + + parameter Real aveTWetBul( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Chilled water supply set temperature"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler + rotSch( + final simTimSta=false, + final weeInt=false, + final dayCou=10) "Equipment rotation happens every 10 days at 2am" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler + rotSch1( + final simTimSta=false, + weeInt=true, + final weeCou=2, + final weekday=2) "Equipment rotation happens bi-weekly on Tuesday at 2am" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler + rotSch2( + final weeInt=false, + final houOfDay=5, + final dayCou=6) "Equipment rotation happens every 5 days at 6am" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler + rotSch3( + final simTimSta=false, + final weeInt=true, + final houOfDay=12, + final weeCou=4, + final weekday=6) "Equipment rotation happens every 4 weeks on Saturday at noon" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler + rotSch4( + final rotationPeriod=86400, + simTimSta=true, + final weeInt=true, + final houOfDay=12, + final weeCou=4, + final weekday=6) "Equipment rotation happens every 4 weeks on Saturday at noon" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=1800, + final falseHoldDuration=0) "Holds the signal for visualization purposes" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=1800, + final falseHoldDuration=0) "Holds the signal for visualization purposes" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol2( + final trueHoldDuration=1800, + final falseHoldDuration=0) "Holds the signal for visualization purposes" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol3( + final trueHoldDuration=1800, + final falseHoldDuration=0) "Holds the signal for visualization purposes" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol4( + final trueHoldDuration=1800, + final falseHoldDuration=0) + "Holds the signal for visualization purposes" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + +equation + connect(rotSch.yRot, truFalHol.u) + annotation (Line(points={{-18,80},{18,80}}, color={255,0,255})); + connect(rotSch1.yRot, truFalHol1.u) + annotation (Line(points={{-18,40},{18,40}},color={255,0,255})); + connect(rotSch2.yRot, truFalHol2.u) + annotation (Line(points={{-18,0},{18,0}}, color={255,0,255})); + connect(rotSch3.yRot, truFalHol3.u) + annotation (Line(points={{-18,-40},{18,-40}},color={255,0,255})); + connect(rotSch4.yRot,truFalHol4. u) + annotation (Line(points={{-18,-80},{18,-80}},color={255,0,255})); +annotation ( + experiment(StopTime=3000000, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Scheduler. +

+", revisions=" + +"), + Icon(coordinateSystem(extent={{-60,-100},{60,100}}), + graphics={Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-60,-100},{60,100}}))); +end Scheduler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mo new file mode 100644 index 00000000000..6cbd27d72af --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mo @@ -0,0 +1,55 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model Two_uRot + "Validation sequence for device role rotation for two devices or groups of devices" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two rotTwo + "Rotates roles between two devices or groups of devices" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two rotTwo1 + "Rotates roles between two devices or groups of devices" + annotation (Placement(transformation(extent={{20,-40},{40,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger rotation(period( + displayUnit="h") = 86400, shift=7200) "Rotation trigger" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger rotation1(period( + displayUnit="h") = 172800, shift=7200) "Rotation trigger" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + +equation + connect(rotation.y, rotTwo.uRot) + annotation (Line(points={{-18,30},{18,30}}, color={255,0,255})); + connect(rotation1.y, rotTwo1.uRot) + annotation (Line(points={{-18,-30},{18,-30}}, color={255,0,255})); +annotation ( + experiment(StopTime=1000000, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences.Two. +

+", revisions=" + +"), + Icon(graphics={Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-60,-60},{60,60}}))); +end Two_uRot; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..0b3887a2463 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.order new file mode 100644 index 00000000000..7b775d54c4e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.order @@ -0,0 +1,5 @@ +ContinuousLeadSwapTwo_uDevSta +LeastRuntime_uDevRol +MinimumLeadRuntime_uDevRol +Scheduler +Two_uRot diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/package.mo new file mode 100644 index 00000000000..fa2dc10860c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation; +package Subsequences "Equipment rotation control subsequences" + +annotation (preferredView="info", Documentation(info=" +

+This package contains equipment staging and rotation control subsequences. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/package.order new file mode 100644 index 00000000000..8a7466fd0ea --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/package.order @@ -0,0 +1,6 @@ +ContinuousLeadSwapTwo +LeastRuntime +MinimumLeadRuntime +Scheduler +Two +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mo new file mode 100644 index 00000000000..60a6c2d6f7c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mo @@ -0,0 +1,155 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Validation; +model ControllerTwo + "Validates lead/lag and lead/standby equipment rotation controller for two devices or groups of devices" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + leaLag( + final lag=true, + final minLim=false) "Lead/lag rotation" + annotation (Placement(transformation(extent={{-20,80},{0,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + leaLag1( + final lag=true, + final minLim=false) "Lead/lag rotation" + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + leaSta( + final lag=false, + final minLim=false) "Lead/lag rotation" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + conLeaSimSta( + final lag=false, + final continuous=true, + final weeInt=false, + final rotationPeriod=1800, + final houOfDay=2, + final weeCou=1, + final weekday=6, + final dayCou=3) + "Lead/standby rotation for continuously operating device. Rotation time is measured from simulation start" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + conLeaSch( + final lag=false, + final continuous=true, + final minLim=false, + final simTimSta=false, + weeInt=false, + zerTim=Buildings.Controls.OBC.CDL.Types.ZeroTime.Custom, + yearRef=2020, + houOfDay=2, + weekday=3, + dayCou=1) + "Lead/standby rotation for continuous operation" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1[2](final delayTime={300, + 400}, + final delayOnInit={true,true}) + "Emulates device start-up time" + annotation (Placement(transformation(extent={{20,-40},{40,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel[2]( + final delayTime={600,600}, + final delayOnInit={true,true}) "Emulates device start-up time" + annotation (Placement(transformation(extent={{20,0},{40,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre[2] "Boolean pre" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] "Boolean pre" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leadLoad( + final width=0.8, final period(displayUnit="s") = 7200) + "Lead device ON/OFF status" + annotation (Placement(transformation(extent={{-100,80},{-80,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad( + final width=0.2, + final period=3600) "Lag device ON/OFF status" + annotation (Placement(transformation(extent={{-100,40},{-80,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad1( + final width=0.2, + final period=5400) "Lag device ON/OFF status" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2[2]( + final delayTime={600,600}, + final delayOnInit={true,true}) + "Emulates device start-up time" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2[2] "Boolean pre" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + +equation + connect(conLeaSimSta.yDevStaSet, truDel1.u) annotation (Line(points={{2,-24},{ + 10,-24},{10,-30},{18,-30}}, color={255,0,255})); + connect(leadLoad.y, leaLag.uLeaStaSet) annotation (Line(points={{-78,90},{-50, + 90},{-50,96},{-22,96}}, color={255,0,255})); + connect(lagLoad.y, leaLag.uLagStaSet) annotation (Line(points={{-78,50},{-40,50}, + {-40,90},{-22,90}}, color={255,0,255})); + connect(leadLoad.y, leaSta.uLeaStaSet) annotation (Line(points={{-78,90},{-70, + 90},{-70,16},{-22,16}}, color={255,0,255})); + connect(lagLoad1.y, leaLag1.uLagStaSet) annotation (Line(points={{-78,10},{-32, + 10},{-32,50},{-22,50}}, color={255,0,255})); + connect(leadLoad.y, leaLag1.uLeaStaSet) annotation (Line(points={{-78,90},{-50, + 90},{-50,56},{-22,56}}, color={255,0,255})); + connect(leaSta.yDevStaSet, truDel.u) annotation (Line(points={{2,16},{10,16},{ + 10,10},{18,10}}, color={255,0,255})); + connect(leaLag.yDevStaSet, leaLag.uDevSta) annotation (Line(points={{2,96},{20, + 96},{20,70},{-30,70},{-30,84},{-22,84}}, color={255,0,255})); + connect(leaLag1.yDevStaSet, leaLag1.uDevSta) annotation (Line(points={{2,56},{ + 20,56},{20,32},{-28,32},{-28,44},{-22,44}}, color={255,0,255})); + connect(truDel1.y, pre.u) + annotation (Line(points={{42,-30},{58,-30}}, color={255,0,255})); + connect(pre.y, conLeaSimSta.uDevSta) annotation (Line(points={{82,-30},{90,-30}, + {90,-50},{-30,-50},{-30,-36},{-22,-36}}, color={255,0,255})); + connect(truDel.y, pre1.u) + annotation (Line(points={{42,10},{58,10}}, color={255,0,255})); + connect(pre1.y, leaSta.uDevSta) annotation (Line(points={{82,10},{90,10},{90,-10}, + {-28,-10},{-28,4},{-22,4}}, color={255,0,255})); + connect(conLeaSch.yDevStaSet, truDel2.u) annotation (Line(points={{2,-64},{10, + -64},{10,-70},{18,-70}}, color={255,0,255})); + connect(truDel2.y, pre2.u) + annotation (Line(points={{42,-70},{58,-70}}, color={255,0,255})); + connect(pre2.y, conLeaSch.uDevSta) annotation (Line(points={{82,-70},{90,-70}, + {90,-90},{-30,-90},{-30,-76},{-22,-76}}, color={255,0,255})); + annotation ( + experiment(StopTime=100000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}}))); +end ControllerTwo; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mo new file mode 100644 index 00000000000..b05b56185a1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mo @@ -0,0 +1,104 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.Validation; +model ControllerTwo_MinimumLeadRuntime + "Validates lead/lag and lead/standby equipment rotation controller for two devices or groups of devices" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + leaLag( + final lag=true, + minLim=true, + final minLeaRuntime=43200) + "Lead/lag rotation" + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + leaLag1( + final lag=true, + minLim=true, + final minLeaRuntime=54000) + "Lead/lag rotation" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo + leaSta( + final lag=false, + minLim=true, + final minLeaRuntime=43200) + "Lead/standby rotation" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel[2]( + final delayTime={600,600}, + final delayOnInit={true,true}) "Emulates device start-up time" + annotation (Placement(transformation(extent={{20,-40},{40,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] "Boolean pre" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leadLoad( + final width=0.8, + final period=7200) "Lead device ON/OFF status" + annotation (Placement(transformation(extent={{-100,40},{-80,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad( + final width=0.2, + final period=3600) "Lag device ON/OFF status" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse lagLoad1( + final width=0.2, + final period=5400) "Lag device ON/OFF status" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + +equation + connect(leadLoad.y, leaLag.uLeaStaSet) annotation (Line(points={{-78,50},{-50, + 50},{-50,56},{-22,56}}, color={255,0,255})); + connect(lagLoad.y, leaLag.uLagStaSet) annotation (Line(points={{-78,10},{-40,10}, + {-40,50},{-22,50}}, color={255,0,255})); + connect(leadLoad.y, leaSta.uLeaStaSet) annotation (Line(points={{-78,50},{-70, + 50},{-70,-24},{-22,-24}}, + color={255,0,255})); + connect(lagLoad1.y, leaLag1.uLagStaSet) annotation (Line(points={{-78,-30},{-32, + -30},{-32,10},{-22,10}}, color={255,0,255})); + connect(leadLoad.y, leaLag1.uLeaStaSet) annotation (Line(points={{-78,50},{-50, + 50},{-50,16},{-22,16}}, color={255,0,255})); + connect(leaSta.yDevStaSet, truDel.u) annotation (Line(points={{2,-24},{10,-24}, + {10,-30},{18,-30}}, color={255,0,255})); + connect(leaLag.yDevStaSet, leaLag.uDevSta) annotation (Line(points={{2,56},{20, + 56},{20,30},{-30,30},{-30,44},{-22,44}}, color={255,0,255})); + connect(leaLag1.yDevStaSet, leaLag1.uDevSta) annotation (Line(points={{2,16},{ + 20,16},{20,-8},{-28,-8},{-28,4},{-22,4}}, color={255,0,255})); + connect(truDel.y, pre1.u) + annotation (Line(points={{42,-30},{58,-30}}, color={255,0,255})); + connect(pre1.y, leaSta.uDevSta) annotation (Line(points={{82,-30},{90,-30},{90, + -50},{-28,-50},{-28,-36},{-22,-36}}, color={255,0,255})); + annotation ( + experiment(StopTime=100000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation.ControllerTwo. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-120,-80},{120,80}}))); +end ControllerTwo_MinimumLeadRuntime; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/package.mo new file mode 100644 index 00000000000..cf21515766b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.EquipmentRotation. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/package.order new file mode 100644 index 00000000000..cfbefbf6d93 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Validation/package.order @@ -0,0 +1,2 @@ +ControllerTwo +ControllerTwo_MinimumLeadRuntime diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.mo new file mode 100644 index 00000000000..6dcd8d3c4d9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.mo @@ -0,0 +1,49 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic; +package EquipmentRotation "Equipment rotation sequences to maintain even wear" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains equipment staging and rotation sequences implemented based on +ASHRAE Guideline36-2021, section 5.1.15. The control intent of these sequences is, +where the device configuration allows for it, +to have the devices be lead/lag or lead/standby rotated to maintain even wear. +"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={-26.6667,38.6207}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={93.3333,-81.3793}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={-26.6667,-81.3793}, + lineColor={128,128,128}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={93.333,38.6207}, + lineColor={128,128,128}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Line(points={{-40,60},{0,60},{0,-60},{40,-60}}, color={128,128,128}), + Line(points={{-40,-60},{0,-60},{0,60},{40,60}}, color={128,128,128}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end EquipmentRotation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.order new file mode 100644 index 00000000000..d6215f892f4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.order @@ -0,0 +1,3 @@ +ControllerTwo +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/IdentifyStage.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/IdentifyStage.mo new file mode 100644 index 00000000000..8d9a69760e5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/IdentifyStage.mo @@ -0,0 +1,134 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic; +block IdentifyStage + "Identify current chiller stage according to the proven on status of the chillers" + + parameter Integer nSta = 3 + "Number of chiller stages"; + + parameter Integer nChi = 2 + "Number of chillers"; + + parameter Integer staMat[nSta, nChi] = {{1,0},{0,1},{1,1}} + "Staging matrix with chiller stage as row index and chiller as column index"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Vector of chiller proven on status: true=ON" + annotation(Placement(transformation(extent={{-140,10},{-100,50}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput ySta + "Current stage index" + annotation (Placement(transformation(extent={{100,-80},{140,-40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + final parameter Real staInd[nSta] = {i for i in 1:nSta} + "Stage index vector"; + Buildings.Controls.OBC.CDL.Routing.BooleanVectorReplicator booVecRep( + final nin=nChi, + final nout=nSta) + "Replicate boolean vector to be a matric with total stages as row size and total chillers as column size" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nSta,nChi] + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nSta,nChi] + "Output true if the first integer input one equals to the second integer input" + annotation (Placement(transformation(extent={{0,60},{20,80}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea [nSta,nChi] + "Convert boolean to real" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + Buildings.Controls.OBC.CDL.Reals.MatrixMax rowMax( + final nRow=nSta, + final nCol=nChi) + "Outputs the row-wise maximum" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Reals.MatrixMin rowMin( + final nRow=nSta, + final nCol=nChi) + "Outputs the row-wise minimum" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul[nSta] + "Output product of the inputs" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con[nSta]( + final k=staInd) + "Stage indices" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul1[nSta] + "Output vector with the elements which equal to either zero or current stage index" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum curSta( + final nin=nSta) + "Current stage" + annotation (Placement(transformation(extent={{30,-70},{50,-50}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt "Convert real to integer signal" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiStaMatr[nSta,nChi]( + final k=staMat) + "Staging matrix" + annotation (Placement(transformation(extent={{-40,60},{-20,80}}))); + +equation + connect(uChi, booVecRep.u) + annotation (Line(points={{-120,30},{-82,30}}, color={255,0,255})); + connect(booVecRep.y, booToInt.u) + annotation (Line(points={{-58,30},{-42,30}}, color={255,0,255})); + connect(chiStaMatr.y, intEqu.u1) + annotation (Line(points={{-18,70},{-2,70}}, color={255,127,0})); + connect(booToInt.y, intEqu.u2) annotation (Line(points={{-18,30},{-10,30},{-10, + 62},{-2,62}}, color={255,127,0})); + connect(intEqu.y, booToRea.u) + annotation (Line(points={{22,70},{38,70}}, color={255,0,255})); + connect(booToRea.y,rowMax. u) annotation (Line(points={{62,70},{70,70},{70,10}, + {-90,10},{-90,-20},{-82,-20}},color={0,0,127})); + connect(booToRea.y,rowMin. u) annotation (Line(points={{62,70},{70,70},{70,10}, + {-90,10},{-90,-60},{-82,-60}},color={0,0,127})); + connect(rowMax.y, mul.u1) annotation (Line(points={{-58,-20},{-50,-20},{-50,-34}, + {-42,-34}},color={0,0,127})); + connect(rowMin.y, mul.u2) annotation (Line(points={{-58,-60},{-50,-60},{-50,-46}, + {-42,-46}},color={0,0,127})); + connect(mul.y, mul1.u1) annotation (Line(points={{-18,-40},{-10,-40},{-10,-54}, + {-2,-54}}, color={0,0,127})); + connect(con.y, mul1.u2) annotation (Line(points={{-18,-80},{-10,-80},{-10,-66}, + {-2,-66}}, color={0,0,127})); + connect(mul1.y, curSta.u) + annotation (Line(points={{22,-60},{28,-60}}, color={0,0,127})); + connect(curSta.y, reaToInt.u) + annotation (Line(points={{52,-60},{58,-60}}, color={0,0,127})); + connect(reaToInt.y, ySta) + annotation (Line(points={{82,-60},{120,-60}}, color={255,127,0})); + +annotation (defaultComponentName="ideSta", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), Diagram(coordinateSystem(preserveAspectRatio=false)), +Documentation(info=" +

+This subsequence is not directly specified in 1711 as it provides +a side calculation pertaining to generalization of the staging +sequences for any number of chillers and stages provided by the +user. +

+

+The subsequence outputs the current chiller stage index ySta according +to the current chillers proven on status uChi +and the given a staging matrix staMat which specified which chillers +should be enabled at each stage. +

+", +revisions=" + +")); +end IdentifyStage; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/DisableChillers.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/DisableChillers.mo new file mode 100644 index 00000000000..590e3657e2d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/DisableChillers.mo @@ -0,0 +1,348 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable; +block DisableChillers + "Disable devices when the plant is disabled from chiller mode" + + parameter Boolean have_WSE=true + "True if the plant has waterside economizer. When the plant has waterside economizer, the condenser water pump speed must be variable"; + parameter Integer nChi=2 + "Total number of chillers"; + parameter Integer nChiWatPum = 2 + "Total number of chilled water pumps"; + parameter Integer nConWatPum = 2 + "Total number of condenser water pumps"; + parameter Integer nTowCel = 2 + "Total number of cooling tower cells"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller commanded on" + annotation (Placement(transformation(extent={{-240,180},{-200,220}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatReq[nChi] + "Chilled water requst status for each chiller" + annotation (Placement(transformation(extent={{-240,140},{-200,180}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) "Chilled water isolation valve position" + annotation(Placement(transformation(extent={{-240,110},{-200,150}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatReq[nChi] + "Condenser water requst status for each chiller" + annotation (Placement(transformation(extent={{-240,30},{-200,70}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chiller condenser water isolation valve position" + annotation (Placement(transformation(extent={{-240,0},{-200,40}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatPumSpe[nChiWatPum] + "Chilled water pump speed" + annotation (Placement(transformation(extent={{-240,-100},{-200,-60}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum] + "Condenser water pump speed" + annotation (Placement(transformation(extent={{-240,-210},{-200,-170}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "Indicate if there is a stage up or stage down command" + annotation (Placement(transformation(extent={{-240,-160},{-200,-120}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-240,-280},{-200,-240}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) + "Chiller chilled water isolation valve position setpoints" + annotation (Placement(transformation(extent={{200,180},{240,220}}), + iconTransformation(extent={{100,30},{140,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) + "Chiller condenser water isolation valve position setpoints" + annotation (Placement(transformation(extent={{200,50},{240,90}}), + iconTransformation(extent={{100,0},{140,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatPumSpe[nChiWatPum]( + final unit=fill("1", nChiWatPum), + final min=fill(0, nChiWatPum), + final max=fill(1, nChiWatPum)) + "Chilled water pump speed" + annotation (Placement(transformation(extent={{200,-80},{240,-40}}), + iconTransformation(extent={{100,-40},{140,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatPumSpe[nConWatPum]( + final unit=fill("1", nConWatPum), + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum)) + "Condenser water pump speed" + annotation (Placement(transformation(extent={{200,-190},{240,-150}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowCel + "True: the tower cells should be enabled" + annotation (Placement(transformation(extent={{200,-250},{240,-210}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=180) + "Threshold time after chiller being disabled" + annotation (Placement(transformation(extent={{-100,190},{-80,210}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChi) + "Check if there is any chilled water request" + annotation (Placement(transformation(extent={{-180,150},{-160,170}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep1( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{80,190},{100,210}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1( + final nin=nChi) + "Check if there is any condenser water request" + annotation (Placement(transformation(extent={{-180,40},{-160,60}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep2( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{80,60},{100,80}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep3( + final nout=nChiWatPum) + "Replicate boolean input" + annotation (Placement(transformation(extent={{100,-70},{120,-50}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep5( + final nout=nConWatPum) + "Replicate boolean input" + annotation (Placement(transformation(extent={{100,-180},{120,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Not noChi "No enabled chiller" + annotation (Placement(transformation(extent={{-140,190},{-120,210}}))); + Buildings.Controls.OBC.CDL.Logical.Not noChiWatReq "No chilled water request" + annotation (Placement(transformation(extent={{-140,150},{-120,170}}))); + Buildings.Controls.OBC.CDL.Logical.Or cloChiIsoVal + "Close all chilled water isolation valve" + annotation (Placement(transformation(extent={{-40,190},{-20,210}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Close valve" + annotation (Placement(transformation(extent={{160,190},{180,210}}))); + Buildings.Controls.OBC.CDL.Logical.Or cloConIsoVal + "Close all condenser water isolation valve" + annotation (Placement(transformation(extent={{-40,60},{-20,80}}))); + Buildings.Controls.OBC.CDL.Logical.Not noConWatReq + "No condenser water request" + annotation (Placement(transformation(extent={{-140,40},{-120,60}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi] + "Close valve" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + Buildings.Controls.OBC.CDL.Logical.Or cloPums "Disable pumps" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2[nChiWatPum] + "Disable pumps" + annotation (Placement(transformation(extent={{160,-70},{180,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi3[nConWatPum] + "Disable pumps" + annotation (Placement(transformation(extent={{160,-180},{180,-160}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "Plant is disabled and it is not in staging process" + annotation (Placement(transformation(extent={{40,190},{60,210}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Plant is disabled and it is not in staging process" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + Buildings.Controls.OBC.CDL.Logical.Not not4 "Not in staging process" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 + "Plant is disabled and it is not in staging process" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 + "Plant is disabled and it is not in staging process" + annotation (Placement(transformation(extent={{20,-180},{40,-160}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr chiMod( + final nin=nChi) + "True: the plant has chiller mode" + annotation (Placement(transformation(extent={{-180,190},{-160,210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con[nChi]( + final k=fill(0, nChi)) "Constant zero" + annotation (Placement(transformation(extent={{20,240},{40,260}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1[nChiWatPum]( + final k=fill(0, nChiWatPum)) + "Constant zero" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con2[nConWatPum]( + final k=fill(0, nConWatPum)) + "Constant zero" + annotation (Placement(transformation(extent={{20,-120},{40,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 if have_WSE + "Not in staging process" + annotation (Placement(transformation(extent={{-80,-270},{-60,-250}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 + "Plant is disabled and it is not in staging process" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And and6 + "Plant is disabled and it is not in staging process" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3( + final k=true) if not have_WSE + "Logical true" + annotation (Placement(transformation(extent={{-80,-220},{-60,-200}}))); + Buildings.Controls.OBC.CDL.Logical.Or disTow + "Disable cooling tower" + annotation (Placement(transformation(extent={{80,-240},{100,-220}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con4( + final k=false) + if not have_WSE "Logical false" + annotation (Placement(transformation(extent={{-20,-290},{0,-270}}))); + +equation + connect(uChiWatReq, mulOr.u) + annotation (Line(points={{-220,160},{-182,160}}, color={255,0,255})); + connect(mulOr.y, noChiWatReq.u) + annotation (Line(points={{-158,160},{-142,160}}, color={255,0,255})); + connect(truDel.y, cloChiIsoVal.u1) + annotation (Line(points={{-78,200},{-42,200}},color={255,0,255})); + connect(noChiWatReq.y, cloChiIsoVal.u2) annotation (Line(points={{-118,160},{-50, + 160},{-50,192},{-42,192}}, color={255,0,255})); + connect(booScaRep1.y, swi.u2) + annotation (Line(points={{102,200},{158,200}}, color={255,0,255})); + connect(uChiWatIsoVal, swi.u3) annotation (Line(points={{-220,130},{130,130},{ + 130,192},{158,192}}, color={0,0,127})); + connect(truDel.y, cloConIsoVal.u1) annotation (Line(points={{-78,200},{-60,200}, + {-60,70},{-42,70}}, color={255,0,255})); + connect(mulOr1.y, noConWatReq.u) + annotation (Line(points={{-158,50},{-142,50}}, color={255,0,255})); + connect(uConWatReq, mulOr1.u) + annotation (Line(points={{-220,50},{-182,50}}, color={255,0,255})); + connect(noConWatReq.y, cloConIsoVal.u2) annotation (Line(points={{-118,50},{ + -60,50},{-60,62},{-42,62}},color={255,0,255})); + connect(booScaRep2.y, swi1.u2) + annotation (Line(points={{102,70},{158,70}}, color={255,0,255})); + connect(uConWatIsoVal, swi1.u3) annotation (Line(points={{-220,20},{140,20},{140, + 62},{158,62}}, color={0,0,127})); + connect(cloChiIsoVal.y, cloPums.u2) annotation (Line(points={{-18,200},{-10,200}, + {-10,140},{-100,140},{-100,-68},{-82,-68}}, color={255,0,255})); + connect(cloConIsoVal.y, cloPums.u1) annotation (Line(points={{-18,70},{-10,70}, + {-10,30},{-90,30},{-90,-60},{-82,-60}},color={255,0,255})); + connect(booScaRep3.y, swi2.u2) annotation (Line(points={{122,-60},{158,-60}}, + color={255,0,255})); + connect(uChiWatPumSpe, swi2.u3) annotation (Line(points={{-220,-80},{140,-80}, + {140,-68},{158,-68}}, color={0,0,127})); + connect(uConWatPumSpe, swi3.u3) annotation (Line(points={{-220,-190},{140,-190}, + {140,-178},{158,-178}}, color={0,0,127})); + connect(booScaRep5.y, swi3.u2) + annotation (Line(points={{122,-170},{158,-170}}, color={255,0,255})); + connect(and2.y, booScaRep1.u) + annotation (Line(points={{62,200},{78,200}}, color={255,0,255})); + connect(cloChiIsoVal.y, and2.u1) + annotation (Line(points={{-18,200},{38,200}}, color={255,0,255})); + connect(and1.y, booScaRep2.u) + annotation (Line(points={{62,70},{78,70}}, color={255,0,255})); + connect(cloConIsoVal.y, and1.u1) + annotation (Line(points={{-18,70},{38,70}},color={255,0,255})); + connect(chaPro, not4.u) + annotation (Line(points={{-220,-140},{-82,-140}}, color={255,0,255})); + connect(not4.y, and1.u2) annotation (Line(points={{-58,-140},{0,-140},{0,62},{ + 38,62}}, color={255,0,255})); + connect(not4.y, and2.u2) annotation (Line(points={{-58,-140},{0,-140},{0,192}, + {38,192}}, color={255,0,255})); + connect(cloPums.y, and3.u1) + annotation (Line(points={{-58,-60},{18,-60}}, color={255,0,255})); + connect(cloPums.y, and4.u1) annotation (Line(points={{-58,-60},{-10,-60},{-10, + -170},{18,-170}}, color={255,0,255})); + connect(not4.y, and4.u2) annotation (Line(points={{-58,-140},{0,-140},{0,-178}, + {18,-178}}, color={255,0,255})); + connect(not4.y, and3.u2) annotation (Line(points={{-58,-140},{0,-140},{0,-68}, + {18,-68}}, color={255,0,255})); + connect(swi3.y, yConWatPumSpe) + annotation (Line(points={{182,-170},{220,-170}}, color={0,0,127})); + connect(swi2.y, yChiWatPumSpe) + annotation (Line(points={{182,-60},{220,-60}}, color={0,0,127})); + connect(swi1.y, yConWatIsoVal) + annotation (Line(points={{182,70},{220,70}}, color={0,0,127})); + connect(swi.y, yChiWatIsoVal) + annotation (Line(points={{182,200},{220,200}}, color={0,0,127})); + connect(uChi, chiMod.u) + annotation (Line(points={{-220,200},{-182,200}}, color={255,0,255})); + connect(chiMod.y, noChi.u) + annotation (Line(points={{-158,200},{-142,200}}, color={255,0,255})); + connect(con.y, swi.u1) annotation (Line(points={{42,250},{140,250},{140,208},{ + 158,208}}, color={0,0,127})); + connect(con.y, swi1.u1) annotation (Line(points={{42,250},{140,250},{140,78},{ + 158,78}}, color={0,0,127})); + connect(con1.y, swi2.u1) annotation (Line(points={{42,-10},{140,-10},{140,-52}, + {158,-52}}, color={0,0,127})); + connect(con2.y, swi3.u1) annotation (Line(points={{42,-110},{140,-110},{140,-162}, + {158,-162}}, color={0,0,127})); + connect(uWSE, not1.u) + annotation (Line(points={{-220,-260},{-82,-260}}, color={255,0,255})); + connect(and3.y, and5.u1) + annotation (Line(points={{42,-60},{58,-60}}, color={255,0,255})); + connect(and5.y, booScaRep3.u) + annotation (Line(points={{82,-60},{98,-60}}, color={255,0,255})); + connect(and4.y, and6.u1) + annotation (Line(points={{42,-170},{58,-170}}, color={255,0,255})); + connect(and6.y, booScaRep5.u) + annotation (Line(points={{82,-170},{98,-170}}, color={255,0,255})); + connect(not1.y, and5.u2) annotation (Line(points={{-58,-260},{50,-260},{50,-68}, + {58,-68}}, color={255,0,255})); + connect(not1.y, and6.u2) annotation (Line(points={{-58,-260},{50,-260},{50,-178}, + {58,-178}}, color={255,0,255})); + connect(con3.y, and5.u2) annotation (Line(points={{-58,-210},{50,-210},{50,-68}, + {58,-68}}, color={255,0,255})); + connect(con3.y, and6.u2) annotation (Line(points={{-58,-210},{50,-210},{50,-178}, + {58,-178}}, color={255,0,255})); + connect(chiMod.y, disTow.u1) annotation (Line(points={{-158,200},{-150,200},{-150, + -230},{78,-230}}, color={255,0,255})); + connect(disTow.y, yTowCel) + annotation (Line(points={{102,-230},{220,-230}}, color={255,0,255})); + connect(uWSE, disTow.u2) annotation (Line(points={{-220,-260},{-150,-260},{-150, + -238},{78,-238}}, color={255,0,255})); + connect(con4.y, disTow.u2) annotation (Line(points={{2,-280},{60,-280},{60,-238}, + {78,-238}}, color={255,0,255})); + connect(noChi.y, truDel.u) + annotation (Line(points={{-118,200},{-102,200}}, color={255,0,255})); +annotation (defaultComponentName = "disChi", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false,extent={{-200,-300},{200,300}})), + Documentation(info=" +

+It disables the devices when the chiller plant is disabled in chiller mode. +It is implemented as ASHRAE Guideline36-2021, section 5.20.2.5 and 5.20.2.7. +

+

+When the plant is disabled: +

+ +", +revisions=" + +")); +end DisableChillers; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Enable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Enable.mo new file mode 100644 index 00000000000..47526f6db3c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Enable.mo @@ -0,0 +1,295 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable; +block Enable "Sequence to enable and disable plant" + + parameter Real schTab[4,2] = [0,1; 6*3600,1; 19*3600,1; 24*3600,1] + "Plant enabling schedule allowing operators to lock out the plant during off-hour"; + + parameter Real TChiLocOut=277.5 + "Outdoor air lockout temperature below which the chiller plant should be disabled"; + + parameter Real plaThrTim( + final unit="s", + final quantity="Time")=900 + "Threshold time to check status of chiller plant"; + + parameter Real reqThrTim( + final unit="s", + final quantity="Time")=180 + "Threshold time to check current chiller plant request"; + + parameter Integer ignReq = 0 + "Ignorable chiller plant requests"; + + parameter Real locDt( + final unit="K", + final quantity="TemperatureDifference") = 5/9 + "Offset temperature for lockout chiller" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput chiPlaReq + "Number of chiller plant cooling requests" + annotation (Placement(transformation(extent={{-240,70},{-200,110}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC") + "Outdoor air temperature" + annotation (Placement(transformation(extent={{-240,-170},{-200,-130}}), + iconTransformation(extent={{-140,-62},{-100,-22}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPla + "Chiller plant enabling status" + annotation (Placement(transformation(extent={{200,70},{220,90}}), + iconTransformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable enaSch( + final table=schTab, + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + final extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic) + "Plant enabling schedule allowing operators to lock out the plant during off-hour" + annotation (Placement(transformation(extent={{-140,40},{-120,60}}))); + +// final parameter Buildings.Controls.OBC.CDL.Types.Smoothness tabSmo= +// Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments +// "Smoothness of table interpolation"; +// +// final parameter Buildings.Controls.OBC.CDL.Types.Extrapolation extrapolation= +// Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic +// "Extrapolation of data outside the definition range"; + +protected + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold schOn( + final t=0.5) + "Check if enabling schedule is active" + annotation (Placement(transformation(extent={{-100,40},{-80,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-140,110},{-120,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer disTim( + final t=plaThrTim) + "Check if chiller plant has been disabled more than threshold time" + annotation (Placement(transformation(extent={{-100,110},{-80,130}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold hasReq( + final t=ignReq) + "Check if the number of chiller plant request is greater than the number of ignorable request" + annotation (Placement(transformation(extent={{-140,80},{-120,100}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd enaPla( + final nin=4) "Enable chiller plant" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer enaTim( + final t=plaThrTim) + "Check if chiller plant has been enabled more than threshold time" + annotation (Placement(transformation(extent={{-140,-20},{-120,0}}))); + + CDL.Logical.TrueDelay enaTim1(final delayTime=reqThrTim) + "Check if number of chiller plant request has been less than ignorable request by more than threshold time" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.And disPla + "Disable chiller plant" + annotation (Placement(transformation(extent={{100,-28},{120,-8}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch plaSta + "Chiller plant enabling status" + annotation (Placement(transformation(extent={{140,70},{160,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys( + final uLow=0, + final uHigh=locDt) + "Check if outdoor temperature is lower than chiller lockout temperature" + annotation (Placement(transformation(extent={{-100,-140},{-80,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Or disPlaCon + "Disable chiller plant conditions" + annotation (Placement(transformation(extent={{60,-88},{80,-68}}))); + + Buildings.Controls.OBC.CDL.Logical.Not lesReq + "Check if it is less than the ignorable request" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Not notLoc + "Check if outdoor temperature is higher than the chiller lockout temperature" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 "Pre" + annotation (Placement(transformation(extent={{-180,110},{-160,130}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLocOutTem( + final k=TChiLocOut) + "Outdoor air lockout temperature" + annotation (Placement(transformation(extent={{-180,-120},{-160,-100}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 + "Difference between chiller lockout temperature and outdoor temperature" + annotation (Placement(transformation(extent={{-140,-140},{-120,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Disable chiller plant conditions" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + +equation + connect(enaSch.y[1], schOn.u) + annotation (Line(points={{-118,50},{-102,50}}, color={0,0,127})); + connect(not1.y, disTim.u) + annotation (Line(points={{-118,120},{-102,120}}, color={255,0,255})); + connect(chiPlaReq, hasReq.u) + annotation (Line(points={{-220,90},{-142,90}}, color={255,127,0})); + connect(disTim.passed,enaPla. u[1]) + annotation (Line(points={{-78,112},{20,112},{20,77.375},{38,77.375}}, + color={255,0,255})); + connect(hasReq.y,enaPla. u[2]) + annotation (Line(points={{-118,90},{-20,90},{-20,79.125},{38,79.125}}, + color={255,0,255})); + connect(schOn.y,enaPla. u[3]) + annotation (Line(points={{-78,50},{0,50},{0,80.875},{38,80.875}}, + color={255,0,255})); + connect(schOn.y, not2.u) + annotation (Line(points={{-78,50},{-50,50},{-50,-50},{-42,-50}}, + color={255,0,255})); + connect(enaPla.y, plaSta.u) + annotation (Line(points={{62,80},{138,80}},color={255,0,255})); + connect(plaSta.y, yPla) + annotation (Line(points={{162,80},{210,80}}, color={255,0,255})); + connect(disPlaCon.y, disPla.u2) annotation (Line(points={{82,-78},{90,-78},{90, + -26},{98,-26}}, color={255,0,255})); + connect(not2.y, disPlaCon.u1) annotation (Line(points={{-18,-50},{20,-50},{20, + -78},{58,-78}}, color={255,0,255})); + connect(hasReq.y, lesReq.u) annotation (Line(points={{-118,90},{-20,90},{-20,70}, + {-180,70},{-180,-70},{-142,-70}}, color={255,0,255})); + connect(lesReq.y, enaTim1.u) + annotation (Line(points={{-118,-70},{-102,-70}}, color={255,0,255})); + connect(plaSta.y, pre1.u) annotation (Line(points={{162,80},{180,80},{180,140}, + {-190,140},{-190,120},{-182,120}}, color={255,0,255})); + connect(pre1.y, not1.u) + annotation (Line(points={{-158,120},{-142,120}}, color={255,0,255})); + connect(pre1.y, enaTim.u) + annotation (Line(points={{-158,120},{-150,120},{-150,-10},{-142,-10}}, + color={255,0,255})); + connect(TOut, sub1.u2) + annotation (Line(points={{-220,-150},{-150,-150},{-150,-136},{-142,-136}}, + color={0,0,127})); + connect(chiLocOutTem.y, sub1.u1) + annotation (Line(points={{-158,-110},{-150,-110},{-150,-124},{-142,-124}}, + color={0,0,127})); + connect(sub1.y, hys.u) + annotation (Line(points={{-118,-130},{-102,-130}}, color={0,0,127})); + connect(hys.y, notLoc.u) annotation (Line(points={{-78,-130},{-60,-130},{-60,10}, + {-22,10}}, color={255,0,255})); + connect(notLoc.y, enaPla.u[4]) annotation (Line(points={{2,10},{20,10},{20,82.625}, + {38,82.625}},color={255,0,255})); + connect(disPla.y, plaSta.clr) annotation (Line(points={{122,-18},{130,-18},{ + 130,74},{138,74}}, color={255,0,255})); + connect(enaTim.passed, disPla.u1) annotation (Line(points={{-118,-18},{98,-18}}, + color={255,0,255})); + connect(hys.y, or1.u2) annotation (Line(points={{-78,-130},{-60,-130},{-60,-108}, + {-22,-108}}, color={255,0,255})); + connect(or1.y, disPlaCon.u2) annotation (Line(points={{2,-100},{20,-100},{20,-86}, + {58,-86}}, color={255,0,255})); + connect(enaTim1.y, or1.u1) annotation (Line(points={{-78,-70},{-40,-70},{-40,-100}, + {-22,-100}}, color={255,0,255})); +annotation ( + defaultComponentName = "plaEna", + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-200,-180},{200,180}})), + Icon(graphics={ + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Ellipse(extent={{-80,80},{80,-80}}, lineColor={28,108,200},fillColor={170,255,213}, + fillPattern=FillPattern.Solid), + Ellipse(extent={{-90,90},{90,-90}}, lineColor={28,108,200}), + Rectangle(extent={{-75,2},{75,-2}}, lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Text( + extent={{-66,46},{76,10}}, + textColor={28,108,200}, + textString="START"), + Text( + extent={{-66,-8},{76,-44}}, + textColor={28,108,200}, + textString="STOP")}), + Documentation(info=" +

+Block that generate chiller plant enable signals and output the initial plant stage, +according to ASHRAE Guideline36-2021, section 5.20.2.1, +5.20.2.2 and 5.20.2.3. +

+

+The chiller plant should be enabled and disabled according to following sequences: +

+
    +
  1. +An enabling schedule should be included to allow operators to lock out the +chiller plant during off-hour, e.g. to allow off-hour operation of HVAC systems +except the chiller plant. The default schedule shall be 24/7 and be adjustable. +
  2. +
  3. +The plant should be enabled in the lowest stage when the plant has been +disabled for at least plaThrTim, e.g. 15 minutes and: + +
  4. +
  5. +The plant should be disabled when it has been enabled for at least +plaThrTim, e.g. 15 minutes and: + +
  6. +
+

+The following state machine chart illustrates the transitions between plant enable and plant disable: +

+

+\"Image +

+", +revisions=" + +")); +end Enable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/EnableDevices.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/EnableDevices.mo new file mode 100644 index 00000000000..a7c85649416 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/EnableDevices.mo @@ -0,0 +1,202 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable; +block EnableDevices + "Enable devices when plants is enabled in chiller mode or waterside economizer mode" + + parameter Integer nSta = 3 + "Number of chiller stages"; + parameter Integer nChiWatPum = 2 + "Total number of chilled water pumps"; + parameter Integer nConWatPum = 2 + "Total number of condenser water pumps"; + parameter Real iniPumDel(unit="s") = 5 + "Time to delay pump operation when the plant is just initiated"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-200,80},{-160,120}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uIni( + final min=0, + final max=nSta) + "Initial chiller stage (at plant enable)" + annotation (Placement(transformation(extent={{-200,40},{-160,80}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta( + final min=0, + final max=nSta) + "Current chiller stage" + annotation (Placement(transformation(extent={{-200,0},{-160,40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nChiWatPum] + "Chilled water pump proven on" + annotation (Placement(transformation(extent={{-200,-80},{-160,-40}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatPum[nConWatPum] + "Condenser water pump proven on" + annotation (Placement(transformation(extent={{-200,-130},{-160,-90}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaPlaPro + "True: it is in the plant enabling process" + annotation (Placement(transformation(extent={{160,80},{200,120}}), + iconTransformation(extent={{100,70},{140,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiWatIsoVal + "Lead chiller chilled water isolation valve commanded open" + annotation (Placement(transformation(extent={{160,10},{200,50}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yConWatIsoVal + "Lead chiller condenser water isolation valve commanded open" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaPriChiPum + "Lead primary chilled water pump commanded on" + annotation (Placement(transformation(extent={{160,-50},{200,-10}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaConPum + "Lead condenser water pump commanded on" + annotation (Placement(transformation(extent={{160,-80},{200,-40}}), + iconTransformation(extent={{100,-50},{140,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaTowCel + "Lead cooling tower cell commanded on" + annotation (Placement(transformation(extent={{160,-110},{200,-70}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaChi + "Lead chiller commanded on" + annotation (Placement(transformation(extent={{160,-140},{200,-100}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1 + "Check if current stage is initial stage" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Not in initial stage" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Plant enable edge" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + Buildings.Controls.OBC.CDL.Logical.Latch ecoMod "Plant enabled in economizer mode" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Stage 1, meaning it stages in chiller mode" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intChiMod + "Output true if it is enabled in chiller mode" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Enabled devices associate with chiller mode operation" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr chiWatPumOn(final nin=nChiWatPum) + "Check if there is any chilled water pump proven on" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr conWatPumOn(final nin=nConWatPum) + "Check if there is any condenser water pump proven on" + annotation (Placement(transformation(extent={{-120,-120},{-100,-100}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "Check if the lead pumps are proven on" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 + "Enable lead chiller" + annotation (Placement(transformation(extent={{20,-130},{40,-110}}))); + +equation + connect(uPla, edg.u) + annotation (Line(points={{-180,100},{-102,100}}, color={255,0,255})); + connect(uIni, intEqu1.u1) annotation (Line(points={{-180,60},{-102,60}}, + color={255,127,0})); + connect(uChiSta, intEqu1.u2) + annotation (Line(points={{-180,20},{-140,20},{-140,52},{-102,52}}, color={255,127,0})); + connect(intEqu1.y, not1.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(edg.y, ecoMod.u) + annotation (Line(points={{-78,100},{-2,100}}, color={255,0,255})); + connect(ecoMod.y, yEnaPlaPro) + annotation (Line(points={{22,100},{180,100}}, color={255,0,255})); + connect(conInt.y, intChiMod.u2) annotation (Line(points={{-98,0},{-60,0},{-60, + 22},{-42,22}}, color={255,127,0})); + connect(uIni, intChiMod.u1) annotation (Line(points={{-180,60},{-120,60},{-120, + 30},{-42,30}}, color={255,127,0})); + connect(ecoMod.y, and1.u2) annotation (Line(points={{22,100},{40,100},{40,22}, + {98,22}}, color={255,0,255})); + connect(and1.y, yChiWatIsoVal) + annotation (Line(points={{122,30},{180,30}}, color={255,0,255})); + connect(and1.y, yConWatIsoVal) annotation (Line(points={{122,30},{140,30},{140, + 0},{180,0}}, color={255,0,255})); + connect(uChiWatPum, chiWatPumOn.u) + annotation (Line(points={{-180,-60},{-122,-60}}, color={255,0,255})); + connect(uConWatPum, conWatPumOn.u) + annotation (Line(points={{-180,-110},{-122,-110}}, color={255,0,255})); + connect(chiWatPumOn.y, and2.u1) + annotation (Line(points={{-98,-60},{-62,-60}}, color={255,0,255})); + connect(conWatPumOn.y, and2.u2) annotation (Line(points={{-98,-110},{-80,-110}, + {-80,-68},{-62,-68}}, color={255,0,255})); + connect(and2.y, and3.u2) annotation (Line(points={{-38,-60},{-20,-60},{-20,-128}, + {18,-128}}, color={255,0,255})); + connect(and1.y, and3.u1) annotation (Line(points={{122,30},{140,30},{140,0},{0, + 0},{0,-120},{18,-120}}, color={255,0,255})); + connect(and3.y, yLeaChi) + annotation (Line(points={{42,-120},{180,-120}}, color={255,0,255})); + connect(not1.y, ecoMod.clr) annotation (Line(points={{-38,60},{-20,60},{-20,94}, + {-2,94}}, color={255,0,255})); + connect(intChiMod.y, and1.u1) + annotation (Line(points={{-18,30},{98,30}}, color={255,0,255})); + connect(ecoMod.y, yLeaPriChiPum) annotation (Line(points={{22,100},{40,100},{ + 40,-30},{180,-30}}, color={255,0,255})); + connect(ecoMod.y, yLeaConPum) annotation (Line(points={{22,100},{40,100},{40, + -60},{180,-60}}, color={255,0,255})); + connect(ecoMod.y, yLeaTowCel) annotation (Line(points={{22,100},{40,100},{40, + -90},{180,-90}}, color={255,0,255})); +annotation (defaultComponentName = "enaDev", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-100,138},{100,98}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false,extent={{-160,-140},{160,140}})), + Documentation(info=" +

+It controls the devices when the chiller plant is enabled in chiller mode or +waterside economizer mode. It is implemented as provided in sections 5.20.2.4, +section a and b. +

+
    +
  1. +Open the isolation valves, + +
  2. +
  3. +Stage on lead primary chilled water pump, condenser water pump, and cooling +tower respectively. +
  4. +
  5. +If the plant is enabled in chiller mode, +once the lead pumps are proven on, enable lead chiller. +
  6. +
+", +revisions=" + +")); +end EnableDevices; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/DisableChillers.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/DisableChillers.mo new file mode 100644 index 00000000000..4c4e851a01d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/DisableChillers.mo @@ -0,0 +1,92 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Validation; +model DisableChillers + "Validation sequence for disabling chillers and the associated devices" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.DisableChillers + disPlaFroChi(have_WSE=false) + "Disable plant from chiller mode" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staPro( + final k=false) + "Staging change process" + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiIsoVal[2]( + final k={1,0}) + "Chilled water isolation valve" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conIsoVal1[2]( + final k={1,0}) + "Condenser water isolation valve" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant pumSpe[2]( + final k={0.75,0}) "Pumps speed" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta[2]( + final width={0.5,0.01}, + final period={3600,7200}, + shift={0,-100}) + "Chiller status" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + +equation + connect(chiSta.y, disPlaFroChi.uChi) annotation (Line(points={{-38,50},{44,50}, + {44,19},{58,19}}, color={255,0,255})); + connect(chiSta.y, disPlaFroChi.uChiWatReq) annotation (Line(points={{-38,50}, + {40,50},{40,17},{58,17}},color={255,0,255})); + connect(chiSta.y, disPlaFroChi.uConWatReq) annotation (Line(points={{-38,50}, + {48,50},{48,12},{58,12}}, color={255,0,255})); + connect(chiIsoVal.y, disPlaFroChi.uChiWatIsoVal) annotation (Line(points={{-58,20}, + {20,20},{20,15},{58,15}}, color={0,0,127})); + connect(conIsoVal1.y, disPlaFroChi.uConWatIsoVal) annotation (Line(points={{-38,-10}, + {24,-10},{24,9},{58,9}}, color={0,0,127})); + connect(pumSpe.y, disPlaFroChi.uChiWatPumSpe) annotation (Line(points={{-58,-40}, + {28,-40},{28,7},{58,7}}, color={0,0,127})); + connect(pumSpe.y, disPlaFroChi.uConWatPumSpe) annotation (Line(points={{-58,-40}, + {32,-40},{32,5},{58,5}}, color={0,0,127})); + connect(staPro.y, disPlaFroChi.chaPro) annotation (Line(points={{-18,-70},{36, + -70},{36,3},{58,3}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/DisableChillers.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.DisableChillers. +It demonstrates the control of disabling plants from chiller mode (disPlaFroChi). +

+ +", revisions=" + +"), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end DisableChillers; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/Enable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/Enable.mo new file mode 100644 index 00000000000..c48cbd3e7f0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/Enable.mo @@ -0,0 +1,187 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Validation; +model Enable + "Validation sequence for enabling and disabling chiller plant" + + parameter Real aveTWetBul( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Chilled water supply set temperature"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Enable + disPlaSch( + final schTab=[0,0; + 10*60,1; + 19*3600,0; + 24*3600,0], + ignReq=1) + "Disable plant without waterside economizer, due to schedule" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Enable + disPlaReq( + final schTab=[0,0; + 6*3600,1; + 19*3600,0; + 24*3600,0], + ignReq=1) + "Disable plant without waterside economizer, due to lack of request" + annotation (Placement(transformation(extent={{40,0},{60,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Enable + disPlaOutTem(final schTab=[0,0; 1*3600,1; 19*3600,0; 24*3600,0]) + "Disable plant without waterside economizer, due to low outdoor temperature" + annotation (Placement(transformation(extent={{40,-80},{60,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=3) + "Chiller plant requests above the number of ignored requests" + annotation (Placement(transformation(extent={{-20,100},{0,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conOutTem( + final k=293.15) "Constant outdoor temperature above lockout" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable chiPlaReq2( + final table=[0,1; + 6.5*3600,1; + 9*3600,2; + 9*3600 + 600,0; + 19*3600,0; + 24*3600,1], + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments) + "Number of chiller plant request" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conOutTem1( + final k=282.15) + "Constant outdoor temperature" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable chiPlaReq3( + final table=[0,1; + 6.5*3600,1; + 9*3600,2; + 14*3600,3; + 19*3600,3; + 24*3600,1], + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments) + "Number of chiller plant request" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin outTem1( + final amplitude=7.5, + final freqHz=1/(24*3600), + final offset=275.15) "Outdoor temperature" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + +equation + connect(conOutTem.y, disPlaSch.TOut) + annotation (Line(points={{2,70},{24,70},{24,95.8},{38,95.8}}, color={0,0,127})); + connect(chiPlaReq2.y[1], reaToInt2.u) + annotation (Line(points={{-38,10},{-22,10}}, color={0,0,127})); + connect(reaToInt2.y, disPlaReq.chiPlaReq) annotation (Line(points={{2,10},{20, + 10},{20,14},{38,14}}, color={255,127,0})); + connect(conOutTem1.y, disPlaReq.TOut) + annotation (Line(points={{2,-20},{24,-20},{24,5.8},{38,5.8}}, color={0,0,127})); + connect(chiPlaReq3.y[1], reaToInt3.u) + annotation (Line(points={{-38,-70},{-22,-70}}, color={0,0,127})); + connect(reaToInt3.y, disPlaOutTem.chiPlaReq) annotation (Line(points={{2,-70}, + {20,-70},{20,-66},{38,-66}}, color={255,127,0})); + connect(outTem1.y, disPlaOutTem.TOut) + annotation (Line(points={{2,-100},{24,-100},{24,-74.2},{38,-74.2}}, color={0,0,127})); + connect(conInt.y, disPlaSch.chiPlaReq) annotation (Line(points={{2,110},{20, + 110},{20,104},{38,104}}, color={255,127,0})); +annotation ( + experiment(StopTime=86400.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/Enable.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Enable. +It shows different conditions to enable and disable the plant. +

+ +", revisions=" + +"), + Icon(graphics={Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-140},{140,140}}), + graphics={ + Text( + extent={{40,90},{106,74}}, + textColor={0,0,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Left, + textString="Disable plant +due to inactive schedule"), + Text( + extent={{40,0},{98,-12}}, + textColor={0,0,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Left, + textString="Disable plant +due to zero request"), + Text( + extent={{40,-82},{120,-96}}, + textColor={0,0,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Left, + textString="Disable plant +due to low outdoor temperature")})); +end Enable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/EnableDevices.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/EnableDevices.mo new file mode 100644 index 00000000000..a580d0f27bc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/EnableDevices.mo @@ -0,0 +1,110 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Validation; +model EnableDevices "Validation sequence for enabling plant devices" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.EnableDevices enaDev + "Enable valves and pumps" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.1, + final period=3600) + "Enabled plant" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Stage 1, meaning it stages in chiller mode" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Pulse staSet( + final amplitude=-1, + final width=0.8, + final period=3600, + offset=2) "Stage setpoint" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.3, + final period=3600) + "Proven on pumps" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Logical not" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) + "Disabled pump" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); +equation + connect(booPul.y, not1.u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + connect(not1.y, enaDev.uPla) annotation (Line(points={{-18,80},{40,80},{40,38}, + {58,38}}, color={255,0,255})); + connect(conInt.y, enaDev.uIni) annotation (Line(points={{-38,40},{28,40},{28,34}, + {58,34}}, color={255,127,0})); + connect(staSet.y, enaDev.uChiSta) annotation (Line(points={{-58,0},{0,0},{0,30}, + {58,30}}, color={255,127,0})); + connect(booPul1.y, not2.u) + annotation (Line(points={{-58,-40},{-42,-40}}, color={255,0,255})); + connect(not2.y, enaDev.uChiWatPum[1]) annotation (Line(points={{-18,-40},{20,-40}, + {20,26},{58,26}}, color={255,0,255})); + connect(not2.y, enaDev.uConWatPum[1]) annotation (Line(points={{-18,-40},{20,-40}, + {20,22},{58,22}}, color={255,0,255})); + connect(con.y, enaDev.uChiWatPum[2]) annotation (Line(points={{-18,-80},{40,-80}, + {40,26},{58,26}}, color={255,0,255})); + connect(con.y, enaDev.uConWatPum[2]) annotation (Line(points={{-18,-80},{40,-80}, + {40,22},{58,22}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/EnableDevices.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.EnableDevices. +It shows how to control devices when the plant is just enabled. +

+ + + + +", revisions=" + +"), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end EnableDevices; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/package.mo new file mode 100644 index 00000000000..1fa93695d82 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable; +package Validation "Collection of validation models" + annotation ( preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/package.order new file mode 100644 index 00000000000..4cf17c6ee05 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/package.order @@ -0,0 +1,3 @@ +DisableChillers +Enable +EnableDevices diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.mo new file mode 100644 index 00000000000..c323a0db61b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic; +package PlantEnable "Package of sequences for enabling plant and the associated devices" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains sequences for enabling plant and the associate devices. +The sequences are implemented based on ASHRAE Gudeline36-2021, section 5.20.2. +"), +Icon(graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={28,108,200}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineThickness=5, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Ellipse(extent={{-80,80},{80,-80}}, lineColor={28,108,200},fillColor={170,255,213}, + fillPattern=FillPattern.Solid), + Ellipse(extent={{-90,90},{90,-90}}, lineColor={28,108,200}), + Rectangle(extent={{-75,2},{75,-2}}, lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Text( + extent={{-66,46},{76,10}}, + textColor={28,108,200}, + textString="START"), + Text( + extent={{-66,-8},{76,-44}}, + textColor={28,108,200}, + textString="STOP")})); +end PlantEnable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.order new file mode 100644 index 00000000000..ac6f1b7f7c8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.order @@ -0,0 +1,4 @@ +DisableChillers +Enable +EnableDevices +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/IdentifyStage.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/IdentifyStage.mo new file mode 100644 index 00000000000..9ada5e5796e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/IdentifyStage.mo @@ -0,0 +1,128 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.Validation; +model IdentifyStage "Validation identifying stage index" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.IdentifyStage ideSta + "Idendify stage index" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.IdentifyStage ideSta1( + nChi=3, + staMat={{1,0,0},{1,1,0},{1,1,1}}) + "Idendify stage index" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{0,-80},{20,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chi1( + final width=0.5, + final period=5) + "Chiller one status" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chi2( + final width=0.7, + final period=5) + "Chiller two status" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chi3( + final width=0.9, + final period=5) "Chiller three status" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + +equation + connect(chi1.y, ideSta.uChi[1]) annotation (Line(points={{-58,60},{-40,60},{-40, + 40},{58,40}}, color={255,0,255})); + connect(chi2.y, ideSta.uChi[2]) annotation (Line(points={{-58,20},{-30,20},{-30, + 40},{58,40}}, color={255,0,255})); + connect(chi3.y, not1.u) + annotation (Line(points={{-58,-70},{-2,-70}}, color={255,0,255})); + connect(chi1.y, not3.u) annotation (Line(points={{-58,60},{-40,60},{-40,10},{-2, + 10}},color={255,0,255})); + connect(chi2.y, not2.u) annotation (Line(points={{-58,20},{-30,20},{-30,-30},{ + -2,-30}}, color={255,0,255})); + connect(not3.y, ideSta1.uChi[1]) annotation (Line(points={{22,10},{30,10},{30, + -30.6667},{58,-30.6667}}, color={255,0,255})); + connect(not2.y, ideSta1.uChi[2]) + annotation (Line(points={{22,-30},{58,-30}}, color={255,0,255})); + connect(not1.y, ideSta1.uChi[3]) annotation (Line(points={{22,-70},{40,-70},{ + 40,-29.3333},{58,-29.3333}}, + color={255,0,255})); + +annotation ( + experiment(StopTime=5.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/IdentifyStage.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.IdentifyStage. +It shows how to identify current chiller stage. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end IdentifyStage; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/package.mo new file mode 100644 index 00000000000..05c444583d0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/package.order new file mode 100644 index 00000000000..2485ca85f98 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/Validation/package.order @@ -0,0 +1 @@ +IdentifyStage diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.mo new file mode 100644 index 00000000000..53a2df1c70a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Generic "Generic control sequences" + +annotation (preferredView="info", Documentation(info=" +

+This package contains generic primary plant control sequences. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Generic; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.order new file mode 100644 index 00000000000..5589c56e642 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.order @@ -0,0 +1,4 @@ +IdentifyStage +EquipmentRotation +PlantEnable +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Controller.mo new file mode 100644 index 00000000000..6cfce2b938d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Controller.mo @@ -0,0 +1,288 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure; +block Controller "Head pressure controller for plants with headered condenser water pumps" + parameter Boolean have_heaPreConSig = false + "Flag indicating if there is head pressure control signal from chiller controller" + annotation (Dialog(group="Plant")); + parameter Boolean have_WSE=true + "True if the plant has waterside economizer. When the plant has waterside economizer, the condenser water pump speed must be variable" + annotation (Dialog(group="Plant")); + parameter Boolean have_fixSpeConWatPum=false + "Flag indicating if the plant has fixed speed condenser water pumps" + annotation (Dialog(group="Plant", enable=not have_WSE)); + parameter Real minTowSpe=0.1 + "Minimum cooling tower fan speed" + annotation (Dialog(group="Setpoints")); + parameter Real minConWatPumSpe=0.1 + "Minimum condenser water pump speed" + annotation (Dialog(group="Setpoints", enable= not ((not have_WSE) and have_fixSpeConWatPum))); + parameter Real minHeaPreValPos=0.1 + "Minimum head pressure control valve position" + annotation (Dialog(group="Setpoints", enable= (not ((not have_WSE) and (not have_fixSpeConWatPum))))); + parameter Real minChiLif=10 + "Minimum allowable lift at minimum load for chiller" + annotation (Dialog(tab="Loop signal", enable=not have_heaPreConSig)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Loop signal", group="PID controller", enable=not have_heaPreConSig)); + parameter Real k=1 "Gain of controller" + annotation (Dialog(tab="Loop signal", group="PID controller", enable=not have_heaPreConSig)); + parameter Real Ti( + final unit="s", + final quantity="Time")=0.5 "Time constant of integrator block" + annotation (Dialog(tab="Loop signal", group="PID controller", + enable= not have_heaPreConSig + and (controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real Td( + final unit="s", + final quantity="Time")=0.5 + "Time constant of derivative block" + annotation (Dialog(tab="Loop signal", group="PID controller", + enable= not have_heaPreConSig + and (controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon + "Chillers head pressure control status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-140,100},{-100,140}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not have_heaPreConSig + "Measured condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-140,70},{-100,110}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not have_heaPreConSig + "Measured chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,40},{-100,80}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput desConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Design condenser water pump speed for current stage" + annotation (Placement(transformation(extent={{-140,10},{-100,50}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE + if have_WSE and (not have_fixSpeConWatPum) + "Status of water side economizer: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHeaPreCon( + final min=0, + final max=1, + final unit="1") if have_heaPreConSig + "Chiller head pressure control loop signal from chiller controller" + annotation (Placement(transformation(extent={{-140,-50},{-100,-10}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMaxTowSpeSet( + final min=0, + final max=1, + final unit="1") "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{100,60},{140,100}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaPreConVal( + final min=0, + final max=1, + final unit="1") if have_WSE or ((not have_WSE) and have_fixSpeConWatPum) + "Head pressure control valve position" + annotation (Placement(transformation(extent={{100,10},{140,50}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatPumSpeSet( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{100,-30},{140,10}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.ControlLoop + chiHeaPreLoo( + final minChiLif=minChiLif, + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td) if not have_heaPreConSig + "Generate chiller head pressure control loop signal" + annotation (Placement(transformation(extent={{-20,80},{0,100}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithoutWSE + noWSE( + final have_fixSpeConWatPum=have_fixSpeConWatPum, + final minTowSpe=minTowSpe, + final minConWatPumSpe=minConWatPumSpe, + final minHeaPreValPos=minHeaPreValPos) if not have_WSE + "Controlling equipments for plants without waterside economizer" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithWSE + withWSE( + final minTowSpe=minTowSpe, + final minConWatPumSpe=minConWatPumSpe, + final minHeaPreValPos=minHeaPreValPos) if have_WSE and (not have_fixSpeConWatPum) + "Controlling equipments for plants with waterside economizer" + annotation (Placement(transformation(extent={{40,-20},{60,0}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Switch swi if have_heaPreConSig + "Head pressure control from chiller controller" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con( + final k=0) if have_heaPreConSig "Constant" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Utilities.Assert assMes1( + final message="If the plant has waterside economizer, the condenser water pump cannot be fix speed.") + "Generate alert if the plant has waterside economizer and the condenser water pump has fix speed" + annotation (Placement(transformation(extent={{60,-110},{80,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant havWSE( + final k=have_WSE) + "Have waterside economizer" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fixSpe( + final k=have_fixSpeConWatPum) + "Fix speed condenser water pump" + annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); + Buildings.Controls.OBC.CDL.Logical.And fixSpeWSE + "The plant has waterside economizer and the condenser water pump is fix speed" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre "Break loop" + annotation (Placement(transformation(extent={{-80,110},{-60,130}}))); + +equation + connect(chiHeaPreLoo.TConWatRet, TConWatRet) + annotation (Line(points={{-22,90},{-120,90}}, color={0,0,127})); + connect(chiHeaPreLoo.TChiWatSup, TChiWatSup) + annotation (Line(points={{-22,82},{-60,82},{-60,60},{-120,60}}, color={0,0,127})); + connect(chiHeaPreLoo.yHeaPreCon, noWSE.uHeaPreCon) + annotation (Line(points={{2,90},{20,90},{20,58},{38,58}}, color={0,0,127})); + connect(chiHeaPreLoo.yHeaPreCon, withWSE.uHeaPreCon) + annotation (Line(points={{2,90},{20,90},{20,-2},{38,-2}}, color={0,0,127})); + connect(withWSE.uWSE, uWSE) + annotation (Line(points={{38,-14},{-20,-14},{-20,0},{-120,0}}, + color={255,0,255})); + connect(uHeaPreCon, swi.u1) + annotation (Line(points={{-120,-30},{-60,-30},{-60,-32},{-22,-32}}, + color={0,0,127})); + connect(con.y, swi.u3) + annotation (Line(points={{-58,-60},{-40,-60},{-40,-48},{-22,-48}}, + color={0,0,127})); + connect(swi.y, noWSE.uHeaPreCon) + annotation (Line(points={{2,-40},{20,-40},{20,58},{38,58}}, color={0,0,127})); + connect(swi.y, withWSE.uHeaPreCon) + annotation (Line(points={{2,-40},{20,-40},{20,-2},{38,-2}}, color={0,0,127})); + connect(noWSE.yMaxTowSpeSet, yMaxTowSpeSet) + annotation (Line(points={{62,56},{80,56},{80,80},{120,80}}, color={0,0,127})); + connect(withWSE.yHeaPreConVal, yHeaPreConVal) + annotation (Line(points={{62,-16},{90,-16},{90,30},{120,30}}, color={0,0,127})); + connect(withWSE.yMaxTowSpeSet, yMaxTowSpeSet) + annotation (Line(points={{62,-4},{80,-4},{80,80},{120,80}}, color={0,0,127})); + connect(withWSE.yConWatPumSpeSet, yConWatPumSpeSet) + annotation (Line(points={{62,-10},{120,-10}}, color={0,0,127})); + connect(desConWatPumSpe, withWSE.desConWatPumSpe) + annotation (Line(points={{-120,30},{0,30},{0,-6},{38,-6}}, color={0,0,127})); + connect(noWSE.yConWatPumSpeSet, yConWatPumSpeSet) + annotation (Line(points={{62,42},{70,42},{70,-10},{120,-10}}, color={0,0,127})); + connect(noWSE.yHeaPreConVal, yHeaPreConVal) + annotation (Line(points={{62,46},{90,46},{90,30},{120,30}}, color={0,0,127})); + connect(desConWatPumSpe, noWSE.desConWatPumSpe) + annotation (Line(points={{-120,30},{0,30},{0,50},{38,50}}, color={0,0,127})); + connect(havWSE.y, fixSpeWSE.u1) annotation (Line(points={{-38,-90},{-30,-90},{ + -30,-100},{-22,-100}}, color={255,0,255})); + connect(fixSpe.y, fixSpeWSE.u2) annotation (Line(points={{-38,-120},{-30,-120}, + {-30,-108},{-22,-108}}, color={255,0,255})); + connect(fixSpeWSE.y, not1.u) + annotation (Line(points={{2,-100},{18,-100}}, color={255,0,255})); + connect(not1.y, assMes1.u) + annotation (Line(points={{42,-100},{58,-100}}, color={255,0,255})); + connect(uChiHeaCon, pre.u) + annotation (Line(points={{-120,120},{-82,120}}, color={255,0,255})); + connect(pre.y, swi.u2) annotation (Line(points={{-58,120},{-40,120},{-40,-40}, + {-22,-40}}, color={255,0,255})); + connect(pre.y, chiHeaPreLoo.uHeaPreEna) annotation (Line(points={{-58,120},{-40, + 120},{-40,98},{-22,98}}, color={255,0,255})); + connect(pre.y, noWSE.uHeaPreEna) annotation (Line(points={{-58,120},{-40,120}, + {-40,42},{38,42}}, color={255,0,255})); + connect(pre.y, withWSE.uHeaPreEna) annotation (Line(points={{-58,120},{-40,120}, + {-40,-18},{38,-18}}, color={255,0,255})); +annotation ( + defaultComponentName="heaPreCon", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-80,60},{82,-60}}, + lineColor={28,108,200}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Polygon( + points={{-80,60},{-14,4},{-80,-60},{-80,60}}, + lineColor={175,175,175}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-100,-140},{100,140}})), + Documentation(info=" +

+Block that generates control signals for chiller head pressure control, +according to ASHRAE Guideline36-2021, section 5.20.10 Head pressure control. +

+

+Note that if a plant has waterside economizer, the condenser water pump must be +variable speed. +

+

+This sequence contains three subsequences: +

+ +", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/ControlLoop.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/ControlLoop.mo new file mode 100644 index 00000000000..a67af1ab189 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/ControlLoop.mo @@ -0,0 +1,149 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences; +block ControlLoop + "Sequence to generate head pressure control signal if it is not available from the chiller controller" + parameter Real minChiLif( + final min=1e-5, + final unit="K", + final quantity="TemperatureDifference") = 10 + "Minimum allowable lift at minimum load for chiller"; + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="PID controller")); + parameter Real k=1 "Gain of controller" + annotation (Dialog(group="PID controller")); + parameter Real Ti( + final unit="s", + final quantity="Time")=0.5 + "Time constant of integrator block" + annotation (Dialog(group="PID controller", + enable=controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real Td( + final unit="s", + final quantity="Time")=0.5 + "Time constant of derivative block" + annotation (Dialog(group="PID controller", + enable=controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHeaPreEna + "Status of head pressure control: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-140,0},{-100,40}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-140,-40},{-100,0}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,-100},{-100,-60}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaPreCon( + final unit="1", + final min=0, + final max=1) "Chiller head pressure control loop output" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPID( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=1, + final yMin=0, + final y_reset=0) + "Generate head pressure control signal" + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Subtract lif "Lift temperature" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(final k=1/minChiLif) + "Normalized by minimum allowable lift at minimum load for chiller" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + +equation + connect(TConWatRet, lif.u1) annotation (Line(points={{-120,-20},{-80,-20},{-80, + -34},{-62,-34}}, color={0,0,127})); + connect(con.y, conPID.u_s) + annotation (Line(points={{-18,60},{18,60}}, color={0,0,127})); + connect(conPID.y, yHeaPreCon) + annotation (Line(points={{42,60},{60,60},{60,0},{120,0}}, color={0,0,127})); + connect(lif.y, gai.u) + annotation (Line(points={{-38,-40},{-22,-40}}, color={0,0,127})); + connect(gai.y, conPID.u_m) + annotation (Line(points={{2,-40},{30,-40},{30,48}}, color={0,0,127})); + connect(uHeaPreEna, conPID.trigger) + annotation (Line(points={{-120,20},{24,20},{24,48}}, color={255,0,255})); + connect(TChiWatSup, lif.u2) annotation (Line(points={{-120,-80},{-80,-80},{-80, + -46},{-62,-46}}, color={0,0,127})); + +annotation ( + defaultComponentName= "chiHeaPreLoo", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={170,255,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Polygon( + points={{-80,90},{-88,68},{-72,68},{-80,90}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(points={{-80,78},{-80,-90}}, color={192,192,192}), + Line(points={{-90,0},{82,0}}, color={192,192,192}), + Polygon( + points={{90,0},{68,8},{68,-8},{90,0}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line(origin = {-1.939,-1.816}, + points={{61.939,7.816},{37.939,15.816},{11.939,-80.184},{-29.966,113.485}, + {-65.374,-61.217},{-78.061,-78.184}}, + color = {0,0,127}, + smooth = Smooth.Bezier)}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that generates chiller head pressure control loop signal when the signal +is not available from chiller controller, +according to ASHRAE Guideline36-2021, +section 5.20.10 Head pressure control, part 5.20.10.1 and 5.20.10.2. +

+

+1. When head pressure control loop is enabled, a reverse acting PID loop shall +maintain the temperature differential between the chiller condenser water +return (condenser leaving) temperature TConWatRet and chilled water supply temperature +TChiWatSup at minimum allowable lift minChiLif (chiller lift +equals to TConWatRet minus TChiWatSup) +

+

+2. Each operating chiller shall have its own head pressure control loop. +

+", +revisions=" + +")); +end ControlLoop; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithWSE.mo new file mode 100644 index 00000000000..3417face081 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithWSE.mo @@ -0,0 +1,322 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences; +block MappingWithWSE + "Equipment setpoints when chiller head pressure control is enabled, for plants with waterside economizer and headered condenser water pumps" + parameter Real minTowSpe = 0.1 + "Minimum cooling tower fan speed"; + parameter Real minConWatPumSpe = 0.1 + "Minimum condenser water pump speed"; + parameter Real minHeaPreValPos = 0.1 + "Minimum head pressure control valve position"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHeaPreCon( + final unit="1", + final min=0, + final max=1) + "Chiller head pressure control loop signal" + annotation (Placement(transformation(extent={{-220,110},{-180,150}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput desConWatPumSpe( + final unit="1", + final min=0, + final max=1) + "Design condenser water pump speed for current stage" + annotation (Placement(transformation(extent={{-220,40},{-180,80}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE + "Status of water side economizer: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-220,-40},{-180,0}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHeaPreEna + "Status of head pressure control: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-220,-180},{-180,-140}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMaxTowSpeSet( + final unit="1", + final min=0, + final max=1) "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{180,120},{220,160}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatPumSpeSet( + final unit="1", + final min=0, + final max=1) "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{180,20},{220,60}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaPreConVal( + final unit="1", + final min=0, + final max=1) "Head pressure control valve position" + annotation (Placement(transformation(extent={{180,-180},{220,-140}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Line maxCooTowSpeSet + "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{0,120},{20,140}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowMaxSpe( + final k=minTowSpe) + "Minimum allowable tower speed" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Reals.Line conWatPumSpe + "Condenser water pump speed" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal1(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one2(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con( + final k=minConWatPumSpe) "Minimum condenser water pump speed" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one3(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,-50},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one4(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,-100},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1( + final k=minHeaPreValPos) + "Minimum head pressure control valve position" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(final k=0) + "Constant value" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Line heaPreConVal + "Head pressure control valve position" + annotation (Placement(transformation(extent={{0,-78},{20,-58}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Switch the maximum tower speed setpoint based on the economizer status" + annotation (Placement(transformation(extent={{60,170},{80,190}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Switch the condenser water pump speed setpoint based on the economizer status" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2 + "Switch the head pressure control valve setpoint based on the economizer status" + annotation (Placement(transformation(extent={{60,-130},{80,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi3 + "Switch the valve setpoint to 0 when the head pressure control is disabled" + annotation (Placement(transformation(extent={{140,-170},{160,-150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2(final k=0) + "Constant value" + annotation (Placement(transformation(extent={{40,-190},{60,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi4 + "Switch the pump speed setpoint to 0 when the head pressure control is disabled" + annotation (Placement(transformation(extent={{140,30},{160,50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi5 + "Switch the maximum tower speed setpoint to 0 when the head pressure control is disabled" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + +equation + connect(zer.y, maxCooTowSpeSet.x1) + annotation (Line(points={{-38,160},{-20,160},{-20,138},{-2,138}}, color={0,0,127})); + connect(one.y, maxCooTowSpeSet.f1) + annotation (Line(points={{-98,160},{-80,160},{-80,134},{-2,134}}, + color={0,0,127})); + connect(hal.y, maxCooTowSpeSet.x2) + annotation (Line(points={{-98,100},{-80,100},{-80,126},{-2,126}}, + color={0,0,127})); + connect(hpTowMaxSpe.y, maxCooTowSpeSet.f2) + annotation (Line(points={{-38,100},{-20,100},{-20,122},{-2,122}}, color={0,0,127})); + connect(uHeaPreCon, maxCooTowSpeSet.u) + annotation (Line(points={{-200,130},{-2,130}}, color={0,0,127})); + connect(hal1.y,conWatPumSpe. x1) + annotation (Line(points={{-38,50},{-20,50},{-20,38},{-2,38}}, color={0,0,127})); + connect(con.y,conWatPumSpe. f2) + annotation (Line(points={{-38,0},{-20,0},{-20,22},{-2,22}}, color={0,0,127})); + connect(one2.y,conWatPumSpe. x2) + annotation (Line(points={{-98,0},{-80,0},{-80,26},{-2,26}}, color={0,0,127})); + connect(uHeaPreCon,conWatPumSpe. u) + annotation (Line(points={{-200,130},{-140,130},{-140,30},{-2,30}}, + color={0,0,127})); + connect(zer1.y, heaPreConVal.x1) + annotation (Line(points={{-38,-40},{-20,-40},{-20,-60},{-2,-60}}, color={0,0,127})); + connect(one3.y, heaPreConVal.f1) + annotation (Line(points={{-98,-40},{-80,-40},{-80,-64},{-2,-64}}, + color={0,0,127})); + connect(one4.y, heaPreConVal.x2) + annotation (Line(points={{-98,-90},{-80,-90},{-80,-72},{-2,-72}}, + color={0,0,127})); + connect(con1.y, heaPreConVal.f2) + annotation (Line(points={{-38,-90},{-20,-90},{-20,-76},{-2,-76}}, color={0,0,127})); + connect(uHeaPreCon, heaPreConVal.u) + annotation (Line(points={{-200,130},{-140,130},{-140,-68},{-2,-68}}, + color={0,0,127})); + connect(maxCooTowSpeSet.y, swi.u3) + annotation (Line(points={{22,130},{40,130},{40,172},{58,172}}, + color={0,0,127})); + connect(desConWatPumSpe, swi1.u1) + annotation (Line(points={{-200,60},{-120,60},{-120,78},{58,78}}, color={0,0,127})); + connect(conWatPumSpe.y, swi1.u3) + annotation (Line(points={{22,30},{40,30},{40,62},{58,62}}, + color={0,0,127})); + connect(uWSE, swi2.u2) + annotation (Line(points={{-200,-20},{-160,-20},{-160,-120},{58,-120}}, + color={255,0,255})); + connect(zer2.y, swi3.u3) + annotation (Line(points={{62,-180},{110,-180},{110,-168},{138,-168}}, + color={0,0,127})); + connect(uHeaPreEna, swi3.u2) + annotation (Line(points={{-200,-160},{138,-160}},color={255,0,255})); + connect(swi2.y, swi3.u1) + annotation (Line(points={{82,-120},{120,-120},{120,-152},{138,-152}}, + color={0,0,127})); + connect(swi3.y, yHeaPreConVal) + annotation (Line(points={{162,-160},{200,-160}}, color={0,0,127})); + connect(one.y, swi.u1) + annotation (Line(points={{-98,160},{-80,160},{-80,188},{58,188}}, + color={0,0,127})); + connect(desConWatPumSpe, conWatPumSpe.f1) + annotation (Line(points={{-200,60},{-120,60},{-120,34},{-2,34}}, + color={0,0,127})); + connect(one4.y, swi2.u3) + annotation (Line(points={{-98,-90},{-80,-90},{-80,-128},{58,-128}}, + color={0,0,127})); + connect(heaPreConVal.y, swi2.u1) + annotation (Line(points={{22,-68},{40,-68},{40,-112},{58,-112}}, + color={0,0,127})); + connect(uWSE, swi.u2) annotation (Line(points={{-200,-20},{-160,-20},{-160,180}, + {58,180}}, color={255,0,255})); + connect(uWSE, swi1.u2) annotation (Line(points={{-200,-20},{-160,-20},{-160,70}, + {58,70}}, color={255,0,255})); + connect(uHeaPreEna, swi4.u2) annotation (Line(points={{-200,-160},{100,-160},{ + 100,40},{138,40}}, color={255,0,255})); + connect(swi1.y, swi4.u1) annotation (Line(points={{82,70},{120,70},{120,48},{138, + 48}}, color={0,0,127})); + connect(zer2.y, swi4.u3) annotation (Line(points={{62,-180},{110,-180},{110,32}, + {138,32}}, color={0,0,127})); + connect(swi4.y, yConWatPumSpeSet) + annotation (Line(points={{162,40},{200,40}}, color={0,0,127})); + connect(swi.y, swi5.u1) annotation (Line(points={{82,180},{120,180},{120,148}, + {138,148}}, color={0,0,127})); + connect(zer2.y, swi5.u3) annotation (Line(points={{62,-180},{110,-180},{110,132}, + {138,132}}, color={0,0,127})); + connect(uHeaPreEna, swi5.u2) annotation (Line(points={{-200,-160},{100,-160},{ + 100,140},{138,140}}, color={255,0,255})); + connect(swi5.y, yMaxTowSpeSet) + annotation (Line(points={{162,140},{200,140}}, color={0,0,127})); +annotation ( + defaultComponentName= "heaPreConEqu", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Line(points={{-70,60},{-70,-54},{70,-54},{70,58}}, color={28,108,200}), + Line( + points={{-70,36},{-2,36},{70,-34}}, + color={28,108,200}, + thickness=0.5), + Line( + points={{-70,36},{-2,-30}}, + color={28,108,200}, + thickness=0.5), + Polygon( + points={{-70,60},{-72,56},{-68,56},{-70,60}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Polygon( + points={{70,60},{68,56},{72,56},{70,60}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Line( + points={{-2,-54},{-2,52}}, + color={28,108,200}, + pattern=LinePattern.Dash)}), + Diagram(coordinateSystem( + preserveAspectRatio=false, extent={{-180,-200},{180,200}})), + Documentation(info=" +

+Block that resets maximum cooling tower speed setpoint yMaxTowSpeSet, +controls condenser water pump speed yConWatPumSpeSet and +head pressure control valve position yHeaPreConVal +for plants with water side economizers and headered condenser water pumps. +The development follows ASHRAE Guideline36-2021, +section 5.20.10 Head pressure control, part 5.20.10.5, 5.20.10.6 and 5.20.10.7. +

+

+1. For each chiller, when the waterside economizer is disabled (uWSE = false), +map chiller head pressure control loop signal uHeaPreCon as follows: +

+ + +

+\"HeadControlCWP_WSE.png\" +

+ +

+2. When the waterside economizer is enabled (uWSE = true), +

+ + +

+\"HeadControlValve_WSE.png\" +

+ +

+3. When the head pressure control loop is disabled (uHeaPreEna = false), +the head pressure control valve shall be closed; the maximum tower speed setpoint +and the condenser water pump speed setpoint becomes 0. +

+", +revisions=" + +")); +end MappingWithWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithoutWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithoutWSE.mo new file mode 100644 index 00000000000..8d057c0703c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithoutWSE.mo @@ -0,0 +1,241 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences; +block MappingWithoutWSE + "Equipment setpoints when chiller head pressure control is enabled, for plants without waterside economizer" + parameter Boolean have_fixSpeConWatPum = true + "Flag: true=fixed speed condenser water pumps, false=variable speed condenser water pumps"; + parameter Real minTowSpe = 0.1 + "Minimum cooling tower fan speed"; + parameter Real minConWatPumSpe = 0.1 "Minimum condenser water pump speed" + annotation (Dialog(enable=not have_fixSpeConWatPum)); + parameter Real minHeaPreValPos = 0.1 "Minimum head pressure control valve position" + annotation (Dialog(enable=have_fixSpeConWatPum)); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHeaPreCon( + final min=0, + final max=1, + final unit="1") + "Chiller head pressure control loop signal" + annotation (Placement(transformation(extent={{-200,70},{-160,110}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput desConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Design condenser water pump speed for current stage" + annotation (Placement(transformation(extent={{-200,-10},{-160,30}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHeaPreEna + "Status of head pressure control: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-200,-120},{-160,-80}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMaxTowSpeSet( + final unit="1", + final min=0, + final max=1) "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{160,10},{200,50}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaPreConVal( + final unit="1", + final min=0, + final max=1) if have_fixSpeConWatPum + "Head pressure control valve position" + annotation (Placement(transformation(extent={{160,-60},{200,-20}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yConWatPumSpeSet( + final unit="1", + final min=0, + final max=1) if not have_fixSpeConWatPum + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{160,-120},{200,-80}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Line maxCooTowSpeSet + "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{60,80},{80,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,110},{-100,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowMaxSpe( + final k=minTowSpe) + "Minimum allowable tower speed" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + Buildings.Controls.OBC.CDL.Reals.Line lin + "Head pressure control valve position, or condenser water pump speed" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal1(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpeVal( + final k=1) if have_fixSpeConWatPum "Fully open valve position" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one2(k=1) "Constant one" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minValPos( + final k=minHeaPreValPos) if have_fixSpeConWatPum + "Minimum head pressure control valve position" + annotation (Placement(transformation(extent={{0,-80},{20,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Switch the setpoint to 0 if the head pressure control loop is disabled" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minPumSpe( + final k=minConWatPumSpe) if not have_fixSpeConWatPum + "Minimum condenser water pump speed" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Switch the setpoint to 0 if the head pressure control loop is disabled" + annotation (Placement(transformation(extent={{120,20},{140,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zero(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,-140},{20,-120}}))); +equation + connect(zer.y, maxCooTowSpeSet.x1) + annotation (Line(points={{-18,120},{40,120},{40,98},{58,98}}, color={0,0,127})); + connect(one.y, maxCooTowSpeSet.f1) + annotation (Line(points={{-98,120},{-80,120},{-80,94},{58,94}}, color={0,0,127})); + connect(hal.y, maxCooTowSpeSet.x2) + annotation (Line(points={{-38,50},{-20,50},{-20,86},{58,86}}, color={0,0,127})); + connect(hpTowMaxSpe.y, maxCooTowSpeSet.f2) + annotation (Line(points={{22,50},{40,50},{40,82},{58,82}},color={0,0,127})); + connect(uHeaPreCon, maxCooTowSpeSet.u) + annotation (Line(points={{-180,90},{58,90}}, color={0,0,127})); + connect(hal1.y, lin.x1) + annotation (Line(points={{22,0},{40,0},{40,-32},{58,-32}}, color={0,0,127})); + connect(fulOpeVal.y, lin.f1) + annotation (Line(points={{-38,0},{-20,0},{-20,-36},{58,-36}}, color={0,0,127})); + connect(minValPos.y, lin.f2) + annotation (Line(points={{22,-70},{40,-70},{40,-48},{58,-48}}, + color={0,0,127})); + connect(one2.y, lin.x2) + annotation (Line(points={{-98,-70},{-80,-70},{-80,-44},{58,-44}}, + color={0,0,127})); + connect(uHeaPreCon, lin.u) + annotation (Line(points={{-180,90},{-100,90},{-100,-40},{58,-40}}, + color={0,0,127})); + connect(uHeaPreEna, swi.u2) + annotation (Line(points={{-180,-100},{118,-100}}, color={255,0,255})); + connect(lin.y, swi.u1) + annotation (Line(points={{82,-40},{100,-40},{100,-92},{118,-92}}, color={0,0,127})); + connect(swi.y, yConWatPumSpeSet) + annotation (Line(points={{142,-100},{180,-100}}, color={0,0,127})); + connect(desConWatPumSpe, lin.f1) + annotation (Line(points={{-180,10},{-140,10},{-140,-36},{58,-36}}, + color={0,0,127})); + connect(minPumSpe.y, lin.f2) + annotation (Line(points={{-38,-70},{-20,-70},{-20,-48},{58,-48}}, + color={0,0,127})); + connect(swi.y, yHeaPreConVal) + annotation (Line(points={{142,-100},{150,-100},{150,-40},{180,-40}}, color={0,0,127})); + connect(uHeaPreEna, swi1.u2) + annotation (Line(points={{-180,-100},{90,-100},{90,30},{118,30}}, + color={255,0,255})); + connect(maxCooTowSpeSet.y, swi1.u1) + annotation (Line(points={{82,90},{100,90},{100,38},{118,38}}, + color={0,0,127})); + connect(swi1.y, yMaxTowSpeSet) + annotation (Line(points={{142,30},{180,30}}, color={0,0,127})); + connect(zero.y, swi.u3) annotation (Line(points={{22,-130},{110,-130},{110,-108}, + {118,-108}}, color={0,0,127})); + connect(zero.y, swi1.u3) annotation (Line(points={{22,-130},{110,-130},{110,22}, + {118,22}}, color={0,0,127})); +annotation ( + defaultComponentName= "heaPreConEqu", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Line(points={{-70,60},{-70,-54},{70,-54},{70,58}}, color={28,108,200}), + Line( + points={{-70,36},{-2,36},{70,-34}}, + color={28,108,200}, + thickness=0.5), + Line( + points={{-70,36},{-2,-30}}, + color={28,108,200}, + thickness=0.5), + Polygon( + points={{-70,60},{-72,56},{-68,56},{-70,60}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Polygon( + points={{70,60},{68,56},{72,56},{70,60}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Line( + points={{-2,-54},{-2,52}}, + color={28,108,200}, + pattern=LinePattern.Dash)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-160},{160,160}})), + Documentation(info=" +

+Block that resets maximum cooling tower speed setpoint yMaxTowSpeSet, +controls head pressure control valve position yHeaPreConVal or +condenser water pump speed yConWatPumSpeSet +for plants without water side economizers. The development follows +ASHRAE Guideline36-2021, +section 5.20.10 Head pressure control, part 5.20.10.3, part 5.20.10.4 and 5.20.10.7. +

+

+1. For each chiller, map chiller head pressure control loop signal +uHeaPreCon as follows: +

+ + +

+\"HeadControlValve_noWSE.png\" +

+ +

+2. When the head pressure control loop is disabled (uHeaPreEna = false), +the head pressure control valve shall be closed, or the pump should be disabled; the +maximum tower speed setpoint becomes 0. +

+", +revisions=" + +")); +end MappingWithoutWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/ControlLoop.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/ControlLoop.mo new file mode 100644 index 00000000000..ca156ec625a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/ControlLoop.mo @@ -0,0 +1,92 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.Validation; +model ControlLoop "Validate sequence of output head pressure control signal" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.ControlLoop + chiHeaPreLoo + "Output chiller head pressure control loop signal" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.7, + final period=5, + final shift=0.5) "Head pressure control enabling status" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSup(k=280.15) + "Measured chilled water supply temperature" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse TConWatRet( + final amplitude=-11, + period=5, + final offset=273.15 + 20) + "Measured condenser water return temperature" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + +equation + connect(TChiWatSup.y, chiHeaPreLoo.TChiWatSup) + annotation (Line(points={{-38,-50},{0,-50},{0,-8},{38,-8}}, color={0,0,127})); + connect(booPul.y, chiHeaPreLoo.uHeaPreEna) + annotation (Line(points={{-38,50},{0,50},{0,8},{38,8}}, color={255,0,255})); + connect(TConWatRet.y, chiHeaPreLoo.TConWatRet) + annotation (Line(points={{-38,0},{38,0}}, color={0,0,127})); + +annotation ( + experiment(StopTime=5.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/ControlLoop.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.ControlLoop. +It demonstrates how the head pressure control loop +signal being generated. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false))); +end ControlLoop; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithWSE.mo new file mode 100644 index 00000000000..0c254a8a36e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithWSE.mo @@ -0,0 +1,123 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.Validation; +model MappingWithWSE + "Validate sequence of specifying equipment setpoint based on head pressure control loop output" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithWSE + witWSE + "Specify setpoints for plant when waterside economizer is enabled" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithWSE + noWSE + "Specify setpoints for plant when waterside economizer is disabled" + annotation (Placement(transformation(extent={{60,-90},{80,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant enaWSE( + k=true) "Constant true" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant desPumSpe( + k=0.75) "Design condenser water pump speed at current stage" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conLoo(duration=3.5) + "Control loop output" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not disWSE + "Disabled economizer" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPreCon( + width=0.9, + period=5) + "Pressure control enabling status" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + +equation + connect(conLoo.y, witWSE.uHeaPreCon) + annotation (Line(points={{-38,80},{-24,80},{-24,68},{58,68}}, color={0,0,127})); + connect(desPumSpe.y, witWSE.desConWatPumSpe) + annotation (Line(points={{-38,40},{-20,40},{-20,64},{58,64}}, color={0,0,127})); + connect(enaWSE.y, witWSE.uWSE) + annotation (Line(points={{-38,0},{-16,0},{-16,56},{58,56}}, color={255,0,255})); + connect(conLoo.y, noWSE.uHeaPreCon) + annotation (Line(points={{-38,80},{-24,80},{-24,-72},{58,-72}}, color={0,0,127})); + connect(desPumSpe.y, noWSE.desConWatPumSpe) + annotation (Line(points={{-38,40},{-20,40},{-20,-76},{58,-76}}, color={0,0,127})); + connect(enaWSE.y, disWSE.u) + annotation (Line(points={{-38,0},{-2,0}}, color={255,0,255})); + connect(disWSE.y, noWSE.uWSE) annotation (Line(points={{22,0},{40,0},{40,-84}, + {58,-84}}, color={255,0,255})); + connect(enaPreCon.y, witWSE.uHeaPreEna) annotation (Line(points={{-38,-40},{-12, + -40},{-12,52},{58,52}}, color={255,0,255})); + connect(enaPreCon.y, noWSE.uHeaPreEna) annotation (Line(points={{-38,-40},{-12, + -40},{-12,-88},{58,-88}}, color={255,0,255})); +annotation ( + experiment(StopTime=5.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithWSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithWSE. +It demonstrates the setpoints control based on the output +from the head pressure control loop. +

+

+The instances witWSE and noWSE shows +the control when the waterside economizer is enabled and disabled +respectively. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end MappingWithWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithoutWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithoutWSE.mo new file mode 100644 index 00000000000..e702a025fda --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithoutWSE.mo @@ -0,0 +1,117 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.Validation; +model MappingWithoutWSE + "Validate sequence of specifying equipment setpoint based on head pressure control loop output" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithoutWSE + fixPumSpe + "Specify setpoints for plant with constant speed condenser water pumps" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithoutWSE + varPumSpe(final have_fixSpeConWatPum=false) + "Specify setpoints for plant with constant speed condenser water pumps" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPreCon( + width=0.8, + period=5) "Constant true" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant desPumSpe( + k=0.75) "Design condenser water pump speed at current stage" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conLoo(duration=3.5) + "Control loop output" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + +equation + connect(conLoo.y, fixPumSpe.uHeaPreCon) + annotation (Line(points={{-38,60},{-20,60},{-20,48},{-2,48}}, color={0,0,127})); + connect(enaPreCon.y, fixPumSpe.uHeaPreEna) + annotation (Line(points={{-38,0},{-12,0},{-12,32},{-2,32}}, color={255,0,255})); + connect(conLoo.y, varPumSpe.uHeaPreCon) + annotation (Line(points={{-38,60},{-20,60},{-20,-32},{-2,-32}}, color={0,0,127})); + connect(enaPreCon.y, varPumSpe.uHeaPreEna) + annotation (Line(points={{-38,0},{-12,0},{-12,-48},{-2,-48}}, color={255,0,255})); + connect(desPumSpe.y, varPumSpe.desConWatPumSpe) + annotation (Line(points={{-38,-40},{-2,-40}}, color={0,0,127})); + +annotation ( + experiment(StopTime=5.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithoutWSE.mos" + "Simulate and plot"), + Documentation(info=" + +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithoutWSE. +It demonstrates the setpoints control based on the output +from the head pressure control loop. +

+

+The instances fixPumSpe and varPumSpe shows +the control of the plants with the fixed speed condenser water pump +and the variable speed condenser water pump respectively. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end MappingWithoutWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..2ae2c13c15d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/package.order new file mode 100644 index 00000000000..39d5c4147c0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/package.order @@ -0,0 +1,3 @@ +ControlLoop +MappingWithWSE +MappingWithoutWSE diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/package.mo new file mode 100644 index 00000000000..3a2dbf02a21 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure; +package Subsequences "Subsequences for chiller head pressure control" + +annotation (preferredView="info", Documentation(info=" +

+This package contains chiller head pressure control subsequences. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/package.order new file mode 100644 index 00000000000..af2e13caba3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/package.order @@ -0,0 +1,4 @@ +ControlLoop +MappingWithWSE +MappingWithoutWSE +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/Controller.mo new file mode 100644 index 00000000000..b88a27d8432 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/Controller.mo @@ -0,0 +1,186 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Validation; +model Controller "Validation head pressure controller" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller + enaWSE "Head pressure for plant with waterside economizer that is enabled" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller + disWSE "Head pressure for plant with waterside economizer that is disabled" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller + conSpePum( + final have_WSE=false, have_fixSpeConWatPum=true) + "Head pressure for plant without waterside economizer, constant speed condenser water pump" + annotation (Placement(transformation(extent={{100,30},{120,50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller + varSpePum( + final have_WSE=false) + "Head pressure for plant without waterside economizer, variable speed condenser water pump" + annotation (Placement(transformation(extent={{100,-110},{120,-90}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.7, + final period=5, + final shift=0.5) "Head pressure control enabling status" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TConWatRet( + final amplitude=-11, + final freqHz=2/10, + final offset=273.15 + 27) "Measured condenser water return temperature" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatSup( + final amplitude=1, + final freqHz=1/5, + final offset=273.15 + 6) "Measured chilled water supply temperature" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant runWSE( + final k=true) "Constant true" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant desPumSpe( + final k=0.75) "Design condenser water pump speed at current stage" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + +equation + connect(booPul.y,enaWSE.uChiHeaCon) + annotation (Line(points={{-98,100},{20,100},{20,90},{58,90}}, color={255,0,255})); + connect(TConWatRet.y, enaWSE.TConWatRet) + annotation (Line(points={{-98,60},{-20,60},{-20,86},{58,86}}, color={0,0,127})); + connect(TChiWatSup.y, enaWSE.TChiWatSup) + annotation (Line(points={{-98,20},{-10,20},{-10,82},{58,82}}, color={0,0,127})); + connect(desPumSpe.y, enaWSE.desConWatPumSpe) + annotation (Line(points={{-98,-20},{10,-20},{10,78},{58,78}}, color={0,0,127})); + connect(runWSE.y, enaWSE.uWSE) + annotation (Line(points={{-98,-60},{0,-60},{0,74},{58,74}}, color={255,0,255})); + connect(booPul.y,disWSE.uChiHeaCon) + annotation (Line(points={{-98,100},{20,100},{20,-50},{58,-50}}, color={255,0,255})); + connect(TConWatRet.y, disWSE.TConWatRet) + annotation (Line(points={{-98,60},{-20,60},{-20,-54},{58,-54}}, color={0,0,127})); + connect(TChiWatSup.y, disWSE.TChiWatSup) + annotation (Line(points={{-98,20},{-10,20},{-10,-58},{58,-58}}, color={0,0,127})); + connect(desPumSpe.y, disWSE.desConWatPumSpe) + annotation (Line(points={{-98,-20},{10,-20},{10,-62},{58,-62}}, color={0,0,127})); + connect(runWSE.y, not1.u) + annotation (Line(points={{-98,-60},{-80,-60},{-80,-80},{-62,-80}}, color={255,0,255})); + connect(not1.y, disWSE.uWSE) + annotation (Line(points={{-38,-80},{-28,-80},{-28,-66},{58,-66}}, color={255,0,255})); + connect(booPul.y,conSpePum.uChiHeaCon) + annotation (Line(points={{-98,100},{20,100},{20,50},{98,50}}, color={255,0,255})); + connect(booPul.y,varSpePum.uChiHeaCon) + annotation (Line(points={{-98,100},{20,100},{20,-90},{98,-90}}, color={255,0,255})); + connect(TConWatRet.y, conSpePum.TConWatRet) + annotation (Line(points={{-98,60},{-20,60},{-20,46},{98,46}}, color={0,0,127})); + connect(TChiWatSup.y, conSpePum.TChiWatSup) + annotation (Line(points={{-98,20},{-10,20},{-10,42},{98,42}}, color={0,0,127})); + connect(TConWatRet.y, varSpePum.TConWatRet) + annotation (Line(points={{-98,60},{-20,60},{-20,-94},{98,-94}}, color={0,0,127})); + connect(TChiWatSup.y, varSpePum.TChiWatSup) + annotation (Line(points={{-98,20},{-10,20},{-10,-98},{98,-98}}, color={0,0,127})); + connect(desPumSpe.y, varSpePum.desConWatPumSpe) + annotation (Line(points={{-98,-20},{10,-20},{10,-102},{98,-102}}, color={0,0,127})); + +annotation ( + experiment(StopTime=5.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller. +It demonstrates the setpoint controls according to the head +pressure control. It has four instances: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
InstanceWaterside economizerCondenser water pump speedNote
enaWSEYesVariableEconomizer enabled
disWSEYesVariableEconomizer disabled
conSpePumNoConstantn/a
varSpePumNoVariablen/a
+
+ +

+It shows following process: +

+ + +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-140,-120},{140,120}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/package.mo new file mode 100644 index 00000000000..276dcac6da8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.mo new file mode 100644 index 00000000000..87eba568683 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package HeadPressure "Chiller head pressure control sequence" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains chiller head pressure control sequences. +The implementation is based on section 5.20.10. in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end HeadPressure; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Controller.mo new file mode 100644 index 00000000000..0747eb57b92 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Controller.mo @@ -0,0 +1,192 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass; +block Controller + "Controller for chilled water minimum flow bypass valve" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Real minFloSet[nChi]( + final min=fill(0,nChi), + final unit=fill("m3/s",nChi), + quantity=fill("VolumeFlowRate",nChi)) + "Minimum chilled water flow through each chiller" + annotation (Evaluate=true); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="Controller")); + parameter Real k=1 "Gain of controller" + annotation (Dialog(group="Controller")); + parameter Real Ti( + final unit="s", + final quantity="Time")=0.5 "Time constant of integrator block" + annotation (Dialog(group="Controller", enable=controllerType==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + controllerType==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real Td( + final unit="s", + final quantity="Time")=0 "Time constant of derivative block" + annotation (Dialog(group="Controller", enable=controllerType==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerType==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real yMax=1 "Upper limit of output" + annotation (Dialog(group="Controller")); + parameter Real yMin=0.1 "Lower limit of output" + annotation (Dialog(group="Controller")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum + "Maximum status feedback of all the chilled water pumps: true means at least one pump is proven on" + annotation (Placement(transformation(extent={{-180,30},{-140,70}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final min=0, + final unit="m3/s", + quantity="VolumeFlowRate") + "Measured chilled water flow rate through chillers" + annotation (Placement(transformation(extent={{-180,-10},{-140,30}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWatSet_flow( + final min=0, + final unit="m3/s", + quantity="VolumeFlowRate") "Chiller water minimum flow setpoint" + annotation (Placement(transformation(extent={{-180,-60},{-140,-20}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValPos( + final min=0, + final max=1, + final unit="1") "Chilled water minimum flow bypass valve position" + annotation (Placement(transformation(extent={{140,30},{180,70}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.PIDWithReset valPos( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=yMax, + final yMin=yMin, + final y_reset=1) "Bypass valve position PI controller" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minFlo[nChi]( + final k=minFloSet) "Minimum bypass flow rate at each stage" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum( + final nin=nChi) + "Sum of minimum chilled water flow of all chillers" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div + "Normalized minimum flow setpoint" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div1 + "Normalized minimum bypass flow " + annotation (Placement(transformation(extent={{-20,-20},{0,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{100,40},{120,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant opeVal( + final k=1) "Valve open" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + +equation + connect(minFlo.y, mulSum.u) + annotation (Line(points={{-98,-80},{-82,-80}},color={0,0,127})); + connect(VChiWat_flow, div1.u1) + annotation (Line(points={{-160,10},{-80,10},{-80,-4},{-22,-4}},color={0,0,127})); + connect(mulSum.y, div1.u2) + annotation (Line(points={{-58,-80},{-40,-80},{-40,-16},{-22,-16}}, + color={0,0,127})); + connect(mulSum.y, div.u2) + annotation (Line(points={{-58,-80},{-40,-80},{-40,-66},{-22,-66}}, + color={0,0,127})); + connect(div1.y, valPos.u_m) + annotation (Line(points={{2,-10},{50,-10},{50,68}}, color={0,0,127})); + connect(div.y, valPos.u_s) + annotation (Line(points={{2,-60},{20,-60},{20,80},{38,80}}, + color={0,0,127})); + connect(uChiWatPum, swi.u2) + annotation (Line(points={{-160,50},{98,50}}, color={255,0,255})); + connect(opeVal.y, swi.u3) + annotation (Line(points={{-38,30},{80,30},{80,42},{98,42}}, color={0,0,127})); + connect(swi.y, yValPos) + annotation (Line(points={{122,50},{160,50}},color={0,0,127})); + connect(div.u1, VChiWatSet_flow) + annotation (Line(points={{-22,-54},{-80,-54},{-80,-40},{-160,-40}}, + color={0,0,127})); + connect(uChiWatPum, valPos.trigger) + annotation (Line(points={{-160,50},{44,50},{44,68}}, + color={255,0,255})); + connect(valPos.y, swi.u1) + annotation (Line(points={{62,80},{80,80},{80,58},{98,58}}, + color={0,0,127})); + +annotation ( + defaultComponentName="minBypValCon", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-60,40},{80,-40}}, + lineColor={28,108,200}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Polygon( + points={{-60,40},{-20,0},{-60,-40},{-60,40}}, + lineColor={175,175,175}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,88},{-54,74}}, + textColor={255,0,255}, + textString="uChiWatPum"), + Text( + extent={{-98,6},{-54,-4}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{68,6},{102,-4}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yValPos"), + Text( + extent={{-98,-74},{-42,-86}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWatSet_flow")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-140,-100},{140,100}})), + Documentation(info=" +

+Block that controls chilled water minimum flow for primary-only +plants with a minimum flow bypass valve, +according to ASHRAE Guideline36-2021, +section 5.20.8 Chilled water minimum flow bypass valve. +

+

+The minimum chilled water flow setpoint VChiWatSet_flow is specified by block + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint. +

+

+When any chilled water pump is proven on (uChiWatPum = true), +the bypass valve PID loop shall be enabled. The valve shall be opened 100% otherwise. +When enabled, the bypass valve loop shall be biased to start with the valve +100% open. +

+", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/FlowSetpoint.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/FlowSetpoint.mo new file mode 100644 index 00000000000..f0bbd58904c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/FlowSetpoint.mo @@ -0,0 +1,1079 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass; +block FlowSetpoint "Chilled water minimum flow setpoint for primary-only plants" + + parameter Integer nChi = 3 + "Total number of chillers"; + parameter Boolean have_parChi=true + "Flag: true means that the plant has parallel chillers"; + parameter Real byPasSetTim( + final unit="s", + final quantity="Time")=300 + "Time constant for resetting minimum bypass flow"; + parameter Real minFloSet[nChi]( + final unit=fill("m3/s",nChi), + final quantity=fill("VolumeFlowRate",nChi), + displayUnit=fill("m3/s",nChi)) = {0.005, 0.005, 0.005} + "Minimum chilled water flow through each chiller"; + parameter Real maxFloSet[nChi]( + final unit=fill("m3/s",nChi), + final quantity=fill("VolumeFlowRate",nChi), + displayUnit=fill("m3/s",nChi)) = {0.025, 0.025, 0.025} + "Maximum chilled water flow through each chiller"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp + "Stage up logical signal" + annotation (Placement(transformation(extent={{-480,500},{-440,540}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Resetting status of upstream device (in staging up or down process) before reset minimum chilled water flow setpoint" + annotation (Placement(transformation(extent={{-480,460},{-440,500}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-480,420},{-440,460}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaChi + "Index of next chiller to be enabled" + annotation (Placement(transformation(extent={{-480,150},{-440,190}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexDisChi + "Index of next chiller to be disabled" + annotation (Placement(transformation(extent={{-480,10},{-440,50}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uSubCha + "Indicate if upstream device has been reset in the sub-process. This input is used when the stage change needs chiller on-off" + annotation (Placement(transformation(extent={{-480,-200},{-440,-160}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "Indicate if the stage change requires one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{-480,-240},{-440,-200}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow + "Stage down logical signal" + annotation (Placement(transformation(extent={{-480,-310},{-440,-270}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatMinFloSet( + final quantity="VolumeFlowRate", + final unit="m3/s", + final min=0) + "Chilled water minimum flow setpoint" + annotation (Placement(transformation(extent={{440,100},{480,140}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaSet + "True: it is in the setpoint changing process" + annotation (Placement(transformation(extent={{440,-460},{480,-420}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + final parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con3( + final k=byPasSetTim) + "Duration time to change old setpoint to new setpoint" + annotation (Placement(transformation(extent={{-60,258},{-40,278}}))); + Buildings.Controls.OBC.CDL.Reals.Line oneMorSet + "Minimum flow setpoint when adding one more chiller" + annotation (Placement(transformation(extent={{100,320},{120,340}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con2(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-60,300},{-40,320}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim(final t=byPasSetTim) + "Time after suppress chiller demand" + annotation (Placement(transformation(extent={{-220,510},{-200,530}}))); + Buildings.Controls.OBC.CDL.Reals.Line oneLeSet + "Minimum flow setpoint when disabling one chiller" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim1(final t=byPasSetTim) + "Time after suppress chiller demand" + annotation (Placement(transformation(extent={{-220,-300},{-200,-280}}))); + Buildings.Controls.OBC.CDL.Reals.Switch dowSet + "Minimum flow chilled water flow setpoint when there is stage-down command" + annotation (Placement(transformation(extent={{240,-32},{260,-12}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-220,-330},{-200,-310}}))); + Buildings.Controls.OBC.CDL.Reals.Switch byPasSet1 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{400,230},{420,250}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-320,510},{-300,530}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{-320,-300},{-300,-280}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minFlo[nChi]( + final k=minFloSet) + "Minimum chilled water flow through each chiller" + annotation (Placement(transformation(extent={{-400,290},{-380,310}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxFlo[nChi]( + final k=maxFloSet) + "Maximum chilled water flow through each chiller" + annotation (Placement(transformation(extent={{-400,250},{-380,270}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[nChi]( + final k=fill(0,nChi)) "Constant zero" + annotation (Placement(transformation(extent={{-400,210},{-380,230}}))); + Buildings.Controls.OBC.CDL.Reals.Divide floRat[nChi] + "Flow rate ratio through each chiller" + annotation (Placement(transformation(extent={{-280,270},{-260,290}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor nexChiRat(final nin=nChi) + if have_parChi + "Flow rate ratio of next enabling chiller" + annotation (Placement(transformation(extent={{-220,180},{-200,200}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor nexChiMaxFlo(final nin=nChi) + if have_parChi "Maximum flow rate of next enabling chiller" + annotation (Placement(transformation(extent={{-220,140},{-200,160}}))); + Buildings.Controls.OBC.CDL.Reals.Max max if have_parChi + "Maximum flow rate ratio of operating chillers after one chiller being enabled" + annotation (Placement(transformation(extent={{-80,180},{-60,200}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 if have_parChi + "Sum of maximum chilled water flow rate setpoint of operating chillers after one chiller being enabled" + annotation (Placement(transformation(extent={{-80,140},{-60,160}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nChi]( + final k=chiInd) "Chiller index vector" + annotation (Placement(transformation(extent={{-400,60},{-380,80}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nChi) "Replicate integer input" + annotation (Placement(transformation(extent={{-400,20},{-380,40}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nChi] "Check equality of two integer inputs" + annotation (Placement(transformation(extent={{-320,60},{-300,80}}))); + Buildings.Controls.OBC.CDL.Logical.Xor xor[nChi] "Outputs true if exactly one input is true" + annotation (Placement(transformation(extent={{-220,60},{-200,80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi3[nChi] if have_parChi + "Flow rate ratio of operating chiller" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi4[nChi] if have_parChi + "Maximum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-120,30},{-100,50}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro2 if have_parChi + "Chilled water flow setpoint after disabling next chiller" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + Buildings.Controls.OBC.CDL.Reals.Max max1 if not have_parChi + "Largest minimum flow rate setpoint of operating chillers after one chiller being enabled" + annotation (Placement(transformation(extent={{-20,-100},{0,-80}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum1(final nin=nChi) + if have_parChi + "Sum of maximum chilled water flow rate setpoint of operating chillers after one chiller being disabled" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax1(final nin=nChi) + if not have_parChi + "Largest minimum flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax2(final nin=nChi) + if have_parChi + "Maximum flow rate ratio of operating chillers after one chiller being disabled" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax3(final nin=nChi) + if not have_parChi + "Largest minimum flow rate setpoint of operating chillers after one chiller being disabled" + annotation (Placement(transformation(extent={{-20,-140},{0,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi5[nChi] if not have_parChi + "Minimum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-120,-60},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor nexChiMinFlo(final nin=nChi) + if not have_parChi "Minimum flow rate of next enabling chiller" + annotation (Placement(transformation(extent={{-220,-100},{-200,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi6[nChi] if not have_parChi + "Minimum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-100,-140},{-80,-120}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical and" + annotation (Placement(transformation(extent={{-400,110},{-380,130}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi9[nChi] if have_parChi + "Flow rate ratio of operating chiller" + annotation (Placement(transformation(extent={{-220,440},{-200,460}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax4( + final nin=nChi) if have_parChi + "Maximum flow rate ratio of operating chillers" + annotation (Placement(transformation(extent={{-180,440},{-160,460}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi10[nChi] if have_parChi + "Maximum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-220,400},{-200,420}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum2( + final nin=nChi) if have_parChi + "Sum of maximum chilled water flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-180,400},{-160,420}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro3 if have_parChi + "Chilled water flow setpoint for current operating chillers" + annotation (Placement(transformation(extent={{-60,420},{-40,440}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi11[nChi] if have_parChi + "Maximum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-220,320},{-200,340}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum3( + final nin=nChi) if have_parChi + "Sum of maximum chilled water flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-180,320},{-160,340}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi12[nChi] if have_parChi + "Flow rate ratio of operating chiller" + annotation (Placement(transformation(extent={{-220,360},{-200,380}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax5(final nin=nChi) + if have_parChi + "Maximum flow rate ratio of operating chillers" + annotation (Placement(transformation(extent={{-180,360},{-160,380}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro4 if have_parChi + "Chilled water flow setpoint for current operating chillers" + annotation (Placement(transformation(extent={{-60,340},{-40,360}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro1 if have_parChi + "Chilled water flow setpoint for current operating chillers" + annotation (Placement(transformation(extent={{-20,160},{0,180}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax6( + final nin=nChi) if not have_parChi + "Largest minimum flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi] if not have_parChi + "Minimum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-120,-20},{-100,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch byPasSet2 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{180,350},{200,370}}))); + Buildings.Controls.OBC.CDL.Reals.Switch upSet + "Minimum flow chilled water flow setpoint when there is stage-up command" + annotation (Placement(transformation(extent={{240,310},{260,330}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim2(final t=byPasSetTim) + "Time after suppress chiller demand" + annotation (Placement(transformation(extent={{-220,-260},{-200,-240}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-320,-260},{-300,-240}}))); + Buildings.Controls.OBC.CDL.Reals.Line oneMorSet1 + "Minimum flow setpoint when adding one more chiller" + annotation (Placement(transformation(extent={{100,-260},{120,-240}}))); + Buildings.Controls.OBC.CDL.Reals.Switch byPasSet4 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{160,-210},{180,-190}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chaSet + "Minimum flow chilled water flow setpoint when there is stage-change command" + annotation (Placement(transformation(extent={{300,190},{320,210}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{300,230},{320,250}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 "Logical and" + annotation (Placement(transformation(extent={{340,230},{360,250}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi] + "Hold the chiller status when there is any stage change" + annotation (Placement(transformation(extent={{-360,340},{-340,360}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] "Boolean to real" + annotation (Placement(transformation(extent={{-400,340},{-380,360}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) "Replicate boolean input" + annotation (Placement(transformation(extent={{-380,150},{-360,170}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr[nChi]( + final t=fill(0.5, nChi)) + "Convert real to boolean" + annotation (Placement(transformation(extent={{-320,340},{-300,360}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr( + final t=1) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-400,-80},{-380,-60}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr( + final t=nChi) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-400,-170},{-380,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Dummy index so the extractor will not have out of range index" + annotation (Placement(transformation(extent={{-360,-170},{-340,-150}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 + "Check if index is in the range" + annotation (Placement(transformation(extent={{-360,-80},{-340,-60}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1 + "Convert boolean to real" + annotation (Placement(transformation(extent={{-320,-80},{-300,-60}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi "Valid index" + annotation (Placement(transformation(extent={{-320,-140},{-300,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul3 if not have_parChi + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul1[2] if have_parChi + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{-160,140},{-140,160}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaScaRep( + final nout=3) + "Replicate real input" + annotation (Placement(transformation(extent={{-270,-80},{-250,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Or or1 + "True: if it is time to change the setpoint" + annotation (Placement(transformation(extent={{-160,-430},{-140,-410}}))); + Buildings.Controls.OBC.CDL.Logical.Or or3 + "True: if it is time to change the setpoint" + annotation (Placement(transformation(extent={{-60,-450},{-40,-430}}))); + Buildings.Controls.OBC.CDL.Logical.Or or4 + "Check if the setpoint has been changed" + annotation (Placement(transformation(extent={{-98,-360},{-78,-340}}))); + Buildings.Controls.OBC.CDL.Logical.Or or5 + "True: the setpoint has been changed" + annotation (Placement(transformation(extent={{20,-380},{40,-360}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "True: the setpoint has been changed" + annotation (Placement(transformation(extent={{60,-380},{80,-360}}))); + Buildings.Controls.OBC.CDL.Logical.Not notChaSet + "True: if it is not time to change the setpoint" + annotation (Placement(transformation(extent={{22,-490},{42,-470}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Setpoint being set" + annotation (Placement(transformation(extent={{120,-450},{140,-430}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Check if the setpoint is being changed" + annotation (Placement(transformation(extent={{240,-450},{260,-430}}))); + Buildings.Controls.OBC.CDL.Logical.Edge staChaSet + "Start changing the setpoint" + annotation (Placement(transformation(extent={{160,-510},{180,-490}}))); + Buildings.Controls.OBC.CDL.Logical.Not chaSetPro + "True: it is in the setpoint changing process" + annotation (Placement(transformation(extent={{320,-450},{340,-430}}))); + Buildings.Controls.OBC.CDL.Reals.Switch byPasSet3 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{400,110},{420,130}}))); + Buildings.Controls.OBC.CDL.Logical.Latch inStaCha + "In stage changing process" + annotation (Placement(transformation(extent={{340,110},{360,130}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam1 + "Setpoint at the moment when ending stage change" + annotation (Placement(transformation(extent={{340,70},{360,90}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge endSta + "End staging change" + annotation (Placement(transformation(extent={{240,50},{260,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge staChaSet1 + "Start changing the setpoint" + annotation (Placement(transformation(extent={{180,-450},{200,-430}}))); +equation + connect(uStaDow, not2.u) + annotation (Line(points={{-460,-290},{-410,-290},{-410,-320},{-222,-320}}, + color={255,0,255})); + connect(and1.y, tim.u) + annotation (Line(points={{-298,520},{-222,520}}, color={255,0,255})); + connect(uStaDow, and3.u1) + annotation (Line(points={{-460,-290},{-322,-290}}, color={255,0,255})); + connect(and3.y, tim1.u) + annotation (Line(points={{-298,-290},{-222,-290}}, color={255,0,255})); + connect(minFlo.y, floRat.u1) + annotation (Line(points={{-378,300},{-300,300},{-300,286},{-282,286}}, + color={0,0,127})); + connect(maxFlo.y, floRat.u2) + annotation (Line(points={{-378,260},{-290,260},{-290,274},{-282,274}}, + color={0,0,127})); + connect(nexDisChi, intRep.u) + annotation (Line(points={{-460,30},{-402,30}}, color={255,127,0})); + connect(conInt.y, intEqu.u1) + annotation (Line(points={{-378,70},{-322,70}}, color={255,127,0})); + connect(intRep.y, intEqu.u2) + annotation (Line(points={{-378,30},{-360,30},{-360,62},{-322,62}}, + color={255,127,0})); + connect(intEqu.y, xor.u1) + annotation (Line(points={{-298,70},{-222,70}}, color={255,0,255})); + connect(xor.y, swi3.u2) + annotation (Line(points={{-198,70},{-140,70},{-140,100},{-122,100}}, + color={255,0,255})); + connect(xor.y, swi4.u2) + annotation (Line(points={{-198,70},{-140,70},{-140,40},{-122,40}}, + color={255,0,255})); + connect(multiMax2.y, pro2.u1) + annotation (Line(points={{-58,100},{-40,100},{-40,76},{-22,76}}, + color={0,0,127})); + connect(mulSum1.y, pro2.u2) + annotation (Line(points={{-58,40},{-40,40},{-40,64},{-22,64}}, + color={0,0,127})); + connect(swi3.y, multiMax2.u) + annotation (Line(points={{-98,100},{-82,100}}, color={0,0,127})); + connect(swi4.y, mulSum1.u) + annotation (Line(points={{-98,40},{-82,40}}, color={0,0,127})); + connect(swi5.y, multiMax1.u) + annotation (Line(points={{-98,-50},{-82,-50}}, color={0,0,127})); + connect(swi6.y, multiMax3.u) + annotation (Line(points={{-78,-130},{-22,-130}}, color={0,0,127})); + connect(multiMax1.y, max1.u1) + annotation (Line(points={{-58,-50},{-40,-50},{-40,-84},{-22,-84}}, + color={0,0,127})); + connect(xor.y, swi6.u2) + annotation (Line(points={{-198,70},{-140,70},{-140,-130},{-102,-130}}, + color={255,0,255})); + connect(uStaDow, or2.u2) + annotation (Line(points={{-460,-290},{-410,-290},{-410,112},{-402,112}}, + color={255,0,255})); + connect(uStaUp, or2.u1) + annotation (Line(points={{-460,520},{-410,520},{-410,120},{-402,120}}, + color={255,0,255})); + connect(booToRea.y, triSam.u) + annotation (Line(points={{-378,350},{-362,350}}, color={0,0,127})); + connect(or2.y, booRep.u) + annotation (Line(points={{-378,120},{-370,120},{-370,140},{-390,140},{-390,160}, + {-382,160}}, color={255,0,255})); + connect(booRep.y, triSam.trigger) + annotation (Line(points={{-358,160},{-350,160},{-350,338}}, color={255,0,255})); + connect(uChi, booToRea.u) + annotation (Line(points={{-460,440},{-420,440},{-420,350},{-402,350}}, + color={255,0,255})); + connect(uChi, swi9.u2) + annotation (Line(points={{-460,440},{-330,440},{-330,450},{-222,450}}, + color={255,0,255})); + connect(uChi, swi10.u2) + annotation (Line(points={{-460,440},{-330,440},{-330,410},{-222,410}}, + color={255,0,255})); + connect(floRat.y, swi9.u1) + annotation (Line(points={{-258,280},{-250,280},{-250,458},{-222,458}}, + color={0,0,127})); + connect(swi9.y, multiMax4.u) + annotation (Line(points={{-198,450},{-182,450}}, + color={0,0,127})); + connect(maxFlo.y, swi10.u1) + annotation (Line(points={{-378,260},{-290,260},{-290,418},{-222,418}}, + color={0,0,127})); + connect(zer.y, swi9.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,442},{-222,442}}, + color={0,0,127})); + connect(zer.y, swi10.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,402},{-222,402}}, + color={0,0,127})); + connect(swi10.y, mulSum2.u) + annotation (Line(points={{-198,410},{-182,410}}, + color={0,0,127})); + connect(multiMax4.y, pro3.u1) + annotation (Line(points={{-158,450},{-140,450},{-140,436},{-62,436}}, + color={0,0,127})); + connect(mulSum2.y, pro3.u2) + annotation (Line(points={{-158,410},{-140,410},{-140,424},{-62,424}}, + color={0,0,127})); + connect(floRat.y, swi12.u1) + annotation (Line(points={{-258,280},{-250,280},{-250,378},{-222,378}}, + color={0,0,127})); + connect(triSam.y, greEquThr.u) + annotation (Line(points={{-338,350},{-322,350}}, color={0,0,127})); + connect(greEquThr.y, swi12.u2) + annotation (Line(points={{-298,350},{-230,350},{-230,370},{-222,370}}, + color={255,0,255})); + connect(greEquThr.y, swi11.u2) + annotation (Line(points={{-298,350},{-230,350},{-230,330},{-222,330}}, + color={255,0,255})); + connect(zer.y, swi12.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,362},{-222,362}}, + color={0,0,127})); + connect(maxFlo.y, swi11.u1) + annotation (Line(points={{-378,260},{-290,260},{-290,338},{-222,338}}, + color={0,0,127})); + connect(zer.y, swi11.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,322},{-222,322}}, + color={0,0,127})); + connect(swi12.y, multiMax5.u) + annotation (Line(points={{-198,370},{-182,370}}, + color={0,0,127})); + connect(swi11.y, mulSum3.u) + annotation (Line(points={{-198,330},{-182,330}}, + color={0,0,127})); + connect(multiMax5.y, pro4.u1) + annotation (Line(points={{-158,370},{-120,370},{-120,356},{-62,356}}, + color={0,0,127})); + connect(mulSum3.y, pro4.u2) + annotation (Line(points={{-158,330},{-100,330},{-100,344},{-62,344}}, + color={0,0,127})); + connect(multiMax5.y, max.u1) + annotation (Line(points={{-158,370},{-120,370},{-120,196},{-82,196}}, + color={0,0,127})); + connect(mulSum3.y, add2.u1) + annotation (Line(points={{-158,330},{-100,330},{-100,156},{-82,156}}, + color={0,0,127})); + connect(max.y, pro1.u1) + annotation (Line(points={{-58,190},{-40,190},{-40,176},{-22,176}}, color={0,0,127})); + connect(add2.y, pro1.u2) + annotation (Line(points={{-58,150},{-40,150},{-40,164},{-22,164}}, color={0,0,127})); + connect(maxFlo.y, nexChiMaxFlo.u) + annotation (Line(points={{-378,260},{-290,260},{-290,150},{-222,150}}, + color={0,0,127})); + connect(greEquThr.y, xor.u2) + annotation (Line(points={{-298,350},{-230,350},{-230,62},{-222,62}}, + color={255,0,255})); + connect(floRat.y, swi3.u1) + annotation (Line(points={{-258,280},{-250,280},{-250,108},{-122,108}}, + color={0,0,127})); + connect(zer.y, swi3.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,92},{-122,92}}, + color={0,0,127})); + connect(zer.y, swi4.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,32},{-122,32}}, + color={0,0,127})); + connect(maxFlo.y, swi4.u1) + annotation (Line(points={{-378,260},{-290,260},{-290,48},{-122,48}}, + color={0,0,127})); + connect(uChi, swi1.u2) + annotation (Line(points={{-460,440},{-330,440},{-330,-10},{-122,-10}}, + color={255,0,255})); + connect(greEquThr.y, swi5.u2) + annotation (Line(points={{-298,350},{-230,350},{-230,-50},{-122,-50}}, + color={255,0,255})); + connect(swi1.y, multiMax6.u) + annotation (Line(points={{-98,-10},{-82,-10}}, + color={0,0,127})); + connect(zer.y, swi1.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,-18},{-122,-18}}, + color={0,0,127})); + connect(zer.y, swi5.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,-58},{-122,-58}}, + color={0,0,127})); + connect(maxFlo.y, swi1.u1) + annotation (Line(points={{-378,260},{-290,260},{-290,-2},{-122,-2}}, + color={0,0,127})); + connect(maxFlo.y, swi5.u1) + annotation (Line(points={{-378,260},{-290,260},{-290,-42},{-122,-42}}, + color={0,0,127})); + connect(maxFlo.y, nexChiMinFlo.u) + annotation (Line(points={{-378,260},{-290,260},{-290,-90},{-222,-90}}, + color={0,0,127})); + connect(maxFlo.y, swi6.u1) + annotation (Line(points={{-378,260},{-290,260},{-290,-122},{-102,-122}}, + color={0,0,127})); + connect(zer.y, swi6.u3) + annotation (Line(points={{-378,220},{-240,220},{-240,-138},{-102,-138}}, + color={0,0,127})); + connect(uUpsDevSta, and1.u2) + annotation (Line(points={{-460,480},{-380,480},{-380,512},{-322,512}}, + color={255,0,255})); + connect(uStaUp, and1.u1) + annotation (Line(points={{-460,520},{-322,520}}, color={255,0,255})); + connect(con2.y, oneMorSet.x1) + annotation (Line(points={{-38,310},{70,310},{70,338},{98,338}}, color={0,0,127})); + connect(pro4.y, oneMorSet.f1) + annotation (Line(points={{-38,350},{60,350},{60,334},{98,334}}, color={0,0,127})); + connect(con3.y, oneMorSet.x2) + annotation (Line(points={{-38,268},{80,268},{80,326},{98,326}}, color={0,0,127})); + connect(pro1.y, oneMorSet.f2) + annotation (Line(points={{2,170},{90,170},{90,322},{98,322}}, + color={0,0,127})); + connect(tim.y, oneMorSet.u) + annotation (Line(points={{-198,520},{50,520},{50,330},{98,330}}, + color={0,0,127})); + connect(con2.y, oneLeSet.x1) + annotation (Line(points={{-38,310},{70,310},{70,-22},{98,-22}}, + color={0,0,127})); + connect(pro4.y, oneLeSet.f1) + annotation (Line(points={{-38,350},{60,350},{60,-26},{98,-26}}, + color={0,0,127})); + connect(con3.y, oneLeSet.x2) + annotation (Line(points={{-38,268},{80,268},{80,-34},{98,-34}}, + color={0,0,127})); + connect(pro2.y, oneLeSet.f2) + annotation (Line(points={{2,70},{50,70},{50,-38},{98,-38}}, + color={0,0,127})); + connect(oneMorSet.y, byPasSet2.u3) + annotation (Line(points={{122,330},{170,330},{170,352},{178,352}}, + color={0,0,127})); + connect(pro3.y, byPasSet2.u1) + annotation (Line(points={{-38,430},{40,430},{40,368},{178,368}}, + color={0,0,127})); + connect(uSubCha, byPasSet2.u2) + annotation (Line(points={{-460,-180},{150,-180},{150,360},{178,360}}, + color={255,0,255})); + connect(uOnOff, upSet.u2) + annotation (Line(points={{-460,-220},{220,-220},{220,320},{238,320}}, + color={255,0,255})); + connect(byPasSet2.y, upSet.u1) + annotation (Line(points={{202,360},{220,360},{220,328},{238,328}}, + color={0,0,127})); + connect(oneMorSet.y, upSet.u3) + annotation (Line(points={{122,330},{170,330},{170,312},{238,312}}, + color={0,0,127})); + connect(uStaDow, and2.u2) + annotation (Line(points={{-460,-290},{-410,-290},{-410,-258},{-322,-258}}, + color={255,0,255})); + connect(uSubCha, and2.u1) + annotation (Line(points={{-460,-180},{-420,-180},{-420,-250},{-322,-250}}, + color={255,0,255})); + connect(and2.y, tim2.u) + annotation (Line(points={{-298,-250},{-222,-250}}, color={255,0,255})); + connect(con2.y, oneMorSet1.x1) + annotation (Line(points={{-38,310},{70,310},{70,-242},{98,-242}}, + color={0,0,127})); + connect(pro4.y, oneMorSet1.f1) + annotation (Line(points={{-38,350},{60,350},{60,-246},{98,-246}}, + color={0,0,127})); + connect(con3.y, oneMorSet1.x2) + annotation (Line(points={{-38,268},{80,268},{80,-254},{98,-254}}, + color={0,0,127})); + connect(pro1.y, oneMorSet1.f2) + annotation (Line(points={{2,170},{90,170},{90,-258},{98,-258}}, + color={0,0,127})); + connect(tim2.y, oneMorSet1.u) + annotation (Line(points={{-198,-250},{98,-250}}, color={0,0,127})); + connect(oneMorSet1.y, byPasSet4.u3) + annotation (Line(points={{122,-250},{140,-250},{140,-208},{158,-208}}, + color={0,0,127})); + connect(uUpsDevSta, byPasSet4.u2) + annotation (Line(points={{-460,480},{-430,480},{-430,-200},{158,-200}}, + color={255,0,255})); + connect(pro3.y, byPasSet4.u1) + annotation (Line(points={{-38,430},{40,430},{40,-192},{158,-192}}, + color={0,0,127})); + connect(uOnOff, dowSet.u2) + annotation (Line(points={{-460,-220},{220,-220},{220,-22},{238,-22}}, + color={255,0,255})); + connect(byPasSet4.y, dowSet.u1) + annotation (Line(points={{182,-200},{200,-200},{200,-14},{238,-14}}, + color={0,0,127})); + connect(uUpsDevSta, and3.u2) + annotation (Line(points={{-460,480},{-430,480},{-430,-298},{-322,-298}}, + color={255,0,255})); + connect(tim1.y, oneLeSet.u) + annotation (Line(points={{-198,-290},{30,-290},{30,-30},{98,-30}}, + color={0,0,127})); + connect(oneLeSet.y, dowSet.u3) + annotation (Line(points={{122,-30},{238,-30}}, + color={0,0,127})); + connect(dowSet.y, chaSet.u3) + annotation (Line(points={{262,-22},{270,-22},{270,192},{298,192}}, + color={0,0,127})); + connect(upSet.y, chaSet.u1) + annotation (Line(points={{262,320},{270,320},{270,208},{298,208}}, + color={0,0,127})); + connect(uStaUp, chaSet.u2) + annotation (Line(points={{-460,520},{-410,520},{-410,500},{280,500},{280,200}, + {298,200}}, color={255,0,255})); + connect(not1.y, and4.u1) + annotation (Line(points={{322,240},{338,240}}, color={255,0,255})); + connect(and4.y, byPasSet1.u2) + annotation (Line(points={{362,240},{398,240}}, color={255,0,255})); + connect(not2.y, and4.u2) + annotation (Line(points={{-198,-320},{330,-320},{330,232},{338,232}}, + color={255,0,255})); + connect(chaSet.y, byPasSet1.u3) + annotation (Line(points={{322,200},{380,200},{380,232},{398,232}}, + color={0,0,127})); + connect(pro3.y, byPasSet1.u1) + annotation (Line(points={{-38,430},{380,430},{380,248},{398,248}}, + color={0,0,127})); + connect(uStaUp, not1.u) + annotation (Line(points={{-460,520},{-410,520},{-410,500},{280,500},{280,240}, + {298,240}}, color={255,0,255})); + connect(multiMax1.y, oneMorSet.f1) + annotation (Line(points={{-58,-50},{60,-50},{60,334},{98,334}}, + color={0,0,127})); + connect(multiMax1.y, oneMorSet1.f1) + annotation (Line(points={{-58,-50},{60,-50},{60,-246},{98,-246}}, + color={0,0,127})); + connect(max1.y, oneMorSet.f2) + annotation (Line(points={{2,-90},{90,-90},{90,322},{98,322}}, + color={0,0,127})); + connect(max1.y, oneMorSet1.f2) + annotation (Line(points={{2,-90},{90,-90},{90,-258},{98,-258}}, + color={0,0,127})); + connect(multiMax3.y, oneLeSet.f2) + annotation (Line(points={{2,-130},{50,-130},{50,-38},{98,-38}}, + color={0,0,127})); + connect(multiMax6.y, byPasSet2.u1) + annotation (Line(points={{-58,-10},{40,-10},{40,368},{178,368}}, + color={0,0,127})); + connect(multiMax6.y, byPasSet4.u1) + annotation (Line(points={{-58,-10},{40,-10},{40,-192},{158,-192}}, + color={0,0,127})); + connect(multiMax6.y, byPasSet1.u1) + annotation (Line(points={{-58,-10},{40,-10},{40,280},{380,280},{380,248},{398, + 248}}, color={0,0,127})); + connect(multiMax1.y, oneLeSet.f1) + annotation (Line(points={{-58,-50},{60,-50},{60,-26},{98,-26}}, + color={0,0,127})); + connect(floRat.y, nexChiRat.u) + annotation (Line(points={{-258,280},{-250,280},{-250,190},{-222,190}}, + color={0,0,127})); + connect(conInt1.y, intSwi.u3) annotation (Line(points={{-338,-160},{-330,-160}, + {-330,-138},{-322,-138}}, color={255,127,0})); + connect(and5.y, booToRea1.u) + annotation (Line(points={{-338,-70},{-322,-70}}, color={255,0,255})); + connect(and5.y, intSwi.u2) annotation (Line(points={{-338,-70},{-330,-70},{-330, + -130},{-322,-130}}, color={255,0,255})); + connect(intGreEquThr.y, and5.u1) + annotation (Line(points={{-378,-70},{-362,-70}}, color={255,0,255})); + connect(intLesEquThr.y, and5.u2) annotation (Line(points={{-378,-160},{-370,-160}, + {-370,-78},{-362,-78}}, color={255,0,255})); + connect(nexEnaChi, intGreEquThr.u) annotation (Line(points={{-460,170},{-420,170}, + {-420,-70},{-402,-70}}, color={255,127,0})); + connect(nexEnaChi, intSwi.u1) annotation (Line(points={{-460,170},{-420,170},{ + -420,-122},{-322,-122}}, color={255,127,0})); + connect(nexEnaChi, intLesEquThr.u) annotation (Line(points={{-460,170},{-420,170}, + {-420,-160},{-402,-160}}, color={255,127,0})); + connect(intSwi.y, nexChiMinFlo.index) annotation (Line(points={{-298,-130},{-280, + -130},{-280,-110},{-210,-110},{-210,-102}}, color={255,127,0})); + connect(intSwi.y, nexChiMaxFlo.index) annotation (Line(points={{-298,-130},{-280, + -130},{-280,130},{-210,130},{-210,138}}, color={255,127,0})); + connect(intSwi.y, nexChiRat.index) annotation (Line(points={{-298,-130},{-280, + -130},{-280,170},{-210,170},{-210,178}}, color={255,127,0})); + connect(booToRea1.y, reaScaRep.u) + annotation (Line(points={{-298,-70},{-272,-70}}, color={0,0,127})); + connect(mul3.y, max1.u2) annotation (Line(points={{-98,-80},{-80,-80},{-80,-96}, + {-22,-96}}, color={0,0,127})); + connect(reaScaRep.y[3], mul3.u1) annotation (Line(points={{-248,-69.3333},{ + -180,-69.3333},{-180,-74},{-122,-74}}, + color={0,0,127})); + connect(reaScaRep.y[1], mul1[1].u2) annotation (Line(points={{-248,-70.6667}, + {-180,-70.6667},{-180,144},{-162,144}},color={0,0,127})); + connect(reaScaRep.y[2], mul1[2].u2) annotation (Line(points={{-248,-70},{-180, + -70},{-180,144},{-162,144}},color={0,0,127})); + connect(nexChiMaxFlo.y, mul1[2].u1) annotation (Line(points={{-198,150},{-180, + 150},{-180,156},{-162,156}}, color={0,0,127})); + connect(nexChiRat.y, mul1[1].u1) annotation (Line(points={{-198,190},{-180,190}, + {-180,156},{-162,156}}, color={0,0,127})); + connect(mul1[1].y, max.u2) annotation (Line(points={{-138,150},{-120,150},{-120, + 184},{-82,184}}, color={0,0,127})); + connect(mul1[2].y, add2.u2) annotation (Line(points={{-138,150},{-120,150},{-120, + 144},{-82,144}}, color={0,0,127})); + connect(nexChiMinFlo.y, mul3.u2) annotation (Line(points={{-198,-90},{-180,-90}, + {-180,-86},{-122,-86}}, color={0,0,127})); + connect(and2.y, or1.u1) annotation (Line(points={{-298,-250},{-270,-250},{-270, + -420},{-162,-420}}, color={255,0,255})); + connect(and3.y, or1.u2) annotation (Line(points={{-298,-290},{-260,-290},{-260, + -428},{-162,-428}}, color={255,0,255})); + connect(tim2.passed, or4.u1) annotation (Line(points={{-198,-258},{-120,-258}, + {-120,-350},{-100,-350}}, color={255,0,255})); + connect(tim1.passed, or4.u2) annotation (Line(points={{-198,-298},{-140,-298}, + {-140,-358},{-100,-358}}, color={255,0,255})); + connect(or1.y, or3.u1) annotation (Line(points={{-138,-420},{-100,-420},{-100, + -440},{-62,-440}}, color={255,0,255})); + connect(or4.y, or5.u1) annotation (Line(points={{-76,-350},{-30,-350},{-30,-370}, + {18,-370}}, color={255,0,255})); + connect(and1.y, or3.u2) annotation (Line(points={{-298,520},{-284,520},{-284,-448}, + {-62,-448}}, color={255,0,255})); + connect(tim.passed, or5.u2) annotation (Line(points={{-198,512},{-132,512},{-132, + -378},{18,-378}}, color={255,0,255})); + connect(or5.y, edg.u) + annotation (Line(points={{42,-370},{58,-370}}, color={255,0,255})); + connect(or3.y, logSwi.u2) + annotation (Line(points={{-38,-440},{118,-440}}, color={255,0,255})); + connect(edg.y, logSwi.u1) annotation (Line(points={{82,-370},{100,-370},{100, + -432},{118,-432}}, + color={255,0,255})); + connect(or3.y, notChaSet.u) annotation (Line(points={{-38,-440},{-20,-440},{-20, + -480},{20,-480}}, color={255,0,255})); + connect(notChaSet.y, logSwi.u3) annotation (Line(points={{44,-480},{100,-480}, + {100,-448},{118,-448}}, color={255,0,255})); + connect(or3.y, staChaSet.u) annotation (Line(points={{-38,-440},{-20,-440},{-20, + -500},{158,-500}}, color={255,0,255})); + connect(staChaSet.y, lat.clr) annotation (Line(points={{182,-500},{220,-500},{ + 220,-446},{238,-446}}, color={255,0,255})); + connect(lat.y, chaSetPro.u) + annotation (Line(points={{262,-440},{318,-440}}, color={255,0,255})); + connect(chaSetPro.y, yChaSet) + annotation (Line(points={{342,-440},{460,-440}}, color={255,0,255})); + connect(byPasSet1.y, byPasSet3.u1) annotation (Line(points={{422,240},{430,240}, + {430,180},{380,180},{380,128},{398,128}}, color={0,0,127})); + connect(inStaCha.y, byPasSet3.u2) + annotation (Line(points={{362,120},{398,120}}, color={255,0,255})); + connect(or2.y, inStaCha.u) + annotation (Line(points={{-378,120},{338,120}}, color={255,0,255})); + connect(byPasSet1.y, triSam1.u) annotation (Line(points={{422,240},{430,240},{ + 430,180},{320,180},{320,80},{338,80}}, color={0,0,127})); + connect(endSta.y, triSam1.trigger) + annotation (Line(points={{262,60},{350,60},{350,68}}, color={255,0,255})); + connect(or2.y, endSta.u) annotation (Line(points={{-378,120},{200,120},{200,60}, + {238,60}}, color={255,0,255})); + connect(endSta.y, inStaCha.clr) annotation (Line(points={{262,60},{300,60},{300, + 114},{338,114}}, color={255,0,255})); + connect(triSam1.y, byPasSet3.u3) annotation (Line(points={{362,80},{380,80},{380, + 112},{398,112}}, color={0,0,127})); + connect(byPasSet3.y, yChiWatMinFloSet) + annotation (Line(points={{422,120},{460,120}}, color={0,0,127})); + connect(logSwi.y, staChaSet1.u) + annotation (Line(points={{142,-440},{178,-440}}, color={255,0,255})); + connect(staChaSet1.y, lat.u) + annotation (Line(points={{202,-440},{238,-440}}, color={255,0,255})); +annotation ( + defaultComponentName="minChiFloSet", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle(extent={{-36,42},{0,28}}, lineColor={28,108,200}), + Rectangle(extent={{-36,28},{0,14}}, lineColor={28,108,200}), + Rectangle(extent={{-36,14},{0,0}}, lineColor={28,108,200}), + Rectangle(extent={{-36,0},{0,-14}}, lineColor={28,108,200}), + Rectangle(extent={{-36,-14},{0,-28}}, lineColor={28,108,200}), + Text( + extent={{-32,38},{-12,32}}, + textColor={28,108,200}, + textString="Stage #"), + Text( + extent={{-30,24},{-10,18}}, + textColor={28,108,200}, + textString="0"), + Text( + extent={{-30,10},{-10,4}}, + textColor={28,108,200}, + textString="1"), + Text( + extent={{-30,-4},{-10,-10}}, + textColor={28,108,200}, + textString="2"), + Rectangle(extent={{-36,-28},{0,-42}}, lineColor={28,108,200}), + Text( + extent={{-30,-18},{-10,-24}}, + textColor={28,108,200}, + textString="..."), + Text( + extent={{-30,-32},{-10,-38}}, + textColor={28,108,200}, + textString="n"), + Rectangle(extent={{2,42},{38,28}}, lineColor={28,108,200}), + Rectangle(extent={{2,28},{38,14}}, lineColor={28,108,200}), + Rectangle(extent={{2,14},{38,0}}, lineColor={28,108,200}), + Rectangle(extent={{2,0},{38,-14}}, lineColor={28,108,200}), + Rectangle(extent={{2,-14},{38,-28}}, lineColor={28,108,200}), + Text( + extent={{8,38},{34,32}}, + textColor={28,108,200}, + textString="Min flow"), + Text( + extent={{6,24},{34,18}}, + textColor={28,108,200}, + textString="minFloSet[1]"), + Rectangle(extent={{2,-28},{38,-42}}, lineColor={28,108,200}), + Text( + extent={{8,-18},{28,-24}}, + textColor={28,108,200}, + textString="..."), + Text( + extent={{6,10},{34,4}}, + textColor={28,108,200}, + textString="minFloSet[2]"), + Text( + extent={{6,-32},{34,-38}}, + textColor={28,108,200}, + textString="minFloSet[n]"), + Text( + extent={{6,-4},{34,-10}}, + textColor={28,108,200}, + textString="minFloSet[3]"), + Text( + extent={{-98,20},{-44,4}}, + textColor={255,127,0}, + textString="nexEnaChi"), + Text( + extent={{-98,0},{-44,-16}}, + textColor={255,127,0}, + textString="nexDisChi"), + Text( + extent={{-98,-82},{-52,-96}}, + textColor={255,0,255}, + textString="uStaDow"), + Text( + extent={{-102,-64},{-60,-76}}, + textColor={255,0,255}, + textString="uOnOff"), + Text( + extent={{-98,-32},{-52,-46}}, + textColor={255,0,255}, + textString="uSubCha"), + Text( + extent={{-98,98},{-58,84}}, + textColor={255,0,255}, + textString="uStaUp"), + Text( + extent={{-98,78},{-38,64}}, + textColor={255,0,255}, + textString="uUpsDevSta"), + Text( + extent={{-98,48},{-70,34}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{44,6},{98,-6}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatMinFloSet"), + Text( + extent={{58,-68},{96,-88}}, + textColor={255,0,255}, + textString="yChaSet")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-440,-540},{440,540}}), graphics={ + Rectangle( + extent={{-398,498},{18,42}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-398,18},{18,-178}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-92,494},{14,478}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Plant with parallel chillers"), + Text( + extent={{-80,22},{18,6}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Plant with series chillers"), + Text( + extent={{-54,214},{18,198}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint when"), + Text( + extent={{-46,202},{18,188}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="enabling additional chiller"), + Text( + extent={{-34,102},{18,88}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="disabling one chiller"), + Text( + extent={{-54,114},{18,98}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint when"), + Text( + extent={{-38,-60},{26,-74}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="enabling additional chiller"), + Text( + extent={{-30,-142},{22,-156}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="disabling one chiller"), + Text( + extent={{-92,472},{10,456}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint according to"), + Text( + extent={{-54,460},{10,446}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="current chillers status"), + Text( + extent={{-88,402},{14,386}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint according to"), + Text( + extent={{-66,390},{14,376}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="chillers status at the moment"), + Text( + extent={{-62,380},{16,366}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="when requiring stage change"), + Text( + extent={{-38,4},{26,-10}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="current chillers status"), + Rectangle( + extent={{-438,-320},{238,-538}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{124,-330},{270,-350}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Check if it is in the setpoint changing process")}), + Documentation(info=" +

+Block that outputs chilled water minimum flow setpoint for primary-only +plants with a minimum flow bypass valve, +according to ASHRAE Guideline36-2021, +section 5.20.8 Chilled water minimum flow bypass valve. +

+

+1. For plants with parallel chillers, bypass valve shall modulate to maintain minimum +flow as measured by the chilled water flow meter at a setpoint that ensures minimum +flow through all operating chillers, as follows: +

+ + + + + + + + + + + + + + + + + + + + + + +
Chiller Minimum flow Maximum flow
1minFloSet[1]maxFloSet[1]
2minFloSet[2]maxFloSet[2]
.........
+
+ +

+2. For plants with series chillers, bypass valve shall modulate to maintain minimum +flow as measured by the chilled water flow meter at a setpoint equal to the largest +minFloSet of the operating chillers in current stage. +

+

+3. If there is any stage change requiring a chiller on and another chiller off, +the minimum flow setpoint shall temporarily change to account for the +minFloSet of both the chiller to be enabled and to be disabled +prior to starting the newly enabled chiller. +

+

+Note that when there is a stage change requiring a change in the +minimum flow setpoint, the change should be slowly. +For example, this could be accomplished by resetting the setpoint X GPM/second, +where X = (NewSetpoint - OldSetpoint) / byPasSetTim. +

+", revisions=" + +")); +end FlowSetpoint; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/Controller.mo new file mode 100644 index 00000000000..3071613bfd2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/Controller.mo @@ -0,0 +1,106 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Validation; +model Controller "Validate control of minimum bypass valve" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Controller + minBypValCon( + nChi=3, + minFloSet={0.005,0.005,0.005}) + "Minimum bypass valve position" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse chiFloSet( + amplitude=-0.005, + period=3, + offset=0.015) + "Minimum flow setpoint" + annotation (Placement(transformation(extent={{-80,-82},{-60,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiWatPum( + width=0.15, + period=4, + shift=0.1) + "Chilled water pump on command" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not4 "Logical not" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + amplitude=0.0025, + freqHz=1/2, + offset=0.005) + "Output sine wave value" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram( + height=0.015, + duration=2, + startTime=1.2) + "Output ramp value" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 + "Measured minimum bypass flow rate" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + +equation + connect(chiWatPum.y, not4.u) + annotation (Line(points={{-58,60},{-42,60}}, color={255,0,255})); + connect(not4.y, minBypValCon.uChiWatPum) + annotation (Line(points={{-18,60},{20,60},{20,8},{38,8}}, + color={255,0,255})); + connect(sin.y, add2.u1) + annotation (Line(points={{-58,20},{-40,20},{-40,6},{-22,6}}, + color={0,0,127})); + connect(ram.y, add2.u2) + annotation (Line(points={{-58,-20},{-40,-20},{-40,-6},{-22,-6}}, + color={0,0,127})); + connect(add2.y, minBypValCon.VChiWat_flow) + annotation (Line(points={{2,0},{38,0}}, + color={0,0,127})); + connect(chiFloSet.y, minBypValCon.VChiWatSet_flow) + annotation (Line(points={{-58,-71},{20,-71},{20,-8},{38,-8}}, color={0,0,127})); + +annotation ( + experiment(StopTime=4.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Controller. +It demonstrates the bypass valve control to maintain the minimum +chilled water flow through the chillers. +

+ +", revisions=" + +"), +Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/FlowSetpoint.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/FlowSetpoint.mo new file mode 100644 index 00000000000..366299b9dda --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/FlowSetpoint.mo @@ -0,0 +1,255 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Validation; +model FlowSetpoint + "Validation sequence of specifying minimum bypass flow setpoint" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + staUp( + nChi=3, + byPasSetTim=1.5) + "Minimum flow setpoint when there is stage up command" + annotation (Placement(transformation(extent={{120,170},{140,190}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + onOffStaUp( + nChi=3, + byPasSetTim=1.5) + "Minimum flow setpoint when there is stage up command and the change requires one chiller off and another chiller on" + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + staDow( + nChi=3, + byPasSetTim=1.5) + "Minimum flow setpoint when there is stage down command" + annotation (Placement(transformation(extent={{120,-170},{140,-150}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noOnOff( + final k=false) + "No chiller on/off during the stage change" + annotation (Placement(transformation(extent={{-140,50},{-120,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse staCha( + final width=0.25, + final period=4) "Stage up command" + annotation (Placement(transformation(extent={{-140,190},{-120,210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse upDev( + final width=0.3, + final period=4) + "Status of upflow device" + annotation (Placement(transformation(extent={{-140,160},{-120,180}}))); + Buildings.Controls.OBC.CDL.Reals.Switch enaChi "Next enabling chiller" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noStaCha( + final k=false) "No stage change" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-100,190},{-80,210}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-100,160},{-80,180}}))); + Buildings.Controls.OBC.CDL.Reals.Switch disChi "Disabling chiller" + annotation (Placement(transformation(extent={{-40,-130},{-20,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant haveOnOff( + final k=true) + "Have chiller on/off during the stage change" + annotation (Placement(transformation(extent={{-140,-70},{-120,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaNexChi( + final width=0.8, + final period=4) + "Enable next chiller" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con( + final k=3) "Index of enabling chiller" + annotation (Placement(transformation(extent={{-140,110},{-120,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) "Zero" + annotation (Placement(transformation(extent={{-140,-190},{-120,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1( + final k=2) "Index of disabling chiller" + annotation (Placement(transformation(extent={{-140,-110},{-120,-90}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real input to integer output" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{0,-130},{20,-110}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{0,-190},{20,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta[3]( + final k={true,true,false}) + "Current chiller status" + annotation (Placement(transformation(extent={{-40,130},{-20,150}}))); + +equation + connect(noOnOff.y, staUp.uOnOff) + annotation (Line(points={{-118,60},{76,60},{76,173},{118,173}}, + color={255,0,255})); + connect(noStaCha.y, staUp.uStaDow) + annotation (Line(points={{-118,20},{92,20},{92,171},{118,171}}, + color={255,0,255})); + connect(staCha.y, not1.u) + annotation (Line(points={{-118,200},{-102,200}}, color={255,0,255})); + connect(upDev.y, not2.u) + annotation (Line(points={{-118,170},{-102,170}}, color={255,0,255})); + connect(not1.y,enaChi. u2) + annotation (Line(points={{-78,200},{-60,200},{-60,100},{-42,100}}, + color={255,0,255})); + connect(not1.y, staUp.uStaUp) + annotation (Line(points={{-78,200},{68,200},{68,189},{118,189}}, + color={255,0,255})); + connect(not2.y, staUp.uUpsDevSta) + annotation (Line(points={{-78,170},{72,170},{72,187},{118,187}}, + color={255,0,255})); + connect(not1.y, disChi.u2) + annotation (Line(points={{-78,200},{-60,200},{-60,-120},{-42,-120}}, + color={255,0,255})); + connect(noOnOff.y, staDow.uOnOff) + annotation (Line(points={{-118,60},{76,60},{76,-167},{118,-167}}, + color={255,0,255})); + connect(noStaCha.y, staDow.uStaUp) + annotation (Line(points={{-118,20},{92,20},{92,-151},{118,-151}}, + color={255,0,255})); + connect(not2.y, staDow.uUpsDevSta) + annotation (Line(points={{-78,170},{72,170},{72,-153},{118,-153}}, + color={255,0,255})); + connect(not1.y, staDow.uStaDow) + annotation (Line(points={{-78,200},{68,200},{68,-169},{118,-169}}, + color={255,0,255})); + connect(not1.y, onOffStaUp.uStaUp) + annotation (Line(points={{-78,200},{68,200},{68,9},{118,9}}, + color={255,0,255})); + connect(not2.y, onOffStaUp.uUpsDevSta) + annotation (Line(points={{-78,170},{72,170},{72,7},{118,7}}, + color={255,0,255})); + connect(haveOnOff.y, onOffStaUp.uOnOff) + annotation (Line(points={{-118,-60},{40,-60},{40,-7},{118,-7}}, + color={255,0,255})); + connect(noStaCha.y, onOffStaUp.uStaDow) + annotation (Line(points={{-118,20},{0,20},{0,-9},{118,-9}}, + color={255,0,255})); + connect(con.y, enaChi.u1) + annotation (Line(points={{-118,120},{-100,120},{-100,108},{-42,108}}, + color={0,0,127})); + connect(con1.y, disChi.u1) + annotation (Line(points={{-118,-100},{-100,-100},{-100,-112},{-42,-112}}, + color={0,0,127})); + connect(zer.y, enaChi.u3) + annotation (Line(points={{-118,-180},{-64,-180},{-64,92},{-42,92}}, + color={0,0,127})); + connect(zer.y, disChi.u3) + annotation (Line(points={{-118,-180},{-64,-180},{-64,-128},{-42,-128}}, + color={0,0,127})); + connect(enaChi.y, reaToInt.u) + annotation (Line(points={{-18,100},{-2,100}}, color={0,0,127})); + connect(disChi.y, reaToInt1.u) + annotation (Line(points={{-18,-120},{-2,-120}}, color={0,0,127})); + connect(zer.y, reaToInt2.u) + annotation (Line(points={{-118,-180},{-60,-180},{-60,-180},{-2,-180}}, + color={0,0,127})); + connect(chiSta.y, staUp.uChi) + annotation (Line(points={{-18,140},{80,140},{80,184},{118,184}}, + color={255,0,255})); + connect(chiSta.y, onOffStaUp.uChi) + annotation (Line(points={{-18,140},{80,140},{80,4},{118,4}}, + color={255,0,255})); + connect(chiSta.y, staDow.uChi) + annotation (Line(points={{-18,140},{80,140},{80,-156},{118,-156}}, + color={255,0,255})); + connect(reaToInt.y, staUp.nexEnaChi) + annotation (Line(points={{22,100},{88,100},{88,181},{118,181}}, + color={255,127,0})); + connect(reaToInt2.y, staUp.nexDisChi) + annotation (Line(points={{22,-180},{84,-180},{84,179},{118,179}}, + color={255,127,0})); + connect(reaToInt2.y, staDow.nexEnaChi) + annotation (Line(points={{22,-180},{84,-180},{84,-159},{118,-159}}, + color={255,127,0})); + connect(reaToInt1.y, staDow.nexDisChi) + annotation (Line(points={{22,-120},{88,-120},{88,-161},{118,-161}}, + color={255,127,0})); + connect(reaToInt.y, onOffStaUp.nexEnaChi) + annotation (Line(points={{22,100},{88,100},{88,1},{118,1}}, + color={255,127,0})); + connect(reaToInt1.y, onOffStaUp.nexDisChi) + annotation (Line(points={{22,-120},{88,-120},{88,-1},{118,-1}}, + color={255,127,0})); + connect(enaNexChi.y, not3.u) + annotation (Line(points={{-118,-20},{-102,-20}}, color={255,0,255})); + connect(noOnOff.y, staUp.uSubCha) annotation (Line(points={{-118,60},{ + 76,60},{76,176},{118,176}}, color={255,0,255})); + connect(noOnOff.y, staDow.uSubCha) annotation (Line(points={{-118,60},{ + 76,60},{76,-164},{118,-164}}, color={255,0,255})); + connect(not3.y, onOffStaUp.uSubCha) annotation (Line(points={{-78,-20}, + {20,-20},{20,-4},{118,-4}}, color={255,0,255})); + +annotation ( + experiment(StopTime=4.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/FlowSetpoint.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint. +It shows the calculation of the minimum chilled waterflow through +the operating chillers. +

+

+It includes three instances staUp, staDow, +and onOffStaUp that shows the minimum chilled waterflow +setpoint when the plant is stageing up, staging down, and staging up +with one chiller being enabled and another one chiller being disabled. +

+ +", revisions=" + +"), +Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100, + -100},{100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-220},{160, + 220}}))); +end FlowSetpoint; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/package.mo new file mode 100644 index 00000000000..fdc1f0fd350 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/package.mo @@ -0,0 +1,29 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/package.order new file mode 100644 index 00000000000..963d7cb2bbf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/package.order @@ -0,0 +1,2 @@ +Controller +FlowSetpoint diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.mo new file mode 100644 index 00000000000..cfce18c7f18 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.mo @@ -0,0 +1,44 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package MinimumFlowBypass "Sequences for controlling chilled water minimum flow bypass valve" + +annotation (preferredView="info", Documentation(info=" +

+This package contains chilled water minimum flow bypass valve control sequences. +The implementation is based on section 5.20.8. in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end MinimumFlowBypass; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.order new file mode 100644 index 00000000000..f9fe0732435 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.order @@ -0,0 +1,3 @@ +Controller +FlowSetpoint +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Controller.mo new file mode 100644 index 00000000000..bc739f1e489 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Controller.mo @@ -0,0 +1,671 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater; +block Controller + "Sequences to control chilled water pumps in primary-only plant system" + + parameter Boolean have_heaPum = true + "Flag of headered chilled water pumps design: true=headered, false=dedicated"; + parameter Boolean have_locSen = false + "Flag of local DP sensor: true=local DP sensor hardwired to controller"; + parameter Boolean have_WSE = false + "True: the plant has waterside economizer"; + parameter Integer nPum = 2 + "Total number of chilled water pumps"; + parameter Integer nChi = 2 + "Total number of chillers"; + parameter Integer nSen=2 + "Total number of remote differential pressure sensors"; + parameter Real minPumSpe=0.1 "Minimum pump speed"; + parameter Real maxPumSpe=1 "Maximum pump speed"; + parameter Integer nPum_nominal( + final max=nPum, + final min=1)=nPum + "Total number of pumps that operate at design conditions" + annotation (Dialog(group="Nominal conditions")); + parameter Real VChiWat_flow_nominal( + final unit="m3/s", + final quantity="VolumeFlowRate", + final min=1e-6)=0.5 + "Total plant design chilled water flow rate" + annotation (Dialog(group="Nominal conditions")); + parameter Real maxLocDp( + final unit="Pa", + final quantity="PressureDifference")=15*6894.75 + "Maximum chilled water loop local differential pressure setpoint" + annotation (Dialog(group="Pump speed control when there is local DP sensor", enable=have_locSen)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="Speed controller")); + parameter Real k=1 "Gain of controller" + annotation (Dialog(group="Speed controller")); + parameter Real Ti( + final unit="s", + final quantity="Time", + displayUnit="s")=0.5 "Time constant of integrator block" + annotation (Dialog(group="Speed controller")); + parameter Real Td( + final unit="s", + final quantity="Time", + displayUnit="s")=0.1 "Time constant of derivative block" + annotation (Dialog(group="Speed controller", + enable= + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uPumLeaLag[nPum] if have_heaPum + "Index of chilled water pumps in lead-lag order: lead pump, first lag pump, second lag pump, etc." + annotation (Placement(transformation(extent={{-320,210},{-280,250}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla if not have_heaPum + "True: plant is enabled" + annotation (Placement(transformation(extent={{-320,170},{-280,210}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nPum] + "Chilled water pumps proven on status" + annotation (Placement(transformation(extent={{-320,130},{-280,170}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiEna if not have_heaPum + "Lead chiller enabling status" + annotation (Placement(transformation(extent={{-320,100},{-280,140}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiSta if not have_heaPum + "Lead chiller proven on status" + annotation (Placement(transformation(extent={{-320,70},{-280,110}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiWatReq + if not have_heaPum + "Status indicating if lead chiller is requesting chilled water" + annotation (Placement(transformation(extent={{-320,40},{-280,80}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_heaPum and have_WSE + "True: the plant has waterside economizer" + annotation (Placement(transformation(extent={{-320,-20},{-280,20}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) if have_heaPum + "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-320,10},{-280,50}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final unit="m3/s") if have_heaPum + "Chilled water flow" + annotation (Placement(transformation(extent={{-320,-70},{-280,-30}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_local( + final unit="Pa", + final quantity="PressureDifference") if have_locSen + "Chilled water differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-320,-180},{-280,-140}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen)) + "Chilled water differential static pressure from remote sensor" + annotation (Placement(transformation(extent={{-320,-220},{-280,-180}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatSet_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference",nSen)) + "Chilled water differential static pressure setpoint" + annotation (Placement(transformation(extent={{-320,-270},{-280,-230}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea + "Lead pump status setpoint" + annotation (Placement(transformation(extent={{280,60},{320,100}}), + iconTransformation(extent={{100,60},{140,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiWatPum[nPum] + if have_heaPum + "Chilled water pump status setpoint" + annotation (Placement(transformation(extent={{280,20},{320,60}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumSpe( + final min=0, + final max=1, + final unit="1") "Enabled chilled water pump speed" + annotation (Placement(transformation(extent={{280,-220},{320,-180}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpChiWatPumSet_local( + final quantity="PressureDifference", + final unit="Pa", + displayUnit="Pa") if have_locSen + "Local differential pressure setpoint" + annotation (Placement(transformation(extent={{280,-260},{320,-220}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_dedicated + enaDedLeaPum if not have_heaPum + "Enable lead pump of dedicated pumps" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_headered + enaHeaLeaPum(final nChi=nChi, final have_WSE=have_WSE) + if have_heaPum + "Enable lead pump of headered pumps" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLag_primary_dP + enaLagChiPum( + final nPum=nPum, + final nPum_nominal=nPum_nominal, + final VChiWat_flow_nominal=VChiWat_flow_nominal) if have_heaPum + "Enable lag pump for primary-only plants using differential pressure pump speed control" + annotation (Placement(transformation(extent={{-240,-26},{-220,-6}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Speed_primary_localDp + pumSpeLocDp( + final nSen=nSen, + final nPum=nPum, + final minLocDp=minLocDp, + final maxLocDp=maxLocDp, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td) if have_locSen + "Chilled water pump speed control with local DP sensor" + annotation (Placement(transformation(extent={{0,-220},{20,-200}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Speed_primary_remoteDp + pumSpeRemDp( + final nSen=nSen, + final nPum=nPum, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td) if not have_locSen + "Chilled water pump speed control with remote DP sensor" + annotation (Placement(transformation(extent={{-60,-250},{-40,-230}}))); + +protected + final parameter Real minLocDp( + final unit="Pa", + final quantity="PressureDifference")=5*6894.75 + "Minimum chilled water loop local differential pressure setpoint" + annotation (Dialog(group="Pump speed control when there is local DP sensor", enable=have_locSen)); + final parameter Integer pumInd[nPum]={i for i in 1:nPum} + "Pump index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) if have_heaPum + "Constant one" + annotation (Placement(transformation(extent={{-220,190},{-200,210}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nPum) if have_heaPum + "Replicate integer input" + annotation (Placement(transformation(extent={{0,220},{20,240}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nPum) if have_heaPum + "Replicate boolean input" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1( + final nout=nPum) if have_heaPum + "Replicate integer input" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nPum) if have_heaPum + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep2( + final nout=nPum) if have_heaPum + "Replicate integer input" + annotation (Placement(transformation(extent={{20,-100},{40,-80}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nPum) if have_heaPum + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nPum] + if have_heaPum + "Convert integer to real number" + annotation (Placement(transformation(extent={{-220,220},{-200,240}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor leaPum( + final nin=nPum) if have_heaPum + "Lead pump index" + annotation (Placement(transformation(extent={{-80,220},{-60,240}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt if have_heaPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,220},{-20,240}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant pumIndCon[nPum]( + final k=pumInd) if have_heaPum + "Pump index array" + annotation (Placement(transformation(extent={{-220,160},{-200,180}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nPum] if have_heaPum + "Check lead pump" + annotation (Placement(transformation(extent={{60,180},{80,200}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor nexLagPum( + final nin=nPum) if have_heaPum + "Next lag pump" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 if have_heaPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu2[nPum] if have_heaPum + "Check next lag pump" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor lasLagPum( + final nin=nPum) if have_heaPum + "Last lag pump" + annotation (Placement(transformation(extent={{-80,-100},{-60,-80}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 if have_heaPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-50,-100},{-30,-80}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu3[nPum] if have_heaPum + "Check next lag pump" + annotation (Placement(transformation(extent={{60,-100},{80,-80}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nPum] + if have_heaPum + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-240,-130},{-220,-110}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nPum) if have_heaPum + "Sum of integer inputs" + annotation (Placement(transformation(extent={{-200,-130},{-180,-110}}))); + Buildings.Controls.OBC.CDL.Integers.Add addInt if have_heaPum + "Integer add" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu4[nPum] if have_heaPum + "Check if all the pumps have achieved the setpoint status" + annotation (Placement(transformation(extent={{-200,-80},{-180,-60}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nPum] if have_heaPum + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-240,-80},{-220,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[nPum] if have_heaPum + "Breaks algebraic loops" + annotation (Placement(transformation(extent={{220,-130},{240,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch leaPumSta[nPum] if have_heaPum + "Lead pump status" + annotation (Placement(transformation(extent={{120,180},{140,200}}))); + Buildings.Controls.OBC.CDL.Logical.Switch nexLagPumSta[nPum] if have_heaPum + "Next lag pump status" + annotation (Placement(transformation(extent={{120,-40},{140,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Switch lasLagPumSta[nPum] if have_heaPum + "Last lag pump status" + annotation (Placement(transformation(extent={{120,-100},{140,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Or enaPum[nPum] if have_heaPum + "Chilled water pump status" + annotation (Placement(transformation(extent={{180,-40},{200,-20}}))); + Buildings.Controls.OBC.CDL.Logical.And pumSta[nPum] if have_heaPum + "Chilled water pump status" + annotation (Placement(transformation(extent={{180,-100},{200,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Switch addPum[nPum] if have_heaPum + "Add pump" + annotation (Placement(transformation(extent={{240,-10},{260,10}}))); + Buildings.Controls.OBC.CDL.Logical.Switch remPum[nPum] if have_heaPum + "Remove pump" + annotation (Placement(transformation(extent={{220,-80},{240,-60}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=nPum) if have_heaPum + "Check if all the pumps have achieved the setpoint status" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Latch enaNexLag if have_heaPum + "Hold the enabling signal till the pump is proven on" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + Buildings.Controls.OBC.CDL.Logical.Latch disLasLag if have_heaPum + "Hold the disabling signal till the pump is proven off" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 if have_heaPum + "Logical not" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Logical.And pumSta1[nPum] if have_heaPum + "Chilled water pump status" + annotation (Placement(transformation(extent={{240,30},{260,50}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Check if there is any enabled pump" + annotation (Placement(transformation(extent={{-100,110},{-80,130}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Check if the lead pump is enabled" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr if have_heaPum + "Check if there is any pump running" + annotation (Placement(transformation(extent={{-160,-170},{-140,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1(final k=1) + if have_heaPum + "Dummy index" + annotation (Placement(transformation(extent={{-200,-190},{-180,-170}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi if have_heaPum + "Output 1 when there is no pump running, to avoid warning downstream" + annotation (Placement(transformation(extent={{-100,-170},{-80,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply mulInt if have_heaPum + "Output zero when there is no pump running" + annotation (Placement(transformation(extent={{-10,-100},{10,-80}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt2 + if have_heaPum + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-50,-130},{-30,-110}}))); + +equation + connect(enaDedLeaPum.uLeaChiEna, uLeaChiEna) + annotation (Line(points={{-202,113},{-250,113},{-250,120},{-300,120}}, + color={255,0,255})); + connect(enaDedLeaPum.uLeaChiSta, uLeaChiSta) + annotation (Line(points={{-202,107},{-240,107},{-240,90},{-300,90}}, + color={255,0,255})); + connect(enaDedLeaPum.uLeaChiWatReq, uLeaChiWatReq) + annotation (Line(points={{-202,102},{-230,102},{-230,60},{-300,60}}, + color={255,0,255})); + connect(uPumLeaLag, intToRea.u) + annotation (Line(points={{-300,230},{-222,230}}, color={255,127,0})); + connect(intToRea.y, leaPum.u) + annotation (Line(points={{-198,230},{-82,230}}, color={0,0,127})); + connect(conInt.y, leaPum.index) + annotation (Line(points={{-198,200},{-70,200},{-70,218}}, color={255,127,0})); + connect(leaPum.y, reaToInt.u) + annotation (Line(points={{-58,230},{-42,230}},color={0,0,127})); + connect(reaToInt.y, intRep.u) + annotation (Line(points={{-18,230},{-2,230}}, color={255,127,0})); + connect(intRep.y, intEqu1.u1) + annotation (Line(points={{22,230},{30,230},{30,190},{58,190}}, color={255,127,0})); + connect(pumIndCon.y, intEqu1.u2) + annotation (Line(points={{-198,170},{50,170},{50,182},{58,182}}, + color={255,127,0})); + connect(intEqu1.y, leaPumSta.u2) + annotation (Line(points={{82,190},{118,190}}, color={255,0,255})); + connect(uChiWatPum, leaPumSta.u3) + annotation (Line(points={{-300,150},{100,150},{100,182},{118,182}}, + color={255,0,255})); + connect(booRep.y, leaPumSta.u1) + annotation (Line(points={{22,100},{90,100},{90,198},{118,198}}, + color={255,0,255})); + connect(intToRea.y, nexLagPum.u) + annotation (Line(points={{-198,230},{-160,230},{-160,-50},{-82,-50}}, + color={0,0,127})); + connect(nexLagPum.y, reaToInt1.u) + annotation (Line(points={{-58,-50},{-42,-50}}, color={0,0,127})); + connect(reaToInt1.y, intRep1.u) + annotation (Line(points={{-18,-50},{-2,-50}}, color={255,127,0})); + connect(intRep1.y, intEqu2.u2) + annotation (Line(points={{22,-50},{40,-50},{40,-38},{58,-38}}, color={255,127,0})); + connect(pumIndCon.y, intEqu2.u1) + annotation (Line(points={{-198,170},{50,170},{50,-30},{58,-30}}, + color={255,127,0})); + connect(intEqu2.y, nexLagPumSta.u2) + annotation (Line(points={{82,-30},{118,-30}}, color={255,0,255})); + connect(booRep1.y, nexLagPumSta.u1) + annotation (Line(points={{82,30},{110,30},{110,-22},{118,-22}}, + color={255,0,255})); + connect(uChiWatPum, nexLagPumSta.u3) + annotation (Line(points={{-300,150},{100,150},{100,-38},{118,-38}}, + color={255,0,255})); + connect(lasLagPum.y, reaToInt2.u) + annotation (Line(points={{-58,-90},{-52,-90}}, color={0,0,127})); + connect(intRep2.y, intEqu3.u2) + annotation (Line(points={{42,-90},{46,-90},{46,-98},{58,-98}}, + color={255,127,0})); + connect(pumIndCon.y, intEqu3.u1) + annotation (Line(points={{-198,170},{50,170},{50,-90},{58,-90}}, + color={255,127,0})); + connect(intEqu3.y, lasLagPumSta.u2) + annotation (Line(points={{82,-90},{118,-90}}, color={255,0,255})); + connect(enaLagChiPum.VChiWat_flow, VChiWat_flow) + annotation (Line(points={{-242,-12},{-250,-12},{-250,-50},{-300,-50}}, + color={0,0,127})); + connect(uChiWatPum, enaLagChiPum.uChiWatPum) + annotation (Line(points={{-300,150},{-260,150},{-260,-19.8},{-242,-19.8}}, + color={255,0,255})); + connect(intToRea.y, lasLagPum.u) + annotation (Line(points={{-198,230},{-160,230},{-160,-90},{-82,-90}}, + color={0,0,127})); + connect(booRep2.y, lasLagPumSta.u1) + annotation (Line(points={{82,0},{90,0},{90,-82},{118,-82}}, + color={255,0,255})); + connect(uChiWatPum, lasLagPumSta.u3) + annotation (Line(points={{-300,150},{100,150},{100,-98},{118,-98}}, + color={255,0,255})); + connect(nexLagPumSta.y,enaPum. u2) + annotation (Line(points={{142,-30},{150,-30},{150,-38},{178,-38}}, + color={255,0,255})); + connect(leaPumSta.y,enaPum. u1) + annotation (Line(points={{142,190},{160,190},{160,-30},{178,-30}}, + color={255,0,255})); + connect(pumSpeLocDp.dpChiWat_local, dpChiWat_local) + annotation (Line(points={{-2,-202},{-240,-202},{-240,-160},{-300,-160}}, + color={0,0,127})); + connect(pumSpeLocDp.dpChiWat_remote, dpChiWat_remote) + annotation (Line(points={{-2,-214},{-270,-214},{-270,-200},{-300,-200}}, + color={0,0,127})); + connect(pumSpeLocDp.dpChiWatSet_remote, dpChiWatSet_remote) annotation (Line( + points={{-2,-218},{-220,-218},{-220,-250},{-300,-250}}, color={0,0,127})); + connect(dpChiWat_remote, pumSpeRemDp.dpChiWat_remote) annotation (Line(points={{-300, + -200},{-270,-200},{-270,-240},{-62,-240}}, color={0,0,127})); + connect(dpChiWatSet_remote, pumSpeRemDp.dpChiWatSet_remote) annotation (Line( + points={{-300,-250},{-220,-250},{-220,-248},{-62,-248}}, color={0,0,127})); + connect(enaPum.y, pumSta.u2) + annotation (Line(points={{202,-30},{210,-30},{210,-50},{150,-50},{150,-98}, + {178,-98}}, color={255,0,255})); + connect(lasLagPumSta.y, pumSta.u1) + annotation (Line(points={{142,-90},{178,-90}}, color={255,0,255})); + connect(booRep2.y, remPum.u2) + annotation (Line(points={{82,0},{90,0},{90,-70},{218,-70}}, + color={255,0,255})); + connect(pumSta.y, remPum.u3) + annotation (Line(points={{202,-90},{210,-90},{210,-78},{218,-78}}, + color={255,0,255})); + connect(leaPumSta.y, remPum.u1) + annotation (Line(points={{142,190},{160,190},{160,-62},{218,-62}}, color={255,0,255})); + connect(enaPum.y, addPum.u1) + annotation (Line(points={{202,-30},{210,-30},{210,8},{238,8}}, color={255,0,255})); + connect(booRep1.y, addPum.u2) + annotation (Line(points={{82,30},{110,30},{110,0},{238,0}}, color={255,0,255})); + connect(remPum.y, addPum.u3) + annotation (Line(points={{242,-70},{250,-70},{250,-20},{220,-20},{220,-8}, + {238,-8}}, color={255,0,255})); + connect(uChiWatPum, booToInt.u) + annotation (Line(points={{-300,150},{-260,150},{-260,-120},{-242,-120}}, + color={255,0,255})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-218,-120},{-202,-120}}, color={255,127,0})); + connect(addInt.y, nexLagPum.index) + annotation (Line(points={{-118,-70},{-70,-70},{-70,-62}},color={255,127,0})); + connect(mulSumInt.y, addInt.u2) + annotation (Line(points={{-178,-120},{-170,-120},{-170,-76},{-142,-76}}, + color={255,127,0})); + connect(conInt.y, addInt.u1) + annotation (Line(points={{-198,200},{-150,200},{-150,-64},{-142,-64}}, + color={255,127,0})); + connect(enaDedLeaPum.uPla, uPla) + annotation (Line(points={{-202,118},{-240,118},{-240,190},{-300,190}}, + color={255,0,255})); + connect(uChiWatPum, pumSpeLocDp.uChiWatPum) annotation (Line(points={{-300,150}, + {-260,150},{-260,-206},{-2,-206}}, color={255,0,255})); + connect(uChiWatPum, pumSpeRemDp.uChiWatPum) annotation (Line(points={{-300,150}, + {-260,150},{-260,-232},{-62,-232}}, color={255,0,255})); + connect(pumSpeLocDp.yChiWatPumSpe, yPumSpe) + annotation (Line(points={{22,-210},{162,-210},{162,-200},{300,-200}}, + color={0,0,127})); + connect(pumSpeRemDp.yChiWatPumSpe, yPumSpe) annotation (Line(points={{-39,-240}, + {40,-240},{40,-200},{300,-200}}, color={0,0,127})); + connect(enaLagChiPum.yUp, enaNexLag.u) annotation (Line(points={{-218,-12},{-196, + -12},{-196,30},{-2,30}}, + color={255,0,255})); + connect(enaNexLag.y, booRep1.u) + annotation (Line(points={{22,30},{58,30}}, color={255,0,255})); + connect(booToInt1.y, intEqu4.u1) + annotation (Line(points={{-218,-70},{-202,-70}}, color={255,127,0})); + connect(booToInt.y, intEqu4.u2) annotation (Line(points={{-218,-120},{-210,-120}, + {-210,-78},{-202,-78}}, color={255,127,0})); + connect(intEqu4.y, mulAnd.u) annotation (Line(points={{-178,-70},{-170,-70},{-170, + -20},{-142,-20}}, color={255,0,255})); + connect(disLasLag.y, not2.u) + annotation (Line(points={{-18,0},{-2,0}}, color={255,0,255})); + connect(not2.y, booRep2.u) + annotation (Line(points={{22,0},{58,0}}, color={255,0,255})); + connect(pumSpeLocDp.dpChiWatPumSet_local, dpChiWatPumSet_local) annotation ( + Line(points={{22,-216},{200,-216},{200,-240},{300,-240}}, color={0,0,127})); + connect(booRep.y, pumSta1.u1) annotation (Line(points={{22,100},{90,100},{90,40}, + {238,40}}, color={255,0,255})); + connect(addPum.y, pumSta1.u2) annotation (Line(points={{262,0},{268,0},{268,20}, + {220,20},{220,32},{238,32}}, color={255,0,255})); + connect(pumSta1.y, yChiWatPum) + annotation (Line(points={{262,40},{300,40}}, color={255,0,255})); + connect(pumSta1.y, pre1.u) annotation (Line(points={{262,40},{272,40},{272,-100}, + {210,-100},{210,-120},{218,-120}}, color={255,0,255})); + connect(uChiWatIsoVal, enaHeaLeaPum.uChiWatIsoVal) annotation (Line(points={{-300,30}, + {-222,30},{-222,70},{-202,70}}, color={0,0,127})); + connect(uChiWatPum, mulOr.u) annotation (Line(points={{-300,150},{-140,150},{-140, + 120},{-102,120}}, color={255,0,255})); + connect(mulOr.y, or2.u1) annotation (Line(points={{-78,120},{-70,120},{-70,100}, + {-62,100}}, color={255,0,255})); + connect(enaDedLeaPum.yLea, or2.u2) annotation (Line(points={{-178,110},{-120,110}, + {-120,92},{-62,92}}, color={255,0,255})); + connect(enaHeaLeaPum.yLea, or2.u2) annotation (Line(points={{-178,70},{-120,70}, + {-120,92},{-62,92}}, color={255,0,255})); + connect(or2.y, yLea) annotation (Line(points={{-38,100},{-20,100},{-20,80},{300, + 80}}, color={255,0,255})); + connect(or2.y, booRep.u) + annotation (Line(points={{-38,100},{-2,100}}, color={255,0,255})); + connect(mulSumInt.y, intGreThr.u) annotation (Line(points={{-178,-120},{-170,-120}, + {-170,-160},{-162,-160}}, color={255,127,0})); + connect(intGreThr.y, intSwi.u2) + annotation (Line(points={{-138,-160},{-102,-160}}, color={255,0,255})); + connect(intSwi.y, lasLagPum.index) annotation (Line(points={{-78,-160},{-70,-160}, + {-70,-102}}, color={255,127,0})); + connect(mulSumInt.y, intSwi.u1) annotation (Line(points={{-178,-120},{-130,-120}, + {-130,-152},{-102,-152}}, color={255,127,0})); + connect(conInt1.y, intSwi.u3) annotation (Line(points={{-178,-180},{-130,-180}, + {-130,-168},{-102,-168}}, color={255,127,0})); + connect(intGreThr.y, booToInt2.u) annotation (Line(points={{-138,-160},{-120,-160}, + {-120,-120},{-52,-120}}, color={255,0,255})); + connect(booToInt2.y, mulInt.u2) annotation (Line(points={{-28,-120},{-20,-120}, + {-20,-96},{-12,-96}}, color={255,127,0})); + connect(reaToInt2.y, mulInt.u1) annotation (Line(points={{-28,-90},{-20,-90},{ + -20,-84},{-12,-84}}, color={255,127,0})); + connect(mulInt.y, intRep2.u) + annotation (Line(points={{12,-90},{18,-90}}, color={255,127,0})); + connect(mulAnd.y, disLasLag.clr) annotation (Line(points={{-118,-20},{-100, + -20},{-100,-6},{-42,-6}}, color={255,0,255})); + connect(mulAnd.y, enaNexLag.clr) annotation (Line(points={{-118,-20},{-100, + -20},{-100,24},{-2,24}}, color={255,0,255})); + connect(pre1.y, booToInt1.u) annotation (Line(points={{242,-120},{260,-120},{ + 260,-140},{-250,-140},{-250,-70},{-242,-70}}, color={255,0,255})); + connect(enaLagChiPum.yDown, disLasLag.u) annotation (Line(points={{-218,-20},{ + -188,-20},{-188,0},{-42,0}},color={255,0,255})); + connect(uWse, enaHeaLeaPum.uWse) annotation (Line(points={{-300,0},{-214,0},{-214, + 64},{-202,64}}, color={255,0,255})); +annotation ( + defaultComponentName="chiWatPum", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-280,-260},{280,260}}), graphics={ + Rectangle( + extent={{-276,256},{156,64}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{66,252},{140,236}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable lead pump"), + Rectangle( + extent={{-276,56},{156,-136}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{70,58},{154,44}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable next lag pump"), + Text( + extent={{70,-116},{152,-134}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable last lag pump"), + Rectangle( + extent={{-276,-146},{156,-258}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{70,-154},{152,-168}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enabled pump speed")}), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-80,60},{82,-60}}, + lineColor={28,108,200}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Polygon( + points={{-80,60},{-14,4},{-80,-60},{-80,60}}, + lineColor={175,175,175}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid)}), + Documentation(info=" +

+Primary chilled water pump control sequence per ASHRAE Guideline36-2021, +section 5.20.6.1 to section 5.20.6.11, except section 3 and 4. It includes: +

+ +", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLag_primary_dP.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLag_primary_dP.mo new file mode 100644 index 00000000000..371c196d12b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLag_primary_dP.mo @@ -0,0 +1,257 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences; +block EnableLag_primary_dP + "Sequences for enabling and disabling lag pumps for primary-only plants using differential pressure pump speed control" + parameter Integer nPum = 2 "Total number of pumps"; + parameter Real timPer( + final unit="s", + final quantity="Time")=600 + "Delay time period for enabling and disabling lag pumps"; + parameter Real staCon = -0.03 "Constant used in the staging equation" + annotation (Dialog(tab="Advanced")); + parameter Real relFloHys = 0.01 + "Constant value used in hysteresis for checking relative flow rate" + annotation (Dialog(tab="Advanced")); + parameter Integer nPum_nominal( + final max = nPum, + final min = 1) = nPum + "Total number of pumps that operate at design conditions" + annotation (Dialog(group="Nominal conditions")); + parameter Real VChiWat_flow_nominal( + final unit="m3/s", + final quantity="VolumeFlowRate", + final min=1e-6)=0.5 + "Total plant design chilled water flow rate" + annotation (Dialog(group="Nominal conditions")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final unit="m3/s", + final quantity="VolumeFlowRate") "Chilled water flow" + annotation (Placement(transformation(extent={{-260,60},{-220,100}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nPum] + "Chilled water pump status" + annotation (Placement(transformation(extent={{-260,-20},{-220,20}}), + iconTransformation(extent={{-140,-58},{-100,-18}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yUp + "Next lag pump status, a rising edge indicates that next lag pump should be enabled" + annotation (Placement(transformation(extent={{220,80},{260,120}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDown + "Last lag pump status, a falling edge indicates that last lag pump should be disabled" + annotation (Placement(transformation(extent={{220,-180},{260,-140}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=timPer) + "Check if the condition for enabling the pump has been constantly satisfied for enough time" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=timPer) + "Check if the condition for disabling the pump has been constantly satisfied for enough time" + annotation (Placement(transformation(extent={{40,-170},{60,-150}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis enaPum( + final uLow=(-1)*relFloHys, + final uHigh=relFloHys) + "Check if the condition for enabling next lag pump is satisfied" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis disPum( + final uLow=(-1)*relFloHys, + final uHigh=relFloHys) + "Check if the condition for disabling last lag pump is satisfied" + annotation (Placement(transformation(extent={{-80,-170},{-60,-150}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter chiWatFloRat( + final k=1/VChiWat_flow_nominal) "Chiller water flow ratio" + annotation (Placement(transformation(extent={{-200,70},{-180,90}}))); + +protected + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nPum] + "Convert boolean input to integer number" + annotation (Placement(transformation(extent={{-200,-10},{-180,10}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum numOpePum(final nin=nPum) + "Total number of operating pumps" + annotation (Placement(transformation(extent={{-140,-10},{-120,10}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Convert integer to real" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter addPar1( + final p=-1) "Add real inputs" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub2 + "Find inputs difference" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 + "Find inputs difference" + annotation (Placement(transformation(extent={{-120,-170},{-100,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Switch enaNexLag + "Enabling next lag pump" + annotation (Placement(transformation(extent={{180,90},{200,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch shuLasLag + "Shut off last lag pump" + annotation (Placement(transformation(extent={{180,-170},{200,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) + "Logical true" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Logical false" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter nomPum( + final k=1/nPum_nominal) + "Pump number ratio" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter nomPum1( + final k=1/nPum_nominal) + "Pump number ratio" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con2( + final k=0.03) + "Constant" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub + "Input difference" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub3 + "Input difference" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + +equation + connect(VChiWat_flow,chiWatFloRat. u) + annotation (Line(points={{-240,80},{-202,80}}, color={0,0,127})); + connect(uChiWatPum,booToInt. u) + annotation (Line(points={{-240,0},{-202,0}}, color={255,0,255})); + connect(booToInt.y,numOpePum. u) + annotation (Line(points={{-178,0},{-142,0}}, + color={255,127,0})); + connect(numOpePum.y,intToRea. u) + annotation (Line(points={{-118,0},{-102,0}}, color={255,127,0})); + connect(sub2.y, enaPum.u) + annotation (Line(points={{-98,100},{-82,100}}, color={0,0,127})); + connect(sub1.y, disPum.u) + annotation (Line(points={{-98,-160},{-82,-160}}, color={0,0,127})); + connect(intToRea.y, addPar1.u) + annotation (Line(points={{-78,0},{-60,0},{-60,-40},{-42,-40}}, + color={0,0,127})); + connect(chiWatFloRat.y, sub2.u1) + annotation (Line(points={{-178,80},{-160,80},{-160,106},{-122,106}}, + color={0,0,127})); + connect(chiWatFloRat.y, sub1.u2) + annotation (Line(points={{-178,80},{-160,80},{-160,-166},{-122,-166}}, + color={0,0,127})); + connect(con.y, enaNexLag.u1) + annotation (Line(points={{142,160},{160,160},{160,108},{178,108}}, + color={255,0,255})); + connect(shuLasLag.y, yDown) + annotation (Line(points={{202,-160},{240,-160}}, color={255,0,255})); + connect(enaNexLag.y, yUp) + annotation (Line(points={{202,100},{240,100}}, color={255,0,255})); + connect(con1.y, enaNexLag.u3) + annotation (Line(points={{122,0},{140,0},{140,92},{178,92}}, + color={255,0,255})); + connect(intToRea.y, nomPum.u) + annotation (Line(points={{-78,0},{-2,0}}, color={0,0,127})); + connect(addPar1.y, nomPum1.u) + annotation (Line(points={{-18,-40},{-2,-40}}, color={0,0,127})); + connect(enaPum.y, truDel.u) + annotation (Line(points={{-58,100},{38,100}}, color={255,0,255})); + connect(truDel.y, enaNexLag.u2) + annotation (Line(points={{62,100},{178,100}}, color={255,0,255})); + connect(disPum.y, truDel1.u) + annotation (Line(points={{-58,-160},{38,-160}}, color={255,0,255})); + connect(truDel1.y, shuLasLag.u2) + annotation (Line(points={{62,-160},{178,-160}}, color={255,0,255})); + connect(nomPum.y, sub3.u1) + annotation (Line(points={{22,0},{30,0},{30,46},{58,46}}, color={0,0,127})); + connect(nomPum1.y, sub.u1) annotation (Line(points={{22,-40},{30,-40},{30,-34}, + {58,-34}}, color={0,0,127})); + connect(con2.y, sub3.u2) annotation (Line(points={{22,-80},{40,-80},{40,34},{58, + 34}}, color={0,0,127})); + connect(con2.y, sub.u2) annotation (Line(points={{22,-80},{40,-80},{40,-46},{58, + -46}}, color={0,0,127})); + connect(sub3.y, sub2.u2) annotation (Line(points={{82,40},{100,40},{100,70},{-140, + 70},{-140,94},{-122,94}}, color={0,0,127})); + connect(sub.y, sub1.u1) annotation (Line(points={{82,-40},{100,-40},{100,-120}, + {-140,-120},{-140,-154},{-122,-154}}, color={0,0,127})); + connect(con.y, shuLasLag.u1) annotation (Line(points={{142,160},{160,160},{160, + -152},{178,-152}}, color={255,0,255})); + connect(con1.y, shuLasLag.u3) annotation (Line(points={{122,0},{140,0},{140,-168}, + {178,-168}}, color={255,0,255})); +annotation ( + defaultComponentName="enaLagChiPum", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,52},{-38,30}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{-98,-24},{-34,-48}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiWatPum"), + Text( + extent={{64,48},{98,34}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yUp"), + Text( + extent={{62,-26},{96,-50}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yDown")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-220,-200},{220,200}})), + Documentation(info=" +

+Block that enable and disable lag primary chilled water pump, for plants +with headered primary chilled water pumps, +according to ASHRAE Guideline36-2021, +section 5.20.6 Primary chilled water pumps, part 5.20.6.6. +

+

+Chilled water pump shall be staged as a function of chilled water flow ratio (CHWFR), +i.e. the ratio of current chilled water flow VChiWat_flow to design +flow VChiWat_flow_nominal, and the number of pumps num_nominal +that operate at design conditions. Pumps are assumed to be equally sized. +

+
+                  VChiWat_flow
+     CHWFR = ----------------------
+              VChiWat_flow_nominal
+
+

+1. Start the next lag pump yNexLagPum whenever the following is +true for 10 minutes: +

+
+              Number_of_operating_pumps
+     CHWFR > ---------------------------  - 0.03
+                       num_nominal
+
+

+2. Shut off the last lag pump whenever the following is true for 10 minutes: +

+
+              Number_of_operating_pumps - 1
+     CHWFR ≤ -------------------------------  - 0.03
+                       num_nominal
+
+", revisions=" + +")); +end EnableLag_primary_dP; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_dedicated.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_dedicated.mo new file mode 100644 index 00000000000..72f7ca53f21 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_dedicated.mo @@ -0,0 +1,138 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences; +block EnableLead_dedicated + "Sequence to enable or disable the lead pump of plants with dedicated primary chilled water pumps" + + final parameter Real offTimThr( + final unit="s", + final quantity="Time")=180 + "Threshold to check lead chiller off time"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "True: plant is enabled" + annotation (Placement(transformation(extent={{-140,50},{-100,90}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiEna + "True: lead chiller is enabled" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiSta + "True: lead chiller is proven on" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiWatReq + "True: lead chiller is requesting chilled water" + annotation (Placement(transformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea + "Lead pump status setpoint" + annotation (Placement(transformation(extent={{100,50},{140,90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch leaPumSta + "Lead pump status" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not noChiWatReq "No chilled water request" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not proOff "Lead chiller proven off" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=offTimThr) + "Check if the chiller has been OFF for more than 3 minutes" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not disLeaChi "Disabled lead chiller" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Logical.Edge disLeaPum + "Disable lead pump when the input has rising edge" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); +equation + connect(uLeaChiWatReq, noChiWatReq.u) + annotation (Line(points={{-120,-80},{-82,-80}}, color={255,0,255})); + connect(uLeaChiSta, proOff.u) + annotation (Line(points={{-120,-40},{-82,-40}}, color={255,0,255})); + connect(proOff.y, tim.u) + annotation (Line(points={{-58,-40},{-42,-40}}, color={255,0,255})); + connect(noChiWatReq.y, or2.u2) + annotation (Line(points={{-58,-80},{30,-80},{30,-48},{38,-48}}, + color={255,0,255})); + connect(uLeaChiEna, disLeaChi.u) + annotation (Line(points={{-120,40},{-82,40}}, color={255,0,255})); + connect(disLeaChi.y, and2.u1) + annotation (Line(points={{-58,40},{-42,40}}, color={255,0,255})); + connect(or2.y, and2.u2) + annotation (Line(points={{62,-40},{80,-40},{80,-10},{-50,-10},{-50,32},{-42, + 32}}, color={255,0,255})); + connect(uPla, leaPumSta.u) + annotation (Line(points={{-120,70},{38,70}}, color={255,0,255})); + connect(and2.y, disLeaPum.u) + annotation (Line(points={{-18,40},{-2,40}}, color={255,0,255})); + connect(disLeaPum.y, leaPumSta.clr) + annotation (Line(points={{22,40},{30,40},{30,64},{38,64}}, color={255,0,255})); + connect(tim.passed, or2.u1) annotation (Line(points={{-18,-48},{20,-48},{20,-40}, + {38,-40}}, color={255,0,255})); + connect(leaPumSta.y, yLea) + annotation (Line(points={{62,70},{120,70}}, color={255,0,255})); +annotation ( + defaultComponentName="enaLeaChiPum", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,42},{-44,20}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uLeaChiEna"), + Text( + extent={{62,10},{98,-6}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yUp"), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,-18},{-44,-40}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uLeaChiOn"), + Text( + extent={{-98,-68},{-26,-90}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uLeaChiWatReq"), + Text( + extent={{-94,90},{-74,74}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uPla")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that enable and disable leading primary chilled water pump, for plants +with dedicated primary chilled water pumps and parallel chillers, +according to ASHRAE Guideline36-2021, section 5.20.6.6. +

+

+The lead primary chilled water pump should be enabled when the plant is enabled +(uPla = true). It should be disabled when the lead +chiller is disabled (uLeaChiEna = false) and either the lead chiller +has been proven off (uLeaChiSta = false) for 3 minutes or is not +requesting chilled water flow (uLeaChiWatReq = false). +

+", revisions=" + +")); +end EnableLead_dedicated; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_headered.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_headered.mo new file mode 100644 index 00000000000..7cfd5e7dec2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_headered.mo @@ -0,0 +1,126 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences; +block EnableLead_headered + "Sequence to enable or disable the lead pump of plants with headered primary chilled water pumps" + + parameter Integer nChi=2 + "Total number of chiller CHW isolation valves"; + parameter Boolean have_WSE + "True: the plant has waterside economizer"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_WSE + "Waterside economizer proven on status: true=ON" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea + "Lead pump status setpoint" + annotation (Placement(transformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Switch leaPumSta "Lead pump status" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(final k=true) + "Logical true" + annotation (Placement(transformation(extent={{0,60},{20,80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Logical false" + annotation (Placement(transformation(extent={{0,-80},{20,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys4[nChi]( + final uLow=fill(0.925,nChi), + final uHigh=fill(0.975, nChi)) + "Check if isolation valve is open more than 95%" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyIsoVal(final nin=nChi) + "Check if any chilled water isolation valve is proven on" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=false) + if not have_WSE + "Logical false" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Check if the chilled water pump should be enabled" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + +equation + connect(con.y,leaPumSta. u1) + annotation (Line(points={{22,70},{40,70},{40,8},{58,8}}, color={255,0,255})); + connect(con1.y,leaPumSta. u3) + annotation (Line(points={{22,-70},{40,-70},{40,-8},{58,-8}}, + color={255,0,255})); + connect(leaPumSta.y, yLea) + annotation (Line(points={{82,0},{120,0}}, color={255,0,255})); + connect(uChiWatIsoVal, hys4.u) + annotation (Line(points={{-120,0},{-82,0}}, color={0,0,127})); + connect(hys4.y, anyIsoVal.u) + annotation (Line(points={{-58,0},{-42,0}}, color={255,0,255})); + connect(anyIsoVal.y, or2.u1) + annotation (Line(points={{-18,0},{-2,0}}, color={255,0,255})); + connect(uWse, or2.u2) annotation (Line(points={{-120,-40},{-10,-40},{-10,-8},{ + -2,-8}}, color={255,0,255})); + connect(or2.y, leaPumSta.u2) + annotation (Line(points={{22,0},{58,0}}, color={255,0,255})); + connect(con2.y, or2.u2) annotation (Line(points={{-38,-70},{-10,-70},{-10,-8}, + {-2,-8}}, color={255,0,255})); +annotation ( + defaultComponentName="enaLeaChiPum", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-96,12},{-20,-8}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiWatIsoVal"), + Text( + extent={{42,12},{96,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yLeaPum"), + Text( + extent={{-98,-48},{-44,-70}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uWse")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that enable and disable leading primary chilled water pump, for plants +with headered primary chilled water pumps and parallel chillers, +according to ASHRAE Guideline36-2021, +section 5.20.6 Primary chilled water pumps, part 1, 2, and 3. +

+
    +
  1. +Primary chilled water pumps shall be lead-lag. Note that the lead-lag control is +implemented in a separated sequence. +
  2. +
  3. +The lead primary chilled water pump shall be enabled when any chiller +CHW isolation valve uChiIsoVal is fully open, or if the plant +has waterside economizer and the economizer is enabled, shall be disabled +when chiller CHW isolation valves are commanded closed and the economizer is diabled +if the plant has the economizer. +
  4. +
+", revisions=" + +")); +end EnableLead_headered; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Speed_primary_localDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Speed_primary_localDp.mo new file mode 100644 index 00000000000..a4629bfceb2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Speed_primary_localDp.mo @@ -0,0 +1,295 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences; +block Speed_primary_localDp + "Pump speed control for primary-only plants where the remote DP sensor(s) is not hardwired to the plant controller, but a local DP sensor is hardwired" + parameter Integer nSen = 2 + "Total number of remote differential pressure sensors"; + parameter Integer nPum = 2 + "Total number of chilled water pumps"; + parameter Real minLocDp( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=0)=5*6894.75 + "Minimum chilled water loop local differential pressure setpoint"; + parameter Real maxLocDp( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=minLocDp) = 15*6894.75 + "Maximum chilled water loop local differential pressure setpoint"; + parameter Real minPumSpe = 0.1 "Minimum pump speed"; + parameter Real maxPumSpe = 1 "Maximum pump speed"; + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(group="Speed controller")); + parameter Real k=1 "Gain of controller" + annotation(Dialog(group="Speed controller")); + parameter Real Ti( + final unit="s", + final quantity="Time")=0.5 "Time constant of integrator block" + annotation(Dialog(group="Speed controller")); + parameter Real Td( + final unit="s", + final quantity="Time")=0.1 "Time constant of derivative block" + annotation (Dialog(group="Speed controller", + enable= + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_local( + final unit="Pa", + final quantity="PressureDifference") + "Chilled water differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-180,80},{-140,120}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nPum] + "Chilled water pump status" + annotation (Placement(transformation(extent={{-180,-60},{-140,-20}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen)) + "Chilled water differential static pressure from remote sensor" + annotation (Placement(transformation(extent={{-180,-100},{-140,-60}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatSet_remote[nSen]( + final unit=fill("Pa", nSen), final quantity=fill("PressureDifference", + nSen)) "Chilled water differential static pressure setpoint" + annotation (Placement(transformation(extent={{-180,-140},{-140,-100}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatPumSpe( + final min=minPumSpe, + final max=maxPumSpe, + final unit="1") "Chilled water pump speed" + annotation (Placement(transformation(extent={{140,100},{180,140}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpChiWatPumSet_local( + final quantity="PressureDifference", + final unit="Pa", + displayUnit="Pa") + "Local differential pressure setpoint" + annotation (Placement(transformation(extent={{140,-40},{180,0}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPID1( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=1, + final yMin=0, + final y_reset=0) "Pump speed controller" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Reals.Line pumSpe "Pump speed" + annotation (Placement(transformation(extent={{100,50},{120,70}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax maxRemDP( + final nin=nSen) + "Highest output from differential pressure control loops" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Line locDpSet + "Local differential pressure setpoint" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}))); + Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPID[nSen]( + final controllerType=fill(controllerType, nSen), + final k=fill(k, nSen), + final Ti=fill(Ti, nSen), + final Td=fill(Td, nSen), + final yMax=fill(1, nSen), + final yMin=fill(0, nSen), + final y_reset=fill(0, nSen)) "Pump speed controller" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + +protected + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nSen) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant locDp_min( + final k=minLocDp) + "Minimum local differential pressure" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant locDp_max( + final k=maxLocDp) + "Maximum local differential pressure " + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant pumSpe_min( + final k=minPumSpe) "Minimum pump speed" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant pumSpe_max( + final k=maxPumSpe) "Maximum pump speed" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div[nSen] + "Normalized pressure difference" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div1 + "Normalized pressure difference" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1( + final nout=nSen) "Replicate real input" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{100,110},{120,130}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(final nin=nPum) + "Check if there is any pump enabled" + annotation (Placement(transformation(extent={{-120,-50},{-100,-30}}))); + +equation + connect(conPID.y, maxRemDP.u) + annotation (Line(points={{22,-20},{38,-20}}, color={0,0,127})); + connect(booRep.y, conPID.trigger) + annotation (Line(points={{-18,-40},{4,-40},{4,-32}}, color={255,0,255})); + connect(maxRemDP.y, locDpSet.u) + annotation (Line(points={{62,-20},{98,-20}}, color={0,0,127})); + connect(zer.y, locDpSet.x1) + annotation (Line(points={{82,20},{90,20},{90,-12},{98,-12}}, color={0,0,127})); + connect(locDp_min.y, locDpSet.f1) + annotation (Line(points={{62,-60},{70,-60},{70,-16},{98,-16}}, + color={0,0,127})); + connect(one.y, locDpSet.x2) + annotation (Line(points={{-98,20},{40,20},{40,0},{80,0},{80,-24},{98,-24}}, + color={0,0,127})); + connect(locDp_max.y, locDpSet.f2) + annotation (Line(points={{62,-120},{80,-120},{80,-28},{98,-28}}, + color={0,0,127})); + connect(zer.y, pumSpe.x1) + annotation (Line(points={{82,20},{90,20},{90,68},{98,68}}, color={0,0,127})); + connect(pumSpe_min.y, pumSpe.f1) + annotation (Line(points={{62,100},{70,100},{70,64},{98,64}}, color={0,0,127})); + connect(conPID1.y, pumSpe.u) + annotation (Line(points={{-18,60},{98,60}}, color={0,0,127})); + connect(one.y, pumSpe.x2) + annotation (Line(points={{-98,20},{40,20},{40,56},{98,56}},color={0,0,127})); + connect(pumSpe_max.y, pumSpe.f2) + annotation (Line(points={{2,100},{20,100},{20,52},{98,52}}, color={0,0,127})); + connect(dpChiWat_remote, div.u1) + annotation (Line(points={{-160,-80},{-80,-80},{-80,-94},{-42,-94}}, + color={0,0,127})); + connect(locDpSet.y, div1.u2) + annotation (Line(points={{122,-20},{130,-20},{130,40},{-120,40},{-120,74}, + {-102,74}}, color={0,0,127})); + connect(dpChiWat_local, div1.u1) + annotation (Line(points={{-160,100},{-120,100},{-120,86},{-102,86}}, + color={0,0,127})); + connect(one.y, reaRep1.u) + annotation (Line(points={{-98,20},{-90,20},{-90,0},{-82,0}}, color={0,0,127})); + connect(reaRep1.y, conPID.u_s) + annotation (Line(points={{-58,0},{-20,0},{-20,-20},{-2,-20}}, color={0,0,127})); + connect(div.y, conPID.u_m) + annotation (Line(points={{-18,-100},{10,-100},{10,-32}}, color={0,0,127})); + connect(one.y, conPID1.u_s) + annotation (Line(points={{-98,20},{-90,20},{-90,60},{-42,60}}, color={0,0,127})); + connect(div1.y, conPID1.u_m) + annotation (Line(points={{-78,80},{-60,80},{-60,32},{-30,32},{-30,48}}, + color={0,0,127})); + connect(pumSpe.y, swi.u1) + annotation (Line(points={{122,60},{130,60},{130,100},{80,100},{80,128},{98,128}}, + color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{82,20},{90,20},{90,112},{98,112}}, + color={0,0,127})); + connect(swi.y, yChiWatPumSpe) + annotation (Line(points={{122,120},{160,120}}, color={0,0,127})); + connect(mulOr.y, booRep.u) + annotation (Line(points={{-98,-40},{-42,-40}}, color={255,0,255})); + connect(mulOr.y, swi.u2) + annotation (Line(points={{-98,-40},{-50,-40},{-50,120},{98,120}}, + color={255,0,255})); + connect(mulOr.y, conPID1.trigger) + annotation (Line(points={{-98,-40},{-50,-40},{-50,-20},{-36,-20},{-36,48}}, + color={255,0,255})); + connect(uChiWatPum, mulOr.u) + annotation (Line(points={{-160,-40},{-122,-40}},color={255,0,255})); + connect(dpChiWatSet_remote, div.u2) annotation (Line(points={{-160,-120},{-80, + -120},{-80,-106},{-42,-106}}, color={0,0,127})); + connect(locDpSet.y, dpChiWatPumSet_local) + annotation (Line(points={{122,-20},{160,-20}}, color={0,0,127})); +annotation ( + defaultComponentName="chiPumSpe", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,52},{-44,30}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiWatPum"), + Text( + extent={{-98,-30},{-30,-52}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWat_remote"), + Text( + extent={{22,12},{98,-10}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatPumSpe"), + Text( + extent={{-98,-68},{-20,-92}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatSet_remote"), + Text( + extent={{-98,92},{-30,70}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWat_local"), + Text( + extent={{6,-46},{98,-70}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatPumSet_local")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-140},{140,140}})), + Documentation(info=" +

+Block that control speed of enabled chilled water pumps for primary-only plants where +the remote pressure differential (DP) sensor(s) is not hardwired to the plant controller, +but a local DP sensor is hardwired to the plant controller, +according to ASHRAE Guideline36-2021, +section 5.20.6 Primary chilled water pumps, part 5.20.6.9, 5.20.6.10 and 5.20.6.11. +

+
    +
  1. +Remote DP shall be maintained at setpoint dpChiWatSet by a reverse +acting PID loop running in the controller to which the remote sensor is wired. +The loop output shall be a DP setpoint for the local primary loop DP sensor +hardwired to the plant controller. Reset local DP from minLocDp, +e.g. 5 psi (34473.8 Pa), at 0% loop output to maxLocDp at 100% +loop output. +
  2. +
  3. +When any pump is proven on, pump speed shall be controlled by a reverse acting +PID loop maintaining the local primary DP signal at the DP setpoint output +from the remote sensor control loop. All pumps receive the same speed signal. +PID loop output shall be mapped from minimum pump speed (minPumSpe) +at 0% to maximum pump speed (maxPumSpe) at 100%. +
  4. +
  5. +Where multiple remote DP sensors exist, a PID loop shall run for each sensor. +The DP setpoint for the local DP sensor shall be the highest DP setpoint output +from each of the remote loops. +
  6. +
+", revisions=" + +")); +end Speed_primary_localDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Speed_primary_remoteDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Speed_primary_remoteDp.mo new file mode 100644 index 00000000000..3ad90bcf8e9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Speed_primary_remoteDp.mo @@ -0,0 +1,205 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences; +block Speed_primary_remoteDp + "Pump speed control for primary-only plants where the remote DP sensor(s) is hardwired to the plant controller" + parameter Integer nSen = 2 + "Total number of remote differential pressure sensors"; + parameter Integer nPum = 2 + "Total number of chilled water pumps"; + parameter Real minPumSpe = 0.1 "Minimum pump speed"; + parameter Real maxPumSpe = 1 "Maximum pump speed"; + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(group="Speed controller")); + parameter Real k=1 "Gain of controller" + annotation(Dialog(group="Speed controller")); + parameter Real Ti( + final unit="s", + final quantity="Time")=0.5 + "Time constant of integrator block" + annotation(Dialog(group="Speed controller")); + parameter Real Td( + final unit="s", + final quantity="Time")=0.1 + "Time constant of derivative block" + annotation (Dialog(group="Speed controller", + enable=controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nPum] + "Chilled water pump status" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen)) + "Chilled water differential static pressure" + annotation (Placement(transformation(extent={{-160,-80},{-120,-40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatSet_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference",nSen)) + "Chilled water differential static pressure setpoint" + annotation (Placement(transformation(extent={{-160,-120},{-120,-80}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatPumSpe( + final min=minPumSpe, + final max=maxPumSpe, + final unit="1") "Chilled water pump speed" + annotation (Placement(transformation(extent={{120,80},{160,120}}), + iconTransformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMax maxLoo( + final nin=nSen) + "Maximum DP loop output" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Reals.Line pumSpe "Pump speed" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPID[nSen]( + final controllerType=fill(controllerType, nSen), + final k=fill(k, nSen), + final Ti=fill(Ti, nSen), + final Td=fill(Td, nSen), + final yMax=fill(1, nSen), + final yMin=fill(0, nSen), + final y_reset=fill(0, nSen)) "Pump speed controller" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +protected + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nSen) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant pumSpe_min( + final k=minPumSpe) "Minimum pump speed" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant pumSpe_max( + final k=maxPumSpe) "Maximum pump speed" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div[nSen] + "Normalized pressure difference" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1( + final nout=nSen) "Replicate real input" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(final nin=nPum) + "Check if there is any pump enabled" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + +equation + connect(conPID.y, maxLoo.u) + annotation (Line(points={{42,0},{58,0}}, color={0,0,127})); + connect(booRep.y, conPID.trigger) + annotation (Line(points={{2,-40},{24,-40},{24,-12}}, color={255,0,255})); + connect(zer.y, pumSpe.x1) + annotation (Line(points={{2,80},{20,80},{20,68},{58,68}}, color={0,0,127})); + connect(pumSpe_min.y, pumSpe.f1) + annotation (Line(points={{-58,80},{-40,80},{-40,64},{58,64}}, color={0,0,127})); + connect(one.y, pumSpe.x2) + annotation (Line(points={{-58,40},{-40,40},{-40,56},{58,56}}, color={0,0,127})); + connect(pumSpe_max.y, pumSpe.f2) + annotation (Line(points={{2,40},{20,40},{20,52},{58,52}}, color={0,0,127})); + connect(maxLoo.y, pumSpe.u) + annotation (Line(points={{82,0},{100,0},{100,40},{40,40},{40,60},{58,60}}, + color={0,0,127})); + connect(dpChiWat_remote, div.u1) annotation (Line(points={{-140,-60},{-40,-60}, + {-40,-74},{-22,-74}}, color={0,0,127})); + connect(div.y, conPID.u_m) + annotation (Line(points={{2,-80},{30,-80},{30,-12}}, color={0,0,127})); + connect(one.y, reaRep1.u) + annotation (Line(points={{-58,40},{-40,40},{-40,0},{-22,0}}, + color={0,0,127})); + connect(reaRep1.y, conPID.u_s) + annotation (Line(points={{2,0},{18,0}}, color={0,0,127})); + connect(pumSpe.y, swi.u1) + annotation (Line(points={{82,60},{100,60},{100,80},{60,80},{60,108},{78,108}}, + color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{2,80},{20,80},{20,92},{78,92}}, + color={0,0,127})); + connect(swi.y, yChiWatPumSpe) + annotation (Line(points={{102,100},{140,100}}, color={0,0,127})); + connect(mulOr.y, booRep.u) + annotation (Line(points={{-78,0},{-50,0},{-50,-40},{-22,-40}}, + color={255,0,255})); + connect(mulOr.y, swi.u2) + annotation (Line(points={{-78,0},{-50,0},{-50,100},{78,100}}, + color={255,0,255})); + connect(uChiWatPum, mulOr.u) + annotation (Line(points={{-140,0},{-102,0}}, color={255,0,255})); + connect(dpChiWatSet_remote, div.u2) annotation (Line(points={{-140,-100},{-40, + -100},{-40,-86},{-22,-86}}, color={0,0,127})); + +annotation ( + defaultComponentName="chiPumSpe", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,92},{-44,70}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiWatPum"), + Text( + extent={{-98,10},{-26,-10}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWat_remote"), + Text( + extent={{22,12},{98,-10}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatPumSpe"), + Text( + extent={{-98,-68},{-10,-88}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatSet_remote")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}})), + Documentation(info=" +

+Block that output chilled water pump speed setpoint for primary-only plants where +the remote pressure differential sensor is hardwired to the plant controller, +according to ASHRAE Guideline36-2021, +section 5.20.6 Primary chilled water pumps, part 5.20.6.7 and 5.20.6.8. +

+
    +
  1. +When any chilled water pump is proven on, uChiWatPum = true, +pump speed will be controlled by a reverse acting PID loop maintaining the +differential pressure signal at a setpoint dpChiWatSet. All pumps +receive the same speed signal. PID loop output shall be mapped from minimum +pump speed (minPumSpe) at 0% to maximum pump speed +(maxPumSpe) at 100%. +
  2. +
  3. +Where multiple differential pressure sensors exist, a PID loop shall run for +each sensor. Chilled water pumps shall be controlled to the maximum signal output +of all DP sensor loops. +
  4. +
+", revisions=" + +")); +end Speed_primary_remoteDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLag_primary_dP.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLag_primary_dP.mo new file mode 100644 index 00000000000..cd729fa99c0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLag_primary_dP.mo @@ -0,0 +1,80 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Validation; +model EnableLag_primary_dP + "Validate sequence for enabling lag pump for primary-only plants using differential pressure pump speed control" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLag_primary_dP + enaLagChiPum( + final nPum=3, + final VChiWat_flow_nominal=0.5) + "Enable lag pump for primary-only plants using differential pressure pump speed control" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[2]( + final k=fill(true, 2)) "Constant true" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + final amplitude=0.25, + final freqHz=1/3600, + final offset=0.25) "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + +equation + connect(con[1].y, enaLagChiPum.uChiWatPum[1]) + annotation (Line(points={{-38,0},{-20,0},{-20,-4.46667},{18,-4.46667}}, + color={255,0,255})); + connect(con[2].y, enaLagChiPum.uChiWatPum[2]) + annotation (Line(points={{-38,0},{-20,0},{-20,-3.8},{18,-3.8}}, + color={255,0,255})); + connect(con1.y, enaLagChiPum.uChiWatPum[3]) + annotation (Line(points={{-38,-40},{0,-40},{0,-3.13333},{18,-3.13333}}, + color={255,0,255})); + connect(sin.y, enaLagChiPum.VChiWat_flow) + annotation (Line(points={{-38,40},{-20,40},{-20,4},{18,4}}, + color={0,0,127})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLag_primary_dP.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLag_primary_dP. +It validates the conditions for enabling and disabling the lag pump. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end EnableLag_primary_dP; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_dedicated.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_dedicated.mo new file mode 100644 index 00000000000..7c69076dc6f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_dedicated.mo @@ -0,0 +1,96 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Validation; +model EnableLead_dedicated + "Validate sequence for enabling lead pump of plants with dedicated primary chilled water pumps" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_dedicated + enaLeaChiPum + "Enable lead chilled water pump when the lead chiller is enabled" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_dedicated + disLeaChiPum + "Disable lead pump due to that the lead chiller has been proven off" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay leaChiProOn( + final delayTime=120) + "Lead chiller proven on status" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leaChiEna( + final period=7200, + final shift=400) + "Lead chiller enabling status" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPla( + final period=7200, + final shift=200) + "Plant enabling status" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPla1( + final width=0.75, final period=4000) + "Plant enabling status" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); +equation + connect(leaChiEna.y, enaLeaChiPum.uLeaChiEna) annotation (Line(points={{-58,40}, + {30,40},{30,83},{58,83}}, color={255,0,255})); + connect(leaChiEna.y, leaChiProOn.u) annotation (Line(points={{-58,40},{-50,40}, + {-50,60},{-22,60}}, color={255,0,255})); + connect(leaChiProOn.y, enaLeaChiPum.uLeaChiSta) annotation (Line(points={{2,60},{ + 40,60},{40,77},{58,77}}, color={255,0,255})); + connect(leaChiProOn.y, enaLeaChiPum.uLeaChiWatReq) annotation (Line(points={{2,60},{ + 40,60},{40,72},{58,72}}, color={255,0,255})); + connect(enaPla.y, enaLeaChiPum.uPla) annotation (Line(points={{-58,80},{20,80}, + {20,88},{58,88}}, color={255,0,255})); + connect(enaPla1.y, disLeaChiPum.uPla) annotation (Line(points={{-58,-10},{20,-10}, + {20,-22},{58,-22}}, color={255,0,255})); + connect(enaPla1.y, disLeaChiPum.uLeaChiEna) annotation (Line(points={{-58,-10}, + {20,-10},{20,-27},{58,-27}}, color={255,0,255})); + connect(enaPla1.y, disLeaChiPum.uLeaChiSta) annotation (Line(points={{-58,-10}, + {20,-10},{20,-33},{58,-33}}, color={255,0,255})); + connect(enaPla1.y, disLeaChiPum.uLeaChiWatReq) annotation (Line(points={{-58,-10}, + {20,-10},{20,-38},{58,-38}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_dedicated.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_dedicated. +The instances enaLeaChiPum and disLeaChiPum shows how the +lead pump being enabled and disabled. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end EnableLead_dedicated; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_headered.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_headered.mo new file mode 100644 index 00000000000..d099ddea6b8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_headered.mo @@ -0,0 +1,61 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Validation; +model EnableLead_headered + "Validate sequence for enabling lead pump of plants with headered primary chilled water pumps" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_headered + enaLeaChiPum(final nChi=2, have_WSE=true) + "Enable lead chilled water pump based on the status of chilled water isolation valves" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp isoVal1( + duration=3000, + startTime=300) + "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp isoVal2( + duration=3000, + startTime=900) + "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant wse(k=false) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + +equation + connect(isoVal1.y, enaLeaChiPum.uChiWatIsoVal[1]) annotation (Line(points={{-18, + 20},{0,20},{0,-0.5},{18,-0.5}}, color={0,0,127})); + connect(isoVal2.y, enaLeaChiPum.uChiWatIsoVal[2]) annotation (Line(points={{-18, + -20},{0,-20},{0,0.5},{18,0.5}}, color={0,0,127})); + connect(wse.y, enaLeaChiPum.uWse) annotation (Line(points={{-18,-60},{10,-60}, + {10,-6},{18,-6}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_headered.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.EnableLead_headered. +

+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end EnableLead_headered; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_localDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_localDp.mo new file mode 100644 index 00000000000..11a9ec9b4de --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_localDp.mo @@ -0,0 +1,117 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Validation; +model Speed_primary_localDp + "Validate sequence of controlling chilled water pump speed for primary-only plants with local DP sensor hardwired to the plant controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Speed_primary_localDp + chiPumSpe(nSen=2, nPum=2) + "Chilled water pump speed control based local pressure difference sensor" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumSta[2]( + final width=fill(0.9, 2), + final period=fill(10, 2), + final shift=fill(1, 2)) "Pump status" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin remPreSen1( + final offset=8.5*6894.75, + final freqHz=1/10, + final amplitude=1.5*6894.75) "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin remPreSen2( + final offset=8.5*6894.75, + final freqHz=1/10, + final startTime=2, + final amplitude=1*6894.75) "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin locPreSen( + final freqHz=1/5, + final amplitude=1*6894.75, + final offset=8.5*6894.75) "Local pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=2) "Replicate real input" + annotation (Placement(transformation(extent={{-30,-90},{-10,-70}}))); + +equation + connect(locPreSen.y, chiPumSpe.dpChiWat_local) + annotation (Line(points={{-38,80},{0,80},{0,8},{18,8}}, + color={0,0,127})); + connect(remPreSen1.y, chiPumSpe.dpChiWat_remote[1]) + annotation (Line(points={{-38,0},{-20,0},{-20,-4.5},{18,-4.5}}, + color={0,0,127})); + connect(remPreSen2.y, chiPumSpe.dpChiWat_remote[2]) + annotation (Line(points={{-38,-40},{-20,-40},{-20,-3.5},{18,-3.5}}, + color={0,0,127})); + connect(pumSta.y, chiPumSpe.uChiWatPum) + annotation (Line(points={{-38,40},{-20,40},{-20,4},{18,4}}, + color={255,0,255})); + connect(difPreSet.y, reaRep.u) + annotation (Line(points={{-38,-80},{-32,-80}}, color={0,0,127})); + connect(reaRep.y, chiPumSpe.dpChiWatSet_remote) + annotation (Line(points={{-8,-80},{0,-80},{0,-8},{18,-8}}, color={0,0,127})); + +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_localDp.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Speed_primary_localDp. +

+

+It shows the process of specifying the chilled water pump speed +for a primary-only plant, with one local pressure sensor and two +remote pressure sensors. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end Speed_primary_localDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_remoteDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_remoteDp.mo new file mode 100644 index 00000000000..0ab5765c1fc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_remoteDp.mo @@ -0,0 +1,99 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Validation; +model Speed_primary_remoteDp + "Validate sequence of controlling chilled water pump speed for primary-only plants with remote DP sensor hardwired to the plant controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Speed_primary_remoteDp + chiPumSpe(nSen=2, nPum=2) + "Chilled water pump speed control based remote pressure difference sensor" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +//protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumSta[2]( + final width=fill(0.9, 2), + final period=fill(10, 2), + final shift=fill(1, 2)) "Pump status" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin remPreSen1( + final offset=8.5*6894.75, + final freqHz=1/10, + final amplitude=1.5*6894.75) "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin remPreSen2( + final offset=8.5*6894.75, + final freqHz=1/10, + final startTime=2, + final amplitude=1*6894.75) "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=2) "Replicate real input" + annotation (Placement(transformation(extent={{-30,-90},{-10,-70}}))); + +equation + connect(pumSta.y, chiPumSpe.uChiWatPum) + annotation (Line(points={{-38,40},{-20,40},{-20,8},{18,8}}, + color={255,0,255})); + connect(remPreSen1.y, chiPumSpe.dpChiWat_remote[1]) annotation (Line(points={{-38,0}, + {-10,0},{-10,-0.5},{18,-0.5}}, color={0,0,127})); + connect(remPreSen2.y, chiPumSpe.dpChiWat_remote[2]) annotation (Line(points={{-38,-40}, + {-28,-40},{-28,0.5},{18,0.5}}, color={0,0,127})); + connect(difPreSet.y, reaRep.u) + annotation (Line(points={{-38,-80},{-32,-80}}, color={0,0,127})); + connect(reaRep.y, chiPumSpe.dpChiWatSet_remote) annotation (Line(points={{-8, + -80},{0,-80},{0,-8},{18,-8}}, color={0,0,127})); + +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_remoteDp.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences.Speed_primary_remoteDp. +

+

+It shows the process of specifying the chilled water pump speed +for a primary-only plant, with two remote pressure sensors hardwired +to the controller. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end Speed_primary_remoteDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..d30e244dc53 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/package.order new file mode 100644 index 00000000000..d16f96117bb --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/package.order @@ -0,0 +1,5 @@ +EnableLag_primary_dP +EnableLead_dedicated +EnableLead_headered +Speed_primary_localDp +Speed_primary_remoteDp diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/package.mo new file mode 100644 index 00000000000..d6272b5fe84 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater; +package Subsequences "Chilled water pump control sequences" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for chilled water pumps control for plants with +parallel chillers. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/package.order new file mode 100644 index 00000000000..9e96bb60c2d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/package.order @@ -0,0 +1,6 @@ +EnableLag_primary_dP +EnableLead_dedicated +EnableLead_headered +Speed_primary_localDp +Speed_primary_remoteDp +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/Controller.mo new file mode 100644 index 00000000000..63784202069 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/Controller.mo @@ -0,0 +1,184 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Validation; +model Controller "Validate chiller water pump control sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Controller + heaNoLoc( + final nPum=3, + final nPum_nominal=3) + "Pump speed control for plant with headered primary chilled water pump and without local DP sensor" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Controller + dedNoLoc( + final have_heaPum=false, + final nPum=3, + final nPum_nominal=3) + "Pump speed control for plant with dedicated primary chilled water pump and without local DP sensor" + annotation (Placement(transformation(extent={{80,60},{100,80}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Controller + dedLoc( + final have_heaPum=false, + final have_locSen=true, + final nPum=3, + final nPum_nominal=3) + "Pump speed control for plant with dedicated primary chilled water pump and with local DP sensor" + annotation (Placement(transformation(extent={{80,-90},{100,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp isoVal[2]( + duration=fill(1200, 2), + startTime={0,300}) + "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-100,130},{-80,150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[3]( + final k={2,1,3}) + "Chilled water pump operating priority" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlo( + final amplitude=0.25, + final freqHz=1/3600, + final offset=0.25) "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin remPreSen1( + final offset=8.4*6894.75, + final freqHz=1/3600, + final amplitude=0.2*6894.75) "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin remPreSen2( + final offset=8.5*6894.75, + final freqHz=1/3600, + final startTime=2, + final amplitude=0.05*6894.75) "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-140},{-40,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin locPreSen( + final offset=8.5*6894.75, + final freqHz=1/3600, + final startTime=2, + final amplitude=0.2*6894.75) "Local pressure difference sensor reading" + annotation (Placement(transformation(extent={{-100,-120},{-80,-100}}))); + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold leaChiProOn( + final trueHoldDuration=2000, falseHoldDuration=0) + "Lead chiller proven on status" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=3) "Replicate plant enabling status" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse enaPla( + final period=7200, + final shift=200) + "Plant enabling status" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leaChiEna( + final period=3600, + final shift=300) "Lead chiller enabling status" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=2) + "Replicate real input" + annotation (Placement(transformation(extent={{-20,-140},{0,-120}}))); + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol[3]( + trueHoldDuration=fill(5, 3)) "Chilled water pump status" + annotation (Placement(transformation(extent={{0,110},{20,130}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre[3] "Break loop" + annotation (Placement(transformation(extent={{80,110},{100,130}}))); + +equation + connect(conInt.y, heaNoLoc.uPumLeaLag) + annotation (Line(points={{-38,160},{32,160},{32,171},{78,171}}, color={255,127,0})); + connect(chiWatFlo.y, heaNoLoc.VChiWat_flow) + annotation (Line(points={{-38,-50},{48,-50},{48,155},{78,155}}, + color={0,0,127})); + connect(remPreSen1.y, heaNoLoc.dpChiWat_remote[1]) + annotation (Line(points={{-78,-70},{52,-70},{52,151},{78,151}}, + color={0,0,127})); + connect(remPreSen2.y, heaNoLoc.dpChiWat_remote[2]) + annotation (Line(points={{-38,-90},{52,-90},{52,151},{78,151}}, + color={0,0,127})); + connect(remPreSen1.y, dedNoLoc.dpChiWat_remote[1]) + annotation (Line(points={{-78,-70},{52,-70},{52,61},{78,61}}, + color={0,0,127})); + connect(remPreSen2.y, dedNoLoc.dpChiWat_remote[2]) + annotation (Line(points={{-38,-90},{52,-90},{52,61},{78,61}}, + color={0,0,127})); + connect(locPreSen.y, dedLoc.dpChiWat_local) + annotation (Line(points={{-78,-110},{48,-110},{48,-87},{78,-87}}, color={0,0,127})); + connect(remPreSen1.y, dedLoc.dpChiWat_remote[1]) + annotation (Line(points={{-78,-70},{52,-70},{52,-89},{78,-89}}, + color={0,0,127})); + connect(remPreSen2.y, dedLoc.dpChiWat_remote[2]) + annotation (Line(points={{-38,-90},{52,-90},{52,-89},{78,-89}}, + color={0,0,127})); + connect(enaPla.y, dedNoLoc.uPla) annotation (Line(points={{-38,60},{20,60},{ + 20,79},{78,79}}, color={255,0,255})); + connect(enaPla.y, dedLoc.uPla) annotation (Line(points={{-38,60},{20,60},{20, + -71},{78,-71}}, color={255,0,255})); + connect(leaChiEna.y, dedNoLoc.uLeaChiEna) annotation (Line(points={{-38,10},{ + 24,10},{24,75},{78,75}}, color={255,0,255})); + connect(leaChiEna.y, dedLoc.uLeaChiEna) annotation (Line(points={{-38,10},{24, + 10},{24,-75},{78,-75}}, color={255,0,255})); + connect(leaChiEna.y, leaChiProOn.u) annotation (Line(points={{-38,10},{-30,10}, + {-30,-20},{-22,-20}}, color={255,0,255})); + connect(leaChiProOn.y, dedNoLoc.uLeaChiSta) annotation (Line(points={{2,-20}, + {28,-20},{28,73},{78,73}},color={255,0,255})); + connect(leaChiProOn.y, dedLoc.uLeaChiSta) annotation (Line(points={{2,-20},{ + 28,-20},{28,-77},{78,-77}}, color={255,0,255})); + connect(leaChiProOn.y, dedNoLoc.uLeaChiWatReq) annotation (Line(points={{2,-20}, + {28,-20},{28,71},{78,71}}, color={255,0,255})); + connect(leaChiProOn.y, dedLoc.uLeaChiWatReq) annotation (Line(points={{2,-20}, + {28,-20},{28,-79},{78,-79}}, color={255,0,255})); + connect(enaPla.y, booRep.u) annotation (Line(points={{-38,60},{-30,60},{-30,40}, + {-22,40}}, color={255,0,255})); + connect(booRep.y, dedNoLoc.uChiWatPum) annotation (Line(points={{2,40},{32,40}, + {32,77},{78,77}}, color={255,0,255})); + connect(booRep.y, dedLoc.uChiWatPum) annotation (Line(points={{2,40},{32,40}, + {32,-73},{78,-73}},color={255,0,255})); + connect(difPreSet.y, reaRep.u) + annotation (Line(points={{-38,-130},{-22,-130}}, color={0,0,127})); + connect(reaRep.y, heaNoLoc.dpChiWatSet_remote) annotation (Line(points={{2,-130}, + {56,-130},{56,149},{78,149}}, color={0,0,127})); + connect(reaRep.y, dedNoLoc.dpChiWatSet_remote) annotation (Line(points={{2,-130}, + {56,-130},{56,59},{78,59}}, color={0,0,127})); + connect(reaRep.y, dedLoc.dpChiWatSet_remote) annotation (Line(points={{2,-130}, + {56,-130},{56,-91},{78,-91}}, color={0,0,127})); + connect(isoVal.y, heaNoLoc.uChiWatIsoVal) annotation (Line(points={{-78,140}, + {40,140},{40,157},{78,157}},color={0,0,127})); + connect(truFalHol.y, heaNoLoc.uChiWatPum) annotation (Line(points={{22,120},{ + 44,120},{44,167},{78,167}}, color={255,0,255})); + connect(heaNoLoc.yChiWatPum, pre.u) annotation (Line(points={{102,160},{120,160}, + {120,140},{70,140},{70,120},{78,120}}, color={255,0,255})); + connect(pre.y, truFalHol.u) annotation (Line(points={{102,120},{110,120},{110, + 100},{-10,100},{-10,120},{-2,120}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Controller. +

+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-180},{140,180}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/package.mo new file mode 100644 index 00000000000..abf439d8131 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.mo new file mode 100644 index 00000000000..75356b59422 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.mo @@ -0,0 +1,32 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps; +package ChilledWater "Sequences for chilled water pump control" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for chilled water pumps. +The implementations are based on section 5.20.6 Primary chilled water pumps, +in ASHRAE Guideline36-2021. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + extent={{-66,66},{68,-68}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), Polygon( + points={{0,66},{0,-68},{68,0},{0,66}}, + lineColor={0,0,0}, + fillColor={0,127,255}, + fillPattern=FillPattern.Solid)})); +end ChilledWater; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Controller.mo new file mode 100644 index 00000000000..24343818a6b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Controller.mo @@ -0,0 +1,317 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater; +block Controller "Condenser water pump controller" + + parameter Boolean have_heaPum = true + "Flag of headered condenser water pumps design: true=headered, false=dedicated"; + parameter Boolean have_WSE = true + "Flag of waterside economizer: true=have WSE, false=no WSE"; + parameter Boolean fixSpe = false + "Flag to indicate if the plant has fix speed condenser water pump"; + parameter Integer nChi=2 "Total number of chillers"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Integer totSta=6 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable" + annotation (Dialog(group="Stage design speed")); + parameter Integer nChiSta = 3 + "Total number of chiller stages, including stage zero but not the stages with a WSE, if applicable"; + parameter Real staVec[totSta]={0,0.5,1,1.5,2,2.5} + "Chiller stage vector, element value like x.5 means chiller stage x plus WSE" + annotation (Dialog(group="Stage design speed")); + parameter Real desConWatPumSpe[totSta]={0,0.5,0.75,0.6,0.75,0.9} + "Design condenser water pump speed setpoints, according to current chiller stage and WSE status" + annotation (Dialog(group="Stage design speed")); + parameter Real desConWatPumNum[totSta]={0,1,1,2,2,2} + "Design number of condenser water pumps that should be ON, according to current chiller stage and WSE status" + annotation (Dialog(group="Stage design speed")); + parameter Real desChiNum[nChiSta]={0,1,2} + "Design number of chiller that should be ON, according to current chiller stage" + annotation (Dialog(group="Stage design speed", enable=fixSpe)); + parameter Real pumSpeChe = 0.05 + "Lower threshold value to check if condenser water pump has achieved setpoint"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiConIsoVal[nChi] + "Chiller condenser water isolation valve status" + annotation (Placement(transformation(extent={{-160,130},{-120,170}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiEna + "Lead chiller enabling status: true=lead chiller is enabled" + annotation (Placement(transformation(extent={{-160,100},{-120,140}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiSta + "Lead chiller status: true=lead chiller proven on" + annotation (Placement(transformation(extent={{-162,70},{-122,110}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaConWatReq + "Status indicating if chiller is requesting condenser water" + annotation (Placement(transformation(extent={{-162,40},{-122,80}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-160,10},{-120,50}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage that does not include WSE" + annotation (Placement(transformation(extent={{-160,-26},{-120,14}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-160,-60},{-120,-20}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpeSet( + final min=0, + final max=1, + final unit="1") if not fixSpe + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{-160,-90},{-120,-50}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not fixSpe + "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-160,-130},{-120,-90}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatPum[nConWatPum] if fixSpe + "Status indicating if condenser water pump is running" + annotation (Placement(transformation(extent={{-160,-160},{-120,-120}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaPum + "Lead pump status setpoint" + annotation (Placement(transformation(extent={{120,110},{160,150}}), + iconTransformation(extent={{100,70},{140,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDesConWatPumSpe + if not fixSpe + "Condenser water pump design speed at current stage" + annotation (Placement(transformation(extent={{120,40},{160,80}}), + iconTransformation(extent={{100,10},{140,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yConWatPumNum + "Number of operating condenser water pumps" + annotation (Placement(transformation(extent={{120,0},{160,40}}), + iconTransformation(extent={{100,-50},{140,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPumSpeChe + "Flag to indicate if pump speed achieves setpoint" + annotation (Placement(transformation(extent={{120,-70},{160,-30}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_headered + enaLeaHeaPum(final have_WSE=have_WSE) if have_heaPum + "Enable lead pumps for plants with headered condenser water pump" + annotation (Placement(transformation(extent={{20,120},{40,140}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_dedicated + enaLeaDedPum if not have_heaPum + "Enable lead pumps for plants with dedicated condenser water pump" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.Speed + pumSpe( + final have_WSE=have_WSE, + final fixSpe=fixSpe, + final totSta=totSta, + final nChiSta=nChiSta, + final staVec=staVec, + final desConWatPumSpe=desConWatPumSpe, + final desConWatPumNum=desConWatPumNum, + final desChiNum=desChiNum) + "Design pump speed of condenser water pump at current stage" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract speDif if not fixSpe + "Calculate difference between speed setpoint and operating speed" + annotation (Placement(transformation(extent={{-80,-100},{-60,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Abs abs if not fixSpe + "Absolute difference" + annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(final uLow=pumSpeChe, + final uHigh=2*pumSpeChe) if not fixSpe + "Check if operating speed equals to setpoint" + annotation (Placement(transformation(extent={{0,-100},{20,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 if not fixSpe + "Logical not" + annotation (Placement(transformation(extent={{40,-100},{60,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) + if not fixSpe + "Constant zero" + annotation (Placement(transformation(extent={{-60,42},{-40,62}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant zer1(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-60,2},{-40,22}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi if not fixSpe + "Real switch" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi "Integer switch" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) if not have_WSE + "Logical true" + annotation (Placement(transformation(extent={{-60,100},{-40,120}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nConWatPum] if fixSpe + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-100,-150},{-80,-130}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nConWatPum) if fixSpe + "Calculate total number of pumps that are running" + annotation (Placement(transformation(extent={{-40,-150},{-20,-130}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu if fixSpe + "Check if total number of running pumps are equal to setpoint" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + +equation + connect(uWSE, enaLeaHeaPum.uWseConIsoVal) + annotation (Line(points={{-140,-40},{0,-40},{0,130},{18,130}}, + color={255,0,255})); + connect(enaLeaDedPum.uLeaChiSta, uLeaChiSta) + annotation (Line(points={{18,76},{-90,76},{-90,90},{-142,90}}, color={255,0,255})); + connect(enaLeaDedPum.uLeaConWatReq, uLeaConWatReq) + annotation (Line(points={{18,72},{-80,72},{-80,60},{-142,60}}, + color={255,0,255})); + connect(uWSE, pumSpe.uWSE) + annotation (Line(points={{-140,-40},{0,-40},{0,-14},{18,-14}}, color={255,0,255})); + connect(enaLeaHeaPum.yLea, yLeaPum) + annotation (Line(points={{42,130},{140,130}}, color={255,0,255})); + connect(enaLeaDedPum.yLea, yLeaPum) + annotation (Line(points={{42,80},{50,80},{50,130},{140,130}}, color={255,0,255})); + connect(speDif.y, abs.u) + annotation (Line(points={{-58,-90},{-42,-90}}, color={0,0,127})); + connect(hys.y, not1.u) + annotation (Line(points={{22,-90},{38,-90}}, color={255,0,255})); + connect(uChiSta, pumSpe.uChiSta) + annotation (Line(points={{-140,-6},{18,-6}}, + color={255,127,0})); + connect(swi.y,yDesConWatPumSpe) + annotation (Line(points={{102,60},{140,60}}, color={0,0,127})); + connect(enaLeaDedPum.yLea, swi.u2) + annotation (Line(points={{42,80},{50,80},{50,60},{78,60}}, color={255,0,255})); + connect(enaLeaHeaPum.yLea, swi.u2) + annotation (Line(points={{42,130},{50,130},{50,60},{78,60}}, color={255,0,255})); + connect(zer.y, swi.u3) + annotation (Line(points={{-38,52},{78,52}}, color={0,0,127})); + connect(enaLeaHeaPum.yLea, intSwi.u2) + annotation (Line(points={{42,130},{50,130},{50,20},{78,20}}, color={255,0,255})); + connect(enaLeaDedPum.yLea, intSwi.u2) + annotation (Line(points={{42,80},{50,80},{50,20},{78,20}}, color={255,0,255})); + connect(pumSpe.yConWatPumNum, intSwi.u1) + annotation (Line(points={{42,-10},{68,-10},{68,28},{78,28}}, color={255,127,0})); + connect(intSwi.y, yConWatPumNum) + annotation (Line(points={{102,20},{140,20}}, color={255,127,0})); + connect(zer1.y, intSwi.u3) + annotation (Line(points={{-38,12},{78,12}}, color={255,127,0})); + connect(and2.y, yPumSpeChe) + annotation (Line(points={{102,-50},{140,-50}}, color={255,0,255})); + connect(not1.y, and2.u2) + annotation (Line(points={{62,-90},{70,-90},{70,-58},{78,-58}}, + color={255,0,255})); + connect(enaLeaHeaPum.yLea, and2.u1) + annotation (Line(points={{42,130},{50,130},{50,-50},{78,-50}}, color={255,0,255})); + connect(enaLeaDedPum.yLea, and2.u1) + annotation (Line(points={{42,80},{50,80},{50,-50},{78,-50}}, color={255,0,255})); + connect(pumSpe.yDesConWatPumSpe, swi.u1) + annotation (Line(points={{42,-4},{60,-4},{60,68},{78,68}}, color={0,0,127})); + connect(con.y, enaLeaHeaPum.uWseConIsoVal) + annotation (Line(points={{-38,110},{-20,110},{-20,130},{18,130}}, + color={255,0,255})); + connect(con.y, pumSpe.uWSE) + annotation (Line(points={{-38,110},{-20,110},{-20,-14},{18,-14}}, + color={255,0,255})); + connect(uLeaChiEna, enaLeaDedPum.uLeaChiEna) + annotation (Line(points={{-140,120},{-80,120},{-80,84},{18,84}}, + color={255,0,255})); + connect(enaLeaHeaPum.uChiConIsoVal, uChiConIsoVal) annotation (Line(points={{18,136}, + {-40,136},{-40,150},{-140,150}}, color={255,0,255})); + connect(uConWatPum, booToInt.u) + annotation (Line(points={{-140,-140},{-102,-140}}, color={255,0,255})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-78,-140},{-42,-140}}, color={255,127,0})); + connect(mulSumInt.y, intEqu.u2) annotation (Line(points={{-18,-140},{20,-140}, + {20,-128},{38,-128}}, color={255,127,0})); + connect(intSwi.y, intEqu.u1) annotation (Line(points={{102,20},{110,20},{110,-30}, + {30,-30},{30,-120},{38,-120}}, color={255,127,0})); + connect(intEqu.y, and2.u2) annotation (Line(points={{62,-120},{70,-120},{70,-58}, + {78,-58}}, color={255,0,255})); + connect(abs.y, hys.u) annotation (Line(points={{-18,-90},{-2,-90}}, + color={0,0,127})); + connect(uConWatPumSpeSet, speDif.u1) annotation (Line(points={{-140,-70},{ + -100,-70},{-100,-84},{-82,-84}}, + color={0,0,127})); + connect(uConWatPumSpe, speDif.u2) annotation (Line(points={{-140,-110},{-100, + -110},{-100,-96},{-82,-96}}, + color={0,0,127})); + connect(uEnaPla, enaLeaHeaPum.uEnaPla) annotation (Line(points={{-140,30},{10, + 30},{10,124},{18,124}}, color={255,0,255})); + connect(uEnaPla, enaLeaDedPum.uEnaPla) annotation (Line(points={{-140,30},{10, + 30},{10,88},{18,88}}, color={255,0,255})); + +annotation (Dialog(tab="Advanced"), + defaultComponentName="conWatPumCon", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-80,60},{82,-60}}, + lineColor={28,108,200}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Polygon( + points={{-80,60},{-14,4},{-80,-60},{-80,60}}, + lineColor={175,175,175}, + fillColor={175,175,175}, + fillPattern=FillPattern.Solid)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-120,-160},{120,160}})), + Documentation(info=" +

+Block that generates control signals for condenser water pumps control, +according to ASHRAE Guideline36-2021, +section 5.20.9 Condenser water pumps. +

+

+This sequence contains three subsequences: +

+ +", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_dedicated.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_dedicated.mo new file mode 100644 index 00000000000..35c1ab74534 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_dedicated.mo @@ -0,0 +1,145 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences; +block EnableLead_dedicated + "Sequence for enabling lead pump of plants with dedicated condenser water pumps" + + final parameter Real offTimThr( + final unit="s", + final quantity="Time")=180 + "Threshold to check lead chiller OFF time"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-140,50},{-100,90}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiEna + "Lead chiller commanded on status" + annotation (Placement(transformation(extent={{-140,10},{-100,50}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaChiSta + "Lead chiller proven on status" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaConWatReq + "Status indicating if chiller is requesting condenser water" + annotation (Placement(transformation(extent={{-140,-100},{-100,-60}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea "Lead pump status" + annotation (Placement(transformation(extent={{100,50},{140,90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Latch leaPumSta + "Lead pump status" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=offTimThr) + "Check if the chiller has been proven off for more than threshold time" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Check if the lead chiller is disabled" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Logical or" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + +equation + connect(uLeaConWatReq, not1.u) + annotation (Line(points={{-120,-80},{-82,-80}}, color={255,0,255})); + connect(uLeaChiEna, leaPumSta.u) + annotation (Line(points={{-120,30},{18,30}}, color={255,0,255})); + connect(uLeaChiSta, not2.u) + annotation (Line(points={{-120,-40},{-82,-40}}, color={255,0,255})); + connect(not2.y, tim.u) + annotation (Line(points={{-58,-40},{-42,-40}}, color={255,0,255})); + connect(not1.y, or2.u2) + annotation (Line(points={{-58,-80},{20,-80},{20,-48},{38,-48}}, + color={255,0,255})); + connect(or2.y, and2.u2) + annotation (Line(points={{62,-40},{80,-40},{80,-20},{-30,-20},{-30,-8}, + {-22,-8}},color={255,0,255})); + connect(uLeaChiEna, not3.u) + annotation (Line(points={{-120,30},{-80,30},{-80,0},{-62,0}}, + color={255,0,255})); + connect(not3.y, and2.u1) + annotation (Line(points={{-38,0},{-22,0}}, color={255,0,255})); + connect(and2.y, leaPumSta.clr) + annotation (Line(points={{2,0},{10,0},{10,24},{18,24}}, color={255,0,255})); + connect(tim.passed, or2.u1) + annotation (Line(points={{-18,-48},{0,-48},{0,-40},{38,-40}}, + color={255,0,255})); + connect(or1.y, yLea) + annotation (Line(points={{82,70},{120,70}}, color={255,0,255})); + connect(uEnaPla, or1.u1) + annotation (Line(points={{-120,70},{58,70}}, color={255,0,255})); + connect(leaPumSta.y, or1.u2) annotation (Line(points={{42,30},{50,30},{50,62}, + {58,62}}, color={255,0,255})); + +annotation ( + defaultComponentName="enaLeaConPum", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,54},{-44,32}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uLeaChiEna"), + Text( + extent={{42,12},{96,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yLeaPum"), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,-28},{-44,-50}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uLeaChiOn"), + Text( + extent={{-98,-68},{-26,-90}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uLeaConWatReq"), + Text( + extent={{-96,90},{-50,70}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uEnaPla")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that enable and disable lead condenser water pump, for plants +with dedicated condenser water pumps, +according to ASHRAE Guideline36-2021, +section 5.20.9 Condenser water pumps, part 5.20.9.4. +

+

+The lead condenser water pump should be enabled when lead chiller is commanded +to run (uLeaChiEna = true). It should be disabled when the lead +chiller is disabled and either the lead chiller has been proven off +(uLeaChiSta = false) for offTimThr, i.e. 3 minutes, or +is not requesting condenser water flow (uLeaConWatReq = false). +

+", revisions=" + +")); +end EnableLead_dedicated; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_headered.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_headered.mo new file mode 100644 index 00000000000..0af50b2ff1e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_headered.mo @@ -0,0 +1,132 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences; +block EnableLead_headered + "Sequence for enabling lead pump of plants with headered condenser water pumps" + parameter Boolean have_WSE = true + "Flag of waterside economizer: true=have WSE, false=no WSE"; + parameter Integer nChi=2 "Total number of chiller"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWseConIsoVal + if have_WSE "WSE condenser water isolation valve commanded status" + annotation (Placement(transformation(extent={{-140,-28},{-100,12}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiConIsoVal[nChi] + "Chiller condenser water isolation valve commanded status" + annotation (Placement(transformation(extent={{-140,30},{-100,70}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-140,-80},{-100,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea "Lead pump status" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Switch leaPumSta "Lead pump status" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) "Logical false" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) "Logical true" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=false) if not have_WSE + "Logical false" + annotation (Placement(transformation(extent={{-80,-48},{-60,-28}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChi) + "Check if there is any chiller enabled" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + Buildings.Controls.OBC.CDL.Logical.Or or1 "Logical or" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + +equation + connect(con1.y, leaPumSta.u3) + annotation (Line(points={{2,-80},{40,-80},{40,-8},{58,-8}}, + color={255,0,255})); + connect(con.y, leaPumSta.u1) + annotation (Line(points={{2,80},{40,80},{40,8},{58,8}}, color={255,0,255})); + connect(leaPumSta.y, yLea) + annotation (Line(points={{82,0},{120,0}}, color={255,0,255})); + connect(uWseConIsoVal, or2.u2) + annotation (Line(points={{-120,-8},{-42,-8}}, + color={255,0,255})); + connect(con2.y, or2.u2) + annotation (Line(points={{-58,-38},{-50,-38},{-50,-8},{-42,-8}}, + color={255,0,255})); + connect(uChiConIsoVal, mulOr.u) + annotation (Line(points={{-120,50},{-82,50}}, color={255,0,255})); + connect(mulOr.y, or2.u1) + annotation (Line(points={{-58,50},{-50,50},{-50,0},{-42,0}}, + color={255,0,255})); + connect(or2.y, or1.u1) annotation (Line(points={{-18,0},{-2,0}}, + color={255,0,255})); + connect(uEnaPla, or1.u2) annotation (Line(points={{-120,-60},{-10,-60},{-10,-8}, + {-2,-8}}, color={255,0,255})); + connect(or1.y, leaPumSta.u2) + annotation (Line(points={{22,0},{58,0}}, color={255,0,255})); + +annotation ( + defaultComponentName="enaLeaConPum", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,72},{-44,50}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiConIsoVal"), + Text( + extent={{42,12},{96,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yLeaPum"), + Text( + extent={{-98,12},{-44,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uWseConIsoVal"), + Text( + extent={{-98,-50},{-58,-68}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uEnaPla")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that enable and disable lead condenser water pump, for plants +with headered condenser water pumps, +according to ASHRAE Guideline36-2021, +section 5.20.9 Condenser water pumps, part 5.20.9.2-3. +

+
    +
  1. +Condenser water pumps shall be lead-lag. +
  2. +
  3. +The lead condenser water pump shall be enabled when condenser water +isolation valve of any chiller uChiConIsoVal or water side economizer +uWseConIsoVal is commanded open. It shall be disabled when +all chiller and water side economizer condenser water isolation valves are +commanded closed. +
  4. +
+", revisions=" + +")); +end EnableLead_headered; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Speed.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Speed.mo new file mode 100644 index 00000000000..78b46f7b91c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Speed.mo @@ -0,0 +1,272 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences; +block Speed + "Output design speed of condenser water pumps at current stage" + + parameter Boolean have_WSE = true + "Flag to indicate if the plant has water side economizer"; + parameter Boolean fixSpe = false + "Flag to indicate if the plant has fix speed condenser water pump"; + parameter Integer totSta = 6 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable"; + parameter Integer nChiSta = 3 + "Total number of chiller stages, including stage zero but not the stages with a WSE, if applicable"; + parameter Real staVec[totSta] = {0, 0.5, 1, 1.5, 2, 2.5} + "Plant stage vector, element value like x.5 means chiller stage x plus WSE"; + parameter Real desConWatPumSpe[totSta] = {0, 0.5, 0.75, 0.6, 0.75, 0.9} + "Design condenser water pump speed setpoint, according to current chiller stage and WSE status" + annotation (Dialog(group="Setpoint according to stage")); + parameter Real desConWatPumNum[totSta] = {0,1,1,2,2,2} + "Design number of condenser water pumps that should be ON, according to current chiller stage and WSE status" + annotation (Dialog(group="Setpoint according to stage")); + parameter Real desChiNum[nChiSta] = {0, 1, 2} + "Design number of chiller that should be ON, according to current chiller stage" + annotation (Dialog(group="Setpoint according to stage", enable=fixSpe)); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage index that does not include the WSE" + annotation (Placement(transformation(extent={{-180,80},{-140,120}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-180,-60},{-140,-20}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yConWatPumNum + "Design number of operating condenser water pumps at current stage" + annotation (Placement(transformation(extent={{140,-40},{180,0}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDesConWatPumSpe + if not fixSpe + "Design condenser water pump speed at current stage" + annotation (Placement(transformation(extent={{140,0},{180,40}}), + iconTransformation(extent={{100,40},{140,80}}))); + +protected + Buildings.Controls.OBC.CDL.Routing.RealExtractor conWatPumOn( + final nin=totSta) if not fixSpe + "Number of condenser water pump should be on" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor conWatPumSpe( + final nin=totSta) if not fixSpe + "Condenser water pump speed" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt if not fixSpe + "Convert real input to integer output" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1[totSta]( + final k=desConWatPumSpe) if not fixSpe + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{40,10},{60,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con2[totSta]( + final k=desConWatPumNum) if not fixSpe + "Number of condenser water pump should be on" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea if not fixSpe + "Convert integer to real number" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con3[totSta]( + final k=staVec) if not fixSpe + "Chiller stage vector, element value like x.5 means chiller stage x plus WSE" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea( + final realTrue=0.5) if have_WSE + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-120,-50},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 if not fixSpe + "Add two real inputs" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=totSta) if not fixSpe + "Replicate real input" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub1[totSta] if not fixSpe + "Add two real inputs" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr[totSta]( + final t=fill(-0.1, totSta)) if not fixSpe + "Identify current stage" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[totSta] + if not fixSpe + "Convert boolean to integer" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=totSta) if not fixSpe + "Current stage index" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con4( + final k=0) if not have_WSE + "Constant zero" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con5[nChiSta]( + final k=desChiNum) if fixSpe + "Number of chiller should be enabled" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor conWatPumOn1( + final nin=nChiSta) if fixSpe + "Number of condenser water pump should be on" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 if fixSpe + "Convert real input to integer output" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.CDL.Integers.AddParameter addPar( + final p=1) + if fixSpe + "Change the chiller stage index to the index for downstream selection" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + +equation + connect(con1.y,conWatPumSpe. u) + annotation (Line(points={{62,20},{78,20}}, color={0,0,127})); + connect(con2.y,conWatPumOn. u) + annotation (Line(points={{2,-20},{18,-20}}, color={0,0,127})); + connect(uChiSta,intToRea. u) + annotation (Line(points={{-160,100},{-122,100}}, color={255,127,0})); + connect(conWatPumSpe.y, yDesConWatPumSpe) + annotation (Line(points={{102,20},{160,20}}, color={0,0,127})); + connect(yConWatPumNum, reaToInt.y) + annotation (Line(points={{160,-20},{82,-20}}, color={255,127,0})); + connect(conWatPumOn.y, reaToInt.u) + annotation (Line(points={{42,-20},{58,-20}}, color={0,0,127})); + connect(uWSE, booToRea.u) + annotation (Line(points={{-160,-40},{-122,-40}}, color={255,0,255})); + connect(intToRea.y, add2.u1) + annotation (Line(points={{-98,100},{-90,100},{-90,106},{-82,106}}, color={0,0,127})); + connect(booToRea.y, add2.u2) + annotation (Line(points={{-98,-40},{-90,-40},{-90,94},{-82,94}}, color={0,0,127})); + connect(add2.y, reaRep.u) + annotation (Line(points={{-58,100},{-42,100}}, color={0,0,127})); + connect(sub1.y,greEquThr. u) + annotation (Line(points={{22,80},{38,80}}, color={0,0,127})); + connect(greEquThr.y, booToInt.u) + annotation (Line(points={{62,80},{78,80}}, color={255,0,255})); + connect(mulSumInt.y, conWatPumSpe.index) + annotation (Line(points={{-38,0},{90,0},{90,8}}, color={255,127,0})); + connect(mulSumInt.y, conWatPumOn.index) + annotation (Line(points={{-38,0},{-30,0},{-30,-40},{30,-40},{30,-32}}, + color={255,127,0})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{102,80},{120,80},{120,40},{-80,40},{-80,0},{-62,0}}, + color={255,127,0})); + connect(con4.y, add2.u2) + annotation (Line(points={{-98,0},{-90,0},{-90,94},{-82,94}}, color={0,0,127})); + connect(con5.y, conWatPumOn1.u) + annotation (Line(points={{2,-60},{18,-60}}, color={0,0,127})); + connect(conWatPumOn1.y, reaToInt1.u) + annotation (Line(points={{42,-60},{58,-60}}, color={0,0,127})); + connect(reaToInt1.y, yConWatPumNum) annotation (Line(points={{82,-60},{120,-60}, + {120,-20},{160,-20}}, color={255,127,0})); + connect(reaRep.y, sub1.u1) annotation (Line(points={{-18,100},{-10,100},{-10,86}, + {-2,86}}, color={0,0,127})); + connect(con3.y, sub1.u2) annotation (Line(points={{-18,60},{-10,60},{-10,74},{ + -2,74}}, color={0,0,127})); + + connect(addPar.y, conWatPumOn1.index) + annotation (Line(points={{-58,-80},{30,-80},{30,-72}}, color={255,127,0})); + connect(uChiSta, addPar.u) annotation (Line(points={{-160,100},{-130,100},{-130, + -80},{-82,-80}}, color={255,127,0})); +annotation ( + defaultComponentName="conPumSpe", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{36,74},{96,50}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yConWatPumSpe"), + Text( + extent={{-98,-32},{-54,-48}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uWSE"), + Text( + extent={{36,14},{96,-10}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yConWatPumNum"), + Text( + extent={{-96,52},{-36,28}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="uChiSta")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-100},{140,120}})), + Documentation(info=" +

+Block that outputs number of operating condenser water pumps and design pump speed +for current stage, according to ASHRAE Guideline36-2021, +section 5.20.9 Condenser water pumps, part 5.20.9.5 and 5.20.9.6. +

+

If the plant has fixed speed condenser water pump (fixSpe=true) and +does not have wateside economizer (have_WSE=false):

+ +

Otherwise:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Chiller stage Number of pump ONDesign pump speed setpoint for current stage
00N/A, Off
0+WSE1Per TAB to provide design flow through HX
11Per TAB to provide design flow through chiller
1+WSE2Per TAB to provide at least design flow through both chiller and WSE
22Per TAB to provide at least design flow through both chillers
2+WSE2Per TAB to provide at least design flow through both chillers and WSE, +or 100% speed if design flow cannot be achieved.
+
+

+Note that this sequence is for plants with the condenser water pumps are equally sized. +

+", revisions=" + +")); +end Speed; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_dedicated.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_dedicated.mo new file mode 100644 index 00000000000..7bdceb29820 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_dedicated.mo @@ -0,0 +1,101 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.Validation; +model EnableLead_dedicated + "Validate sequence for enabling lead pump of plants with dedicated condenser water pumps" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_dedicated + enaLeaConPum + "Enable lead condenser water pump when the lead chiller is enabled" + annotation (Placement(transformation(extent={{40,10},{60,30}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_dedicated + disLeaConPum + "Disable lead pump due to that the lead chiller has been proven off" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=3600, + final shift=300) "Lead chiller enabling status" + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Maintains a true signal until conditions changes" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) "Constant false" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + +equation + connect(booPul.y,enaLeaConPum. uLeaChiEna) + annotation (Line(points={{2,50},{20,50},{20,24},{38,24}}, color={255,0,255})); + connect(booPul.y, enaLeaConPum.uLeaChiSta) + annotation (Line(points={{2,50},{20,50},{20,16},{38,16}}, color={255,0,255})); + connect(booPul.y,disLeaConPum. uLeaChiEna) + annotation (Line(points={{2,50},{20,50},{20,-16},{38,-16}}, color={255,0,255})); + connect(booPul.y, disLeaConPum.uLeaChiSta) + annotation (Line(points={{2,50},{20,50},{20,-24},{38,-24}}, color={255,0,255})); + connect(booPul.y, lat.u) + annotation (Line(points={{2,50},{20,50},{20,-20},{-40,-20},{-40,-40},{-22,-40}}, + color={255,0,255})); + connect(booPul.y, enaLeaConPum.uLeaConWatReq) + annotation (Line(points={{2,50},{20,50},{20,12},{38,12}}, color={255,0,255})); + connect(lat.y,disLeaConPum. uLeaConWatReq) + annotation (Line(points={{2,-40},{20,-40},{20,-28},{38,-28}}, color={255,0,255})); + connect(con.y, lat.clr) + annotation (Line(points={{-38,-60},{-30,-60},{-30,-46},{-22,-46}}, + color={255,0,255})); + connect(con1.y, enaLeaConPum.uEnaPla) annotation (Line(points={{-38,20},{10,20}, + {10,28},{38,28}}, color={255,0,255})); + connect(con1.y, disLeaConPum.uEnaPla) annotation (Line(points={{-38,20},{10,20}, + {10,-12},{38,-12}}, color={255,0,255})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_dedicated.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_dedicated. +

+

+It shows the process of enabling and disabling lead condenser water pump +of the plants with dedicated condenser water pumps. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end EnableLead_dedicated; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_headered.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_headered.mo new file mode 100644 index 00000000000..23a3aa86f06 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_headered.mo @@ -0,0 +1,75 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.Validation; +model EnableLead_headered + "Validate sequence for enabling lead pump of plants with headered condenser water pumps" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_headered + enaLeaConPum + "Enable lead chilled water pump based on status of chilled water isolation valve status" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiConWatIsoVal[2]( + final period=fill(3600, 2), + final shift=fill(300, 2)) + "Chiller condenser water isolation valve status" + annotation (Placement(transformation(extent={{-20,20},{0,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse WSEConWatIsoVal( + final period=3600, + final shift=800) "Water side economizer condenser water isolation valve status" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + +equation + connect(WSEConWatIsoVal.y, enaLeaConPum.uWseConIsoVal) + annotation (Line(points={{2,-30},{20,-30},{20,0},{38,0}}, color={255,0,255})); + connect(chiConWatIsoVal.y, enaLeaConPum.uChiConIsoVal) annotation (Line( + points={{2,30},{20,30},{20,6},{38,6}}, color={255,0,255})); + connect(con1.y, enaLeaConPum.uEnaPla) annotation (Line(points={{2,-70},{30,-70}, + {30,-6},{38,-6}}, color={255,0,255})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_headered.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.EnableLead_headered. +

+

+It shows the process of enabling and disabling lead condenser water pump +of the plants with headered condenser water pumps. +

+

+The instance enaLeaConPum shows that the lead pump is enabled at 300 +seconds when there is chiller condenser water isolation valve being enabled. The pump +becomes disabled when both the chiller condenser water isolation valve and the waterside +economizer condenser water isolation valve are disabled. +

+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end EnableLead_headered; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/Speed.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/Speed.mo new file mode 100644 index 00000000000..65900655cc3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/Speed.mo @@ -0,0 +1,107 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.Validation; +model Speed + "Validate sequence for generating design speed of condenser water pump at current stage" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.Speed + conPumSpe( + final desConWatPumSpe={0,0.5,0.75,0.6,0.75,0.9}, + final desConWatPumNum={0,1,1,2,2,2}) "Condenser water pump speed" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp( + final duration=1, + final height=2.5) + "Block that generates ramp signal" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Reals.Round round(final n=0) + "Round real number to given digits" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real to integer" + annotation (Placement(transformation(extent={{0,10},{20,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + final period=0.75, + final shift=0) "Waterside economizer status" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + +equation + connect(ramp.y, round.u) + annotation (Line(points={{-58,20},{-42,20}}, color={0,0,127})); + connect(round.y, reaToInt.u) + annotation (Line(points={{-18,20},{-2,20}}, color={0,0,127})); + connect(reaToInt.y, conPumSpe.uChiSta) + annotation (Line(points={{22,20},{40,20},{40,4},{58,4}}, color={255,127,0})); + connect(wseSta.y, conPumSpe.uWSE) + annotation (Line(points={{22,-20},{40,-20},{40,-4},{58,-4}}, color={255,0,255})); + +annotation ( + experiment(StopTime=1.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/Speed.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences.Speed. +

+

+The example shows a chiller plant has 3 chiller stages and 6 plant stages. The plant +stage means the stage that considers both chiller stage and waterside economizer +status. The plant stage is specified by the parameter staVec, which +in this exmple is {0, 0.5, 1, 1.5, 2, 2.5}. The element like x.5 +means chiller stage x plus enabled waterside economizer. +At different plant stage, the number of enabled condenser water pumps and the speed +are specified by parameter desConWatPumNum ({0, 1, 1, 2, 2, 2}) +and desConWatPumSpe ({0, 0.5, 0.75, 0.6, 0.75, 0.9}). +

+

+The process of setting the condenser water pump speed and the pump number are +demonstrated as below: +

+ +", revisions=" + +"), Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false))); +end Speed; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..34db91503b4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences; +package Validation "Collection of validation models" + + annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/package.order new file mode 100644 index 00000000000..e77950db8de --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/package.order @@ -0,0 +1,3 @@ +EnableLead_dedicated +EnableLead_headered +Speed diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/package.mo new file mode 100644 index 00000000000..1f4b888a1f5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater; +package Subsequences "Condenser water pump control sequences" + + annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for condenser water pumps control.

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/package.order new file mode 100644 index 00000000000..8bf4f395688 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/package.order @@ -0,0 +1,4 @@ +EnableLead_dedicated +EnableLead_headered +Speed +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/Controller.mo new file mode 100644 index 00000000000..ad92a064947 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/Controller.mo @@ -0,0 +1,195 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Validation; +model Controller "Validate condenser water pump control sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller + heaHavWse + "Condenser water pumps controller for plant with headered condenser water pump and have waterside economizer" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller + dedHavWse( + final have_heaPum=false) + "Condenser water pumps controller for plant with dedicated condenser water pump and have waterside economizer" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller + heaNoWse( + final have_WSE=false, + final totSta=4, + final staVec={0,1,2,3}, + final desConWatPumSpe={0,0.5,0.5,0.75}, + final desConWatPumNum={0,1,1,2}) + "Condenser water pumps controller for plant with headered condenser water pump and without waterside economizer" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse pumSpe( + final amplitude=0.2, + final period=900, + final offset=0.3) "Measured pump speed" + annotation (Placement(transformation(extent={{-80,-36},{-60,-16}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp1( + final duration=3600, + final height=2.4) "Block that generates ramp signal" + annotation (Placement(transformation(extent={{-90,80},{-70,100}}))); + Buildings.Controls.OBC.CDL.Reals.Round round1(final n=0) + "Round real number to given digits" + annotation (Placement(transformation(extent={{-50,80},{-30,100}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger chiSta + "Convert real to integer" + annotation (Placement(transformation(extent={{-10,80},{10,100}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold chiOn "Chiller status" + annotation (Placement(transformation(extent={{-10,50},{10,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + final period=1800) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-10,14},{10,34}}))); + Buildings.Controls.OBC.CDL.Reals.Switch meaPumSpe "Measured pump speed" + annotation (Placement(transformation(extent={{-10,-46},{10,-26}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) + "Zero pump speed" + annotation (Placement(transformation(extent={{-80,-66},{-60,-46}}))); + Buildings.Controls.OBC.CDL.Reals.Switch pumSpeSet "Pump speed setpoint" + annotation (Placement(transformation(extent={{-10,-16},{10,4}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Pulse pumSpeSetVal( + final amplitude=0.2, + final period=900, + final offset=0.3, + final shift=100) "Pump speed setpoint" + annotation (Placement(transformation(extent={{-80,4},{-60,24}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal( + final k=false) "Logical false" + annotation (Placement(transformation(extent={{-80,34},{-60,54}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=3600) "Output boolean pulse" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt( + final integerTrue=2) "Convert boolean to integer" + annotation (Placement(transformation(extent={{-50,-110},{-30,-90}}))); + Buildings.Controls.OBC.CDL.Integers.Add addInt "Add two integer inputs" + annotation (Placement(transformation(extent={{-10,-110},{10,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-10,-74},{10,-54}}))); + +equation + connect(ramp1.y,round1. u) + annotation (Line(points={{-68,90},{-52,90}}, color={0,0,127})); + connect(round1.y, chiSta.u) + annotation (Line(points={{-28,90},{-12,90}}, color={0,0,127})); + connect(chiSta.y, chiOn.u) + annotation (Line(points={{12,90},{20,90},{20,76},{-20,76},{-20,60},{-12,60}}, + color={255,127,0})); + connect(chiSta.y, heaHavWse.uChiSta) + annotation (Line(points={{12,90},{20,90},{20,99},{58,99}}, color={255,127,0})); + connect(chiSta.y, dedHavWse.uChiSta) + annotation (Line(points={{12,90},{20,90},{20,69},{58,69}}, color={255,127,0})); + connect(wseSta.y, heaHavWse.uWSE) + annotation (Line(points={{12,24},{32,24},{32,97},{58,97}}, color={255,0,255})); + connect(wseSta.y, dedHavWse.uWSE) + annotation (Line(points={{12,24},{32,24},{32,67},{58,67}}, color={255,0,255})); + connect(heaHavWse.yLeaPum, meaPumSpe.u2) + annotation (Line(points={{82,109},{90,109},{90,36},{-40,36},{-40,-36},{-12,-36}}, + color={255,0,255})); + connect(pumSpe.y, meaPumSpe.u1) + annotation (Line(points={{-58,-26},{-20,-26},{-20,-28},{-12,-28}}, + color={0,0,127})); + connect(zer.y, meaPumSpe.u3) + annotation (Line(points={{-58,-56},{-30,-56},{-30,-44},{-12,-44}}, + color={0,0,127})); + connect(meaPumSpe.y, heaHavWse.uConWatPumSpe) + annotation (Line(points={{12,-36},{46,-36},{46,93},{58,93}}, color={0,0,127})); + connect(meaPumSpe.y, dedHavWse.uConWatPumSpe) + annotation (Line(points={{12,-36},{46,-36},{46,63},{58,63}}, color={0,0,127})); + connect(meaPumSpe.y, heaNoWse.uConWatPumSpe) + annotation (Line(points={{12,-36},{46,-36},{46,-67},{58,-67}}, color={0,0,127})); + connect(pumSpeSet.u2, heaHavWse.yLeaPum) + annotation (Line(points={{-12,-6},{-40,-6},{-40,36},{90,36},{90,109},{82,109}}, + color={255,0,255})); + connect(pumSpeSetVal.y, pumSpeSet.u1) + annotation (Line(points={{-58,14},{-20,14},{-20,2},{-12,2}}, color={0,0,127})); + connect(zer.y, pumSpeSet.u3) + annotation (Line(points={{-58,-56},{-30,-56},{-30,-14},{-12,-14}}, + color={0,0,127})); + connect(pumSpeSet.y, heaHavWse.uConWatPumSpeSet) + annotation (Line(points={{12,-6},{40,-6},{40,95},{58,95}}, color={0,0,127})); + connect(pumSpeSet.y, dedHavWse.uConWatPumSpeSet) + annotation (Line(points={{12,-6},{40,-6},{40,65},{58,65}}, color={0,0,127})); + connect(pumSpeSet.y, heaNoWse.uConWatPumSpeSet) + annotation (Line(points={{12,-6},{40,-6},{40,-65},{58,-65}}, color={0,0,127})); + connect(chiOn.y, heaHavWse.uLeaChiSta) + annotation (Line(points={{12,60},{26,60},{26,106},{58,106}}, color={255,0,255})); + connect(chiOn.y, heaHavWse.uLeaConWatReq) + annotation (Line(points={{12,60},{26,60},{26,104},{58,104}}, color={255,0,255})); + connect(chiOn.y, dedHavWse.uLeaChiSta) + annotation (Line(points={{12,60},{26,60},{26,76},{58,76}}, color={255,0,255})); + connect(chiOn.y, dedHavWse.uLeaConWatReq) + annotation (Line(points={{12,60},{26,60},{26,74},{58,74}}, color={255,0,255})); + connect(chiOn.y, heaNoWse.uLeaChiSta) + annotation (Line(points={{12,60},{26,60},{26,-54},{58,-54}}, color={255,0,255})); + connect(chiOn.y, heaNoWse.uLeaConWatReq) + annotation (Line(points={{12,60},{26,60},{26,-56},{58,-56}}, color={255,0,255})); + connect(booPul.y, booToInt.u) + annotation (Line(points={{-58,-100},{-52,-100}}, color={255,0,255})); + connect(booToInt.y, addInt.u2) + annotation (Line(points={{-28,-100},{-20,-100},{-20,-106},{-12,-106}}, + color={255,127,0})); + connect(chiSta.y, addInt.u1) + annotation (Line(points={{12,90},{20,90},{20,-80},{-20,-80},{-20,-94}, + {-12,-94}}, color={255,127,0})); + connect(addInt.y, heaNoWse.uChiSta) + annotation (Line(points={{12,-100},{26,-100},{26,-61},{58,-61}}, color={255,127,0})); + connect(chiOn.y, heaHavWse.uLeaChiEna) + annotation (Line(points={{12,60},{28,60},{28,108},{58,108}}, color={255,0,255})); + connect(chiOn.y, dedHavWse.uLeaChiEna) + annotation (Line(points={{12,60},{28,60},{28,78},{58,78}}, color={255,0,255})); + connect(chiOn.y, heaNoWse.uLeaChiEna) + annotation (Line(points={{12,60},{28,60},{28,-52},{58,-52}}, color={255,0,255})); + connect(chiOn.y, heaHavWse.uChiConIsoVal[1]) + annotation (Line(points={{12,60},{28,60},{28,110},{58,110}}, color={255,0,255})); + connect(chiOn.y, dedHavWse.uChiConIsoVal[1]) + annotation (Line(points={{12,60},{28,60},{28,80},{58,80}}, color={255,0,255})); + connect(chiOn.y, heaNoWse.uChiConIsoVal[1]) + annotation (Line(points={{12,60},{28,60},{28,-50},{58,-50}}, color={255,0,255})); + connect(fal.y, heaHavWse.uChiConIsoVal[2]) + annotation (Line(points={{-58,44},{30,44},{30,110},{58,110}}, color={255,0,255})); + connect(fal.y, dedHavWse.uChiConIsoVal[2]) + annotation (Line(points={{-58,44},{30,44},{30,80},{58,80}}, color={255,0,255})); + connect(fal.y, heaNoWse.uChiConIsoVal[2]) + annotation (Line(points={{-58,44},{30,44},{30,-50},{58,-50}}, color={255,0,255})); + connect(con1.y, heaHavWse.uEnaPla) annotation (Line(points={{12,-64},{36,-64}, + {36,102},{58,102}}, color={255,0,255})); + connect(con1.y, dedHavWse.uEnaPla) annotation (Line(points={{12,-64},{36,-64}, + {36,72},{58,72}}, color={255,0,255})); + connect(con1.y, heaNoWse.uEnaPla) annotation (Line(points={{12,-64},{36,-64},{ + 36,-58},{58,-58}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller. +

+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-120},{100,120}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/package.mo new file mode 100644 index 00000000000..3e7ed99cc2d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater; +package Validation "Collection of validation models" + + annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.mo new file mode 100644 index 00000000000..e9e03f624da --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.mo @@ -0,0 +1,30 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps; +package CondenserWater "Sequences for condenser water pump control" + +annotation (preferredView="info", Documentation(info=" +

+This package contains control sequences for condenser water pumps. +The implementations are based on section 5.20.9 Condener water water pumps, +in ASHRAE Guideline36-2021. +

+"), Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + extent={{-66,66},{68,-68}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), Polygon( + points={{0,66},{0,-68},{68,0},{0,66}}, + lineColor={0,0,0}, + fillColor={238,46,47}, + fillPattern=FillPattern.Solid)})); +end CondenserWater; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.mo new file mode 100644 index 00000000000..5444f42705a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Pumps "Sequences for condenser water and chiller water pumps control" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for condenser and chilled water pumps. +The implementations are based on section 5.20.9 Condenser water pumps and +section 5.20.6 Primary chilled water pumps, in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Pumps; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.order new file mode 100644 index 00000000000..6648c541436 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.order @@ -0,0 +1,2 @@ +ChilledWater +CondenserWater diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterPlantReset.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterPlantReset.mo new file mode 100644 index 00000000000..d1950bb9f26 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterPlantReset.mo @@ -0,0 +1,252 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints; +block ChilledWaterPlantReset + "Sequences to generate chilled water plant reset" + + parameter Integer nPum = 2 "Total number of chilled water pumps"; + parameter Real holTim( + final unit="s", + final quantity="Time")=900 + "Time to fix plant reset value"; + parameter Real iniSet = 0 "Initial setpoint" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real minSet = 0 "Minimum setpoint" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real maxSet = 1 "Maximum setpoint" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real delTim( + final unit="s", + final quantity="Time")=900 + "Delay time after which trim and respond is activated" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real samplePeriod( + final unit="s", + final quantity="Time")=300 + "Sample period time" + annotation (Dialog(group="Trim and respond parameters")); + parameter Integer numIgnReq = 2 + "Number of ignored requests" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real triAmo = -0.02 "Trim amount" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real resAmo = 0.03 + "Respond amount (must be opposite in to triAmo)" + annotation (Dialog(group="Trim and respond parameters")); + parameter Real maxRes = 0.07 + "Maximum response per time interval (same sign as resAmo)" + annotation (Dialog(group="Trim and respond parameters")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput TChiWatSupResReq + "Chilled water supply temperature setpoint reset request" + annotation (Placement(transformation(extent={{-160,0},{-120,40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "Plant staging status that indicates if the plant is in the staging process" + annotation (Placement(transformation(extent={{-160,-60},{-120,-20}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nPum] + "Chilled water pump status" + annotation (Placement(transformation(extent={{-160,40},{-120,80}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatPlaRes( + final min=minSet, + final max=maxSet, + final unit="1") "Chilled water plant reset" + annotation (Placement(transformation(extent={{120,-80},{160,-40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond triRes( + final iniSet=iniSet, + final minSet=minSet, + final maxSet=maxSet, + final delTim=delTim, + final samplePeriod=samplePeriod, + final numIgnReq=numIgnReq, + final triAmo=triAmo, + final resAmo=resAmo, + final maxRes=maxRes) "Calculate chilled water plant reset" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Sample last reset value when there is chiller stage change" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truHol( + final trueHoldDuration=holTim, + final falseHoldDuration=0) + "Hold the true input with given time" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Check if the input changes from false to true" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Switch plant reset value depends on if there is chiller stage change" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nPum] "Logical not" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=nPum) "Logical and" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Check if these is any CHW pump is proven on" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Set reset value to zero when device is disabled" + annotation (Placement(transformation(extent={{80,-70},{100,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1( + final k=0) + "Zero request when device is OFF" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + +equation + connect(not1.y, mulAnd.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(mulAnd.y, not2.u) + annotation (Line(points={{-38,60},{-22,60}}, color={255,0,255})); + connect(uChiWatPum, not1.u) + annotation (Line(points={{-140,60},{-102,60}}, color={255,0,255})); + connect(triRes.y, triSam.u) + annotation (Line(points={{-38,20},{-22,20}}, color={0,0,127})); + connect(truHol.y, swi.u2) + annotation (Line(points={{-58,-40},{38,-40}}, color={255,0,255})); + connect(triRes.y, swi.u3) + annotation (Line(points={{-38,20},{-30,20},{-30,-48},{38,-48}}, + color={0,0,127})); + connect(triSam.y, swi.u1) + annotation (Line(points={{2,20},{10,20},{10,-32},{38,-32}}, + color={0,0,127})); + connect(edg.y, triSam.trigger) + annotation (Line(points={{-58,-10},{-10,-10},{-10,8}}, color={255,0,255})); + connect(chaPro, truHol.u) + annotation (Line(points={{-140,-40},{-82,-40}},color={255,0,255})); + connect(chaPro, edg.u) + annotation (Line(points={{-140,-40},{-100,-40},{-100,-10},{-82,-10}}, + color={255,0,255})); + connect(TChiWatSupResReq, triRes.numOfReq) annotation (Line(points={{-140,20}, + {-80,20},{-80,12},{-62,12}}, color={255,127,0})); + connect(not2.y, triRes.uDevSta) annotation (Line(points={{2,60},{20,60},{20,40}, + {-80,40},{-80,28},{-62,28}}, color={255,0,255})); + connect(not2.y, swi1.u2) annotation (Line(points={{2,60},{20,60},{20,-60},{78, + -60}}, color={255,0,255})); + connect(swi.y, swi1.u1) annotation (Line(points={{62,-40},{70,-40},{70,-52},{78, + -52}}, color={0,0,127})); + connect(con1.y, swi1.u3) annotation (Line(points={{-18,-80},{70,-80},{70,-68}, + {78,-68}}, color={0,0,127})); + connect(swi1.y, yChiWatPlaRes) + annotation (Line(points={{102,-60},{140,-60}}, color={0,0,127})); + +annotation ( + defaultComponentName="chiWatPlaRes", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-120,-100},{120,100}}),graphics={Rectangle( + extent={{-118,98},{78,-18}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-108,96},{44,80}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,255}, + horizontalAlignment=TextAlignment.Left, + textString="Calculate the plant reset, hold its last value when there is chiller stage change")}), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-94,68},{-36,56}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiWatPum"), + Text( + extent={{-94,12},{-10,-10}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="TChiWatSupResReq"), + Text( + extent={{-94,-52},{-56,-66}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + Text( + extent={{38,12},{96,-12}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatPlaRes")}), +Documentation(info=" +

+Block that output chilled water plant reset yChiWatPlaRes according +to ASHRAE Guideline36-2021, section 5.20.5.2. +

+

+Following implementation is for plants with primary-only and primary-secondary +systems serving differential pressure controlled pumps. +

+ + + + + + + + + + + + + + +
Variable Value Definition
DeviceAny chilled water pump Associated device
SP0iniSetInitial setpoint
SPminminSetMinimum setpoint
SPmaxmaxSetMaximum setpoint
TddelTimDelay timer
TsamplePeriodTime step
InumIgnReqNumber of ignored requests
RTChiWatSupResReqNumber of requests
SPtrimtriAmoTrim amount
SPresresAmoRespond amount
SPres_maxmaxResMaximum response per time interval
+
+ + +

+For primary-secondary plants serving more than one set of differential pressure +controlled pumps, an unique instance of the reset shall be used for each set of +differential pressure controlled secondary pumps. +

+ + +", revisions=" + +")); +end ChilledWaterPlantReset; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterSupply.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterSupply.mo new file mode 100644 index 00000000000..32868759683 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterSupply.mo @@ -0,0 +1,234 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints; +block ChilledWaterSupply + "Sequences to generate setpoints of chilled water supply temperature and the pump differential static pressure" + + parameter Integer nRemDpSen=1 + "Total number of remote pressure differential sensor"; + parameter Real dpChiWatPumMin( + final min=0, + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa") = 34473.8 + "Minimum chilled water pump differential static pressure, default 5 psi"; + parameter Real dpChiWatPumMax[nRemDpSen]( + final min=fill(dpChiWatPumMin,nRemDpSen), + final unit=fill("Pa",nRemDpSen), + final quantity=fill("PressureDifference",nRemDpSen), + displayUnit=fill("Pa",nRemDpSen)) + "Maximum chilled water pump differential static pressure"; + parameter Real TChiWatSupMin( + final quantity="ThermodynamicTemperature", + final unit="K", + displayUnit="degC") + "Minimum chilled water supply temperature. This is the lowest minimum chilled water supply temperature of chillers in the plant"; + parameter Real TChiWatSupMax( + final quantity="ThermodynamicTemperature", + final unit="K", + displayUnit="degC") = 288.706 + "Maximum chilled water supply temperature, default 60 degF"; + parameter Real minSet = 0 "Minimum plant reset value"; + parameter Real maxSet = 1 "Maximum plant reset value"; + parameter Real halSet = 0.5 "Half plant reset value"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatPlaRes( + final min=minSet, + final max=maxSet, + final unit="1") + "Chilled water plant reset" + annotation (Placement(transformation(extent={{-120,-20},{-80,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpChiWatPumSet[nRemDpSen]( + final unit=fill("Pa", nRemDpSen), + final quantity=fill("PressureDifference",nRemDpSen)) + "Chilled water pump differential static pressure setpoint" + annotation (Placement(transformation(extent={{80,30},{120,70}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{80,-70},{120,-30}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Line chiWatPumPre[nRemDpSen] + "Chilled water pump differential pressure setpoint" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerRes[nRemDpSen]( + final k=fill(minSet, nRemDpSen)) "Minimum plant reset" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant halRes[nRemDpSen]( + final k=fill(halSet, nRemDpSen)) "Half one plant reset" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant oneRes( + final k=maxSet) "Maximum plant reset" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minChiWatPumPre[nRemDpSen]( + final k=fill(dpChiWatPumMin, nRemDpSen)) + "Minimum chilled water pump differential pressure setpoint" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxChiWatPumPre[nRemDpSen]( + final k=dpChiWatPumMax) + "Maximum chilled water pump differential pressure setpoint" + annotation (Placement(transformation(extent={{-20,18},{0,38}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxChiWatTem( + final k=TChiWatSupMax) + "Maximum chilled water supply temperature" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minChiWatTem( + final k=TChiWatSupMin) + "Minimum chilled water supply temperature" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Line chiWatTem + "Chilled water temperature setpoint" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nRemDpSen) + "Distribute reset value to each remote sensor" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + +equation + connect(zerRes.y, chiWatPumPre.x1) + annotation (Line(points={{-38,90},{20,90},{20,58},{38,58}}, + color={0,0,127})); + connect(minChiWatPumPre.y, chiWatPumPre.f1) + annotation (Line(points={{2,70},{14,70},{14,54},{38,54}}, + color={0,0,127})); + connect(halRes.y, chiWatPumPre.x2) + annotation (Line(points={{-38,0},{20,0},{20,46},{38,46}}, + color={0,0,127})); + connect(maxChiWatPumPre.y, chiWatPumPre.f2) + annotation (Line(points={{2,28},{14,28},{14,42},{38,42}}, + color={0,0,127})); + connect(maxChiWatTem.y, chiWatTem.f1) + annotation (Line(points={{2,-30},{14,-30},{14,-46},{38,-46}}, + color={0,0,127})); + connect(oneRes.y, chiWatTem.x2) + annotation (Line(points={{-38,-90},{14,-90},{14,-54},{38,-54}}, + color={0,0,127})); + connect(minChiWatTem.y, chiWatTem.f2) + annotation (Line(points={{2,-70},{20,-70},{20,-58},{38,-58}}, + color={0,0,127})); + connect(chiWatPumPre.y, dpChiWatPumSet) + annotation (Line(points={{62,50},{100,50}},color={0,0,127})); + connect(chiWatTem.y, TChiWatSupSet) + annotation (Line(points={{62,-50},{100,-50}},color={0,0,127})); + connect(uChiWatPlaRes, chiWatTem.u) annotation (Line(points={{-100,0},{-70,0}, + {-70,-50},{38,-50}}, color={0,0,127})); + connect(uChiWatPlaRes, reaRep.u) annotation (Line(points={{-100,0},{-70,0},{-70, + 50},{-62,50}}, color={0,0,127})); + connect(halRes[1].y, chiWatTem.x1) annotation (Line(points={{-38,0},{20,0},{20, + -42},{38,-42}}, color={0,0,127})); + connect(reaRep.y, chiWatPumPre.u) + annotation (Line(points={{-38,50},{38,50}}, color={0,0,127})); + +annotation ( + defaultComponentName="chiWatSupSet", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-80,-120},{80,120}}), graphics={Rectangle( + extent={{-78,118},{78,2}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), Rectangle( + extent={{-78,-2},{78,-118}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-26,118},{74,106}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,255}, + horizontalAlignment=TextAlignment.Left, + textString="Chilled water pump differential pressure setpoint"), + Text( + extent={{-22,-104},{74,-116}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,255}, + horizontalAlignment=TextAlignment.Left, + textString="Chilled water supply temperature setpoint")}), + Icon(graphics={Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Line(points={{-80,72},{-80,-54},{80,-54},{80,72}}, color={95,95,95}), + Line( + points={{-80,64},{-2,64},{80,-54}}, + color={0,0,0}, + thickness=0.5), + Line( + points={{-80,-54},{-2,64},{80,64}}, + color={28,108,200}, + pattern=LinePattern.Dash, + thickness=0.5), + Line( + points={{-2,64},{-2,-54}}, + color={215,215,215}, + pattern=LinePattern.Dash), + Polygon( + points={{-72,-66},{-50,-60},{-50,-72},{-72,-66}}, + lineColor={95,95,95}, + fillColor={95,95,95}, + fillPattern=FillPattern.Solid), + Line(points={{-10,-66},{-68,-66}},color={95,95,95}), + Line(points={{8,-66},{70,-66}}, color={95,95,95}), + Polygon( + points={{72,-66},{50,-60},{50,-72},{72,-66}}, + lineColor={95,95,95}, + fillColor={95,95,95}, + fillPattern=FillPattern.Solid), + Text( + extent={{-20,-66},{22,-82}}, + textColor={95,95,95}, + textString="Plant reset"), + Text( + extent={{14,26},{68,6}}, + textColor={95,95,95}, + horizontalAlignment=TextAlignment.Right, + textString="Temperature +setpoint"), + Text( + extent={{-76,22},{-42,8}}, + textColor={95,95,95}, + horizontalAlignment=TextAlignment.Right, + textString="DP +setpoint"), + Text( + extent={{-14,-56},{12,-62}}, + textColor={95,95,95}, + textString="0.5")}), +Documentation(info=" +

+Block that output setpoints for the chilled water supply of primary-only and +primary-secondary systems serving differential pressure controlled pumps. +The outputs include supply temperature setpoint TChiWatSupSet +and pump differential pressure setpoint dpChiWatPumSet, according +to ASHRAE Guideline36-2021, section 5.20.5.2. +

+

+Chilled water supply temperature setpoint TChiWatSupSet and pump +differential pressure setpoint dpChiWatPumSet shall be reset based on +the current value of chilled water plant reset uChiWatPlaRes. +

+

+\"Image +

+", revisions=" + +")); +end ChilledWaterSupply; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterPlantReset.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterPlantReset.mo new file mode 100644 index 00000000000..8e35e0785ce --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterPlantReset.mo @@ -0,0 +1,156 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.Validation; +model ChilledWaterPlantReset + "Validate model of generating chilled water plant reset" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterPlantReset + plaRes "Chilled water plant reset" + annotation (Placement(transformation(extent={{60,80},{80,100}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterPlantReset + devRes "Validate chilled water plant reset affected by device status" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uChiWatPum[2]( + final k={true,false}) "Plant status" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real to integer" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=9500, + final width=0.3, + shift=-2000) + "Generate pulse signal of type Boolean" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Switch between two Real signals" + annotation (Placement(transformation(extent={{-30,-90},{-10,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(final k=0) + "Zero request when device is OFF" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Convert real to integer" + annotation (Placement(transformation(extent={{10,-90},{30,-70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator chiWatPum(nout=2) + "Chilled water pump status" + annotation (Placement(transformation(extent={{10,-50},{30,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTabLin1( + smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + table=[0,0;150,1; 300,2; 450,3; 600,4; 750,5; 900,6; + 1050,5; 1200,4; 1350,3; 1500,2; 1650,1; 1800,0]) + "Time table with smoothness method of constant segments" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTabLin2( + smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + table=[0,0;150,1; 300,2; 450,3; 600,4; 750,5; 900,6; + 1050,5; 1200,4; 1350,3; 1500,2; 1650,1; 1800,0]) + "Time table with smoothness method of constant segments" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + period=3600) + "Generate pulse signal of type Boolean" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch staPro "Staging process" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + k=false) "Constant false" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2(width=0.4, + period=4800) + "Generate pulse signal of type Boolean" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + +equation + connect(uChiWatPum.y, plaRes.uChiWatPum) + annotation (Line(points={{-58,100},{40,100},{40,96},{58,96}}, color={255,0,255})); + connect(con1.y,swi. u1) + annotation (Line(points={{-58,-70},{-40,-70},{-40,-72},{-32,-72}}, + color={0,0,127})); + connect(booPul.y,swi. u2) + annotation (Line(points={{-58,-40},{-50,-40},{-50,-80},{-32,-80}}, + color={255,0,255})); + connect(booPul.y,not1. u) + annotation (Line(points={{-58,-40},{-42,-40}},color={255,0,255})); + connect(not1.y, chiWatPum.u) + annotation (Line(points={{-18,-40},{8,-40}}, color={255,0,255})); + connect(chiWatPum.y, devRes.uChiWatPum) annotation (Line(points={{32,-40},{40, + -40},{40,-44},{58,-44}}, color={255,0,255})); + connect(reaToInt1.y, plaRes.TChiWatSupResReq) + annotation (Line(points={{22,80},{40,80},{40,90},{58,90}}, color={255,127,0})); + connect(reaToInt3.y, devRes.TChiWatSupResReq) + annotation (Line(points={{32,-80},{40,-80},{40,-50},{58,-50}}, color={255,127,0})); + connect(timTabLin1.y[1], reaToInt1.u) + annotation (Line(points={{-18,80},{-2,80}}, color={0,0,127})); + connect(timTabLin2.y[1], swi.u3) + annotation (Line(points={{-58,-100},{-40,-100},{-40,-88},{-32,-88}}, + color={0,0,127})); + connect(swi.y, reaToInt3.u) + annotation (Line(points={{-8,-80},{8,-80}}, color={0,0,127})); + connect(booPul1.y, plaRes.chaPro) + annotation (Line(points={{-58,60},{50,60},{50,84},{58,84}},color={255,0,255})); + connect(staPro.y, devRes.chaPro) annotation (Line(points={{22,10},{50,10},{50, + -56},{58,-56}}, color={255,0,255})); + connect(con.y, staPro.u3) annotation (Line(points={{-58,-10},{-30,-10},{-30,2}, + {-2,2}}, color={255,0,255})); + connect(not1.y, staPro.u2) annotation (Line(points={{-18,-40},{-10,-40},{-10,10}, + {-2,10}}, color={255,0,255})); + connect(booPul2.y, staPro.u1) annotation (Line(points={{-38,30},{-10,30},{-10, + 18},{-2,18}}, color={255,0,255})); + +annotation ( + experiment(StopTime=9000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterPlantReset.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterPlantReset. +

+

+The instance plaRes shows the process of calculating the plant reset. +It also shows that when the plant is in staging process, the reset value will be fixed +at the value when the staging process just starts. +

+ +

+The process of calculating the reset value follows the same steps. +For the instance devRes, besides the same process as showing in the +instance plaRes, the devRes also shows that the reset +value will be zero when the device is disabled (uDevSta=false). +

+", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-120},{100,120}}))); +end ChilledWaterPlantReset; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterSupply.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterSupply.mo new file mode 100644 index 00000000000..58f9a5810d0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterSupply.mo @@ -0,0 +1,49 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.Validation; +model ChilledWaterSupply + "Validate model of generating setpoints for chilled water supply control" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterSupply + chiWatSupSet( + final dpChiWatPumMin=60, + final dpChiWatPumMax={150}, + final TChiWatSupMin=280.15, + final TChiWatSupMax=291.15) "Generate setpoint for chilled water supply control" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plaRes(final duration=3600) + "Chilled water plant reset" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + +equation + connect(plaRes.y, chiWatSupSet.uChiWatPlaRes) + annotation (Line(points={{-18,0},{18,0}}, color={0,0,127})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterSupply.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterSupply. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false))); +end ChilledWaterSupply; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/package.mo new file mode 100644 index 00000000000..f594d9ea7c9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints; +package Validation "Collection of validation models" + +annotation ( +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Setpoints. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/package.order new file mode 100644 index 00000000000..6ae8b2ac697 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/package.order @@ -0,0 +1,2 @@ +ChilledWaterPlantReset +ChilledWaterSupply diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.mo new file mode 100644 index 00000000000..fd43d92aa4e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.mo @@ -0,0 +1,25 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package SetPoints "Sequences for setting the setpoints for chilled water control " + +annotation (preferredView="info", Documentation(info=" +

+This package contains chilled water plant reset control sequences. +The implementation is based on section 5.20.5.2. in ASHRAE Guideline36-2021. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S")})); +end SetPoints; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.order new file mode 100644 index 00000000000..f3e4cf99024 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.order @@ -0,0 +1,3 @@ +ChilledWaterPlantReset +ChilledWaterSupply +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Down.mo new file mode 100644 index 00000000000..aeec64f7817 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Down.mo @@ -0,0 +1,951 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes; +block Down + "Sequence for controlling devices when there is a stage-down command" + + parameter Integer nChi = 2 "Total number of chillers in the plant"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Integer totSta = 3 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable"; + parameter Integer nChiSta=3 + "Total number of chiller stages, including stage zero but not the stages with a WSE, if applicable"; + parameter Boolean have_WSE=true + "True: have waterside economizer"; + parameter Boolean have_ponyChiller=false + "True: have pony chiller"; + parameter Boolean have_parChi=true + "True: the plant has parallel chillers"; + parameter Boolean have_heaConWatPum=true + "True: headered condenser water pumps"; + parameter Boolean have_fixSpeConWatPum=false + "True: fixed speed condenser water pump"; + parameter Boolean need_reduceChillerDemand=false + "True: need limit chiller demand when chiller staging"; + parameter Real chiDemRedFac=0.75 + "Demand reducing factor of current operating chillers" + annotation (Dialog(group="Disable last chiller", enable=have_ponyChiller and need_reduceChillerDemand)); + parameter Real holChiDemTim( + unit="s", + displayUnit="s")=300 + "Maximum time to wait for the actual demand less than percentage of current load" + annotation (Dialog(group="Disable last chiller", enable=have_ponyChiller and need_reduceChillerDemand)); + parameter Real waiTim( + unit="s", + displayUnit="s")=30 + "Waiting time after enabling next head pressure control" + annotation (Dialog(group="Disable last chiller", enable=have_ponyChiller)); + parameter Real proOnTim( + unit="s", + displayUnit="s")=300 + "Enabled chiller operation time to indicate if it is proven on" + annotation (Dialog(group="Disable last chiller", enable=have_ponyChiller)); + parameter Real chaChiWatIsoTim(unit="s", displayUnit="s") + "Time to slowly change isolation valve, should be determined in the field" + annotation (Dialog(group="Disable CHW isolation valve")); + parameter Real staVec[totSta] + "Chiller stage vector, element value like x.5 means chiller stage x plus WSE" + annotation (Dialog(group="Disable condenser water pump")); + parameter Real desConWatPumSpe[totSta] + "Design condenser water pump speed setpoints, according to current chiller stage and WSE status" + annotation (Dialog(group="Disable condenser water pump")); + parameter Real desConWatPumNum[totSta] + "Design number of condenser water pumps that should be ON, according to current chiller stage and WSE status" + annotation (Dialog(group="Disable condenser water pump")); + parameter Real desChiNum[nChiSta]={0,1,2} + "Design number of chiller that should be ON, according to current chiller stage" + annotation (Dialog(group="Disable condenser water pump", enable=have_fixSpeConWatPum)); + parameter Real byPasSetTim(unit="s", displayUnit="s") + "Time to reset minimum by-pass flow" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real minFloSet[nChi]( + unit=fill("m3/s",nChi), + displayUnit=fill("m3/s",nChi)) + "Minimum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real maxFloSet[nChi]( + unit=fill("m3/s",nChi), + displayUnit=fill("m3/s",nChi)) + "Maximum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real aftByPasSetTim( + unit="s", + displayUnit="s")=60 + "Time to allow loop to stabilize after resetting minimum chilled water flow setpoint" + annotation (Dialog(group="Reset bypass")); + parameter Real pumSpeChe = 0.05 + "Lower threshold value to check if condenser water pump has achieved setpoint" + annotation (Dialog(tab="Advanced", group="Disable condenser water pump")); + parameter Real relFloDif=0.05 + "Relative error to the setpoint for checking if it has achieved flow rate setpoint" + annotation (Dialog(tab="Advanced", group="Reset bypass")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Chiller stage setpoint index" + annotation (Placement(transformation(extent={{-320,360},{-280,400}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiSet[nChi] + "Vector of chillers status setpoint" + annotation (Placement(transformation(extent={{-320,320},{-280,360}}), + iconTransformation(extent={{-140,150},{-100,190}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput yOpeParLoaRatMin( + final min=0, + final max=1, + final unit="1") if need_reduceChillerDemand + "Current stage minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-320,260},{-280,300}}), + iconTransformation(extent={{-140,110},{-100,150}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiLoa[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) if need_reduceChillerDemand + "Current chiller load" + annotation (Placement(transformation(extent={{-320,230},{-280,270}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-320,200},{-280,240}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") + "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-320,170},{-280,210}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage, it would be the same as chiller stage setpoint when it is not in staging process" + annotation (Placement(transformation(extent={{-320,140},{-280,180}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-320,110},{-280,150}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-320,80},{-280,120}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatReq[nChi] + "Chilled water requst status for each chiller" + annotation (Placement(transformation(extent={{-320,-30},{-280,10}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatReq[nChi] + "Condenser water requst status for each chiller" + annotation (Placement(transformation(extent={{-320,-140},{-280,-100}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiConIsoVal[nChi] + "Chiller condenser water isolation valve status" + annotation (Placement(transformation(extent={{-320,-200},{-280,-160}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-320,-260},{-280,-220}}), + iconTransformation(extent={{-140,-150},{-100,-110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpeSet( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{-320,-300},{-280,-260}}), + iconTransformation(extent={{-140,-170},{-100,-130}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-320,-360},{-280,-320}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatPum[nConWatPum] if have_fixSpeConWatPum + "Status indicating if condenser water pump is running" + annotation (Placement(transformation(extent={{-320,-400},{-280,-360}}), + iconTransformation(extent={{-140,-210},{-100,-170}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaPro + "Indicate stage-down status: true=in stage-down process" + annotation (Placement(transformation(extent={{280,340},{320,380}}), + iconTransformation(extent={{100,170},{140,210}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiDem[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) if need_reduceChillerDemand + "Chiller demand setpoint" + annotation (Placement(transformation(extent={{280,240},{320,280}}), + iconTransformation(extent={{100,130},{140,170}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{280,200},{320,240}}), + iconTransformation(extent={{100,100},{140,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yReaDemLim + if need_reduceChillerDemand + "Release demand limit" + annotation (Placement(transformation(extent={{280,160},{320,200}}), + iconTransformation(extent={{100,60},{140,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chiller chilled water isolation valve position" + annotation (Placement(transformation(extent={{280,20},{320,60}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowStaDow + "Tower stage down status: true=stage down cooling tower" + annotation (Placement(transformation(extent={{280,-80},{320,-40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiHeaCon[nChi] + "Chiller head pressure control enabling status" + annotation (Placement(transformation(extent={{280,-120},{320,-80}}), + iconTransformation(extent={{100,-50},{140,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaPum + "Lead condenser water pump status" + annotation (Placement(transformation(extent={{280,-170},{320,-130}}), + iconTransformation(extent={{100,-90},{140,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDesConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Condenser water pump design speed at current stage" + annotation (Placement(transformation(extent={{280,-200},{320,-160}}), + iconTransformation(extent={{100,-130},{140,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yConWatPumNum + "Number of operating condenser water pumps" + annotation (Placement(transformation(extent={{280,-240},{320,-200}}), + iconTransformation(extent={{100,-150},{140,-110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatMinFloSet( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") + "Chilled water minimum flow setpoint" + annotation (Placement(transformation(extent={{280,-350},{320,-310}}), + iconTransformation(extent={{100,-180},{140,-140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEndStaTri + "Staging end trigger" + annotation (Placement(transformation(extent={{280,-390},{320,-350}}), + iconTransformation(extent={{100,-210},{140,-170}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if stage setpoint dicreases" + annotation (Placement(transformation(extent={{-240,350},{-220,370}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi(final nChi=nChi) "Identify next enabling chiller" + annotation (Placement(transformation(extent={{-40,330},{-20,350}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DownStart + dowSta( + final nChi=nChi, + final have_parChi=have_parChi, + final need_reduceChillerDemand=need_reduceChillerDemand, + final chiDemRedFac=chiDemRedFac, + final holChiDemTim=holChiDemTim, + final minFloSet=minFloSet, + final maxFloSet=maxFloSet, + final aftByPasSetTim=aftByPasSetTim, + final relFloDif=relFloDif, + final byPasSetTim=byPasSetTim, + final waiTim=waiTim, + final chaChiWatIsoTim=chaChiWatIsoTim, + final proOnTim=proOnTim) "Start stage-down process" + annotation (Placement(transformation(extent={{60,220},{80,240}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal + disChiIsoVal( + final nChi=nChi, + final chaChiWatIsoTim=chaChiWatIsoTim, + final iniValPos=1, + final endValPos=0) "Disable isolation valve of the chiller being disabled" + annotation (Placement(transformation(extent={{200,50},{220,70}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + disHeaCon( + final nChi=nChi, + final thrTimEnb=0, + final waiTim=0, + final heaStaCha=false) + "Disable head pressure control of the chiller being disabled" + annotation (Placement(transformation(extent={{200,-110},{220,-90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump + disNexCWP + "Identify correct stage number for disabling next condenser water pump" + annotation (Placement(transformation(extent={{100,-170},{120,-150}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller + conWatPumCon( + final have_heaPum=have_heaConWatPum, + final have_WSE=have_WSE, + final fixSpe=have_fixSpeConWatPum, + final nChi=nChi, + final nConWatPum=nConWatPum, + final totSta=totSta, + final nChiSta=nChiSta, + final staVec=staVec, + final desConWatPumSpe=desConWatPumSpe, + final desConWatPumNum=desConWatPumNum, + final desChiNum=desChiNum, + final pumSpeChe=pumSpeChe) + "Enabling next condenser water pump or change pump speed" + annotation (Placement(transformation(extent={{140,-192},{160,-172}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + minChiWatFlo( + final nChi=nChi, + final have_parChi=have_parChi, + final maxFloSet=maxFloSet, + final byPasSetTim=byPasSetTim, + final minFloSet=minFloSet) "Minimum chilled water flow setpoint" + annotation (Placement(transformation(extent={{100,-330},{120,-310}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) + "False constant" + annotation (Placement(transformation(extent={{-160,190},{-140,210}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-240,-20},{-220,0}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor curDisChi( + final nin=nChi) + "Current disabling chiller" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesEquThr( + final t=0.5) "Check if the disabled chiller has not chilled water request" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 "Logical and" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2 "Logical switch" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{140,10},{160,30}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] + "Chilled water isolvation valve position" + annotation (Placement(transformation(extent={{140,70},{160,90}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea2[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-240,-130},{-220,-110}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor curDisChi1( + final nin=nChi) + "Current disabling chiller" + annotation (Placement(transformation(extent={{-100,-130},{-80,-110}}))); + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesEquThr1( + final t=0.5) + "Check if the disabled chiller is not requiring condenser water" + annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 "Logical and" + annotation (Placement(transformation(extent={{80,-130},{100,-110}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi [nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{140,-80},{160,-60}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChi) "Multiple or" + annotation (Placement(transformation(extent={{-80,-210},{-60,-190}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1(final nin=nChi) "Multiple or" + annotation (Placement(transformation(extent={{-40,-230},{-20,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{-180,350},{-160,370}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{200,-250},{220,-230}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{220,-380},{240,-360}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre + "Break algebraic loop" + annotation (Placement(transformation(extent={{180,-380},{200,-360}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Maintain ON signal when condenser water pump has been disabled" + annotation (Placement(transformation(extent={{240,-270},{260,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Maintain ON signal when chiller demand has been limited" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiWatMinSet + "Chilled water minimum flow set" + annotation (Placement(transformation(extent={{200,-340},{220,-320}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat3 + "Maintain ON signal when chilled water isolation valve has been disabled" + annotation (Placement(transformation(extent={{200,-40},{220,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat4 + "Maintain ON signal when chiller head pressure control has been disabled" + annotation (Placement(transformation(extent={{200,-140},{220,-120}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical and" + annotation (Placement(transformation(extent={{120,-130},{140,-110}}))); + Buildings.Controls.OBC.CDL.Logical.And and6 "Logical and" + annotation (Placement(transformation(extent={{60,-20},{80,0}}))); + Buildings.Controls.OBC.CDL.Logical.And and7 "Logical and" + annotation (Placement(transformation(extent={{-26,-130},{-6,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Not notInPro + "True: it is not in the setpoint changing process" + annotation (Placement(transformation(extent={{140,-380},{160,-360}}))); +equation + connect(nexChi.yEnaSmaChi,dowSta. nexEnaChi) + annotation (Line(points={{-18,331},{30,331},{30,226},{58,226}}, + color={255,127,0})); + connect(dowSta.uChiWatIsoVal, uChiWatIsoVal) + annotation (Line(points={{58,222},{-60,222},{-60,100},{-300,100}}, + color={0,0,127})); + connect(nexChi.yLasDisChi,dowSta. nexDisChi) + annotation (Line(points={{-18,334},{20,334},{20,220},{58,220}}, + color={255,127,0})); + connect(uChiWatReq, booToRea1.u) + annotation (Line(points={{-300,-10},{-242,-10}}, color={255,0,255})); + connect(booToRea1.y, curDisChi.u) + annotation (Line(points={{-218,-10},{-102,-10}},color={0,0,127})); + connect(curDisChi.y, lesEquThr.u) + annotation (Line(points={{-78,-10},{-62,-10}}, color={0,0,127})); + connect(nexChi.yOnOff, logSwi2.u2) + annotation (Line(points={{-18,337},{0,337},{0,20},{58,20}}, + color={255,0,255})); + connect(and4.y, logSwi2.u1) + annotation (Line(points={{-18,30},{40,30},{40,28},{58,28}}, + color={255,0,255})); + connect(nexChi.yLasDisChi, curDisChi.index) + annotation (Line(points={{-18,334},{20,334},{20,120},{-140,120},{-140,-30}, + {-90,-30},{-90,-22}}, + color={255,127,0})); + connect(logSwi2.y, and1.u1) + annotation (Line(points={{82,20},{138,20}}, color={255,0,255})); + connect(nexChi.yLasDisChi, disChiIsoVal.nexChaChi) + annotation (Line(points={{-18,334},{20,334},{20,68},{198,68}}, + color={255,127,0})); + connect(and1.y,disChiIsoVal.uUpsDevSta) + annotation (Line(points={{162,20},{180,20},{180,55},{198,55}}, + color={255,0,255})); + connect(nexChi.yOnOff, booRep4.u) + annotation (Line(points={{-18,337},{0,337},{0,80},{58,80}}, color={255,0,255})); + connect(booRep4.y, swi.u2) + annotation (Line(points={{82,80},{138,80}}, color={255,0,255})); + connect(uChiWatIsoVal, swi.u3) + annotation (Line(points={{-300,100},{88,100},{88,72},{138,72}}, + color={0,0,127})); + connect(dowSta.yChiWatIsoVal, swi.u1) + annotation (Line(points={{82,228},{96,228},{96,88},{138,88}}, + color={0,0,127})); + connect(swi.y, disChiIsoVal.uChiWatIsoVal) + annotation (Line(points={{162,80},{180,80},{180,65},{198,65}}, + color={0,0,127})); + connect(uConWatReq, booToRea2.u) + annotation (Line(points={{-300,-120},{-242,-120}}, color={255,0,255})); + connect(booToRea2.y, curDisChi1.u) + annotation (Line(points={{-218,-120},{-102,-120}}, + color={0,0,127})); + connect(curDisChi1.y, lesEquThr1.u) + annotation (Line(points={{-78,-120},{-62,-120}}, color={0,0,127})); + connect(logSwi2.y, and5.u1) + annotation (Line(points={{82,20},{90,20},{90,-50},{50,-50},{50,-120},{78, + -120}}, + color={255,0,255})); + connect(uChi,dowSta. uChi) + annotation (Line(points={{-300,220},{-200,220},{-200,234},{58,234}}, + color={255,0,255})); + connect(nexChi.yLasDisChi, curDisChi1.index) + annotation (Line(points={{-18,334},{20,334},{20,120},{-140,120},{-140,-140}, + {-90,-140},{-90,-132}}, + color={255,127,0})); + connect(nexChi.yOnOff, booRep1.u) + annotation (Line(points={{-18,337},{0,337},{0,-70},{58,-70}}, + color={255,0,255})); + connect(booRep1.y, logSwi.u2) + annotation (Line(points={{82,-70},{138,-70}}, color={255,0,255})); + connect(dowSta.yChiHeaCon, logSwi.u1) + annotation (Line(points={{82,232},{100,232},{100,-62},{138,-62}}, + color={255,0,255})); + connect(nexChi.yLasDisChi, disHeaCon.nexChaChi) + annotation (Line(points={{-18,334},{20,334},{20,-104},{198,-104}}, + color={255,127,0})); + connect(logSwi.y, disHeaCon.uChiHeaCon) + annotation (Line(points={{162,-70},{180,-70},{180,-108},{198,-108}}, + color={255,0,255})); + connect(con.y,disNexCWP. uStaUp) + annotation (Line(points={{-138,200},{-120,200},{-120,-158},{98,-158}}, + color={255,0,255})); + connect(disNexCWP.yChiSta, conWatPumCon.uChiSta) + annotation (Line(points={{122,-160},{130,-160},{130,-183},{138,-183}}, + color={255,127,0})); + connect(mulOr1.y, conWatPumCon.uLeaConWatReq) + annotation (Line(points={{-18,-220},{46,-220},{46,-178},{138,-178}}, + color={255,0,255})); + connect(uChi, mulOr.u) + annotation (Line(points={{-300,220},{-200,220},{-200,-200},{-82,-200}}, + color={255,0,255})); + connect(uConWatReq, mulOr1.u) + annotation (Line(points={{-300,-120},{-250,-120},{-250,-220},{-42,-220}}, + color={255,0,255})); + connect(conWatPumCon.uWSE, uWSE) + annotation (Line(points={{138,-185},{52,-185},{52,-240},{-300,-240}}, + color={255,0,255})); + connect(conWatPumCon.uConWatPumSpe, uConWatPumSpe) + annotation (Line(points={{138,-189},{64,-189},{64,-340},{-300,-340}}, + color={0,0,127})); + connect(con.y, minChiWatFlo.uStaUp) + annotation (Line(points={{-138,200},{-120,200},{-120,-311},{98,-311}}, + color={255,0,255})); + connect(nexChi.yOnOff, minChiWatFlo.uOnOff) + annotation (Line(points={{-18,337},{0,337},{0,-327},{98,-327}}, + color={255,0,255})); + connect(dowSta.yChiDem, yChiDem) + annotation (Line(points={{82,239},{179.5,239},{179.5,260},{300,260}}, + color={0,0,127})); + connect(dowSta.yChi, yChi) + annotation (Line(points={{82,224},{180,224},{180,220},{300,220}}, + color={255,0,255})); + connect(disChiIsoVal.yChiWatIsoVal, yChiWatIsoVal) + annotation (Line(points={{222,54},{250,54},{250,40},{300,40}}, + color={0,0,127})); + connect(VChiWat_flow, dowSta.VChiWat_flow) + annotation (Line(points={{-300,190},{-170,190},{-170,232},{58,232}}, + color={0,0,127})); + connect(uChiLoa,dowSta. uChiLoa) + annotation (Line(points={{-300,250},{-170,250},{-170,236},{58,236}}, + color={0,0,127})); + connect(lat.y,dowSta. uStaDow) + annotation (Line(points={{-158,360},{-140,360},{-140,328},{-260,328},{-260,240}, + {58,240}}, color={255,0,255})); + connect(lat.y, disChiIsoVal.uStaPro) annotation (Line(points={{-158,360},{-140, + 360},{-140,328},{-260,328},{-260,52},{198,52}}, color={255,0,255})); + connect(lat.y, and4.u2) + annotation (Line(points={{-158,360},{-140,360},{-140,328},{-260,328},{-260,22}, + {-42,22}}, color={255,0,255})); + connect(lat.y, logSwi2.u3) + annotation (Line(points={{-158,360},{-140,360},{-140,328},{-260,328},{-260,12}, + {58,12}}, color={255,0,255})); + connect(lat.y, disHeaCon.uStaPro) annotation (Line(points={{-158,360},{-140, + 360},{-140,328},{-260,328},{-260,-100},{198,-100}}, color={255,0,255})); + connect(lat.y, minChiWatFlo.uStaDow) + annotation (Line(points={{-158,360},{-140,360},{-140,328},{-260,328},{-260,-329}, + {98,-329}}, color={255,0,255})); + connect(lat.y,disNexCWP. uStaDow) + annotation (Line(points={{-158,360},{-140,360},{-140,328},{-260,328},{-260,-162}, + {98,-162}}, color={255,0,255})); + connect(lat.y, yStaPro) + annotation (Line(points={{-158,360},{300,360}},color={255,0,255})); + connect(dowSta.yOpeParLoaRatMin, yOpeParLoaRatMin) + annotation (Line(points={{58,238},{40,238},{40,280},{-300,280}}, + color={0,0,127})); + connect(conWatPumCon.uChiConIsoVal, uChiConIsoVal) + annotation (Line(points={{138,-172},{-140,-172},{-140,-180},{-300,-180}}, + color={255,0,255})); + connect(mulOr.y, conWatPumCon.uLeaChiEna) + annotation (Line(points={{-58,-200},{40,-200},{40,-174},{138,-174}}, + color={255,0,255})); + connect(mulOr.y, conWatPumCon.uLeaChiSta) + annotation (Line(points={{-58,-200},{40,-200},{40,-176},{138,-176}}, + color={255,0,255})); + connect(conWatPumCon.yDesConWatPumSpe, yDesConWatPumSpe) + annotation (Line(points={{162,-179},{240,-179},{240,-180},{300,-180}}, + color={0,0,127})); + connect(conWatPumCon.uConWatPumSpeSet, uConWatPumSpeSet) + annotation (Line(points={{138,-187},{58,-187},{58,-280},{-300,-280}}, + color={0,0,127})); + connect(uChi, minChiWatFlo.uChi) + annotation (Line(points={{-300,220},{-200,220},{-200,-316},{98,-316}}, + color={255,0,255})); + connect(nexChi.yLasDisChi, minChiWatFlo.nexDisChi) + annotation (Line(points={{-18,334},{20,334},{20,-321},{98,-321}}, + color={255,127,0})); + connect(nexChi.yEnaSmaChi, minChiWatFlo.nexEnaChi) + annotation (Line(points={{-18,331},{30,331},{30,-319},{98,-319}}, + color={255,127,0})); + connect(con.y, minChiWatFlo.uSubCha) + annotation (Line(points={{-138,200},{-120,200},{-120,-324},{98,-324}}, + color={255,0,255})); + connect(edg1.y, lat.clr) + annotation (Line(points={{242,-370},{260,-370},{260,-390},{-190,-390},{-190, + 354},{-182,354}}, color={255,0,255})); + connect(conWatPumCon.yConWatPumNum, yConWatPumNum) + annotation (Line(points={{162,-185},{220,-185},{220,-220},{300,-220}}, + color={255,127,0})); + connect(conWatPumCon.yLeaPum, yLeaPum) + annotation (Line(points={{162,-173},{220,-173},{220,-150},{300,-150}}, + color={255,0,255})); + connect(disHeaCon.yChiHeaCon, yChiHeaCon) + annotation (Line(points={{222,-106},{260,-106},{260,-100},{300,-100}}, + color={255,0,255})); + connect(pre.y, edg1.u) + annotation (Line(points={{202,-370},{218,-370}}, color={255,0,255})); + connect(dowSta.yReaDemLim, yReaDemLim) + annotation (Line(points={{82,221},{92,221},{92,180},{300,180}}, + color={255,0,255})); + connect(dowSta.yReaDemLim, lat2.u) + annotation (Line(points={{82,221},{92,221},{92,160},{118,160}}, + color={255,0,255})); + connect(edg1.y, lat2.clr) + annotation (Line(points={{242,-370},{260,-370},{260,-390},{-190,-390},{-190, + 154},{118,154}}, color={255,0,255})); + connect(lat2.y, and4.u1) + annotation (Line(points={{142,160},{160,160},{160,140},{-80,140},{-80,30}, + {-42,30}}, color={255,0,255})); + connect(conWatPumCon.yPumSpeChe, and2.u1) + annotation (Line(points={{162,-191},{180,-191},{180,-240},{198,-240}}, + color={255,0,255})); + connect(and2.y, lat1.u) + annotation (Line(points={{222,-240},{230,-240},{230,-260},{238,-260}}, + color={255,0,255})); + connect(edg1.y, lat1.clr) + annotation (Line(points={{242,-370},{260,-370},{260,-390},{-190,-390},{-190, + -266},{238,-266}}, color={255,0,255})); + connect(lat1.y, minChiWatFlo.uUpsDevSta) + annotation (Line(points={{262,-260},{270,-260},{270,-290},{-40,-290}, + {-40,-313},{98,-313}}, color={255,0,255})); + connect(dowSta.yChiWatMinFloSet, chiWatMinSet.u3) + annotation (Line(points={{82,236},{170,236},{170,-338},{198,-338}}, + color={0,0,127})); + connect(minChiWatFlo.yChiWatMinFloSet, chiWatMinSet.u1) + annotation (Line(points={{122,-320},{140,-320},{140,-322},{198,-322}}, + color={0,0,127})); + connect(lat1.y, chiWatMinSet.u2) + annotation (Line(points={{262,-260},{270,-260},{270,-290},{160,-290}, + {160,-330},{198,-330}}, color={255,0,255})); + connect(chiWatMinSet.y, yChiWatMinFloSet) + annotation (Line(points={{222,-330},{300,-330}}, color={0,0,127})); + connect(nexChi.yOnOff, dowSta.uOnOff) + annotation (Line(points={{-18,337},{0,337},{0,228},{58,228}}, + color={255,0,255})); + connect(edg1.y, dowSta.clr) + annotation (Line(points={{242,-370},{260,-370},{260,-390},{-190,-390},{-190, + 230},{58,230}}, color={255,0,255})); + connect(disChiIsoVal.yEnaChiWatIsoVal, lat3.u) + annotation (Line(points={{222,66},{240,66},{240,0},{180,0},{180,-30}, + {198,-30}}, color={255,0,255})); + connect(edg1.y, lat3.clr) + annotation (Line(points={{242,-370},{260,-370},{260,-390},{-190,-390},{-190, + -36},{198,-36}}, color={255,0,255})); + connect(disHeaCon.yEnaHeaCon, lat4.u) + annotation (Line(points={{222,-94},{240,-94},{240,-114},{180,-114},{180, + -130},{198,-130}}, color={255,0,255})); + connect(lat4.y, yTowStaDow) + annotation (Line(points={{222,-130},{250,-130},{250,-60},{300,-60}}, + color={255,0,255})); + connect(lat4.y, disNexCWP.uUpsDevSta) + annotation (Line(points={{222,-130},{250,-130},{250,-142},{80,-142},{80,-152}, + {98,-152}}, color={255,0,255})); + connect(lat4.y, and2.u2) + annotation (Line(points={{222,-130},{250,-130},{250,-142},{80,-142},{80,-248}, + {198,-248}}, color={255,0,255})); + connect(edg1.y, lat4.clr) + annotation (Line(points={{242,-370},{260,-370},{260,-390},{-190,-390},{-190, + -136},{198,-136}}, color={255,0,255})); + connect(uStaSet, nexChi.uStaSet) + annotation (Line(points={{-300,380},{-60,380},{-60,347},{-42,347}}, + color={255,127,0})); + connect(nexChi.uChiSet, uChiSet) + annotation (Line(points={{-42,340},{-300,340}}, color={255,0,255})); + connect(uStaSet, cha.u) + annotation (Line(points={{-300,380},{-260,380},{-260,360},{-242,360}}, + color={255,127,0})); + connect(cha.down, lat.u) + annotation (Line(points={{-218,354},{-200,354},{-200,360},{-182,360}}, + color={255,0,255})); + connect(uStaSet, disNexCWP.uStaSet) + annotation (Line(points={{-300,380},{-130,380},{-130,-169},{98,-169}}, + color={255,127,0})); + connect(uChiSta, disNexCWP.uChiSta) + annotation (Line(points={{-300,160},{-150,160},{-150,-165},{98,-165}}, + color={255,127,0})); + connect(dowSta.uChiHeaCon, uChiHeaCon) annotation (Line(points={{58,224},{ + -110,224},{-110,130},{-300,130}}, + color={255,0,255})); + connect(uChiHeaCon, logSwi.u3) annotation (Line(points={{-300,130},{-110,130}, + {-110,-86},{120,-86},{120,-78},{138,-78}}, color={255,0,255})); + connect(conWatPumCon.uConWatPum, uConWatPum) annotation (Line(points={{138,-191}, + {70,-191},{70,-380},{-300,-380}}, color={255,0,255})); + connect(con.y, disHeaCon.uEnaPla) annotation (Line(points={{-138,200},{-120, + 200},{-120,-92},{198,-92}}, + color={255,0,255})); + connect(con.y, conWatPumCon.uEnaPla) annotation (Line(points={{-138,200},{ + -120,200},{-120,-180},{138,-180}}, color={255,0,255})); + connect(and5.y, and3.u1) + annotation (Line(points={{102,-120},{118,-120}},color={255,0,255})); + connect(and3.y, disHeaCon.uUpsDevSta) annotation (Line(points={{142,-120},{ + 160,-120},{160,-96},{198,-96}}, color={255,0,255})); + connect(lat3.y, and3.u2) annotation (Line(points={{222,-30},{240,-30},{240, + -50},{110,-50},{110,-128},{118,-128}}, color={255,0,255})); + connect(edg1.y, yEndStaTri) + annotation (Line(points={{242,-370},{300,-370}}, color={255,0,255})); + connect(edg1.y, nexChi.endPro) annotation (Line(points={{242,-370},{260,-370}, + {260,-390},{-190,-390},{-190,333},{-42,333}}, color={255,0,255})); + connect(lesEquThr.y, and6.u1) + annotation (Line(points={{-38,-10},{58,-10}}, color={255,0,255})); + connect(and6.y, and1.u2) annotation (Line(points={{82,-10},{120,-10},{120,12}, + {138,12}}, color={255,0,255})); + connect(nexChi.yDow, and6.u2) annotation (Line(points={{-18,347},{10,347},{10, + -18},{58,-18}}, color={255,0,255})); + connect(and7.y, and5.u2) annotation (Line(points={{-4,-120},{40,-120},{40, + -128},{78,-128}}, color={255,0,255})); + connect(lesEquThr1.y, and7.u1) + annotation (Line(points={{-38,-120},{-28,-120}}, color={255,0,255})); + connect(nexChi.yDow, and7.u2) annotation (Line(points={{-18,347},{10,347},{10, + -18},{-32,-18},{-32,-128},{-28,-128}}, color={255,0,255})); + connect(minChiWatFlo.yChaSet, notInPro.u) annotation (Line(points={{122,-328}, + {130,-328},{130,-370},{138,-370}}, color={255,0,255})); + connect(notInPro.y, pre.u) + annotation (Line(points={{162,-370},{178,-370}}, color={255,0,255})); +annotation ( + defaultComponentName="dowProCon", + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-280,-400},{280,400}})), + Icon(coordinateSystem(extent={{-100,-200},{100,200}}), graphics={ + Rectangle( + extent={{-100,-200},{100,200}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,240},{120,200}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-10,140},{10,-120}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-120},{-42,-120},{0,-160},{40,-120},{0,-120}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,198},{-58,186}}, + textColor={255,127,0}, + textString="uStaSet"), + Text( + extent={{-96,138},{-26,124}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yOpeParLoaRatMin", + visible=need_reduceChillerDemand), + Text( + extent={{-96,116},{-60,104}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiLoa", + visible=need_reduceChillerDemand), + Text( + extent={{-100,96},{-70,84}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-98,76},{-44,62}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{-100,-14},{-40,-26}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiWatIsoVal"), + Text( + extent={{-100,-44},{-50,-56}}, + textColor={255,0,255}, + textString="uChiWatReq"), + Text( + extent={{-98,-62},{-48,-76}}, + textColor={255,0,255}, + textString="uConWatReq"), + Text( + extent={{-98,-92},{-44,-108}}, + textColor={255,0,255}, + textString="uChiConIsoVal"), + Text( + extent={{-104,-124},{-68,-136}}, + textColor={255,0,255}, + textString="uWSE", + visible=have_WSE), + Text( + extent={{-98,-162},{-32,-176}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uConWatPumSpe", + visible=not have_fixSpeConWatPum), + Text( + extent={{-98,-140},{-26,-158}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uConWatPumSpeSet", + visible=not have_fixSpeConWatPum), + Text( + extent={{60,198},{100,186}}, + textColor={255,0,255}, + textString="yStaPro"), + Text( + extent={{60,158},{96,146}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiDem", + visible=need_reduceChillerDemand), + Text( + extent={{72,126},{96,114}}, + textColor={255,0,255}, + textString="yChi"), + Text( + extent={{36,50},{96,34}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatIsoVal"), + Text( + extent={{42,8},{96,-4}}, + textColor={255,0,255}, + textString="yTowStaDow"), + Text( + extent={{48,-22},{96,-36}}, + textColor={255,0,255}, + textString="yChiHeaCon"), + Text( + extent={{58,-62},{96,-74}}, + textColor={255,0,255}, + textString="yLeaPum"), + Text( + extent={{18,-104},{98,-114}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yDesConWatPumSpe", + visible=not have_fixSpeConWatPum), + Text( + extent={{34,-122},{96,-136}}, + textColor={255,127,0}, + textString="yConWatPumNum"), + Text( + extent={{28,-150},{98,-164}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatMinFloSet"), + Text( + extent={{40,88},{96,74}}, + textColor={255,0,255}, + textString="yReaDemLim", + visible=need_reduceChillerDemand), + Text( + extent={{-100,178},{-60,166}}, + textColor={255,0,255}, + textString="uChiSet"), + Text( + extent={{-100,46},{-58,34}}, + textColor={255,127,0}, + textString="uChiSta"), + Text( + extent={{-98,16},{-44,4}}, + textColor={255,0,255}, + textString="uChiHeaCon"), + Text( + extent={{-98,-182},{-42,-196}}, + textColor={255,0,255}, + textString="uConWatPum", + visible=have_fixSpeConWatPum), + Text( + extent={{50,-180},{98,-194}}, + textColor={255,0,255}, + textString="yEndStaTri")}), +Documentation(info=" +

+Block that controls devices when there is a stage-down command. This sequence is for +water-cooled primary-only parallel chiller plants with headered chilled water pumps +and headered condenser water pumps, or air-cooled primary-only parallel chiller +plants with headered chilled water pumps. +This development is based on ASHRAE Guideline 36-2021, +section 5.20.4.17, which specifies the step-by-step control of +devices during chiller staging down process. +

+
    +
  1. +Identify the chiller(s) that should be enabled (and disabled, if have_ponyChiller=true). +This is implemented in block nexChi. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller +for more decriptions. +
  2. +
  3. +Start the staging down process, + +These are implemented in block dowSta. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DownStart +for more decriptions. +
  4. +
  5. +When the controller of the chiller being shut off indicates no request for chilled +water flow (uChiWatReq=false), slowly (chaChiWatIsoTim) +close the chiller's chilled water isolation valve to avoid a sudden change in flow +through other operating chillers. +This is implemented in block disChiIsoVal. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal +for more decriptions. +
  6. + +
  7. +When the controller of the chiller being shut off indicates no request for condenser +water flow (uConWatReq=false), disable the chiller's head pressure control +loop. +This is implemented in block disHeaCon. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl +for more decriptions. +
  8. + +
  9. +When the condenser water head pressure control valve is fully closed, shut off +the last lag condenser water pump or change the pump speed to that required of +the new stage. +Block disNexCWP identifies chiller stage for the condenser water pump +control +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump) +and block conWatPumCon checks if the condenser water pumps have been reset +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller). +
  10. + +
  11. +Change the chilled water minimum flow setpoint to that appropriate for the new +stage. +The minimum flow setpoint is reset in block minChiWatFlo +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint). +Block minBypSet checks if the new setpoint is achieved +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass). +
  12. +
+", revisions=" + +")); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/CHWIsoVal.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/CHWIsoVal.mo new file mode 100644 index 00000000000..ece625302fa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/CHWIsoVal.mo @@ -0,0 +1,394 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block CHWIsoVal "Sequence of enable or disable chilled water isolation valve" + + parameter Integer nChi=2 + "Total number of chiller, which is also the total number of chilled water isolation valve"; + parameter Real chaChiWatIsoTim( + final unit="s", + final quantity="Time") + "Time to slowly change isolation valve, should be determined in the field"; + parameter Real iniValPos + "Initial valve position, if it needs to turn on chiller, the value should be 0"; + parameter Real endValPos + "Ending valve position, if it needs to turn on chiller, the value should be 1"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexChaChi + "Index of next chiller that should change status" + annotation (Placement(transformation(extent={{-200,-20},{-160,20}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-200,-120},{-160,-80}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of resetting status of device before enabling or disabling isolation valve" + annotation (Placement(transformation(extent={{-200,-160},{-160,-120}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaPro + "Indicate if there is a stage up or stage down command" + annotation (Placement(transformation(extent={{-200,-198},{-160,-158}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) "Chiller chilled water isolation valve position" + annotation (Placement(transformation(extent={{180,-60},{220,-20}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaChiWatIsoVal + "Status of chilled water isolation valve control: true=enabled valve is fully open" + annotation (Placement(transformation(extent={{180,120},{220,160}}), + iconTransformation(extent={{100,40},{140,80}}))); + +protected + final parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con7( + final k=chaChiWatIsoTim) "Time to change chilled water isolation valve" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con8( + final k=endValPos) + "Ending valve position" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con6( + final k=iniValPos) + "Initial isolation valve position" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con9( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Reals.Line lin1 + "Chilled water isolation valve setpoint" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=chaChiWatIsoTim) + "Count the time after changing up-stream device status" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-100,-150},{-80,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{20,-180},{40,-160}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi] + "Record the old chiller chilled water isolation valve status" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{20,-150},{40,-130}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "Check if it is time to change isolation valve position" + annotation (Placement(transformation(extent={{-40,-180},{-20,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-40,-210},{-20,-190}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2[nChi] "Logical not" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi] "Logical switch" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2[nChi] "Logical switch" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nChi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nChi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nChi) + "Replicate real input" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys3[nChi]( + final uLow=fill(0.025, nChi), + final uHigh=fill(0.05, nChi)) "Check if isolation valve is enabled" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys4[nChi]( + final uLow=fill(0.925, nChi), + final uHigh=fill(0.975, nChi)) "Check if isolation valve is open more than 95%" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3[nChi] "Logical not" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + Buildings.Controls.OBC.CDL.Logical.Not not4[nChi] "Logical not" + annotation (Placement(transformation(extent={{-40,150},{-20,170}}))); + Buildings.Controls.OBC.CDL.Logical.And and4[nChi] "Logical and" + annotation (Placement(transformation(extent={{0,180},{20,200}}))); + Buildings.Controls.OBC.CDL.Logical.And and3[nChi] "Logical and" + annotation (Placement(transformation(extent={{0,210},{20,230}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2[nChi] "Logicla or" + annotation (Placement(transformation(extent={{40,210},{60,230}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd1( + final nin=nChi) + "Logical and" + annotation (Placement(transformation(extent={{80,210},{100,230}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 + "Check if the isolation valve has been fully open" + annotation (Placement(transformation(extent={{120,130},{140,150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nChi]( + final k=chiInd) "Chiller index array" + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{-70,130},{-50,150}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=5) "Delay the true input" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Logical and" + annotation (Placement(transformation(extent={{150,130},{170,150}}))); + +equation + connect(uChiWatIsoVal, triSam.u) + annotation (Line(points={{-180,-100},{-82,-100}}, color={0,0,127})); + connect(con9.y, lin1.x1) + annotation (Line(points={{22,80},{30,80},{30,68},{38,68}}, + color={0,0,127})); + connect(con6.y, lin1.f1) + annotation (Line(points={{-18,80},{-10,80},{-10,64},{38,64}}, + color={0,0,127})); + connect(con7.y, lin1.x2) + annotation (Line(points={{-18,30},{-10,30},{-10,56},{38,56}}, + color={0,0,127})); + connect(con8.y, lin1.f2) + annotation (Line(points={{22,30},{30,30},{30,52},{38,52}}, color={0,0,127})); + connect(tim.y, lin1.u) + annotation (Line(points={{-78,60},{38,60}}, color={0,0,127})); + connect(uUpsDevSta, edg.u) + annotation (Line(points={{-180,-140},{-102,-140}}, color={255,0,255})); + connect(uStaPro, and2.u2) + annotation (Line(points={{-180,-178},{-42,-178}}, color={255,0,255})); + connect(edg.y, and2.u1) + annotation (Line(points={{-78,-140},{-60,-140},{-60,-170},{-42,-170}}, + color={255,0,255})); + connect(and2.y, lat.u) + annotation (Line(points={{-18,-170},{18,-170}}, color={255,0,255})); + connect(uStaPro, not1.u) annotation (Line(points={{-180,-178},{-80,-178},{-80, + -200},{-42,-200}}, color={255,0,255})); + connect(not1.y, lat.clr) + annotation (Line(points={{-18,-200},{0,-200},{0,-176},{18,-176}}, + color={255,0,255})); + connect(lat.y, booRep1.u) + annotation (Line(points={{42,-170},{58,-170}}, color={255,0,255})); + connect(booRep1.y, swi.u2) + annotation (Line(points={{82,-170},{100,-170},{100,-40},{118,-40}}, + color={255,0,255})); + connect(swi.y, yChiWatIsoVal) + annotation (Line(points={{142,-40},{200,-40}}, color={0,0,127})); + connect(booRep.y, triSam.trigger) + annotation (Line(points={{42,-140},{60,-140},{60,-120},{-70,-120},{-70,-112}}, + color={255,0,255})); + connect(and2.y, booRep.u) + annotation (Line(points={{-18,-170},{0,-170},{0,-140},{18,-140}}, + color={255,0,255})); + connect(booRep1.y, not2.u) + annotation (Line(points={{82,-170},{100,-170},{100,-110},{-40,-110}, + {-40,-80},{-22,-80}}, color={255,0,255})); + connect(not2.y, swi1.u2) + annotation (Line(points={{2,-80},{20,-80},{20,-60},{58,-60}}, + color={255,0,255})); + connect(triSam.y, swi1.u3) + annotation (Line(points={{-58,-100},{40,-100},{40,-68},{58,-68}}, + color={0,0,127})); + connect(swi1.y, swi.u3) + annotation (Line(points={{82,-60},{110,-60},{110,-48},{118,-48}}, + color={0,0,127})); + connect(uChiWatIsoVal, swi1.u1) + annotation (Line(points={{-180,-100},{-140,-100},{-140,-52},{58,-52}}, + color={0,0,127})); + connect(swi2.y, swi.u1) + annotation (Line(points={{82,0},{100,0},{100,-32},{118,-32}}, + color={0,0,127})); + connect(nexChaChi, intRep.u) + annotation (Line(points={{-180,0},{-82,0}}, color={255,127,0})); + connect(intRep.y, intEqu.u1) + annotation (Line(points={{-58,0},{-22,0}}, color={255,127,0})); + connect(intEqu.y, swi2.u2) + annotation (Line(points={{2,0},{58,0}}, color={255,0,255})); + connect(lin1.y, reaRep.u) + annotation (Line(points={{62,60},{78,60}}, color={0,0,127})); + connect(lat.y, tim.u) + annotation (Line(points={{42,-170},{50,-170},{50,-220},{-110,-220},{-110,60}, + {-102,60}}, color={255,0,255})); + connect(reaRep.y, swi2.u1) + annotation (Line(points={{102,60},{120,60},{120,30},{40,30},{40,8},{58,8}}, + color={0,0,127})); + connect(triSam.y, swi2.u3) + annotation (Line(points={{-58,-100},{40,-100},{40,-8},{58,-8}}, + color={0,0,127})); + connect(uChiWatIsoVal, hys4.u) + annotation (Line(points={{-180,-100},{-140,-100},{-140,160},{-122,160}}, + color={0,0,127})); + connect(uChiWatIsoVal, hys3.u) + annotation (Line(points={{-180,-100},{-140,-100},{-140,220},{-122,220}}, + color={0,0,127})); + connect(hys3.y, and3.u1) + annotation (Line(points={{-98,220},{-2,220}}, color={255,0,255})); + connect(hys4.y, and3.u2) + annotation (Line(points={{-98,160},{-80,160},{-80,212},{-2,212}}, + color={255,0,255})); + connect(hys4.y, not4.u) + annotation (Line(points={{-98,160},{-42,160}}, color={255,0,255})); + connect(hys3.y, not3.u) + annotation (Line(points={{-98,220},{-60,220},{-60,190},{-42,190}}, + color={255,0,255})); + connect(not4.y, and4.u2) + annotation (Line(points={{-18,160},{-12,160},{-12,182},{-2,182}}, + color={255,0,255})); + connect(not3.y, and4.u1) + annotation (Line(points={{-18,190},{-2,190}}, color={255,0,255})); + connect(and3.y, or2.u1) + annotation (Line(points={{22,220},{38,220}}, color={255,0,255})); + connect(and4.y, or2.u2) + annotation (Line(points={{22,190},{30,190},{30,212},{38,212}}, + color={255,0,255})); + connect(mulAnd1.y, and5.u1) + annotation (Line(points={{102,220},{110,220},{110,140},{118,140}}, + color={255,0,255})); + connect(or2.y, mulAnd1.u) + annotation (Line(points={{62,220},{78,220}}, color={255,0,255})); + connect(conInt.y, intEqu.u2) + annotation (Line(points={{-58,-30},{-40,-30},{-40,-8},{-22,-8}}, + color={255,127,0})); + connect(lat1.y, and5.u2) + annotation (Line(points={{-48,140},{46,140},{46,132},{118,132}}, + color={255,0,255})); + connect(uUpsDevSta, lat1.u) annotation (Line(points={{-180,-140},{-130,-140},{ + -130,140},{-72,140}}, color={255,0,255})); + connect(not1.y, truDel.u) annotation (Line(points={{-18,-200},{0,-200},{0,-230}, + {-120,-230},{-120,100},{-102,100}}, color={255,0,255})); + connect(truDel.y, lat1.clr) annotation (Line(points={{-78,100},{-74,100},{-74, + 134},{-72,134}}, color={255,0,255})); + connect(tim.passed, lat2.u) annotation (Line(points={{-78,52},{-60,52},{-60,120}, + {-42,120}}, color={255,0,255})); + connect(truDel.y, lat2.clr) annotation (Line(points={{-78,100},{-74,100},{-74, + 114},{-42,114}}, color={255,0,255})); + connect(and5.y, and1.u1) + annotation (Line(points={{142,140},{148,140}}, color={255,0,255})); + connect(and1.y, yEnaChiWatIsoVal) + annotation (Line(points={{172,140},{200,140}}, color={255,0,255})); + connect(lat2.y, and1.u2) annotation (Line(points={{-18,120},{144,120},{144, + 132},{148,132}}, color={255,0,255})); +annotation ( + defaultComponentName="enaChiIsoVal", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-240},{180,240}}), + graphics={ + Rectangle( + extent={{-158,238},{178,122}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-38,184},{172,150}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Check if all enabled CHW isolation valves +have been fully open")}), + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-96,-74},{-60,-86}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaPro"), + Text( + extent={{-96,-42},{-46,-56}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uUpsDevSta"), + Text( + extent={{-96,86},{-48,74}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexChaChi"), + Text( + extent={{-96,58},{-42,46}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiWatIsoVal"), + Text( + extent={{32,70},{96,54}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yEnaChiWatIsoVal"), + Polygon( + points={{-60,40},{-60,-40},{0,0},{-60,40}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Polygon( + points={{60,40},{60,-40},{0,0},{60,40}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{44,-54},{98,-66}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatIsoVal")}), + Documentation(info=" +

+Block updates chiller chilled water isolation valve enabling-disabling status when +there is stage change command (uStaPro=true). It will also generate +status to indicate if the valve reset process has finished. +This development is based on ASHRAE Guideline 36-2021, +section 5.20.4.16, item e and section 5.20.4.17, item c, which specifies when +and how the isolation valve should be controlled when it is in stage changing process. +

+ +

+The valve should open or close slowly. For example, this could be accomplished by +resetting the valve position X /seconds, where X = (endValPos - +iniValPos) / chaChiWatIsoTim. +The valve time chaChiWatIsoTim should be determined in the field. +

+

+This sequence will generate array yChiWatIsoVal which indicates +chilled water isolation valve position setpoint. yEnaChiWatIsoVal +will be true when all the enabled valves are fully open and all the disabled valves +are fully closed. +

+", revisions=" + +")); +end CHWIsoVal; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DisableChiller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DisableChiller.mo new file mode 100644 index 00000000000..181b63ea62c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DisableChiller.mo @@ -0,0 +1,456 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block DisableChiller "Sequence for disabling chiller in stage-down process" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Real proOnTim( + final unit="s", + final quantity="Time") = 300 + "Enabled chiller operation time to indicate if it is proven on"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaChi + "Index of next enabling chiller" + annotation (Placement(transformation(extent={{-240,180},{-200,220}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow + "Stage-down command" + annotation (Placement(transformation(extent={{-240,120},{-200,160}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaChiWatIsoVal + "Status of chiller chilled water isolation valve control: true=enabled valve is fully open" + annotation (Placement(transformation(extent={{-240,90},{-200,130}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-240,60},{-200,100}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexDisChi + "Next disabling chiller when there is any stage up that need one chiller on and another off" + annotation (Placement(transformation(extent={{-240,-100},{-200,-60}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "Indicate if the stage require one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{-240,-140},{-200,-100}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{200,-140},{240,-100}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yRelDemLim + "Release demand limit" + annotation (Placement(transformation(extent={{200,-70},{240,-30}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + final parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{100,190},{120,210}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "In staging down process and the chilled water isolation valve has open" + annotation (Placement(transformation(extent={{-160,130},{-140,150}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-100,130},{-80,150}}))); + Buildings.Controls.OBC.CDL.Logical.And and1[nChi] "Logical and" + annotation (Placement(transformation(extent={{-40,190},{-20,210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nChi]( + final k=fill(true, nChi)) "True constant" + annotation (Placement(transformation(extent={{-40,220},{-20,240}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr[nChi]( + final t=fill(0.5, nChi)) + "Convert real input to boolean output" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{100,0},{120,20}}))); + Buildings.Controls.OBC.CDL.Logical.And and3[nChi] "Logical and" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nChi]( + final k=fill(false, nChi)) "False constant" + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{160,40},{180,60}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep(final nout=nChi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,190},{-140,210}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nChi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,190},{-80,210}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim(final t=proOnTim) + "Count the time after new chiller has been enabled" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi] + "Record the old chiller chilled water isolation valve status" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{80,40},{100,60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nChi]( + final k=chiInd) "Chiller index array" + annotation (Placement(transformation(extent={{-160,160},{-140,180}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1(final nout=nChi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,-90},{-140,-70}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nChi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-160,-170},{-140,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-160,-250},{-140,-230}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-160,-220},{-140,-200}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam1[nChi] + "Record the old chiller chilled water isolation valve status" + annotation (Placement(transformation(extent={{-80,-220},{-60,-200}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep5(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-120,-250},{-100,-230}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr1[nChi]( + final t=fill(0.5, nChi)) + "Convert real input to boolean output" + annotation (Placement(transformation(extent={{40,-220},{60,-200}}))); + Buildings.Controls.OBC.CDL.Logical.And and4[nChi] "Logical and" + annotation (Placement(transformation(extent={{40,-190},{60,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nChi]( + final k=fill(false, nChi)) + "False constant" + annotation (Placement(transformation(extent={{40,-160},{60,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-190},{120,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{160,-130},{180,-110}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep6( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{100,-130},{120,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi5[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi6[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-250},{120,-230}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi7 + "Logical switch" + annotation (Placement(transformation(extent={{160,-62},{180,-42}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3( + final k=true) + "When the process does not require chiller on-off, there is no need to limit chiller demand" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + +equation + connect(nexEnaChi, intRep.u) + annotation (Line(points={{-220,200},{-162,200}}, color={255,127,0})); + connect(intRep.y, intEqu.u1) + annotation (Line(points={{-138,200},{-102,200}}, color={255,127,0})); + connect(uEnaChiWatIsoVal, and2.u2) + annotation (Line(points={{-220,110},{-170,110},{-170,132},{-162,132}}, + color={255,0,255})); + connect(uStaDow, and2.u1) + annotation (Line(points={{-220,140},{-162,140}}, color={255,0,255})); + connect(and2.y, booRep.u) + annotation (Line(points={{-138,140},{-102,140}}, color={255,0,255})); + connect(intEqu.y, and1.u1) + annotation (Line(points={{-78,200},{-42,200}}, color={255,0,255})); + connect(booRep.y, and1.u2) + annotation (Line(points={{-78,140},{-70,140},{-70,192},{-42,192}}, + color={255,0,255})); + connect(and1.y, logSwi.u2) + annotation (Line(points={{-18,200},{98,200}}, color={255,0,255})); + connect(con.y, logSwi.u1) + annotation (Line(points={{-18,230},{0,230},{0,208},{98,208}}, color={255,0,255})); + connect(uChi, booToRea.u) + annotation (Line(points={{-220,80},{-170,80},{-170,100},{-102,100}}, + color={255,0,255})); + connect(and2.y, edg.u) + annotation (Line(points={{-138,140},{-120,140},{-120,70},{-102,70}}, + color={255,0,255})); + connect(booToRea.y, triSam.u) + annotation (Line(points={{-78,100},{-22,100}}, color={0,0,127})); + connect(edg.y, booRep1.u) + annotation (Line(points={{-78,70},{-62,70}}, color={255,0,255})); + connect(booRep1.y, triSam.trigger) + annotation (Line(points={{-38,70},{-10,70},{-10,88}}, color={255,0,255})); + connect(triSam.y, greEquThr.u) + annotation (Line(points={{2,100},{18,100}}, color={0,0,127})); + connect(greEquThr.y, logSwi.u3) + annotation (Line(points={{42,100},{60,100},{60,192},{98,192}}, + color={255,0,255})); + connect(and2.y, tim.u) + annotation (Line(points={{-138,140},{-120,140},{-120,0},{-102,0}}, + color={255,0,255})); + connect(booRep2.y, and3.u1) + annotation (Line(points={{2,0},{38,0}}, color={255,0,255})); + connect(and3.y, logSwi1.u2) + annotation (Line(points={{62,0},{80,0},{80,10},{98,10}}, + color={255,0,255})); + connect(con1.y, logSwi1.u1) + annotation (Line(points={{62,30},{80,30},{80,18},{98,18}}, + color={255,0,255})); + connect(uChi, logSwi1.u3) + annotation (Line(points={{-220,80},{-170,80},{-170,-20},{90,-20},{90,2}, + {98,2}}, color={255,0,255})); + connect(booRep3.y, logSwi2.u2) + annotation (Line(points={{102,50},{158,50}}, color={255,0,255})); + connect(logSwi1.y, logSwi2.u3) + annotation (Line(points={{122,10},{140,10},{140,42},{158,42}}, + color={255,0,255})); + connect(logSwi.y, logSwi2.u1) + annotation (Line(points={{122,200},{140,200},{140,58},{158,58}}, + color={255,0,255})); + connect(conInt.y, intEqu.u2) + annotation (Line(points={{-138,170},{-110,170},{-110,192},{-102,192}}, + color={255,127,0})); + connect(nexDisChi, intRep1.u) + annotation (Line(points={{-220,-80},{-162,-80}}, color={255,127,0})); + connect(intRep1.y, intEqu1.u1) + annotation (Line(points={{-138,-80},{-102,-80}}, color={255,127,0})); + connect(conInt.y, intEqu1.u2) + annotation (Line(points={{-138,170},{-110,170},{-110,-88},{-102,-88}}, + color={255,127,0})); + connect(intEqu1.y, and3.u2) + annotation (Line(points={{-78,-80},{10,-80},{10,-8},{38,-8}}, + color={255,0,255})); + connect(not1.y, booRep3.u) + annotation (Line(points={{2,50},{78,50}}, color={255,0,255})); + connect(uStaDow, booRep4.u) + annotation (Line(points={{-220,140},{-180,140},{-180,-160},{-162,-160}}, + color={255,0,255})); + connect(uChi, booToRea1.u) + annotation (Line(points={{-220,80},{-170,80},{-170,-210},{-162,-210}}, + color={255,0,255})); + connect(uStaDow, edg1.u) + annotation (Line(points={{-220,140},{-180,140},{-180,-240},{-162,-240}}, + color={255,0,255})); + connect(booToRea1.y, triSam1.u) + annotation (Line(points={{-138,-210},{-82,-210}},color={0,0,127})); + connect(edg1.y, booRep5.u) + annotation (Line(points={{-138,-240},{-122,-240}}, color={255,0,255})); + connect(triSam1.y, greEquThr1.u) + annotation (Line(points={{-58,-210},{38,-210}}, color={0,0,127})); + connect(booRep4.y, and4.u2) + annotation (Line(points={{-138,-160},{0,-160},{0,-188},{38,-188}}, + color={255,0,255})); + connect(intEqu1.y, and4.u1) + annotation (Line(points={{-78,-80},{10,-80},{10,-180},{38,-180}}, + color={255,0,255})); + connect(and4.y, logSwi3.u2) + annotation (Line(points={{62,-180},{98,-180}}, color={255,0,255})); + connect(con2.y, logSwi3.u1) + annotation (Line(points={{62,-150},{72,-150},{72,-172},{98,-172}}, + color={255,0,255})); + connect(greEquThr1.y, logSwi3.u3) + annotation (Line(points={{62,-210},{80,-210},{80,-188},{98,-188}}, + color={255,0,255})); + connect(uOnOff, booRep6.u) + annotation (Line(points={{-220,-120},{98,-120}}, color={255,0,255})); + connect(booRep6.y, logSwi4.u2) + annotation (Line(points={{122,-120},{158,-120}},color={255,0,255})); + connect(logSwi4.y, yChi) + annotation (Line(points={{182,-120},{220,-120}}, color={255,0,255})); + connect(booRep.y, logSwi5.u2) + annotation (Line(points={{-78,140},{-70,140},{-70,-90},{98,-90}}, + color={255,0,255})); + connect(uChi, logSwi5.u3) + annotation (Line(points={{-220,80},{-170,80},{-170,-98},{98,-98}}, + color={255,0,255})); + connect(logSwi2.y, logSwi5.u1) + annotation (Line(points={{182,50},{190,50},{190,-28},{60,-28},{60,-82},{98,-82}}, + color={255,0,255})); + connect(logSwi5.y, logSwi4.u1) + annotation (Line(points={{122,-90},{140,-90},{140,-112},{158,-112}}, + color={255,0,255})); + connect(booRep5.y, triSam1.trigger) + annotation (Line(points={{-98,-240},{-70,-240},{-70,-222}}, color={255,0,255})); + connect(booRep4.y, logSwi6.u2) + annotation (Line(points={{-138,-160},{0,-160},{0,-240},{98,-240}}, color={255,0,255})); + connect(logSwi3.y, logSwi6.u1) + annotation (Line(points={{122,-180},{130,-180},{130,-220},{80,-220}, + {80,-232},{98,-232}}, color={255,0,255})); + connect(uChi, logSwi6.u3) + annotation (Line(points={{-220,80},{-170,80},{-170,-180},{-40,-180}, + {-40,-248},{98,-248}}, color={255,0,255})); + connect(logSwi6.y, logSwi4.u3) + annotation (Line(points={{122,-240},{140,-240},{140,-128},{158,-128}}, + color={255,0,255})); + connect(uOnOff, logSwi7.u2) + annotation (Line(points={{-220,-120},{80,-120},{80,-52},{158,-52}}, + color={255,0,255})); + connect(logSwi7.y,yRelDemLim) + annotation (Line(points={{182,-52},{202,-52},{202,-50},{220,-50}}, + color={255,0,255})); + connect(tim.passed, not1.u) + annotation (Line(points={{-78,-8},{-40,-8},{-40,50},{-22,50}}, + color={255,0,255})); + connect(tim.passed, booRep2.u) + annotation (Line(points={{-78,-8},{-40,-8},{-40,0},{-22,0}}, + color={255,0,255})); + connect(tim.passed, logSwi7.u1) + annotation (Line(points={{-78,-8},{-40,-8},{-40,-44},{158,-44}}, + color={255,0,255})); + connect(con3.y, logSwi7.u3) annotation (Line(points={{42,-70},{90,-70},{90,-60}, + {158,-60}}, color={255,0,255})); +annotation ( + defaultComponentName="disChi", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-60,0},{60,-80}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-52,20},{-40,0}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,20},{52,0}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-60,60},{60,20}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,98},{-44,82}}, + textColor={255,127,0}, + textString="nexEnaChi"), + Text( + extent={{-98,70},{-52,56}}, + textColor={255,0,255}, + textString="uStaDow"), + Text( + extent={{-96,30},{-24,10}}, + textColor={255,0,255}, + textString="uEnaChiWatIsoVal"), + Text( + extent={{-100,-14},{-78,-24}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-98,-82},{-70,-94}}, + textColor={255,0,255}, + textString="uOnOff"), + Text( + extent={{-98,-40},{-44,-56}}, + textColor={255,127,0}, + textString="nexDisChi"), + Text( + extent={{74,6},{98,-6}}, + textColor={255,0,255}, + textString="yChi"), + Text( + extent={{44,-72},{96,-84}}, + textColor={255,0,255}, + textString="yRelDemLim")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-200,-260},{200,260}}), + graphics={ + Rectangle( + extent={{-198,-142},{198,-258}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-198,258},{198,-98}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{100,188},{170,168}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable small chiller"), + Text( + extent={{102,-6},{172,-24}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable large chiller"), + Text( + extent={{-164,-244},{190,-286}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable chiller when the down-process does not require any other chiller being enabled"), + Text( + extent={{-144,278},{166,258}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable chiller when the down-process requires small chiller being enabled")}), +Documentation(info=" +

+Block that controlles chiller when there is staging down command uStaDow=true. +This implementation is based on ASHRAE Guideline36-2021, section 5.20.4.17, +item a.5 and a.6. These two sections specify how to start the smaller chiller and shut +off larger chiller when the stage change requires large chiller off and small chill on. +In other stage change, when it does not require chiller on/off, the chiller will then +be shut off as specified in section 5.20.4.17, item b. +

+

+When the stage-down process requires a smaller chiller being staged on and a larger +chiller being staged off: +

+ +

+If staging-down from any other stage that does not require one chiller off and another +chiller on, then shut off the last stage chiller. +

+", revisions=" + +")); +end DisableChiller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DownStart.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DownStart.mo new file mode 100644 index 00000000000..342c216340f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DownStart.mo @@ -0,0 +1,599 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block DownStart "Sequence for starting stage-down process" + + parameter Integer nChi "Total number of chillers"; + parameter Boolean have_parChi=true + "Flag: true means that the plant has parallel chillers"; + parameter Boolean need_reduceChillerDemand=false + "True: need limit chiller demand when chiller staging"; + parameter Real chiDemRedFac=0.75 + "Demand reducing factor of current operating chillers" + annotation (Dialog(group="Demand limit", enable=need_reduceChillerDemand)); + parameter Real holChiDemTim( + final unit="s", + final quantity="Time")=300 + "Maximum time to wait for the actual demand less than percentage of current load" + annotation (Dialog(group="Demand limit", enable=need_reduceChillerDemand)); + parameter Real byPasSetTim( + final unit="s", + final quantity="Time") + "Time constant for resetting minimum bypass flow" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real minFloSet[nChi]( + final unit=fill("m3/s", nChi), + final quantity=fill("VolumeFlowRate", nChi), + displayUnit=fill("m3/s", nChi)) + "Minimum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real maxFloSet[nChi]( + final unit=fill("m3/s", nChi), + final quantity=fill("VolumeFlowRate", nChi), + displayUnit=fill("m3/s", nChi)) + "Maximum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real aftByPasSetTim( + final unit="s", + final quantity="Time")=60 + "Time after setpoint achieved" + annotation (Dialog(group="Reset bypass")); + parameter Real waiTim( + final unit="s", + final quantity="Time")=30 + "Waiting time after enabling next head pressure control" + annotation (Dialog(group="Head pressure control")); + parameter Real chaChiWatIsoTim( + final unit="s", + final quantity="Time") + "Time to slowly change isolation valve, should be determined in the field" + annotation (Dialog(group="Chilled water isolation valve")); + parameter Real proOnTim( + final unit="s", + final quantity="Time")=300 + "Enabled chiller operation time to indicate if it is proven on" + annotation (Dialog(group="Disable last chiller")); + parameter Real relFloDif=0.05 + "Relative error to the setpoint for checking if it has achieved flow rate setpoint" + annotation (Dialog(tab="Advanced", group="Reset bypass")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow + "Stage down status: true=stage-down" + annotation (Placement(transformation(extent={{-200,190},{-160,230}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput yOpeParLoaRatMin( + final min=0, + final max=1, + final unit="1") if need_reduceChillerDemand + "Current stage minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-200,160},{-160,200}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiLoa[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) + if need_reduceChillerDemand "Current chiller load" + annotation (Placement(transformation(extent={{-200,130},{-160,170}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-200,100},{-160,140}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") + "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-200,70},{-160,110}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput clr + "Clear stage down process" + annotation (Placement(transformation(extent={{-200,30},{-160,70}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "True: if the stage change require enabling one chiller and disable another one" + annotation (Placement(transformation(extent={{-200,0},{-160,40}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaChi + "Index of next enabling chiller" + annotation (Placement(transformation(extent={{-200,-50},{-160,-10}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-200,-80},{-160,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-200,-120},{-160,-80}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexDisChi + "Next disabling chiller when there is any stage up that need one chiller on and another off" + annotation (Placement(transformation(extent={{-200,-190},{-160,-150}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiDem[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) + if need_reduceChillerDemand "Chiller demand setpoint" + annotation (Placement(transformation(extent={{180,120},{220,160}}), + iconTransformation(extent={{100,70},{140,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatMinFloSet + "Chilled water minimum flow setpoint" + annotation (Placement(transformation(extent={{180,50},{220,90}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiHeaCon[nChi] + "Chiller head pressure control enabling status" + annotation (Placement(transformation(extent={{180,-30},{220,10}}), + iconTransformation(extent={{100,0},{140,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chiller chilled water isolation valve position" + annotation (Placement(transformation(extent={{180,-90},{220,-50}}), + iconTransformation(extent={{100,-40},{140,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{180,-120},{220,-80}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yReaDemLim + "Release demand limit" + annotation (Placement(transformation(extent={{180,-160},{220,-120}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand + chiDemRed( + final nChi=nChi, + final chiDemRedFac=chiDemRedFac, + final holChiDemTim=holChiDemTim) if need_reduceChillerDemand + "Reduce chiller demand" + annotation (Placement(transformation(extent={{-20,160},{0,180}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass + minBypRes( + final aftByPasSetTim=aftByPasSetTim, + final relFloDif=relFloDif) + "Slowly change the minimum flow bypass setpoint" + annotation (Placement(transformation(extent={{60,100},{80,120}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + enaHeaCon( + final nChi=nChi, + final thrTimEnb=0, + final waiTim=waiTim, + final heaStaCha=true) + "Enable head pressure control of the chiller being enabled" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal + enaChiIsoVal( + final nChi=nChi, + final chaChiWatIsoTim=chaChiWatIsoTim, + final iniValPos=0, + final endValPos=1) "Enable chiller chilled water isolation valve " + annotation (Placement(transformation(extent={{0,-110},{20,-90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DisableChiller + disChi( + final nChi=nChi, + final proOnTim=proOnTim) "Disable last chiller" + annotation (Placement(transformation(extent={{0,-160},{20,-140}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-100,190},{-80,210}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + minChiWatSet( + final nChi=nChi, + final have_parChi=have_parChi, + final maxFloSet=maxFloSet, + final byPasSetTim=byPasSetTim, + final minFloSet=minFloSet) "Reset minimum chilled water flow setpoint" + annotation (Placement(transformation(extent={{0,60},{20,80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3(final k=false) + "False constant" + annotation (Placement(transformation(extent={{-100,80},{-80,100}}))); + Buildings.Controls.OBC.CDL.Logical.Switch heaPreCon[nChi] "Logical switch" + annotation (Placement(transformation(extent={{140,-20},{160,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiDem[nChi] + if need_reduceChillerDemand "Chiller demand" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiWatIsoVal[nChi] + "Chilled water isolation valve" + annotation (Placement(transformation(extent={{140,-80},{160,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{120,-180},{140,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre(final pre_u_start=false) + "Break algebraic loop" + annotation (Placement(transformation(extent={{80,-180},{100,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Maintain ON signal when minimum chilled water setpoint has been set" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat2 if need_reduceChillerDemand + "Maintain ON signal when chiller demand has been limited" + annotation (Placement(transformation(extent={{20,140},{40,160}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat3 + "Maintain ON signal when chiller head control has been enabled" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat4 + "Maintain ON signal when chilled water isolation valve has been enabled" + annotation (Placement(transformation(extent={{60,-120},{80,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 if not need_reduceChillerDemand + "Dummy or" + annotation (Placement(transformation(extent={{20,190},{40,210}}))); + +equation + connect(chiDemRed.uChiLoa, uChiLoa) + annotation (Line(points={{-22,175},{-100,175},{-100,150},{-180,150}}, + color={0,0,127})); + connect(chiDemRed.uChi, uChi) + annotation (Line(points={{-22,161},{-40,161},{-40,120},{-180,120}},color={255,0,255})); + connect(con3.y, minChiWatSet.uStaUp) + annotation (Line(points={{-78,90},{-60,90},{-60,79},{-2,79}}, color={255,0,255})); + connect(minChiWatSet.uStaDow, uStaDow) + annotation (Line(points={{-2,61},{-140,61},{-140,210},{-180,210}}, + color={255,0,255})); + connect(minChiWatSet.uOnOff, uOnOff) + annotation (Line(points={{-2,63},{-110,63},{-110,20},{-180,20}}, + color={255,0,255})); + connect(uStaDow, minBypRes.uStaPro) annotation (Line(points={{-180,210},{-140, + 210},{-140,114},{58,114}}, color={255,0,255})); + connect(VChiWat_flow, minBypRes.VChiWat_flow) + annotation (Line(points={{-180,90},{-150,90},{-150,110},{58,110}}, + color={0,0,127})); + connect(uStaDow, enaHeaCon.uStaPro) annotation (Line(points={{-180,210},{-140, + 210},{-140,0},{-2,0}}, color={255,0,255})); + connect(enaHeaCon.nexChaChi, nexEnaChi) + annotation (Line(points={{-2,-4},{-60,-4},{-60,-30},{-180,-30}}, + color={255,127,0})); + connect(enaHeaCon.uChiHeaCon, uChiHeaCon) + annotation (Line(points={{-2,-8},{-30,-8},{-30,-60},{-180,-60}}, + color={255,0,255})); + connect(nexEnaChi, enaChiIsoVal.nexChaChi) + annotation (Line(points={{-180,-30},{-60,-30},{-60,-92},{-2,-92}}, + color={255,127,0})); + connect(enaChiIsoVal.uChiWatIsoVal, uChiWatIsoVal) + annotation (Line(points={{-2,-95},{-100,-95},{-100,-100},{-180,-100}}, + color={0,0,127})); + connect(uStaDow, enaChiIsoVal.uStaPro) annotation (Line(points={{-180,210},{-140, + 210},{-140,-108},{-2,-108}}, color={255,0,255})); + connect(nexEnaChi, disChi.nexEnaChi) + annotation (Line(points={{-180,-30},{-60,-30},{-60,-141},{-2,-141}}, + color={255,127,0})); + connect(uStaDow, disChi.uStaDow) + annotation (Line(points={{-180,210},{-140,210},{-140,-144},{-2,-144}}, + color={255,0,255})); + connect(uChi, disChi.uChi) + annotation (Line(points={{-180,120},{-40,120},{-40,-152},{-2,-152}}, + color={255,0,255})); + connect(uOnOff, disChi.uOnOff) + annotation (Line(points={{-180,20},{-110,20},{-110,-159},{-2,-159}}, + color={255,0,255})); + connect(disChi.nexDisChi, nexDisChi) + annotation (Line(points={{-2,-155},{-80,-155},{-80,-170},{-180,-170}}, + color={255,127,0})); + connect(uStaDow, and2.u1) + annotation (Line(points={{-180,210},{-140,210},{-140,200},{-102,200}}, + color={255,0,255})); + connect(and2.y, chiDemRed.uDemLim) + annotation (Line(points={{-78,200},{-40,200},{-40,179},{-22,179}}, + color={255,0,255})); + connect(uOnOff, booRep4.u) + annotation (Line(points={{-180,20},{58,20}}, color={255,0,255})); + connect(booRep4.y, chiDem.u2) + annotation (Line(points={{82,20},{120,20},{120,140},{138,140}}, + color={255,0,255})); + connect(chiDemRed.yChiDem, chiDem.u1) + annotation (Line(points={{2,174},{120,174},{120,148},{138,148}}, + color={0,0,127})); + connect(uChiLoa, chiDem.u3) + annotation (Line(points={{-180,150},{-100,150},{-100,132},{138,132}}, + color={0,0,127})); + connect(booRep4.y, heaPreCon.u2) + annotation (Line(points={{82,20},{120,20},{120,-10},{138,-10}}, + color={255,0,255})); + connect(enaHeaCon.yChiHeaCon, heaPreCon.u1) + annotation (Line(points={{22,-6},{80,-6},{80,-2},{138,-2}}, + color={255,0,255})); + connect(uChiHeaCon, heaPreCon.u3) + annotation (Line(points={{-180,-60},{-30,-60},{-30,-18},{138,-18}}, + color={255,0,255})); + connect(booRep4.y, chiWatIsoVal.u2) + annotation (Line(points={{82,20},{120,20},{120,-70},{138,-70}}, + color={255,0,255})); + connect(enaChiIsoVal.yChiWatIsoVal, chiWatIsoVal.u1) + annotation (Line(points={{22,-106},{40,-106},{40,-62},{138,-62}}, + color={0,0,127})); + connect(uChiWatIsoVal, chiWatIsoVal.u3) + annotation (Line(points={{-180,-100},{-100,-100},{-100,-78},{138,-78}}, + color={0,0,127})); + connect(chiDem.y, yChiDem) + annotation (Line(points={{162,140},{200,140}}, color={0,0,127})); + connect(heaPreCon.y, yChiHeaCon) + annotation (Line(points={{162,-10},{200,-10}}, color={255,0,255})); + connect(chiWatIsoVal.y, yChiWatIsoVal) + annotation (Line(points={{162,-70},{200,-70}}, color={0,0,127})); + connect(disChi.yChi, yChi) + annotation (Line(points={{22,-150},{140,-150},{140,-100},{200,-100}}, + color={255,0,255})); + connect(disChi.yRelDemLim, yReaDemLim) + annotation (Line(points={{22,-158},{60,-158},{60,-140},{200,-140}}, + color={255,0,255})); + connect(yOpeParLoaRatMin, chiDemRed.yOpeParLoaRatMin) + annotation (Line(points={{-180,180},{-110,180},{-110,171},{-22,171}}, + color={0,0,127})); + connect(uStaDow, chiDemRed.uStaDow) + annotation (Line(points={{-180,210},{-140,210},{-140,168},{-22,168}}, + color={255,0,255})); + connect(uOnOff, chiDemRed.uOnOff) + annotation (Line(points={{-180,20},{-110,20},{-110,165},{-22,165}}, + color={255,0,255})); + connect(uChi, minChiWatSet.uChi) + annotation (Line(points={{-180,120},{-40,120},{-40,74},{-2,74}}, + color={255,0,255})); + connect(nexEnaChi, minChiWatSet.nexEnaChi) + annotation (Line(points={{-180,-30},{-60,-30},{-60,71},{-2,71}}, + color={255,127,0})); + connect(nexDisChi, minChiWatSet.nexDisChi) + annotation (Line(points={{-180,-170},{-80,-170},{-80,69},{-2,69}}, + color={255,127,0})); + connect(minChiWatSet.yChiWatMinFloSet, minBypRes.VMinChiWat_setpoint) + annotation (Line(points={{22,70},{40,70},{40,106},{58,106}}, + color={0,0,127})); + connect(con3.y, minChiWatSet.uUpsDevSta) + annotation (Line(points={{-78,90},{-60,90},{-60,77},{-2,77}}, + color={255,0,255})); + connect(minBypRes.yMinBypRes, lat1.u) + annotation (Line(points={{82,110},{100,110},{100,80},{50,80},{50,50},{58,50}}, + color={255,0,255})); + connect(lat1.y, enaHeaCon.uUpsDevSta) + annotation (Line(points={{82,50},{100,50},{100,36},{-20,36},{-20,4},{-2,4}}, + color={255,0,255})); + connect(chiDemRed.yChiDemRed, lat2.u) + annotation (Line(points={{2,166},{10,166},{10,150},{18,150}}, + color={255,0,255})); + connect(lat2.y, minBypRes.uUpsDevSta) + annotation (Line(points={{42,150},{50,150},{50,118},{58,118}}, + color={255,0,255})); + connect(lat2.y, minChiWatSet.uSubCha) + annotation (Line(points={{42,150},{50,150},{50,120},{-20,120},{-20,66},{-2, + 66}}, + color={255,0,255})); + connect(disChi.yRelDemLim, pre.u) + annotation (Line(points={{22,-158},{60,-158},{60,-170},{78,-170}}, + color={255,0,255})); + connect(pre.y, not1.u) + annotation (Line(points={{102,-170},{118,-170}}, color={255,0,255})); + connect(not1.y, and2.u2) + annotation (Line(points={{142,-170},{160,-170},{160,-192},{-120,-192}, + {-120,192},{-102,192}}, color={255,0,255})); + connect(minChiWatSet.yChiWatMinFloSet, yChiWatMinFloSet) + annotation (Line(points={{22,70},{200,70}}, color={0,0,127})); + connect(clr, lat2.clr) + annotation (Line(points={{-180,50},{-130,50},{-130,144},{18,144}}, + color={255,0,255})); + connect(clr, lat1.clr) + annotation (Line(points={{-180,50},{-130,50},{-130,44},{58,44}}, + color={255,0,255})); + connect(enaHeaCon.yEnaHeaCon, lat3.u) + annotation (Line(points={{22,6},{30,6},{30,-40},{58,-40}}, color={255,0,255})); + connect(lat3.y, enaChiIsoVal.uUpsDevSta) + annotation (Line(points={{82,-40},{100,-40},{100,-56},{-20,-56},{-20,-105}, + {-2,-105}}, + color={255,0,255})); + connect(clr, lat3.clr) + annotation (Line(points={{-180,50},{-130,50},{-130,-46},{58,-46}}, + color={255,0,255})); + connect(enaChiIsoVal.yEnaChiWatIsoVal, lat4.u) + annotation (Line(points={{22,-94},{50,-94},{50,-110},{58,-110}}, + color={255,0,255})); + connect(lat4.y, disChi.uEnaChiWatIsoVal) + annotation (Line(points={{82,-110},{120,-110},{120,-130},{-20,-130}, + {-20,-148},{-2,-148}}, color={255,0,255})); + connect(clr, lat4.clr) + annotation (Line(points={{-180,50},{-130,50},{-130,-116},{58,-116}}, + color={255,0,255})); + connect(and2.y, or2.u1) + annotation (Line(points={{-78,200},{18,200}}, color={255,0,255})); + connect(con3.y, or2.u2) annotation (Line(points={{-78,90},{-60,90},{-60,192},{ + 18,192}}, color={255,0,255})); + connect(or2.y, minBypRes.uUpsDevSta) annotation (Line(points={{42,200},{50, + 200},{50,118},{58,118}}, + color={255,0,255})); + connect(or2.y, minChiWatSet.uSubCha) annotation (Line(points={{42,200},{50, + 200},{50,120},{-20,120},{-20,66},{-2,66}}, + color={255,0,255})); + connect(con3.y, enaHeaCon.uEnaPla) annotation (Line(points={{-78,90},{-70,90}, + {-70,8},{-2,8}}, color={255,0,255})); + connect(minChiWatSet.yChaSet, minBypRes.uSetChaPro) annotation (Line(points={ + {22,62},{30,62},{30,102},{58,102}}, color={255,0,255})); +annotation ( + defaultComponentName="staStaDow", + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-160,-200},{180,220}})), + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-40,6},{40,-6}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-2,-6},{2,-72}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-72},{-20,-72},{0,-90},{20,-72},{0,-72}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,-90},{-58,-102}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexDisChi"), + Text( + extent={{-98,-72},{-46,-86}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiWatIsoVal"), + Text( + extent={{-98,28},{-46,16}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="vChiWat_flow"), + Text( + extent={{-98,86},{-58,74}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yOpeParLoaRatMin", + visible=need_reduceChillerDemand), + Text( + extent={{-100,66},{-64,56}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiLoa", + visible=need_reduceChillerDemand), + Text( + extent={{-102,46},{-74,36}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChi"), + Text( + extent={{-98,102},{-64,90}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaDow"), + Text( + extent={{-100,-12},{-66,-22}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uOnOff"), + Text( + extent={{-98,-32},{-54,-44}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexEnaChi"), + Text( + extent={{-98,-54},{-52,-64}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiHeaCon"), + Text( + extent={{64,98},{100,88}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiDem", + visible=need_reduceChillerDemand), + Text( + extent={{60,-14},{96,-24}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiIsoVal"), + Text( + extent={{54,26},{96,14}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChiHeaCon"), + Text( + extent={{66,-54},{104,-64}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChi"), + Text( + extent={{54,-82},{96,-94}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yReaDemLim", + visible=need_reduceChillerDemand), + Text( + extent={{32,66},{98,56}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatMinFloSet"), + Text( + extent={{-100,6},{-84,-4}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="clr")}), +Documentation(info=" +

+Block that controls devices at the first step of chiller staging down process. +This development is based on ASHRAE Guideline 36-2021, +section 5.20.4.17, item a and b. The sections specifies the first step of +staging down process. +

+

+For the stage-down process that requires a smaller chiller being enabled and a +larger chiller being disabled (uOnOff=true): +

+
    +
  1. +Command operating chilers to reduce demand to 75% (chiDemRedFac) of +their current load or a percentage equal to current stage minimum cycling operative +partial load ratio (yOpeParLoaRatMin), whichever is greater. Wait until acutal +demand < 80% of current load up to a maximum of 5 minutes (holChiDemTim) +before proceeding. This is implemented in block chiDemRed. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand +for more decriptions. +
  2. +
  3. +Slowly change the minimum chilled water flow setpoint to that approriate for the +stage transition (minChiWatSet). After new setpoint is achieved, wait +1 minutes (aftByPasSetTim) to allow loop to stabilize (minBypRes). +See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint +and + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass +for more decriptions. +
  4. +
  5. +Enable head pressure control for the chiller being enabled. Wait 30 seconds (waiTim). +It is implemented in block enaHeaCon, see + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl +for more decriptions. +
  6. +
  7. +Slowly open chilled water isolation valve of the smaller chiller being enabled. +Determine valve timing chaChiWatIsoTim in the field as that required +to prevent nuisance trips. +It is implemented in block enaChiIsoVal, see + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal +for more decriptions. +
  8. +
  9. +Start the smaller chiller after its chilled water isolation valve is fully open. +Wait 5 minutes (proOnTim) after the newly enabled chiller to prove that +it is operating correctly, then shut off the larger chiller and release the demand +limit (yReaDemLim=true). +It is implemented in block disChi, see + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DisableChiller +for more decriptions. +
  10. +
+

+For staging down from any other stage (uOnOff=false), just shut off +the last stage chiller. This is implemented in block disChi, see + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DisableChiller +for more decriptions. +

+", revisions=" + +")); +end DownStart; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableCWPump.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableCWPump.mo new file mode 100644 index 00000000000..bfb0c81a0eb --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableCWPump.mo @@ -0,0 +1,185 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block EnableCWPump + "Generate staging index for condenser water pump control" + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of resetting status of device before enabling or disabling condenser water pump" + annotation (Placement(transformation(extent={{-160,60},{-120,100}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp "Stage-up command" + annotation (Placement(transformation(extent={{-160,20},{-120,60}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow + "Stage-down command" + annotation (Placement(transformation(extent={{-160,-30},{-120,10}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage, does not include stages like X + WSE" + annotation (Placement(transformation(extent={{-160,-60},{-120,-20}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Current chiller stage setpoint, does not include stages like X + WSE" + annotation (Placement(transformation(extent={{-160,-100},{-120,-60}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yChiSta + "Stage for condenser water pumps control" + annotation (Placement(transformation(extent={{120,20},{160,60}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Integers.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logicla and" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + Buildings.Controls.OBC.CDL.Integers.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + Buildings.Controls.OBC.CDL.Integers.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{40,-20},{60,0}}))); + +equation + connect(uUpsDevSta, and2.u1) + annotation (Line(points={{-140,80},{-82,80}}, color={255,0,255})); + connect(uStaUp, and2.u2) + annotation (Line(points={{-140,40},{-100,40},{-100,72},{-82,72}}, + color={255,0,255})); + connect(and2.y, swi1.u2) + annotation (Line(points={{-58,80},{-22,80}},color={255,0,255})); + connect(uUpsDevSta, and1.u1) + annotation (Line(points={{-140,80},{-110,80},{-110,10},{-82,10}}, + color={255,0,255})); + connect(uStaDow, and1.u2) + annotation (Line(points={{-140,-10},{-100,-10},{-100,2},{-82,2}}, + color={255,0,255})); + connect(and1.y, swi2.u2) + annotation (Line(points={{-58,10},{-22,10}},color={255,0,255})); + connect(uStaUp, swi.u2) + annotation (Line(points={{-140,40},{78,40}}, color={255,0,255})); + connect(uStaDow, swi3.u2) + annotation (Line(points={{-140,-10},{38,-10}}, color={255,0,255})); + connect(uStaSet, swi3.u3) annotation (Line(points={{-140,-80},{-40,-80},{-40,-18}, + {38,-18}}, color={255,127,0})); + connect(uStaSet, swi2.u1) annotation (Line(points={{-140,-80},{-40,-80},{-40,18}, + {-22,18}}, color={255,127,0})); + connect(uStaSet, swi1.u1) annotation (Line(points={{-140,-80},{-40,-80},{-40,88}, + {-22,88}}, color={255,127,0})); + connect(uChiSta, swi2.u3) annotation (Line(points={{-140,-40},{-30,-40},{-30,2}, + {-22,2}}, color={255,127,0})); + connect(uChiSta, swi1.u3) annotation (Line(points={{-140,-40},{-30,-40},{-30,72}, + {-22,72}}, color={255,127,0})); + connect(swi.y, yChiSta) + annotation (Line(points={{102,40},{140,40}}, color={255,127,0})); + connect(swi2.y, swi3.u1) annotation (Line(points={{2,10},{20,10},{20,-2},{38,-2}}, + color={255,127,0})); + connect(swi3.y, swi.u3) annotation (Line(points={{62,-10},{70,-10},{70,32},{78, + 32}}, color={255,127,0})); + connect(swi1.y, swi.u1) annotation (Line(points={{2,80},{70,80},{70,48},{78,48}}, + color={255,127,0})); +annotation ( + defaultComponentName="enaNexCWP", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-120,-100},{120,100}})), + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-96,-82},{-62,-94}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="uStaSet"), + Text( + extent={{-98,88},{-50,72}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uUpsDevSta"), + Text( + extent={{-98,28},{-64,16}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaUp"), + Text( + extent={{68,8},{98,-8}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yChiSta"), + Text( + extent={{-98,-12},{-60,-24}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaDow"), + Ellipse( + extent={{-60,60},{60,-60}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,60},{0,-60},{60,0},{0,60}}, + lineColor={0,0,0}, + fillColor={238,46,47}, + fillPattern=FillPattern.Solid), + Text( + extent={{-96,-46},{-62,-58}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="uChiSta")}), + Documentation(info=" +

+This block generates stage signal as input for condenser water pump control. +

+ +", +revisions=" + +")); +end EnableCWPump; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableChiller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableChiller.mo new file mode 100644 index 00000000000..7764b4ed979 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableChiller.mo @@ -0,0 +1,411 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block EnableChiller "Sequence for enabling chiller" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Real proOnTim( + final unit="s", + final quantity="Time") = 300 + "Enabled chiller operation time to indicate if it is proven on"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaChi + "Index of next enabling chiller" + annotation (Placement(transformation(extent={{-240,100},{-200,140}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp + "Stage-up command" + annotation (Placement(transformation(extent={{-240,40},{-200,80}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaChiWatIsoVal + "Status of chilled water isolation valve control: true=enabled valve is fully open" + annotation (Placement(transformation(extent={{-240,10},{-200,50}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-240,-20},{-200,20}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "Indicate if the stage require one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{-240,-70},{-200,-30}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexDisChi + "Next disabling chiller when there is any stage up that need one chiller on and another off" + annotation (Placement(transformation(extent={{-240,-170},{-200,-130}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{200,-70},{240,-30}}), + iconTransformation(extent={{100,60},{140,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yNewChiEna + "Newly enabled chiller has been proven on by more than 5 minutes" + annotation (Placement(transformation(extent={{200,-190},{240,-150}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + final parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{100,110},{120,130}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "In staging up process and the chilled water isolation valve has open" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.And and1[nChi] "Logical and" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nChi]( + final k=fill(true, nChi)) "True constant" + annotation (Placement(transformation(extent={{-40,140},{-20,160}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-160,-10},{-140,10}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr[nChi]( + final t=fill(0.5, nChi)) + "Convert real input to boolean output" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-120},{120,-100}}))); + Buildings.Controls.OBC.CDL.Logical.And and3[nChi] "Logical and" + annotation (Placement(transformation(extent={{40,-120},{60,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nChi]( + final k=fill(false, nChi)) "False constant" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{160,-60},{180,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep(final nout=nChi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,110},{-140,130}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nChi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,110},{-80,130}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim(final t=proOnTim) + "Count the time after new chiller has been enabled" + annotation (Placement(transformation(extent={{-100,-120},{-80,-100}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi] + "Record the old chiller status" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-20,-120},{0,-100}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-160,-60},{-140,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nChi]( + final k=chiInd) "Chiller index array" + annotation (Placement(transformation(extent={{-160,80},{-140,100}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1( + final nout=nChi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nChi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,-160},{-80,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4 "Logical switch" + annotation (Placement(transformation(extent={{160,-180},{180,-160}}))); + +equation + connect(nexEnaChi, intRep.u) + annotation (Line(points={{-220,120},{-162,120}}, color={255,127,0})); + connect(intRep.y, intEqu.u1) + annotation (Line(points={{-138,120},{-102,120}}, color={255,127,0})); + connect(uEnaChiWatIsoVal,and2. u2) + annotation (Line(points={{-220,30},{-180,30},{-180,52},{-162,52}}, + color={255,0,255})); + connect(uStaUp, and2.u1) + annotation (Line(points={{-220,60},{-162,60}}, color={255,0,255})); + connect(and2.y, booRep.u) + annotation (Line(points={{-138,60},{-102,60}}, color={255,0,255})); + connect(intEqu.y, and1.u1) + annotation (Line(points={{-78,120},{-42,120}}, color={255,0,255})); + connect(booRep.y, and1.u2) + annotation (Line(points={{-78,60},{-60,60},{-60,112},{-42,112}}, + color={255,0,255})); + connect(and1.y, logSwi.u2) + annotation (Line(points={{-18,120},{98,120}}, color={255,0,255})); + connect(con.y, logSwi.u1) + annotation (Line(points={{-18,150},{0,150},{0,128},{98,128}}, color={255,0,255})); + connect(uChi, booToRea.u) + annotation (Line(points={{-220,0},{-162,0}}, color={255,0,255})); + connect(booToRea.y, triSam.u) + annotation (Line(points={{-138,0},{-22,0}}, color={0,0,127})); + connect(edg.y, booRep1.u) + annotation (Line(points={{-78,-20},{-62,-20}}, color={255,0,255})); + connect(booRep1.y, triSam.trigger) + annotation (Line(points={{-38,-20},{-10,-20},{-10,-12}}, color={255,0,255})); + connect(triSam.y, greEquThr.u) + annotation (Line(points={{2,0},{18,0}}, color={0,0,127})); + connect(and2.y, tim.u) + annotation (Line(points={{-138,60},{-120,60},{-120,-110},{-102,-110}}, + color={255,0,255})); + connect(booRep2.y, and3.u1) + annotation (Line(points={{2,-110},{38,-110}}, color={255,0,255})); + connect(and3.y, logSwi1.u2) + annotation (Line(points={{62,-110},{98,-110}}, color={255,0,255})); + connect(con1.y, logSwi1.u1) + annotation (Line(points={{62,-80},{80,-80},{80,-102},{98,-102}}, + color={255,0,255})); + connect(uChi, logSwi1.u3) + annotation (Line(points={{-220,0},{-180,0},{-180,-130},{80,-130},{80,-118}, + {98,-118}}, color={255,0,255})); + connect(booRep3.y, logSwi2.u2) + annotation (Line(points={{102,-50},{158,-50}}, color={255,0,255})); + connect(uOnOff, not2.u) + annotation (Line(points={{-220,-50},{-162,-50}}, color={255,0,255})); + connect(logSwi1.y, logSwi2.u3) + annotation (Line(points={{122,-110},{140,-110},{140,-58},{158,-58}}, + color={255,0,255})); + connect(logSwi.y, logSwi2.u1) + annotation (Line(points={{122,120},{140,120},{140,-42},{158,-42}}, + color={255,0,255})); + connect(logSwi2.y,yChi) + annotation (Line(points={{182,-50},{220,-50}}, color={255,0,255})); + connect(not2.y, or2.u1) + annotation (Line(points={{-138,-50},{38,-50}},color={255,0,255})); + connect(not1.y, or2.u2) + annotation (Line(points={{2,-70},{20,-70},{20,-58},{38,-58}}, + color={255,0,255})); + connect(or2.y, booRep3.u) + annotation (Line(points={{62,-50},{78,-50}},color={255,0,255})); + connect(conInt.y, intEqu.u2) + annotation (Line(points={{-138,90},{-110,90},{-110,112},{-102,112}}, + color={255,127,0})); + connect(nexDisChi, intRep1.u) + annotation (Line(points={{-220,-150},{-162,-150}}, color={255,127,0})); + connect(intRep1.y, intEqu1.u1) + annotation (Line(points={{-138,-150},{-102,-150}}, color={255,127,0})); + connect(conInt.y, intEqu1.u2) + annotation (Line(points={{-138,90},{-110,90},{-110,-158},{-102,-158}}, + color={255,127,0})); + connect(intEqu1.y, and3.u2) + annotation (Line(points={{-78,-150},{20,-150},{20,-118},{38,-118}}, + color={255,0,255})); + connect(uStaUp, edg.u) + annotation (Line(points={{-220,60},{-190,60},{-190,-20},{-102,-20}}, + color={255,0,255})); + connect(uStaUp, booRep4.u) + annotation (Line(points={{-220,60},{-190,60},{-190,40},{-42,40}}, + color={255,0,255})); + connect(booRep4.y, logSwi3.u2) + annotation (Line(points={{-18,40},{58,40}}, color={255,0,255})); + connect(uChi, logSwi3.u3) + annotation (Line(points={{-220,0},{-180,0},{-180,20},{40,20},{40,32}, + {58,32}}, color={255,0,255})); + connect(greEquThr.y, logSwi3.u1) + annotation (Line(points={{42,0},{50,0},{50,48},{58,48}}, color={255,0,255})); + connect(logSwi3.y, logSwi.u3) + annotation (Line(points={{82,40},{90,40},{90,112},{98,112}}, + color={255,0,255})); + connect(not2.y, logSwi4.u2) + annotation (Line(points={{-138,-50},{-130,-50},{-130,-170},{158,-170}}, + color={255,0,255})); + connect(and2.y, logSwi4.u1) + annotation (Line(points={{-138,60},{-120,60},{-120,-162},{158,-162}}, + color={255,0,255})); + connect(logSwi4.y, yNewChiEna) + annotation (Line(points={{182,-170},{220,-170}}, color={255,0,255})); + connect(tim.passed, not1.u) + annotation (Line(points={{-78,-118},{-40,-118},{-40,-70},{-22,-70}}, + color={255,0,255})); + connect(tim.passed, booRep2.u) + annotation (Line(points={{-78,-118},{-40,-118},{-40,-110},{-22,-110}}, + color={255,0,255})); + connect(tim.passed, logSwi4.u3) + annotation (Line(points={{-78,-118},{-40,-118},{-40,-178},{158,-178}}, + color={255,0,255})); + +annotation ( + defaultComponentName="enaChi", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-60,60},{60,20}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-52,20},{-40,0}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,20},{52,0}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-60,0},{60,-80}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,96},{-50,84}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexEnaChi"), + Text( + extent={{-98,-84},{-50,-96}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexDisChi"), + Text( + extent={{-100,66},{-68,56}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaUp"), + Text( + extent={{-98,26},{-34,14}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uEnaChiWatIsoVal"), + Text( + extent={{-100,-14},{-78,-24}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChi"), + Text( + extent={{-98,-54},{-72,-66}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uOnOff"), + Text( + extent={{74,86},{100,76}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChi"), + Text( + extent={{60,-72},{98,-84}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yNewChiEna")}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-200,-180},{200,180}}), + graphics={ + Rectangle( + extent={{-198,-62},{198,-178}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-198,178},{198,-38}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{14,174},{94,166}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Output new chiller status array:"), + Text( + extent={{40,-72},{120,-88}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable +small chiller"), + Text( + extent={{16,168},{208,148}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString= + "1. When the stage change does not require one chiller off and another chiller on."), + Text( + extent={{16,154},{208,136}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="2. When the stage change does require one chiller off and another chiller on, +but the enabled chiller has not yet finished starting."), + Text( + extent={{-24,-132},{56,-140}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Output new chiller status array:"), + Text( + extent={{-20,-142},{152,-158}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="When the stage change does require one chiller off +and another chiller on, and the enabled chiller has finished starting.")}), +Documentation(info=" +

+Block that controlles chiller when there is staging up command uStaUp=true. +This implementation is based on ASHRAE Guideline36-2021, section 5.20.4.16, +item f and item g.1. These sections specify when the next chiller should be enabled +and when the running smaller chiller should be diabled. +

+

+When the stage-up process does not requires a smaller chiller being staged off and +a larger chiller being staged on (uOnOff=false): +

+ +

+For any stage change during which a smaller chiller is diabled and a larger chiller +is enabled (uOnOff=true): +

+ +", revisions=" + +")); +end EnableChiller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/HeadControl.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/HeadControl.mo new file mode 100644 index 00000000000..28ce359ea47 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/HeadControl.mo @@ -0,0 +1,361 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block HeadControl + "Sequences for enabling or disabling head pressure control for the chiller being enabled or disabled" + + parameter Integer nChi=2 "Total number of chiller"; + parameter Real thrTimEnb( + final unit="s", + final quantity="Time")=10 + "Threshold time to enable head pressure control after condenser water pump being reset"; + parameter Real waiTim( + final unit="s", + final quantity="Time") = 30 + "Waiting time after enabling next head pressure control"; + parameter Boolean heaStaCha = true + "Flag to indicate if head pressure control of next chiller should be ON or OFF: true = in stage-up process so it should be ON"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-220,140},{-180,180}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexChaChi + "Index of next enabling or disabling chiller" + annotation (Placement(transformation(extent={{-220,-50},{-180,-10}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of resetting status of device before enabling or disabling head pressure control" + annotation (Placement(transformation(extent={{-220,110},{-180,150}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-220,-130},{-180,-90}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaPro + "Indicate if there is stage change" + annotation (Placement(transformation(extent={{-220,32},{-180,72}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiHeaCon[nChi] + "Chiller head pressure control enabling status" + annotation (Placement(transformation(extent={{180,-100},{220,-60}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaHeaCon + "Status of heat pressure control: true=enabled head pressure control" + annotation (Placement(transformation(extent={{180,80},{220,120}}), + iconTransformation(extent={{100,40},{140,80}}))); + +protected + final parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Logical.Timer tim + "Count the time after condenser water pump being reset" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr( + final t=thrTimEnb) + "Check if it has been threhold time after condenser water pump achieves its new setpoint" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi] + "Record the old chiller head pressure control status" + annotation (Placement(transformation(extent={{-60,-120},{-40,-100}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-160,-120},{-140,-100}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-100,-140},{-80,-120}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=thrTimEnb + waiTim) + "Check if it has been threshold time after condenser water pump achieves its new setpoint and have waited for another amount of time" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nChi) "Replicate boolean input" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr[nChi]( + final t=fill(0.5, nChi)) + "Convert real input to boolean output" + annotation (Placement(transformation(extent={{140,-30},{160,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi] "Logical switch" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nChi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,-40},{-140,-20}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nChi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2[nChi] "Logical switch" + annotation (Placement(transformation(extent={{40,-40},{60,-20}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[nChi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{40,0},{60,20}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi "Logical switch" + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(final k=false) + "False constant" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=heaStaCha) + "Head control status change" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nChi]( + final k=chiInd) "Chiller index array" + annotation (Placement(transformation(extent={{-160,-70},{-140,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{140,-90},{160,-70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{40,-160},{60,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Plant just enabeld or it is in the chiller staging process" + annotation (Placement(transformation(extent={{-140,150},{-120,170}}))); + +equation + connect(lat.y, tim.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(tim.y, greThr.u) + annotation (Line(points={{-38,60},{-2,60}}, color={0,0,127})); + connect(uChiHeaCon, booToRea.u) + annotation (Line(points={{-200,-110},{-162,-110}}, color={255,0,255})); + connect(booToRea.y, triSam.u) + annotation (Line(points={{-138,-110},{-62,-110}}, color={0,0,127})); + connect(edg.y, and2.u1) + annotation (Line(points={{-138,100},{-120,100},{-120,80},{-170,80},{-170,60}, + {-162,60}}, color={255,0,255})); + connect(uStaPro, and2.u2) + annotation (Line(points={{-200,52},{-162,52}}, color={255,0,255})); + connect(and2.y, lat.u) + annotation (Line(points={{-138,60},{-102,60}}, color={255,0,255})); + connect(uStaPro, not1.u) annotation (Line(points={{-200,52},{-170,52},{-170,20}, + {-162,20}}, color={255,0,255})); + connect(not1.y, lat.clr) + annotation (Line(points={{-138,20},{-110,20},{-110,54},{-102,54}}, + color={255,0,255})); + connect(booRep.y, triSam.trigger) + annotation (Line(points={{-78,-130},{-50,-130},{-50,-122}}, + color={255,0,255})); + connect(tim.y, greThr1.u) + annotation (Line(points={{-38,60},{-20,60},{-20,100},{-2,100}}, color={0,0,127})); + connect(booRep1.y, swi.u2) + annotation (Line(points={{62,60},{80,60},{80,-20},{98,-20}}, + color={255,0,255})); + connect(greThr.y, booRep1.u) + annotation (Line(points={{22,60},{38,60}}, color={255,0,255})); + connect(swi.y, greEquThr.u) + annotation (Line(points={{122,-20},{138,-20}}, color={0,0,127})); + connect(not2.y, booRep2.u) + annotation (Line(points={{-38,-60},{-22,-60}}, color={255,0,255})); + connect(booRep2.y, swi1.u2) + annotation (Line(points={{2,-60},{38,-60}}, color={255,0,255})); + connect(triSam.y, swi1.u3) + annotation (Line(points={{-38,-110},{20,-110},{20,-68},{38,-68}}, + color={0,0,127})); + connect(swi1.y, swi.u3) + annotation (Line(points={{62,-60},{80,-60},{80,-28},{98,-28}}, + color={0,0,127})); + connect(lat.y, not2.u) + annotation (Line(points={{-78,60},{-70,60},{-70,-60},{-62,-60}}, + color={255,0,255})); + connect(nexChaChi, intRep.u) + annotation (Line(points={{-200,-30},{-162,-30}}, color={255,127,0})); + connect(intRep.y, intEqu.u1) + annotation (Line(points={{-138,-30},{-102,-30}}, color={255,127,0})); + connect(booToRea.y, swi1.u1) + annotation (Line(points={{-138,-110},{-100,-110},{-100,-80},{10,-80},{10,-52}, + {38,-52}}, color={0,0,127})); + connect(intEqu.y, swi2.u2) + annotation (Line(points={{-78,-30},{38,-30}}, color={255,0,255})); + connect(swi2.y, swi.u1) + annotation (Line(points={{62,-30},{70,-30},{70,-12},{98,-12}}, + color={0,0,127})); + connect(triSam.y, swi2.u3) + annotation (Line(points={{-38,-110},{20,-110},{20,-38},{38,-38}}, + color={0,0,127})); + connect(con1.y, logSwi.u1) + annotation (Line(points={{-78,30},{-60,30},{-60,18},{-42,18}}, + color={255,0,255})); + connect(con.y, logSwi.u3) + annotation (Line(points={{-78,0},{-60,0},{-60,2},{-42,2}}, + color={255,0,255})); + connect(greThr.y, logSwi.u2) + annotation (Line(points={{22,60},{30,60},{30,40},{-50,40},{-50,10},{-42,10}}, + color={255,0,255})); + connect(logSwi.y, booRep3.u) + annotation (Line(points={{-18,10},{-2,10}},color={255,0,255})); + connect(booRep3.y, booToRea1.u) + annotation (Line(points={{22,10},{38,10}}, color={255,0,255})); + connect(booToRea1.y, swi2.u1) + annotation (Line(points={{62,10},{70,10},{70,-10},{20,-10},{20,-22},{38,-22}}, + color={0,0,127})); + connect(conInt.y, intEqu.u2) + annotation (Line(points={{-138,-60},{-130,-60},{-130,-38},{-102,-38}}, + color={255,127,0})); + connect(greThr1.y, and1.u1) + annotation (Line(points={{22,100},{98,100}}, color={255,0,255})); + connect(and1.y, yEnaHeaCon) + annotation (Line(points={{122,100},{200,100}}, color={255,0,255})); + connect(and2.y, booRep.u) + annotation (Line(points={{-138,60},{-120,60},{-120,-130},{-102,-130}}, + color={255,0,255})); + connect(uStaPro, booRep4.u) annotation (Line(points={{-200,52},{-170,52},{-170, + -150},{38,-150}}, color={255,0,255})); + connect(uChiHeaCon, logSwi1.u3) + annotation (Line(points={{-200,-110},{-166,-110},{-166,-88},{138,-88}}, + color={255,0,255})); + connect(booRep4.y, logSwi1.u2) + annotation (Line(points={{62,-150},{80,-150},{80,-80},{138,-80}}, + color={255,0,255})); + connect(greEquThr.y, logSwi1.u1) + annotation (Line(points={{162,-20},{170,-20},{170,-50},{120,-50},{120,-72},{ + 138,-72}}, color={255,0,255})); + connect(logSwi1.y, yChiHeaCon) + annotation (Line(points={{162,-80},{200,-80}}, color={255,0,255})); + connect(uEnaPla, or1.u1) + annotation (Line(points={{-200,160},{-142,160}}, color={255,0,255})); + connect(or1.y, and1.u2) annotation (Line(points={{-118,160},{80,160},{80,92}, + {98,92}}, color={255,0,255})); + connect(uUpsDevSta, or1.u2) annotation (Line(points={{-200,130},{-160,130},{-160, + 152},{-142,152}}, color={255,0,255})); + connect(or1.y, edg.u) annotation (Line(points={{-118,160},{-100,160},{-100, + 120},{-170,120},{-170,100},{-162,100}}, color={255,0,255})); +annotation ( + defaultComponentName="enaHeaCon", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-180,-180},{180,180}})), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,-34},{-54,-46}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexChaChi"), + Text( + extent={{-96,52},{-44,38}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uUpsDevSta"), + Text( + extent={{-100,6},{-66,-6}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + Text( + extent={{-98,-72},{-46,-86}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiHeaCon"), + Text( + extent={{44,68},{96,54}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yEnaHeaCon"), + Text( + extent={{44,-50},{96,-64}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChiHeaCon"), + Polygon( + points={{-60,40},{-60,-40},{0,0},{-60,40}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Polygon( + points={{60,40},{60,-40},{0,0},{60,40}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,88},{-48,74}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uEnaPla")}), + Documentation(info=" +

+Block that generates chiller head pressure control enabling status array when +there is stage change command (chaPro=true). It also generates status +to indicate if the head pressure control status change process has finished. +This development is based on ASHRAE Guideline 36-2021. +

+

+In stage-up process, section 5.20.4.16, item d: +

+ +

+In stage-up process when requires smaller chiller being shut off and larger chiller +being enabled, section 5.20.4.16, item g.3: +

+ +

+In stage-down process, section 5.20.4.17, item d: +

+ +

+In stage-down process when requires smaller chiller being enabled and larger chiller +being disabled, section 5.20.4.17, item a.3: +

+ +", revisions=" + +")); +end HeadControl; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/NextChiller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/NextChiller.mo new file mode 100644 index 00000000000..910d10f4953 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/NextChiller.mo @@ -0,0 +1,409 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block NextChiller "Identify next enable and disable chillers" + + parameter Integer nChi=2 "Total number of chillers"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-300,110},{-260,150}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiSet[nChi] + "Vector of chillers status setpoint" + annotation (Placement(transformation(extent={{-300,-40},{-260,0}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput endPro + "True: the staging process is end" + annotation (Placement(transformation(extent={{-300,-210},{-260,-170}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yUp + "True if it is in staging up process" + annotation (Placement(transformation(extent={{280,180},{320,220}}), + iconTransformation(extent={{100,70},{140,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDow + "True if it is in staging down process" + annotation (Placement(transformation(extent={{280,120},{320,160}}), + iconTransformation(extent={{100,50},{140,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yNexEnaChi + "Next enabling chiller index" + annotation (Placement(transformation(extent={{280,70},{320,110}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yDisSmaChi + "Smaller chiller to be disabled in staging-up process" + annotation (Placement(transformation(extent={{280,20},{320,60}}), + iconTransformation(extent={{100,-12},{140,28}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yOnOff + "True: if the stage change require one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{280,-40},{320,0}}), + iconTransformation(extent={{100,-50},{140,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yLasDisChi + "Disable last chiller when it is in stage-down process" + annotation (Placement(transformation(extent={{280,-120},{320,-80}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yEnaSmaChi + "Smaller chiller to be enabled in stage-down process" + annotation (Placement(transformation(extent={{280,-170},{320,-130}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + +protected + parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nChi] + "Boolean to integer" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nChi] + "Boolean to integer" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt2 + "Boolean to integer" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt3 + "Boolean to integer" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt4 + "Boolean to integer" + annotation (Placement(transformation(extent={{-60,100},{-40,120}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiIndVec[nChi]( + final k=chiInd) "Vector of chiller index" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-140,-200},{-120,-180}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant one( + final k=1) "Constant 1" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if it is stage up or stage down" + annotation (Placement(transformation(extent={{-240,120},{-220,140}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg[nChi] + "Check if the chiller is being enabled" + annotation (Placement(transformation(extent={{-240,30},{-220,50}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg[nChi] + "Check if the chiller is being disabled" + annotation (Placement(transformation(extent={{-240,-30},{-220,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Latch enaChi[nChi] + "True when the chiller should be enabled" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + Buildings.Controls.OBC.CDL.Logical.Latch disChi[nChi] + "True when the chiller should be disabled" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyEnaChi(final nin=nChi) + "Check if there is any enabling chiller" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyDisChi(final nin=nChi) + "Check if there is any disabling chiller" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.And enaDis + "Check if enabling and disabling chillers at the same process" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt[nChi] + "Find out the index of enabling chiller" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt1[nChi] + "Find out the index of disabling chiller" + annotation (Placement(transformation(extent={{0,-140},{20,-120}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum enaChiInd(final nin = nChi) + "Enabling chiller index" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum disChiInd(final nin = nChi) + "Disabling chiller index" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + Buildings.Controls.OBC.CDL.Logical.Latch upPro + "True when it is in stage up process" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + Buildings.Controls.OBC.CDL.Logical.Latch dowPro + "True when it is in stage down process" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt2 + "Find out the index of enabling chiller" + annotation (Placement(transformation(extent={{120,80},{140,100}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt3 + "Staging up process and it requires chiller on and off" + annotation (Placement(transformation(extent={{120,30},{140,50}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt4 + "Disabling chiller during stage up process" + annotation (Placement(transformation(extent={{160,10},{180,30}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt5 + "Find out the index of disabling chiller" + annotation (Placement(transformation(extent={{120,-140},{140,-120}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt6 + "Staging down process and it requires chiller on and off" + annotation (Placement(transformation(extent={{120,-190},{140,-170}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt7 + "Enabling chiller during stage down process" + annotation (Placement(transformation(extent={{160,-210},{180,-190}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Output 1 when it is not in the staging up process" + annotation (Placement(transformation(extent={{240,30},{260,50}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 + "Output 1 when it is not in the staging up process" + annotation (Placement(transformation(extent={{240,80},{260,100}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 + "Output 1 when it is not in the staging down process" + annotation (Placement(transformation(extent={{240,-160},{260,-140}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi3 + "Output 1 when it is not in the staging down process" + annotation (Placement(transformation(extent={{240,-110},{260,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nChi]( + final k=fill(false, nChi)) + "False constant" + annotation (Placement(transformation(extent={{-240,-130},{-220,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nChi]( + final k=fill(true, nChi)) + "Constant true" + annotation (Placement(transformation(extent={{-240,-90},{-220,-70}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel[nChi]( + final delayTime=fill(1, nChi), + final delayOnInit=fill(true, nChi)) + "Check if it has passed initial time" + annotation (Placement(transformation(extent={{-200,-90},{-180,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); +equation + connect(uChiSet, edg.u) annotation (Line(points={{-280,-20},{-250,-20},{-250,40}, + {-242,40}}, color={255,0,255})); + connect(booRep.y, enaChi.clr) annotation (Line(points={{-118,-190},{-110,-190}, + {-110,34},{-102,34}}, color={255,0,255})); + connect(booRep.y, disChi.clr) annotation (Line(points={{-118,-190},{-110,-190}, + {-110,-86},{-102,-86}}, color={255,0,255})); + connect(enaChi.y, anyEnaChi.u) annotation (Line(points={{-78,40},{-70,40},{-70, + -20},{-62,-20}}, color={255,0,255})); + connect(anyEnaChi.y, enaDis.u1) annotation (Line(points={{-38,-20},{-2,-20}}, + color={255,0,255})); + connect(disChi.y, anyDisChi.u) annotation (Line(points={{-78,-80},{-70,-80},{-70, + -100},{-62,-100}}, color={255,0,255})); + connect(anyDisChi.y, enaDis.u2) annotation (Line(points={{-38,-100},{-10,-100}, + {-10,-28},{-2,-28}}, color={255,0,255})); + connect(enaDis.y, yOnOff) annotation (Line(points={{22,-20},{300,-20}}, + color={255,0,255})); + connect(uStaSet, cha.u) + annotation (Line(points={{-280,130},{-242,130}}, color={255,127,0})); + connect(disChi.y, booToInt1.u) + annotation (Line(points={{-78,-80},{-70,-80},{-70,-140},{-62,-140}}, + color={255,0,255})); + connect(enaChi.y, booToInt.u) + annotation (Line(points={{-78,40},{-62,40}}, color={255,0,255})); + connect(booToInt.y, proInt.u1) annotation (Line(points={{-38,40},{-20,40},{-20, + 46},{-2,46}}, color={255,127,0})); + connect(booToInt1.y, proInt1.u2) annotation (Line(points={{-38,-140},{-20,-140}, + {-20,-136},{-2,-136}}, color={255,127,0})); + connect(chiIndVec.y, proInt.u2) annotation (Line(points={{-78,0},{-20,0},{-20, + 34},{-2,34}}, color={255,127,0})); + connect(proInt.y, enaChiInd.u) + annotation (Line(points={{22,40},{38,40}}, color={255,127,0})); + connect(chiIndVec.y, proInt1.u1) annotation (Line(points={{-78,0},{-20,0},{-20, + -124},{-2,-124}}, color={255,127,0})); + connect(proInt1.y, disChiInd.u) + annotation (Line(points={{22,-130},{38,-130}}, color={255,127,0})); + connect(cha.down, dowPro.u) annotation (Line(points={{-218,124},{-120,124},{-120, + 110},{-102,110}}, color={255,0,255})); + connect(enaDis.y, booToInt2.u) annotation (Line(points={{22,-20},{30,-20},{30, + -60},{38,-60}}, color={255,0,255})); + connect(upPro.y, booToInt3.u) + annotation (Line(points={{-78,160},{-62,160}}, color={255,0,255})); + connect(booToInt3.y, proInt2.u1) annotation (Line(points={{-38,160},{110,160}, + {110,96},{118,96}}, color={255,127,0})); + connect(enaChiInd.y, proInt2.u2) annotation (Line(points={{62,40},{80,40},{80, + 84},{118,84}},color={255,127,0})); + connect(booToInt3.y, proInt3.u1) annotation (Line(points={{-38,160},{110,160}, + {110,46},{118,46}},color={255,127,0})); + connect(booToInt2.y, proInt3.u2) annotation (Line(points={{62,-60},{100,-60},{ + 100,34},{118,34}}, color={255,127,0})); + connect(proInt3.y, proInt4.u1) annotation (Line(points={{142,40},{150,40},{150, + 26},{158,26}}, color={255,127,0})); + connect(disChiInd.y, proInt4.u2) annotation (Line(points={{62,-130},{90,-130}, + {90,14},{158,14}}, color={255,127,0})); + connect(dowPro.y, booToInt4.u) + annotation (Line(points={{-78,110},{-62,110}}, color={255,0,255})); + connect(booToInt4.y, proInt5.u1) annotation (Line(points={{-38,110},{70,110},{ + 70,-124},{118,-124}}, color={255,127,0})); + connect(disChiInd.y, proInt5.u2) annotation (Line(points={{62,-130},{90,-130}, + {90,-136},{118,-136}}, color={255,127,0})); + connect(booToInt2.y, proInt6.u2) annotation (Line(points={{62,-60},{100,-60},{ + 100,-186},{118,-186}}, color={255,127,0})); + connect(booToInt4.y, proInt6.u1) annotation (Line(points={{-38,110},{70,110},{ + 70,-174},{118,-174}}, color={255,127,0})); + connect(proInt6.y, proInt7.u1) annotation (Line(points={{142,-180},{150,-180}, + {150,-194},{158,-194}}, color={255,127,0})); + connect(enaChiInd.y, proInt7.u2) annotation (Line(points={{62,40},{80,40},{80, + -206},{158,-206}}, color={255,127,0})); + connect(endPro, dowPro.clr) annotation (Line(points={{-280,-190},{-210,-190},{ + -210,104},{-102,104}}, color={255,0,255})); + connect(endPro, upPro.clr) annotation (Line(points={{-280,-190},{-210,-190},{-210, + 154},{-102,154}}, color={255,0,255})); + connect(endPro, booRep.u) + annotation (Line(points={{-280,-190},{-142,-190}}, color={255,0,255})); + connect(uChiSet, falEdg.u) annotation (Line(points={{-280,-20},{-242,-20}}, + color={255,0,255})); + connect(upPro.y, yUp) annotation (Line(points={{-78,160},{-70,160},{-70,200},{ + 300,200}}, color={255,0,255})); + connect(dowPro.y, yDow) annotation (Line(points={{-78,110},{-70,110},{-70,140}, + {300,140}},color={255,0,255})); + connect(upPro.y, intSwi1.u2) annotation (Line(points={{-78,160},{-70,160},{-70, + 200},{200,200},{200,90},{238,90}}, color={255,0,255})); + connect(proInt2.y, intSwi1.u1) annotation (Line(points={{142,90},{180,90},{180, + 98},{238,98}}, color={255,127,0})); + connect(one.y, intSwi1.u3) annotation (Line(points={{142,-40},{220,-40},{220,82}, + {238,82}}, color={255,127,0})); + connect(intSwi1.y, yNexEnaChi) + annotation (Line(points={{262,90},{300,90}}, color={255,127,0})); + connect(upPro.y, intSwi.u2) annotation (Line(points={{-78,160},{-70,160},{-70, + 200},{200,200},{200,40},{238,40}}, color={255,0,255})); + connect(proInt4.y, intSwi.u1) annotation (Line(points={{182,20},{210,20},{210, + 48},{238,48}}, color={255,127,0})); + connect(one.y, intSwi.u3) annotation (Line(points={{142,-40},{220,-40},{220,32}, + {238,32}}, color={255,127,0})); + connect(intSwi.y, yDisSmaChi) + annotation (Line(points={{262,40},{300,40}}, color={255,127,0})); + connect(intSwi3.y, yLasDisChi) + annotation (Line(points={{262,-100},{300,-100}}, color={255,127,0})); + connect(dowPro.y, intSwi3.u2) annotation (Line(points={{-78,110},{-70,110},{-70, + 140},{190,140},{190,-100},{238,-100}}, color={255,0,255})); + connect(dowPro.y, intSwi2.u2) annotation (Line(points={{-78,110},{-70,110},{-70, + 140},{190,140},{190,-150},{238,-150}}, color={255,0,255})); + connect(proInt5.y, intSwi3.u1) annotation (Line(points={{142,-130},{180,-130}, + {180,-92},{238,-92}}, color={255,127,0})); + connect(proInt7.y, intSwi2.u1) annotation (Line(points={{182,-200},{200,-200}, + {200,-142},{238,-142}}, color={255,127,0})); + connect(intSwi2.y, yEnaSmaChi) + annotation (Line(points={{262,-150},{300,-150}}, color={255,127,0})); + connect(one.y, intSwi3.u3) annotation (Line(points={{142,-40},{220,-40},{220,-108}, + {238,-108}}, color={255,127,0})); + connect(one.y, intSwi2.u3) annotation (Line(points={{142,-40},{220,-40},{220,-158}, + {238,-158}}, color={255,127,0})); + connect(cha.up, upPro.u) annotation ( + Line(points={{-218,136},{-120,136},{-120,160},{-102,160}}, color = {255, 0, 255})); + connect(con2.y, truDel.u) + annotation (Line(points={{-218,-80},{-202,-80}}, color={255,0,255})); + connect(truDel.y, logSwi1.u2) + annotation (Line(points={{-178,-80},{-142,-80}}, color={255,0,255})); + connect(falEdg.y, logSwi1.u1) annotation (Line(points={{-218,-20},{-150,-20},{ + -150,-72},{-142,-72}}, color={255,0,255})); + connect(con.y, logSwi1.u3) annotation (Line(points={{-218,-120},{-160,-120},{-160, + -88},{-142,-88}}, color={255,0,255})); + connect(logSwi1.y, disChi.u) annotation (Line(points={{-118,-80},{-102,-80}}, + color={255,0,255})); + connect(truDel.y, logSwi2.u2) annotation (Line(points={{-178,-80},{-170,-80},{ + -170,40},{-142,40}}, color={255,0,255})); + connect(logSwi2.y, enaChi.u) + annotation (Line(points={{-118,40},{-102,40}}, color={255,0,255})); + connect(con.y, logSwi2.u3) annotation (Line(points={{-218,-120},{-160,-120},{-160, + 32},{-142,32}}, color={255,0,255})); + connect(edg.y, logSwi2.u1) annotation (Line(points={{-218,40},{-180,40},{-180, + 48},{-142,48}}, color={255,0,255})); +annotation ( + defaultComponentName="nexChi", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-260,-220},{280,220}})), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-100,76},{-64,66}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="uStaSet"), + Text( + extent={{-100,8},{-58,-4}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiSet"), + Text( + extent={{50,50},{98,30}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yNexEnaChi"), + Text( + extent={{-98,-62},{-64,-74}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="endPro"), + Text( + extent={{50,20},{98,0}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yDisSmaChi"), + Text( + extent={{50,-48},{98,-68}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yDisLasChi"), + Text( + extent={{44,-78},{98,-100}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yEnaSmaChi"), + Text( + extent={{54,-22},{96,-34}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yOnOff"), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="?"), + Text( + extent={{60,96},{102,84}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yUp"), + Text( + extent={{60,76},{102,64}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yDow")}), +Documentation(info=" +

+This block identifies index of next enabling (yNexEnaChi and +yEnaSmaChi) or disabling chiller (yDisSmaChi and +yLasDisChi) based on current chiller stage setpoint +uStaSet and the chiller status setpoint uChiSet. +

+

+This implementation assumes that the stage-up process (increased uStaSet) +will enable only one more chiller (yOnOff=false), or enable a larger +chiller and disable a smaller chiller (yOnOff=true); the stage-down +process (dicreased uStaSet) will disable only one existing chiller +(yOnOff=false), or disable a larger chiller and enable a smaller +chiller (yOnOff=true). +

+

+Note that when applying the sequence: +

+ +", revisions=" + +")); +end NextChiller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ReduceDemand.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ReduceDemand.mo new file mode 100644 index 00000000000..5eeb9daa4f4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ReduceDemand.mo @@ -0,0 +1,358 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block ReduceDemand "Sequence for reducing operating chiller demand" + + parameter Integer nChi=2 "Total number of chillers in the plant"; + parameter Real chiDemRedFac = 0.75 + "Demand reducing factor of current operating chillers"; + parameter Real holChiDemTim( + final unit="s", + final quantity="Time") = 300 + "Maximum time to wait for the actual demand less than percentage of current load"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDemLim + "Demand limit: true=limit chiller demand" + annotation (Placement(transformation(extent={{-200,170},{-160,210}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiLoa[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) + "Current chiller load" + annotation (Placement(transformation(extent={{-200,140},{-160,180}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput yOpeParLoaRatMin( + final min=0, + final max=1, + final unit="1") + "Current stage minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-200,0},{-160,40}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow "Stage down status: true=stage-down" + annotation (Placement(transformation(extent={{-200,-50},{-160,-10}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "True: if the stage change require one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{-200,-90},{-160,-50}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-200,-160},{-160,-120}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiDem[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) + "Chiller demand setpoint" + annotation (Placement(transformation(extent={{160,100},{200,140}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiDemRed + "Flag: true if it is not requiring reducing demand or the chiller demand reduction process has finished" + annotation (Placement(transformation(extent={{160,60},{200,100}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi]( + final y_start=fill(1e-6,nChi)) + "Triggered sampler to sample current chiller demand" + annotation (Placement(transformation(extent={{0,150},{20,170}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,180},{-40,200}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi4[nChi] + "Current setpoint to chillers" + annotation (Placement(transformation(extent={{120,110},{140,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con[nChi]( + final k=fill(0.2, nChi)) "Constant value to avoid zero as the denominator" + annotation (Placement(transformation(extent={{-140,-200},{-120,-180}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] + "Change zero input to a given constant if the chiller is not enabled" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys[nChi]( + final uLow=fill(chiDemRedFac + 0.05 - 0.01, nChi), + final uHigh=fill(chiDemRedFac + 0.05 + 0.01, nChi)) + "Check if actual demand has already reduced at instant when receiving stage change signal" + annotation (Placement(transformation(extent={{0,-150},{20,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div[nChi] + "Output result of first input divided by second input" + annotation (Placement(transformation(extent={{-40,-150},{-20,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nChi] "Logical not" + annotation (Placement(transformation(extent={{40,-150},{60,-130}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd(final nin=nChi) + "Current chillers demand have been lower than 80%" + annotation (Placement(transformation(extent={{80,-150},{100,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-100,180},{-80,200}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nChi) + "Replicate boolean input " + annotation (Placement(transformation(extent={{-100,120},{-80,140}}))); + Buildings.Controls.OBC.CDL.Logical.And finRedDem + "Demand reducing process is done" + annotation (Placement(transformation(extent={{120,20},{140,40}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con2( + final k=chiDemRedFac) + "Demand reducing factor of current operating chillers" + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); + Buildings.Controls.OBC.CDL.Reals.Max max "Maximum value of two real inputs" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep(final nout=nChi) + "Replicate real input" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro[nChi] + "Percentage of the current load" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter addPar[nChi]( + final p=fill(1e-6, nChi)) + "Add a small value to avoid potentially zero denominator" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=holChiDemTim) + "Check if the demand limit has been 5 minutes" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Not requiring reducing demand" + annotation (Placement(transformation(extent={{120,70},{140,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not notReqRed + "Not requiring reduce demand" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + Buildings.Controls.OBC.CDL.Logical.Or notRed + "Not requiring reducing demand" + annotation (Placement(transformation(extent={{0,80},{20,100}}))); + +equation + connect(booRep.y, triSam.trigger) + annotation (Line(points={{-38,190},{-20,190},{-20,140},{10,140},{10,148}}, + color={255,0,255})); + connect(uChiLoa, triSam.u) + annotation (Line(points={{-180,160},{-2,160}}, color={0,0,127})); + connect(uChiLoa, swi4.u3) + annotation (Line(points={{-180,160},{-140,160},{-140,112},{118,112}}, color={0,0,127})); + connect(uChi, swi.u2) + annotation (Line(points={{-180,-140},{-82,-140}}, color={255,0,255})); + connect(con.y, swi.u3) + annotation (Line(points={{-118,-190},{-100,-190},{-100,-148},{-82,-148}}, + color={0,0,127})); + connect(swi.y, div.u2) + annotation (Line(points={{-58,-140},{-50,-140},{-50,-146},{-42,-146}}, + color={0,0,127})); + connect(uChiLoa, div.u1) + annotation (Line(points={{-180,160},{-140,160},{-140,-110},{-50,-110},{-50,-134}, + {-42,-134}}, color={0,0,127})); + connect(div.y, hys.u) + annotation (Line(points={{-18,-140},{-2,-140}}, color={0,0,127})); + connect(hys.y, not1.u) + annotation (Line(points={{22,-140},{38,-140}}, color={255,0,255})); + connect(not1.y, mulAnd.u) + annotation (Line(points={{62,-140},{78,-140}}, color={255,0,255})); + connect(swi4.y,yChiDem) + annotation (Line(points={{142,120},{180,120}}, color={0,0,127})); + connect(uDemLim, edg.u) + annotation (Line(points={{-180,190},{-102,190}}, color={255,0,255})); + connect(edg.y, booRep.u) + annotation (Line(points={{-78,190},{-62,190}}, color={255,0,255})); + connect(uDemLim, booRep1.u) + annotation (Line(points={{-180,190},{-120,190},{-120,130},{-102,130}}, + color={255,0,255})); + connect(booRep1.y, swi4.u2) + annotation (Line(points={{-78,130},{-40,130},{-40,120},{118,120}}, + color={255,0,255})); + connect(uDemLim, finRedDem.u1) annotation (Line(points={{-180,190},{-120,190}, + {-120,30},{118,30}}, color={255,0,255})); + connect(uStaDow, and1.u1) + annotation (Line(points={{-180,-30},{-102,-30}}, color={255,0,255})); + connect(uOnOff, and1.u2) + annotation (Line(points={{-180,-70},{-130,-70},{-130,-38},{-102,-38}}, + color={255,0,255})); + connect(yOpeParLoaRatMin, swi1.u1) + annotation (Line(points={{-180,20},{-60,20},{-60,-22},{-42,-22}}, + color={0,0,127})); + connect(and1.y, swi1.u2) + annotation (Line(points={{-78,-30},{-42,-30}}, color={255,0,255})); + connect(con1.y, swi1.u3) + annotation (Line(points={{-78,-60},{-60,-60},{-60,-38},{-42,-38}}, + color={0,0,127})); + connect(swi1.y, max.u2) + annotation (Line(points={{-18,-30},{-10,-30},{-10,-6},{-2,-6}}, color={0,0,127})); + connect(con2.y, max.u1) + annotation (Line(points={{-18,10},{-10,10},{-10,6},{-2,6}}, + color={0,0,127})); + connect(max.y, reaRep.u) + annotation (Line(points={{22,0},{58,0}}, color={0,0,127})); + connect(triSam.y, pro.u1) + annotation (Line(points={{22,160},{40,160},{40,166},{78,166}}, + color={0,0,127})); + connect(reaRep.y, pro.u2) + annotation (Line(points={{82,0},{90,0},{90,130},{60,130},{60,154},{78,154}}, + color={0,0,127})); + connect(pro.y, swi4.u1) + annotation (Line(points={{102,160},{110,160},{110,128},{118,128}}, + color={0,0,127})); + connect(triSam.y, addPar.u) + annotation (Line(points={{22,160},{40,160},{40,-50},{58,-50}}, + color={0,0,127})); + connect(addPar.y, swi.u1) + annotation (Line(points={{82,-50},{100,-50},{100,-82},{-100,-82},{-100,-132}, + {-82,-132}}, color={0,0,127})); + connect(uDemLim, tim.u) + annotation (Line(points={{-180,190},{-120,190},{-120,-100},{-42,-100}}, + color={255,0,255})); + connect(mulAnd.y, or2.u2) + annotation (Line(points={{102,-140},{110,-140},{110,-108},{118,-108}}, + color={255,0,255})); + connect(or2.y, finRedDem.u2) annotation (Line(points={{142,-100},{150,-100},{150, + -30},{100,-30},{100,22},{118,22}}, color={255,0,255})); + connect(tim.passed, or2.u1) + annotation (Line(points={{-18,-108},{40,-108},{40,-100},{118,-100}}, + color={255,0,255})); + connect(edg.y, lat.clr) annotation (Line(points={{-78,190},{-70,190},{-70,74}, + {118,74}}, color={255,0,255})); + connect(uDemLim, notReqRed.u) annotation (Line(points={{-180,190},{-120,190},{ + -120,90},{-62,90}}, color={255,0,255})); + connect(notReqRed.y, notRed.u1) + annotation (Line(points={{-38,90},{-2,90}}, color={255,0,255})); + connect(finRedDem.y, notRed.u2) annotation (Line(points={{142,30},{150,30},{150, + 50},{-20,50},{-20,82},{-2,82}}, color={255,0,255})); + connect(notRed.y, lat.u) annotation (Line(points={{22,90},{60,90},{60,80},{118, + 80}}, color={255,0,255})); + connect(lat.y, yChiDemRed) + annotation (Line(points={{142,80},{180,80}}, color={255,0,255})); +annotation ( + defaultComponentName="chiDemRed", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-60,60},{60,20}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-52,20},{-40,0}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,20},{52,0}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-60,0},{60,-80}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-15,9.5},{15,-9.5}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + origin={-83,49.5}, + rotation=0, + textString="uChiLoa"), + Text( + extent={{-98,98},{-66,86}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uDemLim"), + Text( + extent={{-18,6.5},{18,-6.5}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + origin={78,42.5}, + rotation=0, + textString="yChiDem"), + Text( + extent={{46,-34},{96,-46}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChiDemRed"), + Text( + extent={{-100,-84},{-76,-94}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChi"), + Text( + extent={{-98,-42},{-74,-56}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uOnOff"), + Text( + extent={{-98,-12},{-64,-28}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaDow"), + Text( + extent={{-23,8.5},{23,-8.5}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + origin={-75,10.5}, + rotation=0, + textString="yOpeParLoaRatMin")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-220},{160,220}})), + Documentation(info=" +

+Block that reduces demand of current operating chillers when there is a stage-up +command, according to ASHRAE Guideline36-2021, +section 5.20.4.16, item a which specifies how to start the stage-up +process of the current operating chillers; and section 5.20.4.17, item a.1 which specifies +how to start the stage-down process of the current operating chiller when the +stage-down process requires one chiller off and another chiller on. +

+

+When there is a stage-up command, +

+ +

+When there is a stage-down command (uStaDow=true) and the process +requires a smaller chiller being enabled and a larger chiller being disabled +(uOnOff=true), +

+ +", +revisions=" + +")); +end ReduceDemand; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo new file mode 100644 index 00000000000..634ecbf2e73 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo @@ -0,0 +1,256 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block ResetMinBypass + "Sequence for minimum chilled water flow setpoint reset" + + parameter Real aftByPasSetTim( + final unit="s", + final quantity="Time") = 60 + "Time after setpoint achieved"; + parameter Real relFloDif=0.01 + "Relative error to the setpoint for checking if it has achieved flow rate setpoint" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of resetting status of device before reset minimum flow setpoint" + annotation (Placement(transformation(extent={{-200,100},{-160,140}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaPro + "Indicate if there is stage change" + annotation (Placement(transformation(extent={{-200,60},{-160,100}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") + "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-200,0},{-160,40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinChiWat_setpoint( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") + "Minimum chiller water flow setpoint" + annotation (Placement(transformation(extent={{-200,-90},{-160,-50}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uSetChaPro + "True: it is in the setpoint change process" + annotation (Placement(transformation(extent={{-200,-130},{-160,-90}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yMinBypRes + "True: minimum chilled water flow bypass valve has been resetted successfully" + annotation (Placement(transformation(extent={{160,-120},{200,-80}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{120,110},{140,130}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=aftByPasSetTim) + "Check if it has been over threshold time after new setpoint achieved" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-80,110},{-60,130}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div + "Flow rate error divided by its setpoint" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter addPar( + final p=1e-6) + "Add a small positive to avoid zero output" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg2 + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + Buildings.Controls.OBC.CDL.Reals.Abs abs "Absolute value" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract floDif + "Checkout the flow rate difference" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 + "Logical and" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not notChaSet + "Not in the setpoint changing process" + annotation (Placement(transformation(extent={{-120,-120},{-100,-100}}))); + Buildings.Controls.OBC.CDL.Logical.And and6 "Logical and" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not notChaSet1 + "Not in the setpoint changing process" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Minimum flow valve should not be changed" + annotation (Placement(transformation(extent={{80,-110},{100,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Check if the valve is being changed" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Edge when the valve has been resetted successfully" + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg3 + "Edge when it starts changing the minimum bypass flow valve" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr( + final t=relFloDif, + final h=0.5*relFloDif) + "Check if chiller water flow rate achieves the minimum flow setpoint" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg4 + "Not in the setpoint changing process" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + +equation + connect(uUpsDevSta, and2.u1) + annotation (Line(points={{-180,120},{-82,120}}, color={255,0,255})); + connect(uStaPro, and2.u2) annotation (Line(points={{-180,80},{-140,80},{-140,112}, + {-82,112}}, color={255,0,255})); + connect(and2.y, and1.u1) + annotation (Line(points={{-58,120},{118,120}}, + color={255,0,255})); + connect(uStaPro, not1.u) annotation (Line(points={{-180,80},{-140,80},{-140,60}, + {-122,60}}, color={255,0,255})); + connect(lat.y, and1.u2) + annotation (Line(points={{102,80},{108,80},{108,112},{118,112}}, + color={255,0,255})); + connect(VMinChiWat_setpoint, addPar.u) + annotation (Line(points={{-180,-70},{-142,-70}}, color={0,0,127})); + connect(not1.y, edg1.u) + annotation (Line(points={{-98,60},{-82,60}}, color={255,0,255})); + connect(edg1.y, lat.clr) + annotation (Line(points={{-58,60},{70,60},{70,74},{78,74}}, + color={255,0,255})); + connect(and3.y, tim.u) + annotation (Line(points={{22,0},{38,0}}, color={255,0,255})); + connect(addPar.y, div.u2) + annotation (Line(points={{-118,-70},{-110,-70},{-110,-56},{-102,-56}}, + color={0,0,127})); + connect(and3.y, edg2.u) + annotation (Line(points={{22,0},{30,0},{30,80},{38,80}}, + color={255,0,255})); + connect(edg2.y, lat.u) + annotation (Line(points={{62,80},{78,80}}, color={255,0,255})); + connect(VChiWat_flow, floDif.u1) + annotation (Line(points={{-180,20},{-140,20},{-140,6},{-122,6}}, color={0,0,127})); + connect(floDif.y, abs.u) + annotation (Line(points={{-98,0},{-82,0}}, color={0,0,127})); + connect(and2.y, and3.u1) + annotation (Line(points={{-58,120},{-10,120},{-10,0},{-2,0}}, + color={255,0,255})); + connect(VMinChiWat_setpoint, floDif.u2) annotation (Line(points={{-180,-70},{-150, + -70},{-150,-6},{-122,-6}}, color={0,0,127})); + connect(tim.passed, and4.u2) + annotation (Line(points={{62,-8},{78,-8}}, color={255,0,255})); + connect(uSetChaPro, notChaSet.u) + annotation (Line(points={{-180,-110},{-122,-110}}, color={255,0,255})); + connect(and2.y, and6.u1) annotation (Line(points={{-58,120},{-10,120},{-10,-40}, + {-2,-40}}, color={255,0,255})); + connect(notChaSet.y, and6.u2) annotation (Line(points={{-98,-110},{-10,-110},{ + -10,-48},{-2,-48}}, color={255,0,255})); + connect(and6.y, notChaSet1.u) + annotation (Line(points={{22,-40},{38,-40}}, color={255,0,255})); + connect(and1.y, and4.u1) annotation (Line(points={{142,120},{150,120},{150,40}, + {70,40},{70,0},{78,0}}, color={255,0,255})); + connect(and4.y, edg.u) + annotation (Line(points={{102,0},{118,0}}, color={255,0,255})); + connect(or2.y, lat1.u) + annotation (Line(points={{102,-100},{118,-100}}, color={255,0,255})); + connect(edg3.y, lat1.clr) annotation (Line(points={{62,-130},{110,-130},{110,-106}, + {118,-106}},color={255,0,255})); + connect(lat1.y, yMinBypRes) + annotation (Line(points={{142,-100},{180,-100}}, color={255,0,255})); + connect(abs.y, div.u1) annotation (Line(points={{-58,0},{-50,0},{-50,-20},{-110, + -20},{-110,-44},{-102,-44}}, color={0,0,127})); + connect(div.y, lesThr.u) + annotation (Line(points={{-78,-50},{-62,-50}}, color={0,0,127})); + connect(lesThr.y, and3.u2) annotation (Line(points={{-38,-50},{-20,-50},{-20,-8}, + {-2,-8}}, color={255,0,255})); + connect(uStaPro, edg3.u) annotation (Line(points={{-180,80},{-30,80},{-30, + -130},{38,-130}}, color={255,0,255})); + connect(notChaSet1.y, edg4.u) + annotation (Line(points={{62,-40},{78,-40}}, color={255,0,255})); + connect(edg4.y, or2.u2) annotation (Line(points={{102,-40},{110,-40},{110,-60}, + {60,-60},{60,-108},{78,-108}}, color={255,0,255})); + connect(edg.y, or2.u1) annotation (Line(points={{142,0},{150,0},{150,-70},{70, + -70},{70,-100},{78,-100}}, color={255,0,255})); +annotation ( + defaultComponentName="minBypRes", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{50,8},{98,-8}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yMinBypRes"), + Text( + extent={{-98,8},{-50,-6}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{-98,-32},{-30,-48}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VMinChiWat_setpoint"), + Text( + extent={{-98,46},{-66,36}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaPro"), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S"), + Text( + extent={{-98,88},{-52,76}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uUpsDevSta"), + Text( + extent={{-96,-72},{-54,-86}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uSetChaPro")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-160},{160,160}})), + Documentation(info=" +

+Block that generates minimum bypass flow reset status when there is +stage-change command. +This development is based on ASHRAE Guideline36-2021, section 5.20.4.16, item b. +

+

+When there is stage-change command (uStaPro = true) and the upstream +device has finished its adjustment process (uUpsDevSta = true), +like in the stage-up process the operating chillers have reduced the demand, +check if the minimum chilled water flow rate VChiWat_flow has achieved +its new set point VMinChiWat_setpoint. +After new setpoint is achieved, wait for 1 minute (byPasSetTim) to +allow loop to stabilize. It will then set yMinBypRes to true. +

+", +revisions=" + +")); +end ResetMinBypass; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/UpEnd.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/UpEnd.mo new file mode 100644 index 00000000000..b1bfa4f486c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/UpEnd.mo @@ -0,0 +1,750 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +block UpEnd "Sequence for ending stage-up process" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Boolean have_parChi=true + "True: the plant has parallel chillers"; + + parameter Real proOnTim( + final unit="s", + final quantity="Time") = 300 + "Threshold time to check if newly enabled chiller being operated by more than 5 minutes" + annotation (Dialog(group="Enable next chiller")); + parameter Real chaChiWatIsoTim( + final unit="s", + final quantity="Time") + "Time to slowly change isolation valve, should be determined in the field" + annotation (Dialog(group="Chilled water isolation valve")); + parameter Real byPasSetTim( + final unit="s", + final quantity="Time") + "Time to slowly reset minimum bypass flow" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real minFloSet[nChi]( + final unit=fill("m3/s", nChi), + final quantity=fill("VolumeFlowRate", nChi), + displayUnit=fill("m3/s", nChi)) + "Minimum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real maxFloSet[nChi]( + final unit=fill("m3/s", nChi), + final quantity=fill("VolumeFlowRate", nChi), + displayUnit=fill("m3/s", nChi)) + "Maximum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real aftByPasSetTim( + final unit="s", + final quantity="Time")=60 + "Time after minimum bypass flow being resetted to new setpoint" + annotation (Dialog(group="Reset bypass")); + parameter Real relFloDif=0.05 + "Relative error to the setpoint for checking if it has achieved flow rate setpoint" + annotation (Dialog(tab="Advanced", group="Reset bypass")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaChi + "Index of next enabling chiller" + annotation (Placement(transformation(extent={{-260,260},{-220,300}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp "Stage-up command" + annotation (Placement(transformation(extent={{-260,230},{-220,270}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaChiWatIsoVal + "Status of chiller chilled water isolation valve control: true=enabled valve is fully open" + annotation (Placement(transformation(extent={{-260,200},{-220,240}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-260,170},{-220,210}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "Indicate if the stage require one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{-260,130},{-220,170}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexDisChi + "Next disabling chiller when there is any stage up that need one chiller on and another off" + annotation (Placement(transformation(extent={{-260,90},{-220,130}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatReq[nChi] + "Chilled water request status for each chiller" + annotation (Placement(transformation(extent={{-260,50},{-220,90}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final unit=fill("1", nChi), + final min=fill(0, nChi), + final max=fill(1, nChi)) "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-260,10},{-220,50}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatReq[nChi] + "Condenser water request status for each chiller" + annotation (Placement(transformation(extent={{-260,-50},{-220,-10}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-260,-80},{-220,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final unit="m3/s") + "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-260,-220},{-220,-180}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinChiWat_setpoint( + final unit="m3/s") + "Minimum chiller water flow setpoint calculated from upstream process" + annotation (Placement(transformation(extent={{-260,-250},{-220,-210}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{220,240},{260,280}}), + iconTransformation(extent={{100,70},{140,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chiller chilled water isolation valve position" + annotation (Placement(transformation(extent={{220,80},{260,120}}), + iconTransformation(extent={{100,30},{140,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiHeaCon[nChi] + "Chiller head pressure control enabling status" + annotation (Placement(transformation(extent={{220,-20},{260,20}}), + iconTransformation(extent={{100,-10},{140,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatMinSet( + final unit="m3/s") "Chilled water minimum flow setpoint" + annotation (Placement(transformation(extent={{220,-100},{260,-60}}), + iconTransformation(extent={{100,-50},{140,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEndSta + "Flag to indicate if the staging process is finished" + annotation (Placement(transformation(extent={{220,-240},{260,-200}}), + iconTransformation(extent={{100,-90},{140,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput endStaTri + "Staging end trigger" + annotation (Placement(transformation(extent={{220,-280},{260,-240}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + +protected + parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableChiller + enaChi( + final nChi=nChi, + final proOnTim=proOnTim) "Enable next chiller" + annotation (Placement(transformation(extent={{-80,220},{-60,240}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal + disChiIsoVal( + final nChi=nChi, + final chaChiWatIsoTim=chaChiWatIsoTim, + final iniValPos=1, + final endValPos=0) + "Disable isolation valve of the chiller being disabled" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + disHeaCon( + final nChi=nChi, + final thrTimEnb=0, + final waiTim=0, + final heaStaCha=false) + "Disable head pressure control of the chiller being disabled" + annotation (Placement(transformation(extent={{60,-20},{80,0}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + minChiWatSet( + final nChi=nChi, + final have_parChi=have_parChi, + final byPasSetTim=byPasSetTim, + final minFloSet=minFloSet, + final maxFloSet=maxFloSet) "Reset minimum chilled water flow setpoint" + annotation (Placement(transformation(extent={{60,-100},{80,-80}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass + minBypSet( + final aftByPasSetTim=aftByPasSetTim, + final relFloDif=relFloDif) + "Check if minimum bypass flow has been resetted" + annotation (Placement(transformation(extent={{60,-220},{80,-200}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 "Logical and" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=true) "True constant" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 "Logical and" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3(final k=false) + "False constant" + annotation (Placement(transformation(extent={{-160,-120},{-140,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-140,140},{-120,160}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanExtractor curDisChi(final nin=nChi) + "Current disabling chiller" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanExtractor curDisChi1(final nin=nChi) + "Current disabling chiller" + annotation (Placement(transformation(extent={{-140,-40},{-120,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{180,-10},{200,10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiWatIso[nChi] + "Chilled water isolation valve" + annotation (Placement(transformation(extent={{180,90},{200,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4 + "Logical switch" + annotation (Placement(transformation(extent={{180,-200},{200,-180}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiWatByp + "Chilled water bypass flow setpoint" + annotation (Placement(transformation(extent={{180,-90},{200,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi5 "Logical switch" + annotation (Placement(transformation(extent={{80,-270},{100,-250}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiWatByp1 + "Chilled water bypass flow setpoint" + annotation (Placement(transformation(extent={{120,-100},{140,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Maintain ON signal when the chiller has been proven on" + annotation (Placement(transformation(extent={{-40,200},{-20,220}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre + "Break algebraic loop" + annotation (Placement(transformation(extent={{140,-270},{160,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Rising edge, output true at the moment when input turns from false to true" + annotation (Placement(transformation(extent={{180,-270},{200,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Maintain ON signal when the chilled water isolation valve has been closed" + annotation (Placement(transformation(extent={{140,20},{160,40}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat3 + "Maintain ON signal when the chiller head pressure control has been disabled" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Check if the disabled chiller is not requiring chilled water" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Check if the disabled chiller is not requiring condenser water" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-60,68},{-40,88}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{-58,-40},{-38,-20}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr( + final t=nChi) "Check if index is in the range" + annotation (Placement(transformation(extent={{20,130},{40,150}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr( + final t=1) "Check if index is in the range" + annotation (Placement(transformation(extent={{20,180},{40,200}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Check if index is in the range" + annotation (Placement(transformation(extent={{60,180},{80,200}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi "Valid index" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Dummy index so the extractor will not have out of range index" + annotation (Placement(transformation(extent={{60,130},{80,150}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat4 "Use the new setpoint" + annotation (Placement(transformation(extent={{60,-140},{80,-120}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg "Staging up process starts" + annotation (Placement(transformation(extent={{-100,-180},{-80,-160}}))); + Buildings.Controls.OBC.CDL.Logical.And and6 "Upstream step is done" + annotation (Placement(transformation(extent={{-60,-140},{-40,-120}}))); + Buildings.Controls.OBC.CDL.Logical.And and7 "Check if the process requires chillers ON and OFF" + annotation (Placement(transformation(extent={{120,-160},{140,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat5 + "Use the setpoint when the process requires chiller ON and OFF" + annotation (Placement(transformation(extent={{180,-160},{200,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Indicate if the stage require one chiller to be enabled while another is disabled" + annotation (Placement(transformation(extent={{-200,140},{-180,160}}))); + +equation + connect(lat.y, not2.u) + annotation (Line(points={{-178,150},{-142,150}}, color={255,0,255})); + connect(nexDisChi, disChiIsoVal.nexChaChi) + annotation (Line(points={{-240,110},{-180,110},{-180,48},{78,48}}, + color={255,127,0})); + connect(uChiWatIsoVal,disChiIsoVal. uChiWatIsoVal) + annotation (Line(points={{-240,30},{70,30},{70,45},{78,45}}, + color={0,0,127})); + connect(and4.y,disChiIsoVal.uUpsDevSta) + annotation (Line(points={{22,80},{50,80},{50,35},{78,35}}, color={255,0,255})); + connect(and5.y, disHeaCon.uUpsDevSta) + annotation (Line(points={{22,-30},{26,-30},{26,-6},{58,-6}}, + color={255,0,255})); + connect(nexDisChi, disHeaCon.nexChaChi) + annotation (Line(points={{-240,110},{-180,110},{-180,-50},{40,-50},{40,-14}, + {58,-14}}, color={255,127,0})); + connect(disHeaCon.uChiHeaCon, uChiHeaCon) + annotation (Line(points={{58,-18},{50,-18},{50,-60},{-240,-60}}, + color={255,0,255})); + connect(con3.y, minChiWatSet.uStaDow) + annotation (Line(points={{-138,-110},{36,-110},{36,-99},{58,-99}}, + color={255,0,255})); + connect(minBypSet.VChiWat_flow, VChiWat_flow) + annotation (Line(points={{58,-210},{0,-210},{0,-200},{-240,-200}}, + color={0,0,127})); + connect(not2.y, booRep4.u) + annotation (Line(points={{-118,150},{-110,150},{-110,100},{38,100}}, + color={255,0,255})); + connect(uChiHeaCon, logSwi3.u1) + annotation (Line(points={{-240,-60},{170,-60},{170,8},{178,8}}, + color={255,0,255})); + connect(disHeaCon.yChiHeaCon, logSwi3.u3) + annotation (Line(points={{82,-16},{140,-16},{140,-8},{178,-8}}, + color={255,0,255})); + connect(logSwi3.y, yChiHeaCon) + annotation (Line(points={{202,0},{240,0}}, color={255,0,255})); + connect(booRep4.y, logSwi3.u2) + annotation (Line(points={{62,100},{130,100},{130,0},{178,0}}, + color={255,0,255})); + connect(booRep4.y, chiWatIso.u2) + annotation (Line(points={{62,100},{178,100}}, color={255,0,255})); + connect(uChiWatIsoVal, chiWatIso.u1) + annotation (Line(points={{-240,30},{70,30},{70,108},{178,108}}, + color={0,0,127})); + connect(disChiIsoVal.yChiWatIsoVal, chiWatIso.u3) + annotation (Line(points={{102,34},{110,34},{110,92},{178,92}}, + color={0,0,127})); + connect(chiWatIso.y, yChiWatIsoVal) + annotation (Line(points={{202,100},{240,100}}, color={0,0,127})); + connect(not2.y, logSwi4.u2) + annotation (Line(points={{-118,150},{-110,150},{-110,-190},{178,-190}}, + color={255,0,255})); + connect(con2.y, logSwi4.u1) + annotation (Line(points={{-38,10},{30,10},{30,-182},{178,-182}}, + color={255,0,255})); + connect(minBypSet.yMinBypRes, logSwi4.u3) + annotation (Line(points={{82,-210},{140,-210},{140,-198},{178,-198}}, + color={255,0,255})); + connect(chiWatByp.y,yChiWatMinSet) + annotation (Line(points={{202,-80},{240,-80}}, color={0,0,127})); + connect(not2.y, logSwi5.u2) + annotation (Line(points={{-118,150},{-110,150},{-110,-260},{78,-260}}, + color={255,0,255})); + connect(logSwi4.y, logSwi5.u3) + annotation (Line(points={{202,-190},{210,-190},{210,-240},{60,-240},{60,-268}, + {78,-268}}, color={255,0,255})); + connect(logSwi5.y, yEndSta) + annotation (Line(points={{102,-260},{120,-260},{120,-220},{240,-220}}, + color={255,0,255})); + connect(nexEnaChi, enaChi.nexEnaChi) + annotation (Line(points={{-240,280},{-106,280},{-106,239},{-82,239}}, + color={255,127,0})); + connect(uStaUp, enaChi.uStaUp) + annotation (Line(points={{-240,250},{-116,250},{-116,236},{-82,236}}, + color={255,0,255})); + connect(uEnaChiWatIsoVal, enaChi.uEnaChiWatIsoVal) + annotation (Line(points={{-240,220},{-180,220},{-180,232},{-82,232}}, + color={255,0,255})); + connect(uChi, enaChi.uChi) + annotation (Line(points={{-240,190},{-150,190},{-150,228},{-82,228}}, + color={255,0,255})); + connect(lat.y, enaChi.uOnOff) annotation (Line(points={{-178,150},{-170,150},{ + -170,224},{-82,224}}, color={255,0,255})); + connect(nexDisChi, enaChi.nexDisChi) + annotation (Line(points={{-240,110},{-90,110},{-90,221},{-82,221}}, + color={255,127,0})); + connect(enaChi.yChi, yChi) + annotation (Line(points={{-58,238},{-20,238},{-20,260},{240,260}}, + color={255,0,255})); + connect(uChi, minChiWatSet.uChi) + annotation (Line(points={{-240,190},{-150,190},{-150,-86},{58,-86}}, + color={255,0,255})); + connect(nexDisChi, minChiWatSet.nexDisChi) + annotation (Line(points={{-240,110},{-180,110},{-180,-91},{58,-91}}, + color={255,127,0})); + connect(lat.y, minChiWatSet.uOnOff) annotation (Line(points={{-178,150},{-170, + 150},{-170,-97},{58,-97}}, color={255,0,255})); + connect(minChiWatSet.yChiWatMinFloSet, minBypSet.VMinChiWat_setpoint) + annotation (Line(points={{82,-90},{96,-90},{96,-112},{50,-112},{50,-214},{58, + -214}}, color={0,0,127})); + connect(con3.y, minChiWatSet.uUpsDevSta) + annotation (Line(points={{-138,-110},{36,-110},{36,-83},{58,-83}}, + color={255,0,255})); + connect(minChiWatSet.yChiWatMinFloSet, chiWatByp1.u1) + annotation (Line(points={{82,-90},{96,-90},{96,-82},{118,-82}}, + color={0,0,127})); + connect(VMinChiWat_setpoint, chiWatByp1.u3) + annotation (Line(points={{-240,-230},{112,-230},{112,-98},{118,-98}}, + color={0,0,127})); + connect(nexEnaChi, minChiWatSet.nexEnaChi) + annotation (Line(points={{-240,280},{-106,280},{-106,-89},{58,-89}}, + color={255,127,0})); + connect(enaChi.yNewChiEna, lat1.u) + annotation (Line(points={{-58,222},{-50,222},{-50,210},{-42,210}}, + color={255,0,255})); + connect(lat1.y, and4.u1) + annotation (Line(points={{-18,210},{-10,210},{-10,80},{-2,80}}, + color={255,0,255})); + connect(lat1.y, minChiWatSet.uStaUp) + annotation (Line(points={{-18,210},{-10,210},{-10,-81},{58,-81}}, + color={255,0,255})); + connect(lat1.y, logSwi5.u1) + annotation (Line(points={{-18,210},{-10,210},{-10,-252},{78,-252}}, + color={255,0,255})); + connect(logSwi5.y, pre.u) + annotation (Line(points={{102,-260},{138,-260}},color={255,0,255})); + connect(pre.y, edg1.u) + annotation (Line(points={{162,-260},{178,-260}}, color={255,0,255})); + connect(edg1.y, endStaTri) + annotation (Line(points={{202,-260},{240,-260}}, color={255,0,255})); + connect(edg1.y, lat1.clr) + annotation (Line(points={{202,-260},{210,-260},{210,-280},{-30,-280},{-30,180}, + {-50,180},{-50,204},{-42,204}}, color={255,0,255})); + connect(disChiIsoVal.yEnaChiWatIsoVal, lat2.u) + annotation (Line(points={{102,46},{120,46},{120,30},{138,30}}, + color={255,0,255})); + connect(lat2.y, and5.u2) + annotation (Line(points={{162,30},{180,30},{180,14},{-20,14},{-20,-38},{-2,-38}}, + color={255,0,255})); + connect(edg1.y, lat2.clr) + annotation (Line(points={{202,-260},{210,-260},{210,-280},{-30,-280},{-30,24}, + {138,24}}, color={255,0,255})); + connect(disHeaCon.yEnaHeaCon, lat3.u) + annotation (Line(points={{82,-4},{110,-4},{110,-40},{118,-40}}, color={255,0,255})); + connect(lat3.y, minChiWatSet.uSubCha) + annotation (Line(points={{142,-40},{160,-40},{160,-54},{40,-54},{40,-94},{58, + -94}}, color={255,0,255})); + connect(lat3.y, minBypSet.uUpsDevSta) + annotation (Line(points={{142,-40},{160,-40},{160,-54},{40,-54},{40,-202},{58, + -202}}, color={255,0,255})); + connect(con3.y, disHeaCon.uEnaPla) + annotation (Line(points={{-138,-110},{36,-110},{36,-2},{58,-2}}, + color={255,0,255})); + connect(uChiWatReq, curDisChi.u) + annotation (Line(points={{-240,70},{-142,70}}, color={255,0,255})); + connect(uConWatReq, curDisChi1.u) + annotation (Line(points={{-240,-30},{-142,-30}}, color={255,0,255})); + connect(curDisChi.y, not1.u) + annotation (Line(points={{-118,70},{-102,70}}, color={255,0,255})); + connect(curDisChi1.y, not3.u) + annotation (Line(points={{-118,-30},{-102,-30}}, color={255,0,255})); + connect(nexDisChi, intLesEquThr.u) annotation (Line(points={{-240,110},{-90,110}, + {-90,140},{18,140}}, color={255,127,0})); + connect(nexDisChi, intGreEquThr.u) annotation (Line(points={{-240,110},{-90,110}, + {-90,190},{18,190}}, color={255,127,0})); + connect(intGreEquThr.y, and2.u1) + annotation (Line(points={{42,190},{58,190}}, color={255,0,255})); + connect(intLesEquThr.y, and2.u2) annotation (Line(points={{42,140},{50,140},{50, + 182},{58,182}}, color={255,0,255})); + connect(and2.y, intSwi.u2) annotation (Line(points={{82,190},{100,190},{100,160}, + {118,160}},color={255,0,255})); + connect(nexDisChi, intSwi.u1) annotation (Line(points={{-240,110},{-90,110},{-90, + 168},{118,168}},color={255,127,0})); + connect(conInt.y, intSwi.u3) annotation (Line(points={{82,140},{110,140},{110, + 152},{118,152}}, color={255,127,0})); + connect(intSwi.y, curDisChi.index) annotation (Line(points={{142,160},{150,160}, + {150,120},{-160,120},{-160,40},{-130,40},{-130,58}}, color={255,127,0})); + connect(intSwi.y, curDisChi1.index) annotation (Line(points={{142,160},{150,160}, + {150,120},{-160,120},{-160,-46},{-130,-46},{-130,-42}}, color={255,127,0})); + connect(not1.y, and1.u2) + annotation (Line(points={{-78,70},{-62,70}}, color={255,0,255})); + connect(and1.y, and4.u2) annotation (Line(points={{-38,78},{-10,78},{-10,72},{ + -2,72}}, color={255,0,255})); + connect(not3.y, and3.u1) + annotation (Line(points={{-78,-30},{-60,-30}}, color={255,0,255})); + connect(and3.y, and5.u1) + annotation (Line(points={{-36,-30},{-2,-30}}, color={255,0,255})); + connect(and2.y, and1.u1) annotation (Line(points={{82,190},{100,190},{100,160}, + {-70,160},{-70,78},{-62,78}},color={255,0,255})); + connect(and2.y, and3.u2) annotation (Line(points={{82,190},{100,190},{100,160}, + {-70,160},{-70,-38},{-60,-38}},color={255,0,255})); + connect(minChiWatSet.yChaSet, minBypSet.uSetChaPro) annotation (Line(points={{82,-98}, + {88,-98},{88,-106},{44,-106},{44,-218},{58,-218}}, color={255,0,255})); + connect(uStaUp, minBypSet.uStaPro) annotation (Line(points={{-240,250},{-116,250}, + {-116,-206},{58,-206}}, color={255,0,255})); + connect(uStaUp, disChiIsoVal.uStaPro) annotation (Line(points={{-240,250},{-116, + 250},{-116,32},{78,32}}, color={255,0,255})); + connect(uStaUp, disHeaCon.uStaPro) annotation (Line(points={{-240,250},{-116,250}, + {-116,-10},{58,-10}}, color={255,0,255})); + connect(uOnOff, lat.u) annotation (Line(points={{-240,150},{-202,150}}, + color={255,0,255})); + connect(edg1.y, lat.clr) annotation (Line(points={{202,-260},{210,-260},{210,-280}, + {-210,-280},{-210,144},{-202,144}}, color={255,0,255})); + connect(edg.y, lat4.clr) annotation (Line(points={{-78,-170},{20,-170},{20,-136}, + {58,-136}}, color={255,0,255})); + connect(edg1.y, lat3.clr) annotation (Line(points={{202,-260},{210,-260},{210, + -280},{-30,-280},{-30,-46},{118,-46}}, color={255,0,255})); + connect(uStaUp, edg.u) annotation (Line(points={{-240,250},{-116,250},{-116,-170}, + {-102,-170}}, color={255,0,255})); + connect(uStaUp, and6.u2) annotation (Line(points={{-240,250},{-116,250},{-116, + -138},{-62,-138}}, color={255,0,255})); + connect(lat3.y, and6.u1) annotation (Line(points={{142,-40},{160,-40},{160,-54}, + {-80,-54},{-80,-130},{-62,-130}}, color={255,0,255})); + connect(and6.y, lat4.u) + annotation (Line(points={{-38,-130},{58,-130}}, color={255,0,255})); + connect(lat4.y, chiWatByp1.u2) annotation (Line(points={{82,-130},{104,-130},{ + 104,-90},{118,-90}}, color={255,0,255})); + connect(and7.y, lat5.u) + annotation (Line(points={{142,-150},{178,-150}}, color={255,0,255})); + connect(edg.y, lat5.clr) annotation (Line(points={{-78,-170},{160,-170},{160,-156}, + {178,-156}}, color={255,0,255})); + connect(lat.y, and7.u1) annotation (Line(points={{-178,150},{-170,150},{-170,-150}, + {118,-150}}, color={255,0,255})); + connect(and6.y, and7.u2) annotation (Line(points={{-38,-130},{0,-130},{0,-158}, + {118,-158}}, color={255,0,255})); + connect(chiWatByp1.y, chiWatByp.u1) annotation (Line(points={{142,-90},{150,-90}, + {150,-72},{178,-72}}, color={0,0,127})); + connect(lat5.y, chiWatByp.u2) annotation (Line(points={{202,-150},{210,-150},{ + 210,-120},{160,-120},{160,-80},{178,-80}}, color={255,0,255})); + connect(VMinChiWat_setpoint, chiWatByp.u3) annotation (Line(points={{-240,-230}, + {170,-230},{170,-88},{178,-88}}, color={0,0,127})); +annotation ( + defaultComponentName="endUp", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-220,-300},{220,300}}), graphics={ + Rectangle( + extent={{-218,78},{218,2}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{72,72},{214,54}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Close chilled water +isolation valve"), + Rectangle( + extent={{-218,-22},{218,-58}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{100,-24},{216,-40}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable head +pressure control"), + Rectangle( + extent={{-218,-202},{218,-298}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-130,-100},{-12,-116}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Reset minimum +bypass setpoint"), + Rectangle( + extent={{-218,-62},{218,-198}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-148,-172},{-32,-180}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="End stage-up process"), + Rectangle( + extent={{-218,278},{218,102}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{68,238},{210,230}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable next chiller")}), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-40,6},{40,-6}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-2,72},{2,6}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,90},{-20,72},{0,72},{20,72},{0,90}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-98,122},{-66,112}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexEnaChi"), + Text( + extent={{-98,104},{-76,92}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uStaUp"), + Text( + extent={{-98,86},{-46,72}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uEnaChiWatIsoVal"), + Text( + extent={{-98,62},{-84,54}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChi"), + Text( + extent={{-98,42},{-76,34}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uOnOff"), + Text( + extent={{-98,24},{-68,14}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexDisChi"), + Text( + extent={{-98,4},{-64,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiWatReq"), + Text( + extent={{-98,-14},{-56,-26}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiWatIsoVal"), + Text( + extent={{-98,-34},{-64,-48}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uConWatReq"), + Text( + extent={{-98,-56},{-64,-70}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiHeaCon"), + Text( + extent={{-98,-74},{-56,-86}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{56,-22},{98,-34}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatMinSet"), + Text( + extent={{72,-62},{96,-74}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yEndSta"), + Text( + extent={{64,18},{98,4}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChiHeaCon"), + Text( + extent={{56,58},{98,46}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatIsoVal"), + Text( + extent={{82,96},{96,88}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yChi"), + Text( + extent={{-98,-90},{-30,-100}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VMinChiWat_setpoint"), + Text( + extent={{68,-82},{96,-96}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="endStaTri")}), +Documentation(info=" +

+Block that controls devices at the ending step of chiller staging up process. +This development is based on ASHRAE Guideline 36-2021, +section 5.20.4.16, item f and g. These sections specify the controls of +devices at the ending step of staging up process. +

+

+For the stage-up process that does not require a smaller chiller being disabled +and a larger chiller being enabled (uOnOff=false), +

+ +

+For any stage change during which a smaller chiller is diabled and a larger chiller +is enabled (uOnOff=true), after starting the next stage chiller +specified above, do following: +

+
    +
  1. +Wait 5 minutes (proOnTim) for the newly enabled chiller to prove that +is operating correctly, then shut off the small chiller (nexDisChi). +This is implemented in block enaChi. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableChiller +for more decriptions. +
  2. +
  3. +When the controller of the smaller chiller being shut off indicates no request +for chilled water flow (uChiWatReq=false), slowly close the chiller's +chilled water isolation valve to avoid a sudden change in flow through other +operating chillers. +This is implemented in block disChiIsoVal. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal +for more decriptions. +
  4. +
  5. +When the controller of the smaller chiller being shut off indicates no request for +condenser water flow (uConWatReq=false), disable the chiller's head +pressure control loop. +This is implemented in block disHeaCon. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl +for more decriptions. +
  6. +
  7. +Change the minimum flow bypass setpoint to that appropriate for the new stage. +This is implemented in block minChiWatSet. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint +for more decriptions. +
  8. +
  9. +Block minBypSet will then check if the new chilled water flow setpoint +has been achieved. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass +for more decriptions. +
  10. +
+", revisions=" + +")); +end UpEnd; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/CHWIsoVal.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/CHWIsoVal.mo new file mode 100644 index 00000000000..fd0a996e131 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/CHWIsoVal.mo @@ -0,0 +1,197 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model CHWIsoVal + "Validate isolation valve enable and disable sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal + enaChiIsoVal( + final nChi=2, + final chaChiWatIsoTim=300, + final iniValPos=0, + final endValPos=1) "Enable isolation valve" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal + disChiIsoVal( + final nChi=2, + final chaChiWatIsoTim=300, + final iniValPos=1, + final endValPos=0) "Disable isolation valve" + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,-80},{-180,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not staCha "Stage change command" + annotation (Placement(transformation(extent={{-160,-80},{-140,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.20, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,-40},{-180,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Not upsDevSta "Upstream device status" + annotation (Placement(transformation(extent={{-160,-40},{-140,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant valOne( + final k=1) "Valve one position, fully open" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaChi( + final k=2) "Enabling chiller index" + annotation (Placement(transformation(extent={{-160,70},{-140,90}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=2) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant valOne1( + final k=1) + "Valve one position, fully open" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disChi( + final k=2) + "Disabling chiller index" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=2) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{160,-20},{180,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Second chiller isolation valve position" + annotation (Placement(transformation(extent={{160,30},{180,50}}))); + +equation + connect(booPul.y, staCha.u) + annotation (Line(points={{-178,-70},{-162,-70}}, color={255,0,255})); + connect(booPul1.y, upsDevSta.u) + annotation (Line(points={{-178,-30},{-162,-30}}, color={255,0,255})); + connect(enaChi.y, enaChiIsoVal.nexChaChi) + annotation (Line(points={{-138,80},{-120,80},{-120,18},{-102,18}}, + color={255,127,0})); + connect(valOne.y, enaChiIsoVal.uChiWatIsoVal[1]) + annotation (Line(points={{-178,20},{-160,20},{-160,14.5},{-102,14.5}}, + color={0,0,127})); + connect(upsDevSta.y, enaChiIsoVal.uUpsDevSta) + annotation (Line(points={{-138,-30},{-120,-30},{-120,5},{-102,5}}, + color={255,0,255})); + connect(staCha.y, enaChiIsoVal.uStaPro) annotation (Line(points={{-138,-70},{-110, + -70},{-110,2},{-102,2}}, color={255,0,255})); + connect(enaChiIsoVal.yChiWatIsoVal[2], zerOrdHol.u) + annotation (Line(points={{-78,4.5},{-70,4.5},{-70,0},{-62,0}}, color={0,0,127})); + connect(zerOrdHol.y, enaChiIsoVal.uChiWatIsoVal[2]) + annotation (Line(points={{-38,0},{-20,0},{-20,60},{-140,60},{-140,15.5},{-102, + 15.5}}, color={0,0,127})); + connect(disChi.y, disChiIsoVal.nexChaChi) + annotation (Line(points={{82,80},{110,80},{110,8},{118,8}}, + color={255,127,0})); + connect(valOne1.y, disChiIsoVal.uChiWatIsoVal[1]) + annotation (Line(points={{42,20},{60,20},{60,4.5},{118,4.5}}, color={0,0,127})); + connect(disChiIsoVal.yChiWatIsoVal[2], zerOrdHol1.u) + annotation (Line(points={{142,-5.5},{150,-5.5},{150,-10},{158,-10}}, + color={0,0,127})); + connect(valOne1.y, swi.u3) + annotation (Line(points={{42,20},{60,20},{60,32},{158,32}}, color={0,0,127})); + connect(zerOrdHol1.y, swi.u1) + annotation (Line(points={{182,-10},{200,-10},{200,20},{150,20},{150,48}, + {158,48}}, color={0,0,127})); + connect(swi.y, disChiIsoVal.uChiWatIsoVal[2]) + annotation (Line(points={{182,40},{200,40},{200,60},{80,60},{80,5.5},{118,5.5}}, + color={0,0,127})); + connect(upsDevSta.y, disChiIsoVal.uUpsDevSta) + annotation (Line(points={{-138,-30},{100,-30},{100,-5},{118,-5}}, + color={255,0,255})); + connect(staCha.y, disChiIsoVal.uStaPro) annotation (Line(points={{-138,-70},{110, + -70},{110,-8},{118,-8}}, color={255,0,255})); + connect(upsDevSta.y, swi.u2) + annotation (Line(points={{-138,-30},{100,-30},{100,40},{158,40}}, + color={255,0,255})); + +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/CHWIsoVal.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal. +

+

+It has two instances enaChiIsoVal and disChiIsoVal that +shows the process of controlling chiller chilled water isolation valves during the +chiller staging process. +

+

+Note that when using the subsequences, +

+ +

+For instance enaChiIsoVal, +

+ +

+For instance disChiIsoVal, +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-120},{220,120}}))); +end CHWIsoVal; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DisableChiller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DisableChiller.mo new file mode 100644 index 00000000000..32dff437abd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DisableChiller.mo @@ -0,0 +1,217 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model DisableChiller + "Validate sequence of disabling chiller during stage-down process" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DisableChiller + chiOnOff( + final nChi=3, + final proOnTim=300) "Disable a chiller and enable another chiller" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DisableChiller + chiOff( + final nChi=3, + final proOnTim=300) "Disable chiller" + annotation (Placement(transformation(extent={{102,70},{122,90}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,50},{-180,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not staCha "Stage change command" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.20, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + Buildings.Controls.OBC.CDL.Logical.Not upsDevSta "Upstream device status" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOne( + final k=true) "Operating chiller one" + annotation (Placement(transformation(extent={{-160,-30},{-140,-10}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaChi(final k=3) + "Enabling chiller index" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiTwo "Chiller two status" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff(final k=true) + "Requires one chiller on and another chiller off" + annotation (Placement(transformation(extent={{-160,-110},{-140,-90}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disChi( + final k=2) "Disabling chiller index" + annotation (Placement(transformation(extent={{-160,-70},{-140,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaChi1(final k=0) + "No Chiller needs to be enabled" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noOnOff(final k=false) + "Does not requires one chiller on and another chiller off" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiTwo1 "Chiller two status" + annotation (Placement(transformation(extent={{140,-50},{160,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noUpDev(final k=false) + "Constant false" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiStaRet[2] + "Chiller status return value" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiStaRet1[2] + "Chiller status return value" + annotation (Placement(transformation(extent={{140,70},{160,90}}))); + +equation + connect(booPul.y, staCha.u) + annotation (Line(points={{-178,60},{-162,60}}, color={255,0,255})); + connect(booPul1.y, upsDevSta.u) + annotation (Line(points={{-178,20},{-162,20}}, color={255,0,255})); + connect(enaChi.y, chiOnOff.nexEnaChi) + annotation (Line(points={{-138,100},{-100,100},{-100,89},{-82,89}}, + color={255,127,0})); + connect(staCha.y, chiOnOff.uStaDow) + annotation (Line(points={{-138,60},{-124,60},{-124,86},{-82,86}}, + color={255,0,255})); + connect(upsDevSta.y, chiOnOff.uEnaChiWatIsoVal) + annotation (Line(points={{-138,20},{-116,20},{-116,82},{-82,82}}, + color={255,0,255})); + connect(chiOne.y, chiOnOff.uChi[1]) + annotation (Line(points={{-138,-20},{-108,-20},{-108,77.3333},{-82,77.3333}}, + color={255,0,255})); + connect(upsDevSta.y, chiTwo.u2) + annotation (Line(points={{-138,20},{-116,20},{-116,-40},{-42,-40}}, + color={255,0,255})); + connect(chiOne.y, chiTwo.u3) + annotation (Line(points={{-138,-20},{-108,-20},{-108,-48},{-42,-48}}, + color={255,0,255})); + connect(chiOnOff.yChi[2], chiStaRet[1].u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + connect(chiOnOff.yChi[3], chiStaRet[2].u) annotation (Line(points={{-58, + 80.6667},{-50,80.6667},{-50,80},{-42,80}}, color={255,0,255})); + connect(chiStaRet[1].y, chiTwo.u1) annotation (Line(points={{-18,80},{-10,80}, + {-10,0},{-50,0},{-50,-32},{-42,-32}}, color={255,0,255})); + connect(chiStaRet[2].y, chiOnOff.uChi[3]) annotation (Line(points={{-18,80},{ + -10,80},{-10,40},{-112,40},{-112,78.6667},{-82,78.6667}}, color={255, + 0,255})); + connect(chiTwo.y, chiOnOff.uChi[2]) + annotation (Line(points={{-18,-40},{-10,-40},{-10,-70},{-120,-70},{-120,78}, + {-82,78}}, color={255,0,255})); + connect(disChi.y, chiOnOff.nexDisChi) + annotation (Line(points={{-138,-60},{-104,-60},{-104,75},{-82,75}}, + color={255,127,0})); + connect(onOff.y, chiOnOff.uOnOff) + annotation (Line(points={{-138,-100},{-100,-100},{-100,71},{-82,71}}, + color={255,0,255})); + connect(enaChi1.y, chiOff.nexEnaChi) + annotation (Line(points={{42,100},{80,100},{80,89},{100,89}}, + color={255,127,0})); + connect(staCha.y, chiOff.uStaDow) + annotation (Line(points={{-138,60},{56,60},{56,86},{100,86}}, + color={255,0,255})); + connect(chiOne.y, chiOff.uChi[1]) + annotation (Line(points={{-138,-20},{64,-20},{64,77.3333},{100,77.3333}}, + color={255,0,255})); + connect(disChi.y, chiOff.nexDisChi) + annotation (Line(points={{-138,-60},{76,-60},{76,75},{100,75}}, + color={255,127,0})); + connect(noOnOff.y, chiOff.uOnOff) + annotation (Line(points={{42,-100},{80,-100},{80,71},{100,71}}, + color={255,0,255})); + connect(chiOff.yChi[2], chiStaRet1[1].u) + annotation (Line(points={{124,80},{138,80}}, color={255,0,255})); + connect(chiOff.yChi[3], chiStaRet1[2].u) annotation (Line(points={{124, + 80.6667},{132,80.6667},{132,80},{138,80}}, color={255,0,255})); + connect(staCha.y, chiTwo1.u2) + annotation (Line(points={{-138,60},{56,60},{56,-40},{138,-40}}, + color={255,0,255})); + connect(chiOne.y, chiTwo1.u3) + annotation (Line(points={{-138,-20},{64,-20},{64,-48},{138,-48}}, + color={255,0,255})); + connect(chiStaRet1[1].y, chiTwo1.u1) annotation (Line(points={{162,80},{170, + 80},{170,-20},{130,-20},{130,-32},{138,-32}}, color={255,0,255})); + connect(chiTwo1.y, chiOff.uChi[2]) + annotation (Line(points={{162,-40},{170,-40},{170,-70},{68,-70}, + {68,78},{100,78}}, color={255,0,255})); + connect(chiStaRet1[2].y, chiOff.uChi[3]) annotation (Line(points={{162,80},{ + 170,80},{170,40},{72,40},{72,78.6667},{100,78.6667}}, color={255,0, + 255})); + connect(noUpDev.y, chiOff.uEnaChiWatIsoVal) + annotation (Line(points={{42,20},{60,20},{60,82},{100,82}}, + color={255,0,255})); + +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DisableChiller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DisableChiller. +It shows the substeps of disabling chillers when the plant is in staging down process. +

+

+The instance chiOnOff shows how to enable and disable chillers when +the staging down process requires one chiller being enabled and another chiller +being disabled. The instance chiOff shows how the chiller being +disable when the staging down process does not require other chiller being enabled. +

+

+For the instance chiOnOff, initially the plant has chiller 1 and 2 +operating. When staging down, it requires chiller 3 being enabled and chiller 2 +being disabled. +

+ +

+For the instance chiOff, initially the plant has chiller 1 and 2 +operating. When staging down, it disables chiller 2. +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-120},{220,120}}))); +end DisableChiller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithOn.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithOn.mo new file mode 100644 index 00000000000..4d0c6ca8787 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithOn.mo @@ -0,0 +1,354 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model DownStartWithOn + "Validate sequence of starting the staging down process which requires enabling a chiller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DownStart + staStaDow1( + final nChi=2, + need_reduceChillerDemand=true, + final byPasSetTim=300, + final minFloSet={1,1}, + final maxFloSet={1.5,1.5}, + final chaChiWatIsoTim=300) + "Chiller stage down when the process does require one chiller on and another chiller off" + annotation (Placement(transformation(extent={{0,130},{20,150}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler demLimRel + "To indicate if the demand limit has been released" + annotation (Placement(transformation(extent={{20,190},{40,210}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.15, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-180,210},{-160,230}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow1 "Stage down command" + annotation (Placement(transformation(extent={{-140,210},{-120,230}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{-100,-250},{-80,-230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerLoa( + final k=0) "Zero load" + annotation (Placement(transformation(extent={{-180,100},{-160,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant yOpeParLoaRatMin1(final k=0.7) + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-180,170},{-160,190}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff1( + final k=true) "Chiller on-off command" + annotation (Placement(transformation(extent={{-180,-30},{-160,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiFlo1( + final k=2) "Chilled water flow" + annotation (Placement(transformation(extent={{-180,10},{-160,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant nexDisChi1( + final k=2) "Next disable chiller" + annotation (Placement(transformation(extent={{-180,-230},{-160,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-180,-270},{-160,-250}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-60,-250},{-40,-230}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta( + final pre_u_start=false) "Break algebraic loop" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiOneLoa "Chiller one" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa2(final k=20) + "Chiller load" + annotation (Placement(transformation(extent={{-180,60},{-160,80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiTwoLoa "Chiller two load" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta( + final pre_u_start=true) "Break algebraic loop" + annotation (Placement(transformation(extent={{80,20},{100,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant nexEnaChi3( + final k=1) "Next enable chiller" + annotation (Placement(transformation(extent={{-180,-70},{-160,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer4(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-180,-110},{-160,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi4 "Logical switch" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpe( + final k=1) "Full open" + annotation (Placement(transformation(extent={{-180,-190},{-160,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerOpe( + final k=0) "Zero open" + annotation (Placement(transformation(extent={{-180,-150},{-160,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiIsoVal2 + "Chilled water isolation valve one" + annotation (Placement(transformation(extent={{-100,-190},{-80,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiIsoVal1 + "Chilled water isolation valve one" + annotation (Placement(transformation(extent={{-100,-150},{-80,-130}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=10) "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{60,150},{80,170}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1[2]( + final samplePeriod=fill(10,2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{120,-120},{140,-100}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiLoa1[2] "Chiller load" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer3[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{60,100},{80,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa3(final k=20) + "Chiller load" + annotation (Placement(transformation(extent={{60,190},{80,210}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2( + final samplePeriod=10) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{160,190},{180,210}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneHea( + final pre_u_start=false) "Break algebraic loop" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoHea( + final pre_u_start=true) "Break algebraic loop" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one( + final k=1) "Constant one" + annotation (Placement(transformation(extent={{-20,190},{0,210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.95, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-180,130},{-160,150}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow2 "Stage down command" + annotation (Placement(transformation(extent={{-140,130},{-120,150}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol3( + final samplePeriod=10) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{160,140},{180,160}}))); + +equation + connect(booPul1.y, staDow1.u) + annotation (Line(points={{-158,220},{-142,220}}, color={255,0,255})); + connect(staDow1.y, swi3.u2) + annotation (Line(points={{-118,220},{-110,220},{-110,-240},{-102,-240}}, + color={255,0,255})); + connect(nexDisChi1.y, swi3.u1) + annotation (Line(points={{-158,-220},{-140,-220},{-140,-232},{-102,-232}}, + color={0,0,127})); + connect(zer2.y, swi3.u3) + annotation (Line(points={{-158,-260},{-140,-260},{-140,-248},{-102,-248}}, + color={0,0,127})); + connect(swi3.y, reaToInt1.u) + annotation (Line(points={{-78,-240},{-62,-240}}, color={0,0,127})); + connect(staDow1.y, chiOneLoa.u2) + annotation (Line(points={{-118,220},{-110,220},{-110,110},{-102,110}}, + color={255,0,255})); + connect(zerLoa.y, chiOneLoa.u3) + annotation (Line(points={{-158,110},{-140,110},{-140,102},{-102,102}}, + color={0,0,127})); + connect(staDow1.y, chiTwoLoa.u2) + annotation (Line(points={{-118,220},{-110,220},{-110,70},{-102,70}}, + color={255,0,255})); + connect(chiLoa2.y, chiTwoLoa.u3) + annotation (Line(points={{-158,70},{-140,70},{-140,62},{-102,62}}, + color={0,0,127})); + connect(staStaDow1.yChi[1], chiOneSta.u) + annotation (Line(points={{22,133.5},{52,133.5},{52,60},{78,60}}, + color={255,0,255})); + connect(staStaDow1.yChi[2], chiTwoSta.u) + annotation (Line(points={{22,134.5},{48,134.5},{48,30},{78,30}}, + color={255,0,255})); + connect(staDow1.y, staStaDow1.uStaDow) + annotation (Line(points={{-118,220},{-110,220},{-110,150},{-2,150}}, + color={255,0,255})); + connect(yOpeParLoaRatMin1.y, staStaDow1.yOpeParLoaRatMin) + annotation (Line(points={{-158,180},{-100,180},{-100,148},{-2,148}}, + color={0,0,127})); + connect(chiOneLoa.y, staStaDow1.uChiLoa[1]) + annotation (Line(points={{-78,110},{-56,110},{-56,145.5},{-2,145.5}}, + color={0,0,127})); + connect(chiTwoLoa.y, staStaDow1.uChiLoa[2]) + annotation (Line(points={{-78,70},{-60,70},{-60,146.5},{-2,146.5}}, + color={0,0,127})); + connect(chiOneSta.y, staStaDow1.uChi[1]) + annotation (Line(points={{102,60},{180,60},{180,0},{-52,0},{-52,143.5},{-2,143.5}}, + color={255,0,255})); + connect(chiTwoSta.y, staStaDow1.uChi[2]) + annotation (Line(points={{102,30},{110,30},{110,4},{-48,4},{-48,144.5},{-2,144.5}}, + color={255,0,255})); + connect(onOff1.y, staStaDow1.uOnOff) + annotation (Line(points={{-158,-20},{-40,-20},{-40,138},{-2,138}}, + color={255,0,255})); + connect(zer4.y, swi4.u3) + annotation (Line(points={{-158,-100},{-140,-100},{-140,-88},{-102,-88}}, + color={0,0,127})); + connect(nexEnaChi3.y, swi4.u1) + annotation (Line(points={{-158,-60},{-140,-60},{-140,-72},{-102,-72}}, + color={0,0,127})); + connect(swi4.y, reaToInt2.u) + annotation (Line(points={{-78,-80},{-62,-80}}, color={0,0,127})); + connect(staDow1.y, swi4.u2) + annotation (Line(points={{-118,220},{-110,220},{-110,-80},{-102,-80}}, + color={255,0,255})); + connect(reaToInt2.y, staStaDow1.nexEnaChi) + annotation (Line(points={{-38,-80},{-36,-80},{-36,136},{-2,136}}, + color={255,127,0})); + connect(fulOpe.y, chiIsoVal2.u3) + annotation (Line(points={{-158,-180},{-140,-180},{-140,-188},{-102,-188}}, + color={0,0,127})); + connect(zerOpe.y, chiIsoVal1.u3) + annotation (Line(points={{-158,-140},{-140,-140},{-140,-148},{-102,-148}}, + color={0,0,127})); + connect(staDow1.y, chiIsoVal1.u2) + annotation (Line(points={{-118,220},{-110,220},{-110,-140},{-102,-140}}, + color={255,0,255})); + connect(staDow1.y, chiIsoVal2.u2) + annotation (Line(points={{-118,220},{-110,220},{-110,-180},{-102,-180}}, + color={255,0,255})); + connect(staStaDow1.yChiWatIsoVal, zerOrdHol1.u) + annotation (Line(points={{22,138},{44,138},{44,-110},{118,-110}}, + color={0,0,127})); + connect(zerOrdHol1[1].y, chiIsoVal1.u1) + annotation (Line(points={{142,-110},{160,-110},{160,-160},{-120,-160}, + {-120,-132},{-102,-132}}, color={0,0,127})); + connect(zerOrdHol1[2].y, chiIsoVal2.u1) + annotation (Line(points={{142,-110},{160,-110},{160,-200},{-120,-200}, + {-120,-172},{-102,-172}}, color={0,0,127})); + connect(chiIsoVal1.y, staStaDow1.uChiWatIsoVal[1]) + annotation (Line(points={{-78,-140},{-24,-140},{-24,131.5},{-2,131.5}}, + color={0,0,127})); + connect(chiIsoVal2.y, staStaDow1.uChiWatIsoVal[2]) + annotation (Line(points={{-78,-180},{-20,-180},{-20,132.5},{-2,132.5}}, + color={0,0,127})); + connect(reaToInt1.y, staStaDow1.nexDisChi) + annotation (Line(points={{-38,-240},{-16,-240},{-16,130},{-2,130}}, + color={255,127,0})); + connect(chiOneSta.y, chiLoa1[1].u2) + annotation (Line(points={{102,60},{180,60},{180,130},{110,130},{110,160}, + {118,160}}, color={255,0,255})); + connect(chiTwoSta.y, chiLoa1[2].u2) + annotation (Line(points={{102,30},{110,30},{110,160},{118,160}}, + color={255,0,255})); + connect(zer3.y, chiLoa1.u3) + annotation (Line(points={{82,110},{100,110},{100,152},{118,152}}, + color={0,0,127})); + connect(staStaDow1.yChiDem[2], zerOrdHol.u) + annotation (Line(points={{22,149.5},{52,149.5},{52,160},{58,160}}, + color={0,0,127})); + connect(zerOrdHol.y, chiLoa1[2].u1) + annotation (Line(points={{82,160},{100,160},{100,168},{118,168}}, + color={0,0,127})); + connect(chiLoa3.y, chiLoa1[1].u1) + annotation (Line(points={{82,200},{100,200},{100,168},{118,168}}, + color={0,0,127})); + connect(chiLoa1[1].y, zerOrdHol2.u) + annotation (Line(points={{142,160},{150,160},{150,200},{158,200}}, + color={0,0,127})); + connect(chiLoa1[2].y, chiTwoLoa.u1) + annotation (Line(points={{142,160},{150,160},{150,10},{-120,10},{-120,78}, + {-102,78}}, color={0,0,127})); + connect(zerOrdHol2.y, chiOneLoa.u1) + annotation (Line(points={{182,200},{190,200},{190,90},{-120,90},{-120,118}, + {-102,118}}, color={0,0,127})); + connect(staStaDow1.yChiHeaCon[1], chiOneHea.u) + annotation (Line(points={{22,141.5},{36,141.5},{36,-20},{58,-20}}, + color={255,0,255})); + connect(staStaDow1.yChiHeaCon[2], chiTwoHea.u) + annotation (Line(points={{22,142.5},{40,142.5},{40,-50},{58,-50}}, + color={255,0,255})); + connect(chiOneHea.y, staStaDow1.uChiHeaCon[1]) + annotation (Line(points={{82,-20},{90,-20},{90,-36},{-32,-36},{-32,133.5},{-2, + 133.5}}, color={255,0,255})); + connect(chiTwoHea.y, staStaDow1.uChiHeaCon[2]) + annotation (Line(points={{82,-50},{90,-50},{90,-70},{-28,-70},{-28,134.5},{-2, + 134.5}},color={255,0,255})); + connect(one.y, demLimRel.u) + annotation (Line(points={{2,200},{18,200}}, color={0,0,127})); + connect(staStaDow1.yReaDemLim, demLimRel.trigger) + annotation (Line(points={{22,131},{30,131},{30,188}}, color={255,0,255})); + connect(booPul2.y, staDow2.u) + annotation (Line(points={{-158,140},{-142,140}}, color={255,0,255})); + connect(staDow2.y, staStaDow1.clr) + annotation (Line(points={{-118,140},{-2,140}}, + color={255,0,255})); + connect(staStaDow1.yChiWatMinFloSet, zerOrdHol3.u) annotation (Line(points={{22, + 146},{154,146},{154,150},{158,150}}, color={0,0,127})); + connect(zerOrdHol3.y, staStaDow1.VChiWat_flow) annotation (Line(points={{182,150}, + {196,150},{196,180},{-20,180},{-20,142},{-2,142}}, color={0,0,127})); +annotation ( + experiment(StopTime=1200, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithOn.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DownStart. +It shows the begining steps when the plant starts staging down. In this example, +the staging down process requires enabling one chiller and disabling another chiller. +

+

+It stages from stage 2, which only has larger chiller enabled (chiller 2), down to +stage 1 which only has smaller chiller enabled (chiller 1). +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-200,-300},{200,300}}), + graphics={ + Text( + extent={{-176,264},{14,248}}, + textColor={0,0,127}, + textString="to stage 1 which only has small chiller enabled (chiller 1)."), + Text( + extent={{-174,276},{14,266}}, + textColor={0,0,127}, + textString="from stage 2 which only has large chiller enabled (chiller 2), "), + Text( + extent={{-184,288},{-136,280}}, + textColor={0,0,127}, + textString="Stage down:")})); +end DownStartWithOn; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithoutOn.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithoutOn.mo new file mode 100644 index 00000000000..12176c600d3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithoutOn.mo @@ -0,0 +1,218 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model DownStartWithoutOn + "Validate sequence of starting the staging down process which does not require enabling a chiller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DownStart + staStaDow( + final nChi=2, + need_reduceChillerDemand=true, + final byPasSetTim=300, + final minFloSet={1,1}, + final maxFloSet={1.5,1.5}, + final chaChiWatIsoTim=300) + "Chiller stage down when the process does not require one chiller on and another chiller off" + annotation (Placement(transformation(extent={{60,190},{80,210}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow "Stage down command" + annotation (Placement(transformation(extent={{-80,210},{-60,230}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOn[2]( + final k=fill(true,2)) + "Operating chiller one" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-40,-250},{-20,-230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa[2]( + final k=fill(1000,2)) "Chiller load" + annotation (Placement(transformation(extent={{-120,130},{-100,150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant nexEnaChi( + final k=0) "Next enabling chiller" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant yOpeParLoaRatMin( + final k=0.7) + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-120,170},{-100,190}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff( + final k=false) "Chiller on-off command" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiFlo( + final k=2) "Chilled water flow" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiHea[2]( + final k=fill(true,2)) + "Chiller head pressure control" + annotation (Placement(transformation(extent={{-120,-150},{-100,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiIsoVal[2]( + final k=fill(1,2)) "Chilled water isolation valve" + annotation (Placement(transformation(extent={{-120,-190},{-100,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant nexDisChi( + final k=2) "Next disable chiller" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-120,-270},{-100,-250}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal[2]( + final k=fill(false,2)) "Constant false" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real input to integer output" + annotation (Placement(transformation(extent={{0,-250},{20,-230}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiStaRet[2]( + final pre_u_start=fill(true, 2)) + "Chiller status return value" + annotation (Placement(transformation(extent={{100,170},{120,190}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[2] "Logical switch" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{-40,130},{-20,150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.95, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow2 + "Stage down command" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + +equation + connect(booPul.y,staDow. u) + annotation (Line(points={{-98,220},{-82,220}}, color={255,0,255})); + connect(staDow.y, swi.u2) + annotation (Line(points={{-58,220},{-50,220},{-50,-240},{-42,-240}}, + color={255,0,255})); + connect(nexDisChi.y, swi.u1) + annotation (Line(points={{-98,-220},{-60,-220},{-60,-232},{-42,-232}}, + color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{-98,-260},{-60,-260},{-60,-248},{-42,-248}}, + color={0,0,127})); + connect(staDow.y, staStaDow.uStaDow) + annotation (Line(points={{-58,220},{-50,220},{-50,210},{58,210}}, + color={255,0,255})); + connect(yOpeParLoaRatMin.y, staStaDow.yOpeParLoaRatMin) + annotation (Line(points={{-98,180},{12,180},{12,208},{58,208}}, + color={0,0,127})); + connect(chiFlo.y, staStaDow.VChiWat_flow) + annotation (Line(points={{-98,-20},{24,-20},{24,202},{58,202}}, + color={0,0,127})); + connect(onOff.y, staStaDow.uOnOff) + annotation (Line(points={{-98,-60},{32,-60},{32,198},{58,198}}, + color={255,0,255})); + connect(nexEnaChi.y, staStaDow.nexEnaChi) + annotation (Line(points={{-98,-100},{36,-100},{36,196},{58,196}}, + color={255,127,0})); + connect(swi.y, reaToInt.u) + annotation (Line(points={{-18,-240},{-2,-240}}, color={0,0,127})); + connect(reaToInt.y, staStaDow.nexDisChi) + annotation (Line(points={{22,-240},{48,-240},{48,190},{58,190}}, + color={255,127,0})); + connect(staStaDow.yChi, chiStaRet.u) + annotation (Line(points={{82,194},{90,194},{90,180},{98,180}}, color={255,0,255})); + connect(chiStaRet.y, swi1.u2) + annotation (Line(points={{122,180},{130,180},{130,160},{-60,160},{-60,140}, + {-42,140}}, color={255,0,255})); + connect(chiLoa.y, swi1.u1) + annotation (Line(points={{-98,140},{-90,140},{-90,148},{-42,148}}, + color={0,0,127})); + connect(zer1.y, swi1.u3) + annotation (Line(points={{-98,100},{-80,100},{-80,132},{-42,132}}, + color={0,0,127})); + connect(chiStaRet.y, logSwi.u2) + annotation (Line(points={{122,180},{130,180},{130,160},{-60,160},{-60,60}, + {-42,60}}, color={255,0,255})); + connect(chiOn.y, logSwi.u1) + annotation (Line(points={{-98,60},{-90,60},{-90,68},{-42,68}}, + color={255,0,255})); + connect(fal.y, logSwi.u3) + annotation (Line(points={{-98,20},{-70,20},{-70,52},{-42,52}}, + color={255,0,255})); + connect(swi1.y, staStaDow.uChiLoa) + annotation (Line(points={{-18,140},{16,140},{16,206},{58,206}}, + color={0,0,127})); + connect(logSwi.y, staStaDow.uChi) + annotation (Line(points={{-18,60},{20,60},{20,204},{58,204}}, + color={255,0,255})); + connect(chiHea.y, staStaDow.uChiHeaCon) + annotation (Line(points={{-98,-140},{40,-140},{40,194},{58,194}}, + color={255,0,255})); + connect(chiIsoVal.y, staStaDow.uChiWatIsoVal) + annotation (Line(points={{-98,-180},{44,-180},{44,192},{58,192}}, + color={0,0,127})); + connect(booPul2.y, staDow2.u) + annotation (Line(points={{82,100},{98,100}}, color={255,0,255})); + connect(staDow2.y, staStaDow.clr) + annotation (Line(points={{122,100},{130,100},{130,150},{28,150},{28,200}, + {58,200}}, color={255,0,255})); + +annotation ( + experiment(StopTime=1200, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithoutOn.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.DownStart. +It shows the begining steps when the plant starts staging down. In this example, +the staging down process does not require enabling one chiller and disabling +another chiller. +

+

+It stages from stage 2, which has both chiller 1 and chiller 2 enabled, down to +stage 1 which only has chiller 1 enabled. +

+ +

+The chiller head pressure control, the chilled water isolation valve and the +chilled water minimum flow setpoint will be controlled in the down process after +this down begining process. +

+", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-140,-300},{140,300}}), + graphics={ + Text( + extent={{-122,288},{-74,280}}, + textColor={0,0,127}, + textString="Stage down:"), + Text( + extent={{-114,276},{46,266}}, + textColor={0,0,127}, + textString="from stage 2 which has chiller one and two enabled, "), + Text( + extent={{-116,264},{-14,250}}, + textColor={0,0,127}, + textString="to stage 1 which only has chiller 1.")})); +end DownStartWithoutOn; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableCWPump.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableCWPump.mo new file mode 100644 index 00000000000..49b70d706b9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableCWPump.mo @@ -0,0 +1,184 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model EnableCWPump + "Validate sequence of generating stage index for CW pump control" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump + staUpInd "Generating chiller stage index when there is stage up command" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump + staDowInd "Generating chiller stage index when there is stage down command" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Switch curSta + "Current chiller stage setpoint" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt[2] + "Real input to integer output" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Switch curSta1 + "Current chiller stage setpoint" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1[2] + "Real input to integer output" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not staCha "Stage change command" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.20, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not upsDevSta "Upstream device status" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal( + final k=false) + "No stage change" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staTwo( + final k=2) "Chiller stage index" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staOne( + final k=1) "Chiller stage index" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + +equation + connect(booPul.y, staCha.u) + annotation (Line(points={{-78,40},{-62,40}}, color={255,0,255})); + connect(booPul1.y, upsDevSta.u) + annotation (Line(points={{-78,80},{-62,80}}, color={255,0,255})); + connect(upsDevSta.y, staUpInd.uUpsDevSta) + annotation (Line(points={{-38,80},{-20,80},{-20,68},{-2,68}}, + color={255,0,255})); + connect(staCha.y, staUpInd.uStaUp) + annotation (Line(points={{-38,40},{-30,40},{-30,62},{-2,62}}, + color={255,0,255})); + connect(fal.y, staUpInd.uStaDow) + annotation (Line(points={{-38,0},{-20,0},{-20,58},{-2,58}}, + color={255,0,255})); + connect(upsDevSta.y, staDowInd.uUpsDevSta) + annotation (Line(points={{-38,80},{60,80},{60,68},{78,68}}, + color={255,0,255})); + connect(fal.y, staDowInd.uStaUp) + annotation (Line(points={{-38,0},{60,0},{60,62},{78,62}}, + color={255,0,255})); + connect(staCha.y, staDowInd.uStaDow) + annotation (Line(points={{-38,40},{66,40},{66,58},{78,58}}, + color={255,0,255})); + connect(staCha.y, curSta.u2) + annotation (Line(points={{-38,40},{-30,40},{-30,-40},{-22,-40}}, + color={255,0,255})); + connect(staTwo.y, curSta.u1) + annotation (Line(points={{-78,-60},{-60,-60},{-60,-32},{-22,-32}}, + color={0,0,127})); + connect(staOne.y, curSta.u3) + annotation (Line(points={{-78,-20},{-40,-20},{-40,-48},{-22,-48}}, + color={0,0,127})); + connect(staCha.y, curSta1.u2) + annotation (Line(points={{-38,40},{-30,40},{-30,-80},{-22,-80}}, + color={255,0,255})); + connect(staTwo.y, curSta1.u3) + annotation (Line(points={{-78,-60},{-60,-60},{-60,-88},{-22,-88}}, + color={0,0,127})); + connect(staOne.y, curSta1.u1) + annotation (Line(points={{-78,-20},{-40,-20},{-40,-72},{-22,-72}}, + color={0,0,127})); + connect(staOne.y, reaToInt[1].u) + annotation (Line(points={{-78,-20},{18,-20}}, color={0,0,127})); + connect(curSta.y, reaToInt[2].u) + annotation (Line(points={{2,-40},{10,-40},{10,-20},{18,-20}}, color={0,0,127})); + connect(reaToInt[1].y, staUpInd.uChiSta) + annotation (Line(points={{42,-20},{50,-20},{50,20},{-10,20},{-10,55},{-2,55}}, + color={255,127,0})); + connect(reaToInt[2].y, staUpInd.uStaSet) + annotation (Line(points={{42,-20},{50,-20},{50,20},{-10,20},{-10,51},{-2,51}}, + color={255,127,0})); + connect(staTwo.y, reaToInt1[1].u) + annotation (Line(points={{-78,-60},{18,-60}}, color={0,0,127})); + connect(curSta1.y, reaToInt1[2].u) + annotation (Line(points={{2,-80},{10,-80},{10,-60},{18,-60}}, color={0,0,127})); + connect(reaToInt1[1].y, staDowInd.uChiSta) + annotation (Line(points={{42,-60},{72,-60},{72,55},{78,55}}, color={255,127,0})); + connect(reaToInt1[2].y, staDowInd.uStaSet) + annotation (Line(points={{42,-60},{72,-60},{72,51},{78,51}}, color={255,127,0})); + +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableCWPump.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump. +

+

+It has two instances staUpInd and staDowInd, which shows +the calculation of the chiller stage index in the staging up and staging down process. +

+

+For the instance staUpInd, +

+ +

+For the instance staDowInd, +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-120,-100},{120,100}}))); +end EnableCWPump; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableChiller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableChiller.mo new file mode 100644 index 00000000000..620aebe71c7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableChiller.mo @@ -0,0 +1,204 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model EnableChiller + "Validate sequence of enabling and disabling chiller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableChiller + enaDisChi(final nChi=3) "Enable larger chiller and disable smaller chiller" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableChiller + enaOneChi(final nChi=3) "Enable additional chiller" + annotation (Placement(transformation(extent={{100,70},{120,90}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,50},{-180,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.20, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiIsoVal + "Chilled water isolation valve resetting status" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaChi(final k=3) + "Enabling chiller index" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOne(final k=true) + "Operating chiller one" + annotation (Placement(transformation(extent={{-160,-30},{-140,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff(final k=true) + "Requires one chiller on and another chiller off" + annotation (Placement(transformation(extent={{-160,-70},{-140,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disChi(final k=2) + "Disabling chiller index" + annotation (Placement(transformation(extent={{-160,-110},{-140,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiStaRet[2] + "Chiller status return value" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiTwo "Chiller two status" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiStaRet1 + "Chiller status return value" + annotation (Placement(transformation(extent={{140,70},{160,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noOnOff(final k=false) + "Does not requires one chiller on and another chiller off" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disChi1(final k=0) + "Disabling chiller index" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-178,60},{-162,60}}, color={255,0,255})); + connect(booPul1.y,chiIsoVal. u) + annotation (Line(points={{-178,20},{-162,20}}, color={255,0,255})); + connect(enaChi.y, enaDisChi.nexEnaChi) + annotation (Line(points={{-138,100},{-120,100},{-120,89},{-82,89}}, + color={255,127,0})); + connect(staUp.y, enaDisChi.uStaUp) + annotation (Line(points={{-138,60},{-120,60},{-120,86},{-82,86}}, + color={255,0,255})); + connect(chiIsoVal.y, enaDisChi.uEnaChiWatIsoVal) + annotation (Line(points={{-138,20},{-116,20},{-116,82},{-82,82}}, + color={255,0,255})); + connect(chiOne.y, enaDisChi.uChi[1]) + annotation (Line(points={{-138,-20},{-112,-20},{-112,77.3333},{-82,77.3333}}, + color={255,0,255})); + connect(chiIsoVal.y, chiTwo.u2) + annotation (Line(points={{-138,20},{-116,20},{-116,-40},{-42,-40}}, + color={255,0,255})); + connect(chiStaRet[1].y, chiTwo.u1) + annotation (Line(points={{-18,80},{0,80},{0,0},{-60,0},{-60,-32},{-42,-32}}, + color={255,0,255})); + connect(chiOne.y, chiTwo.u3) + annotation (Line(points={{-138,-20},{-112,-20},{-112,-48},{-42,-48}}, + color={255,0,255})); + connect(chiTwo.y, enaDisChi.uChi[2]) + annotation (Line(points={{-18,-40},{0,-40},{0,-70},{-108,-70},{-108,78}, + {-82,78}}, color={255,0,255})); + connect(enaDisChi.yChi[2], chiStaRet[1].u) + annotation (Line(points={{-58,88},{-50,88},{-50,80},{-42,80}}, + color={255,0,255})); + connect(enaDisChi.yChi[3], chiStaRet[2].u) + annotation (Line(points={{-58,88.6667},{-50,88.6667},{-50,80},{-42,80}}, + color={255,0,255})); + connect(chiStaRet[2].y, enaDisChi.uChi[3]) + annotation (Line(points={{-18,80},{0,80},{0,40},{-104,40},{-104,78.6667},{ + -82,78.6667}}, + color={255,0,255})); + connect(onOff.y, enaDisChi.uOnOff) + annotation (Line(points={{-138,-60},{-100,-60},{-100,74},{-82,74}}, + color={255,0,255})); + connect(disChi.y, enaDisChi.nexDisChi) + annotation (Line(points={{-138,-100},{-96,-100},{-96,71},{-82,71}}, + color={255,127,0})); + connect(enaChi.y, enaOneChi.nexEnaChi) + annotation (Line(points={{-138,100},{40,100},{40,89},{98,89}}, + color={255,127,0})); + connect(staUp.y, enaOneChi.uStaUp) + annotation (Line(points={{-138,60},{40,60},{40,86},{98,86}}, + color={255,0,255})); + connect(chiIsoVal.y, enaOneChi.uEnaChiWatIsoVal) + annotation (Line(points={{-138,20},{44,20},{44,82},{98,82}}, + color={255,0,255})); + connect(chiOne.y, enaOneChi.uChi[1]) + annotation (Line(points={{-138,-20},{48,-20},{48,77.3333},{98,77.3333}}, + color={255,0,255})); + connect(chiOne.y, enaOneChi.uChi[2]) + annotation (Line(points={{-138,-20},{48,-20},{48,78},{98,78}}, + color={255,0,255})); + connect(noOnOff.y, enaOneChi.uOnOff) + annotation (Line(points={{42,-60},{56,-60},{56,74},{98,74}}, + color={255,0,255})); + connect(disChi1.y, enaOneChi.nexDisChi) + annotation (Line(points={{42,-100},{60,-100},{60,71},{98,71}}, + color={255,127,0})); + connect(enaOneChi.yChi[3], chiStaRet1.u) + annotation (Line(points={{122,88.6667},{130,88.6667},{130,80},{138,80}}, + color={255,0,255})); + connect(chiStaRet1.y, enaOneChi.uChi[3]) + annotation (Line(points={{162,80},{180,80},{180,40},{52,40},{52,78.6667},{ + 98,78.6667}}, + color={255,0,255})); + +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableChiller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableChiller. +

+

+The example has two instances enaDisChi and enaOneChi, +which shows the sub-processes of enabling chillers when the plant is in staging up +process. For the instance enaDisChi, the process requires chiller 3 +being enabled and chiller 2 being disabled, while for the instance +enaOneChi, the process just requires chiller 3 being enabled. +

+

+For the instance enaDisChi, +

+ + +

+For the instance enaOneChi, +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-140},{220,140}}))); +end EnableChiller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/HeadControl.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/HeadControl.mo new file mode 100644 index 00000000000..51a08ade5bc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/HeadControl.mo @@ -0,0 +1,355 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model HeadControl + "Validate sequence of enabling and disabling head pressure control loop" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + enaHeaCon( + final nChi=2) + "Enable head pressure control after condenser water pump reset" + annotation (Placement(transformation(extent={{-40,130},{-20,150}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + disHeaCon( + final nChi=2, + final thrTimEnb=0, + final waiTim=0, + final heaStaCha=false) + "Disable head pressure control of smaller chiller when the stage-up requires large chiller on and small chiller off" + annotation (Placement(transformation(extent={{60,130},{80,150}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + disHeaCon1( + final nChi=2, + final thrTimEnb=0, + final waiTim=0, + final heaStaCha=false) + "Disable head pressure control of the chiller being disabled" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + enaHeaCon1( + final nChi=2, + final thrTimEnb=0, + final waiTim=30, + final heaStaCha=true) + "Disable head pressure control of smaller chiller when the stage-up requires large chiller on and small chiller off" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,110},{-120,130}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-100,110},{-80,130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.20, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,150},{-120,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev + "Upstream device reset status" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOne( + final k=true) "Operating chiller one" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaChi(final k=2) + "Enabling chiller index" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.Pre heaPreConRet + "Return value of chiller head pressure control status" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disChi(final k=2) + "Disabling small chiller" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + Buildings.Controls.OBC.CDL.Logical.Pre heaPreConRet1 + "Return value of chiller head pressure control status" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiTwo "Chiller two status" + annotation (Placement(transformation(extent={{140,70},{160,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.15, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,-110},{-120,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp1 "Stage up command" + annotation (Placement(transformation(extent={{-100,-110},{-80,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3( + final width=0.20, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,-70},{-120,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev1 "Upstream device reset status" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOne1(final k=true) + "Operating chiller one" + annotation (Placement(transformation(extent={{-100,-190},{-80,-170}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disChi1(final k=2) + "Disabling chiller index" + annotation (Placement(transformation(extent={{-100,-160},{-80,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Pre heaPreConRet2 + "Return value of chiller head pressure control status" + annotation (Placement(transformation(extent={{0,-130},{20,-110}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaChi1( + final k=2) "Enabling small chiller" + annotation (Placement(transformation(extent={{60,-126},{80,-106}}))); + Buildings.Controls.OBC.CDL.Logical.Pre heaPreConRet3 + "Return value of chiller head pressure control status" + annotation (Placement(transformation(extent={{140,-130},{160,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiTwo1 "Chiller two status" + annotation (Placement(transformation(extent={{40,-150},{60,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant enaPla( + final k=false) + "Plant is just enabled" + annotation (Placement(transformation(extent={{-140,0},{-120,20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant enaPla1( + final k=false) + "Plant is just enabled" + annotation (Placement(transformation(extent={{-140,-210},{-120,-190}}))); +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-118,120},{-102,120}}, color={255,0,255})); + connect(booPul1.y, upStrDev.u) + annotation (Line(points={{-118,160},{-102,160}}, color={255,0,255})); + connect(upStrDev.y, enaHeaCon.uUpsDevSta) + annotation (Line(points={{-78,160},{-60,160},{-60,144},{-42,144}}, + color={255,0,255})); + connect(staUp.y, enaHeaCon.uStaPro) annotation (Line(points={{-78,120},{-60,120}, + {-60,140},{-42,140}}, color={255,0,255})); + connect(enaChi.y, enaHeaCon.nexChaChi) + annotation (Line(points={{-78,60},{-56,60},{-56,136},{-42,136}}, + color={255,127,0})); + connect(chiOne.y, enaHeaCon.uChiHeaCon[1]) + annotation (Line(points={{-78,30},{-52,30},{-52,131.5},{-42,131.5}}, + color={255,0,255})); + connect(enaHeaCon.yChiHeaCon[2], heaPreConRet.u) annotation (Line(points={{-18, + 134.5},{-10,134.5},{-10,100},{-2,100}}, color={255,0,255})); + connect(heaPreConRet.y, enaHeaCon.uChiHeaCon[2]) annotation (Line(points={{22,100}, + {30,100},{30,84},{-48,84},{-48,132.5},{-42,132.5}}, color={255,0,255})); + connect(upStrDev.y, disHeaCon.uUpsDevSta) + annotation (Line(points={{-78,160},{40,160},{40,144},{58,144}}, + color={255,0,255})); + connect(staUp.y, disHeaCon.uStaPro) annotation (Line(points={{-78,120},{40,120}, + {40,140},{58,140}}, color={255,0,255})); + connect(disChi.y, disHeaCon.nexChaChi) + annotation (Line(points={{22,60},{44,60},{44,136},{58,136}}, + color={255,127,0})); + connect(chiOne.y, disHeaCon.uChiHeaCon[1]) + annotation (Line(points={{-78,30},{48,30},{48,131.5},{58,131.5}}, + color={255,0,255})); + connect(disHeaCon.yChiHeaCon[2], heaPreConRet1.u) annotation (Line(points={{82, + 134.5},{90,134.5},{90,100},{98,100}}, color={255,0,255})); + connect(staUp.y, chiTwo.u2) + annotation (Line(points={{-78,120},{-60,120},{-60,80},{138,80}}, + color={255,0,255})); + connect(heaPreConRet1.y, chiTwo.u1) annotation (Line(points={{122,100},{130,100}, + {130,88},{138,88}}, color={255,0,255})); + connect(chiOne.y, chiTwo.u3) + annotation (Line(points={{-78,30},{120,30},{120,72},{138,72}}, + color={255,0,255})); + connect(chiTwo.y, disHeaCon.uChiHeaCon[2]) + annotation (Line(points={{162,80},{170,80},{170,60},{52,60},{52,132.5},{58,132.5}}, + color={255,0,255})); + connect(booPul2.y, staUp1.u) + annotation (Line(points={{-118,-100},{-102,-100}}, color={255,0,255})); + connect(booPul3.y, upStrDev1.u) + annotation (Line(points={{-118,-60},{-102,-60}}, color={255,0,255})); + connect(upStrDev1.y, disHeaCon1.uUpsDevSta) + annotation (Line(points={{-78,-60},{-60,-60},{-60,-76},{-42,-76}}, + color={255,0,255})); + connect(staUp1.y, disHeaCon1.uStaPro) annotation (Line(points={{-78,-100},{-60, + -100},{-60,-80},{-42,-80}}, color={255,0,255})); + connect(disChi1.y, disHeaCon1.nexChaChi) + annotation (Line(points={{-78,-150},{-56,-150},{-56,-84},{-42,-84}}, + color={255,127,0})); + connect(chiOne1.y, disHeaCon1.uChiHeaCon[1]) + annotation (Line(points={{-78,-180},{-52,-180},{-52,-88.5},{-42,-88.5}}, + color={255,0,255})); + connect(disHeaCon1.yChiHeaCon[2], heaPreConRet2.u) annotation (Line(points={{-18, + -85.5},{-10,-85.5},{-10,-120},{-2,-120}}, color={255,0,255})); + connect(enaHeaCon1.yChiHeaCon[2], heaPreConRet3.u) annotation (Line(points={{122, + -85.5},{130,-85.5},{130,-120},{138,-120}}, color={255,0,255})); + connect(staUp1.y, chiTwo1.u2) + annotation (Line(points={{-78,-100},{-60,-100},{-60,-140},{38,-140}}, + color={255,0,255})); + connect(heaPreConRet2.y, chiTwo1.u1) annotation (Line(points={{22,-120},{30,-120}, + {30,-132},{38,-132}}, color={255,0,255})); + connect(chiOne1.y, chiTwo1.u3) + annotation (Line(points={{-78,-180},{-52,-180},{-52,-148},{38,-148}}, + color={255,0,255})); + connect(chiTwo1.y, disHeaCon1.uChiHeaCon[2]) + annotation (Line(points={{62,-140},{70,-140},{70,-170},{-48,-170},{-48,-87.5}, + {-42,-87.5}}, color={255,0,255})); + connect(upStrDev1.y, enaHeaCon1.uUpsDevSta) + annotation (Line(points={{-78,-60},{80,-60},{80,-76},{98,-76}}, + color={255,0,255})); + connect(staUp1.y, enaHeaCon1.uStaPro) annotation (Line(points={{-78,-100},{80, + -100},{80,-80},{98,-80}}, color={255,0,255})); + connect(enaChi1.y, enaHeaCon1.nexChaChi) + annotation (Line(points={{82,-116},{84,-116},{84,-84},{98,-84}}, + color={255,127,0})); + connect(chiOne1.y, enaHeaCon1.uChiHeaCon[1]) + annotation (Line(points={{-78,-180},{88,-180},{88,-88.5},{98,-88.5}}, + color={255,0,255})); + connect(heaPreConRet3.y, enaHeaCon1.uChiHeaCon[2]) + annotation (Line(points={{162,-120},{170,-120},{170,-150},{92,-150},{92,-87.5}, + {98,-87.5}}, color={255,0,255})); + connect(enaPla.y, enaHeaCon.uEnaPla) annotation (Line(points={{-118,10},{-64,10}, + {-64,148},{-42,148}}, color={255,0,255})); + connect(enaPla.y, disHeaCon.uEnaPla) annotation (Line(points={{-118,10},{36,10}, + {36,148},{58,148}}, color={255,0,255})); + connect(enaPla1.y, disHeaCon1.uEnaPla) annotation (Line(points={{-118,-200},{-64, + -200},{-64,-72},{-42,-72}}, color={255,0,255})); + connect(enaPla1.y, enaHeaCon1.uEnaPla) annotation (Line(points={{-118,-200},{34, + -200},{34,-72},{98,-72}}, color={255,0,255})); +annotation ( + experiment(StopTime=120, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/HeadControl.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl. +It has four instances as below to demonstrate the process of chiller head pressure +control when the plant is in staging process. +

+

+The instance enaHeaCon shows the head pressure control when the plant +is in staging up process and it will enable chiller 2 (nexChaChi=2). +

+ +

+The instance disHeaCon shows the head pressure control when the plant +is in staging up process and it requires enabling a large chiller and disabling a +small chiller. In this case, it disables chiller 2 (nexChaChi=2). +

+ +

+The instance disHeaCon1 shows the head pressure control when the plant +is in staging down process and it requires disabling chiller 2 +(nexChaChi=2). +

+ +

+The instance enaHeaCon1 shows the head pressure control when the plant +is in staging down process and it requires disabling a large chiller and enabling +a small chiller. In this case, it enables chiller 2 (nexChaChi=2). +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-220},{180,220}}), + graphics={ + Text( + extent={{-138,194},{-4,174}}, + textColor={0,0,127}, + textString="enable head pressure control of the chiler being enabled."), + Text( + extent={{-140,202},{-52,186}}, + textColor={0,0,127}, + textString="after resetting condenser water pump,"), + Text( + extent={{44,190},{124,176}}, + textColor={0,0,127}, + textString="disable its head pressure control."), + Text( + extent={{44,200},{122,186}}, + textColor={0,0,127}, + textString="after small chiller being shut off,"), + Text( + extent={{-140,210},{-92,200}}, + textColor={0,0,127}, + textString="In stage up process,"), + Text( + extent={{44,210},{166,200}}, + textColor={0,0,127}, + textString="In stage up process that requires chillers on and off,"), + Text( + extent={{-146,-8},{-98,-18}}, + textColor={0,0,127}, + textString="In stage down process,"), + Text( + extent={{-146,-16},{-58,-32}}, + textColor={0,0,127}, + textString="after the disabling chiller being shut off,"), + Text( + extent={{-146,-28},{-72,-38}}, + textColor={0,0,127}, + textString="disable its head pressure control."), + Text( + extent={{42,-18},{120,-32}}, + textColor={0,0,127}, + textString="after minimum bypass being reset,"), + Text( + extent={{42,-8},{164,-18}}, + textColor={0,0,127}, + textString="In stage down process that requires chillers on and off,"), + Text( + extent={{44,-26},{174,-44}}, + textColor={0,0,127}, + textString="enable head pressure control of the chiler being enabled.")})); +end HeadControl; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/NextChiller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/NextChiller.mo new file mode 100644 index 00000000000..dc1a275fb8a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/NextChiller.mo @@ -0,0 +1,481 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model NextChiller + "Validate sequence of identifying next enable or disable chillers" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi + "Identify next enabling and disabling chiller during the staging up process" + annotation (Placement(transformation(extent={{-60,170},{-40,190}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi1 "Identify next enabling during the staging up process" + annotation (Placement(transformation(extent={{240,170},{260,190}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi2 + "Identify next enabling and disabling chiller during the staging down process" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi3 "Identify next disabling chiller during the staging down process" + annotation (Placement(transformation(extent={{240,-150},{260,-130}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Switch chiSet[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{-140,90},{-120,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch inPro + "Check if it is in the staging process" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet1[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{160,90},{180,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch inPro1 + "Check if it is in the staging process" + annotation (Placement(transformation(extent={{160,30},{180,50}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet2[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{-140,-230},{-120,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Switch inPro2 + "Check if it is in the staging process" + annotation (Placement(transformation(extent={{-140,-290},{-120,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet3[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{160,-230},{180,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Switch inPro3 + "Check if it is in the staging process" + annotation (Placement(transformation(extent={{160,-290},{180,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-260,150},{-240,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-220,150},{-200,170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi[2]( + final k={true,false}) "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{-260,70},{-240,90}}))); + CDL.Integers.Sources.Constant upSta( + final k=2) "Stage two" + annotation (Placement(transformation(extent={{-260,230},{-240,250}}))); + CDL.Integers.Sources.Constant dowSta( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-260,190},{-240,210}}))); + CDL.Integers.Switch intSwi + "Logical switch" + annotation (Placement(transformation(extent={{-180,210},{-160,230}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi[2]( + final k={false,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{-260,110},{-240,130}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-180,90},{-160,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul4( + final width=0.5, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-260,30},{-240,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant endPro(final k=true) + "Not in the process" + annotation (Placement(transformation(extent={{-220,10},{-200,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.15, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{40,150},{60,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp1 "Stage up command" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi1[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant upSta1( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{40,230},{60,250}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant dowSta1( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{40,190},{60,210}}))); + CDL.Integers.Switch intSwi3 + "Logical switch" + annotation (Placement(transformation(extent={{120,210},{140,230}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi1[2]( + final k={true,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{40,110},{60,130}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=2) + "Replicate boolean input" + annotation (Placement(transformation(extent={{120,90},{140,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul5( + final width=0.5, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant endPro1(final k=true) + "Process is end" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.15, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-260,-170},{-240,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow "Stage down command" + annotation (Placement(transformation(extent={{-220,-170},{-200,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi2[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{-260,-210},{-240,-190}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant upSta2( + final k=2) "Stage two" + annotation (Placement(transformation(extent={{-260,-130},{-240,-110}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant dowSta2( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-260,-90},{-240,-70}}))); + CDL.Integers.Switch intSwi1 + "Logical switch" + annotation (Placement(transformation(extent={{-180,-110},{-160,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi2[2]( + final k={false,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{-260,-250},{-240,-230}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=2) "Replicate boolean input" + annotation (Placement(transformation(extent={{-180,-230},{-160,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul6( + final width=0.5, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{-260,-290},{-240,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant endPro2(final k=true) + "Not in the process" + annotation (Placement(transformation(extent={{-220,-310},{-200,-290}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3( + final width=0.15, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{40,-170},{60,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow1 "Stage down command" + annotation (Placement(transformation(extent={{80,-170},{100,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi3[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{40,-210},{60,-190}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant upSta3( + final k=2) "Stage two" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant dowSta3( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 + "Logical switch" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi3[2]( + final k={true,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{40,-250},{60,-230}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=2) "Replicate boolean input" + annotation (Placement(transformation(extent={{120,-230},{140,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul7( + final width=0.5, + final period=120) "Boolean pulse" + annotation (Placement(transformation(extent={{40,-290},{60,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant endPro3(final k=true) + "Not in the process" + annotation (Placement(transformation(extent={{80,-310},{100,-290}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not" + annotation (Placement(transformation(extent={{-220,50},{-200,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-220,-270},{-200,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Not not4 "Logical not" + annotation (Placement(transformation(extent={{80,-270},{100,-250}}))); +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-238,160},{-222,160}}, color={255,0,255})); + connect(staUp.y, intSwi.u2) annotation (Line(points={{-198,160},{-190,160},{-190, + 220},{-182,220}}, color={255,0,255})); + connect(staUp.y, booRep.u) annotation (Line(points={{-198,160},{-190,160},{-190, + 100},{-182,100}}, color={255,0,255})); + connect(booRep.y, chiSet.u2) + annotation (Line(points={{-158,100},{-142,100}}, color={255,0,255})); + connect(staUp.y, inPro.u2) annotation (Line(points={{-198,160},{-190,160},{-190, + 40},{-142,40}}, color={255,0,255})); + connect(chiSet.y, nexChi.uChiSet) annotation (Line(points={{-118,100},{-100,100}, + {-100,180},{-62,180}}, color={255,0,255})); + connect(inPro.y,nexChi.endPro) annotation (Line(points={{-118,40},{-80,40},{-80, + 173},{-62,173}}, color={255,0,255})); + connect(booPul1.y, staUp1.u) + annotation (Line(points={{62,160},{78,160}}, color={255,0,255})); + connect(staUp1.y, intSwi3.u2) annotation (Line(points={{102,160},{110,160},{ + 110,220},{118,220}}, color={255,0,255})); + connect(dowSta1.y, intSwi3.u3) annotation (Line(points={{62,200},{80,200},{80, + 212},{118,212}}, color={0,0,127})); + connect(upSta1.y, intSwi3.u1) annotation (Line(points={{62,240},{80,240},{80, + 228},{118,228}}, color={0,0,127})); + connect(staUp1.y, booRep1.u) annotation (Line(points={{102,160},{110,160},{110, + 100},{118,100}}, color={255,0,255})); + connect(booRep1.y, chiSet1.u2) + annotation (Line(points={{142,100},{158,100}}, color={255,0,255})); + connect(staUp1.y, inPro1.u2) annotation (Line(points={{102,160},{110,160},{110, + 40},{158,40}}, color={255,0,255})); + connect(endPro1.y, inPro1.u3) annotation (Line(points={{102,20},{140,20},{140, + 32},{158,32}}, color={255,0,255})); + connect(chiSet1.y, nexChi1.uChiSet) annotation (Line(points={{182,100},{200,100}, + {200,180},{238,180}}, color={255,0,255})); + connect(inPro1.y,nexChi1.endPro) annotation (Line(points={{182,40},{220,40},{ + 220,173},{238,173}}, color={255,0,255})); + connect(booPul2.y, staDow.u) + annotation (Line(points={{-238,-160},{-222,-160}}, color={255,0,255})); + connect(staDow.y, intSwi1.u2) annotation (Line(points={{-198,-160},{-190,-160}, + {-190,-100},{-182,-100}}, color={255,0,255})); + connect(staDow.y, booRep2.u) annotation (Line(points={{-198,-160},{-190,-160}, + {-190,-220},{-182,-220}}, color={255,0,255})); + connect(staOneChi2.y, chiSet2.u1) annotation (Line(points={{-238,-200},{-150,-200}, + {-150,-212},{-142,-212}}, color={255,0,255})); + connect(booRep2.y, chiSet2.u2) + annotation (Line(points={{-158,-220},{-142,-220}}, color={255,0,255})); + connect(staTwoChi2.y, chiSet2.u3) annotation (Line(points={{-238,-240},{-148,-240}, + {-148,-228},{-142,-228}}, color={255,0,255})); + connect(staDow.y, inPro2.u2) annotation (Line(points={{-198,-160},{-190,-160}, + {-190,-280},{-142,-280}}, color={255,0,255})); + connect(endPro2.y, inPro2.u3) annotation (Line(points={{-198,-300},{-160,-300}, + {-160,-288},{-142,-288}}, color={255,0,255})); + connect(chiSet2.y, nexChi2.uChiSet) annotation (Line(points={{-118,-220},{-100, + -220},{-100,-140},{-62,-140}}, color={255,0,255})); + connect(inPro2.y,nexChi2.endPro) annotation (Line(points={{-118,-280},{-80,-280}, + {-80,-147},{-62,-147}}, color={255,0,255})); + connect(dowSta2.y, intSwi1.u1) annotation (Line(points={{-238,-80},{-200,-80}, + {-200,-92},{-182,-92}}, color={0,0,127})); + connect(upSta2.y, intSwi1.u3) annotation (Line(points={{-238,-120},{-200,-120}, + {-200,-108},{-182,-108}}, color={0,0,127})); + connect(staTwoChi.y, chiSet.u1) annotation (Line(points={{-238,120},{-150,120}, + {-150,108},{-142,108}}, color={255,0,255})); + connect(staOneChi.y, chiSet.u3) annotation (Line(points={{-238,80},{-150,80},{ + -150,92},{-142,92}}, color={255,0,255})); + connect(staTwoChi1.y, chiSet1.u1) annotation (Line(points={{62,120},{150,120}, + {150,108},{158,108}}, color={255,0,255})); + connect(staOneChi1.y, chiSet1.u3) annotation (Line(points={{62,80},{150,80},{150, + 92},{158,92}}, color={255,0,255})); + connect(booPul3.y, staDow1.u) + annotation (Line(points={{62,-160},{78,-160}}, color={255,0,255})); + connect(staDow1.y, intSwi2.u2) annotation (Line(points={{102,-160},{110,-160}, + {110,-100},{118,-100}}, color={255,0,255})); + connect(staDow1.y, booRep3.u) annotation (Line(points={{102,-160},{110,-160},{ + 110,-220},{118,-220}}, color={255,0,255})); + connect(staOneChi3.y, chiSet3.u1) annotation (Line(points={{62,-200},{150,-200}, + {150,-212},{158,-212}}, color={255,0,255})); + connect(booRep3.y, chiSet3.u2) + annotation (Line(points={{142,-220},{158,-220}}, color={255,0,255})); + connect(staTwoChi3.y, chiSet3.u3) annotation (Line(points={{62,-240},{150, + -240},{150,-228},{158,-228}}, + color={255,0,255})); + connect(staDow1.y, inPro3.u2) annotation (Line(points={{102,-160},{110,-160},{ + 110,-280},{158,-280}}, color={255,0,255})); + connect(endPro3.y, inPro3.u3) annotation (Line(points={{102,-300},{140,-300}, + {140,-288},{158,-288}}, color={255,0,255})); + connect(chiSet3.y, nexChi3.uChiSet) annotation (Line(points={{182,-220},{200,-220}, + {200,-140},{238,-140}}, color={255,0,255})); + connect(inPro3.y,nexChi3.endPro) annotation (Line(points={{182,-280},{220,-280}, + {220,-147},{238,-147}}, color={255,0,255})); + connect(dowSta3.y, intSwi2.u1) annotation (Line(points={{62,-80},{100,-80},{ + 100,-92},{118,-92}}, color={0,0,127})); + connect(upSta3.y, intSwi2.u3) annotation (Line(points={{62,-120},{100,-120},{ + 100,-108},{118,-108}}, color={0,0,127})); + + connect(intSwi.y, nexChi.uStaSet) annotation (Line(points={{-158,220},{-80,220}, + {-80,187},{-62,187}}, color={255,127,0})); + connect(upSta.y, intSwi.u1) annotation (Line(points={{-238,240},{-220,240},{-220, + 228},{-182,228}}, color={255,127,0})); + connect(dowSta.y, intSwi.u3) annotation (Line(points={{-238,200},{-220,200},{-220, + 212},{-182,212}}, color={255,127,0})); + connect(intSwi3.y, nexChi1.uStaSet) annotation (Line(points={{142,220},{220, + 220},{220,187},{238,187}}, color={255,127,0})); + connect(intSwi2.y, nexChi3.uStaSet) annotation (Line(points={{142,-100},{220, + -100},{220,-133},{238,-133}}, color={255,127,0})); + connect(intSwi1.y, nexChi2.uStaSet) annotation (Line(points={{-158,-100},{-80, + -100},{-80,-133},{-62,-133}}, color={255,127,0})); + connect(booPul4.y, not3.u) annotation (Line(points={{-238,40},{-230,40},{-230, + 60},{-222,60}}, color={255,0,255})); + connect(endPro.y, inPro.u3) annotation (Line(points={{-198,20},{-160,20},{ + -160,32},{-142,32}}, color={255,0,255})); + connect(not3.y, inPro.u1) annotation (Line(points={{-198,60},{-160,60},{-160, + 48},{-142,48}}, color={255,0,255})); + connect(booPul5.y, not1.u) annotation (Line(points={{62,40},{70,40},{70,60},{ + 78,60}}, color={255,0,255})); + connect(not1.y, inPro1.u1) annotation (Line(points={{102,60},{140,60},{140,48}, + {158,48}}, color={255,0,255})); + connect(booPul6.y, not2.u) annotation (Line(points={{-238,-280},{-230,-280},{ + -230,-260},{-222,-260}}, color={255,0,255})); + connect(not2.y, inPro2.u1) annotation (Line(points={{-198,-260},{-160,-260},{ + -160,-272},{-142,-272}}, color={255,0,255})); + connect(booPul7.y, not4.u) annotation (Line(points={{62,-280},{70,-280},{70, + -260},{78,-260}}, color={255,0,255})); + connect(not4.y, inPro3.u1) annotation (Line(points={{102,-260},{140,-260},{ + 140,-272},{158,-272}}, color={255,0,255})); +annotation ( + experiment(StopTime=120, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/NextChiller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller. +

+

+It has four instances as below to demonstrate the process of identifying next +changing chiller(s) when the plant is in staging process. +

+

+The instance nexChi shows how the changing chillers being identified +in a staging up process that requires a large chiller being enabled and a small +chiller being disabled. The plant stages up from stage 1 that requires chiller 1 +operating to stage 2 that requires chiller 2 operating. +

+ + +

+The instance nexChi1 shows how the changing chillers being identified +in a staging up process that requires one additional chiller being enabled. The +plant stages up from stage 1 that requires chiller 1 operating to stage 2 that +requires both chiller 1 and chiller 2 operating. +

+ + +

+The instance nexChi2 shows how the changing chillers being identified +in a staging down process that requires a large chiller being disabled and a small +chiller being enabled. The plant stages down from stage 2 that requires chiller 2 +operating to stage 1 that requires chiller 1 operating. +

+ + +

+The instance nexChi3 shows how the changing chillers being identified +in a staging down process that requires one additional chiller being disabled. The +plant stages down from stage 2 that requires both chiller 1 and chiller 2 operating +to stage 1 that requires just chiller 1 operating. +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-280,-320},{280,320}}), + graphics={ + Text( + extent={{-258,292},{-146,280}}, + textColor={0,0,127}, + textString="In stage up process (stage 1 to 2),"), + Text( + extent={{-254,278},{-94,266}}, + textColor={0,0,127}, + textString="requires small chiller (1) off and large chiller (2) on."), + Text( + extent={{64,278},{228,268}}, + textColor={0,0,127}, + textString="add one more chiller (1) on top of current chiller (2)."), + Text( + extent={{62,292},{174,280}}, + textColor={0,0,127}, + textString="In stage up process (stage 2 to 3),"), + Text( + extent={{-256,-40},{-96,-52}}, + textColor={0,0,127}, + textString="requires large chiller (2) off and small chiller (1) on."), + Text( + extent={{-260,-26},{-140,-36}}, + textColor={0,0,127}, + textString="In stage down process (stage 2 to 1),"), + Text( + extent={{58,-42},{130,-52}}, + textColor={0,0,127}, + textString="disable chiller (2)."), + Text( + extent={{62,-28},{182,-38}}, + textColor={0,0,127}, + textString="In stage down process (stage 2 to 1),")})); +end NextChiller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ReduceDemand.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ReduceDemand.mo new file mode 100644 index 00000000000..f258a60579b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ReduceDemand.mo @@ -0,0 +1,250 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model ReduceDemand + "Validate sequence of reducing chiller demand when there is stage up command" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand + chiDemRed( + final nChi=2) + "Reduce operaing chiller load as the first step of stage up process" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand + chiDemRed1( + final nChi=2) + "Reduce operaing chiller load as the first step of stage down process when it requires another chiller on" + annotation (Placement(transformation(extent={{200,50},{220,70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, final period=600) "Boolean pulse" + annotation (Placement(transformation(extent={{-260,90},{-240,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not limDem "Limit demand command" + annotation (Placement(transformation(extent={{-220,90},{-200,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOn( + final k=true) "Operating chiller one" + annotation (Placement(transformation(extent={{-260,-150},{-240,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa(final k=50) + "Chiller load" + annotation (Placement(transformation(extent={{-260,50},{-240,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerLoa( + final k=0) "Zero chiller load" + annotation (Placement(transformation(extent={{-260,10},{-240,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant yOpeParLoaRatMin( + final k=0.7) + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-260,-30},{-240,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staDow( + final k=false) "Stage down command" + annotation (Placement(transformation(extent={{-260,-70},{-240,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff( + final k=false) "Chiller on-off command" + annotation (Placement(transformation(extent={{-260,-110},{-240,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.15, final period=600) + "Boolean pulse" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not limDem1 "Limit demand command" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiOn1[2]( + final k=fill(true,2)) "Operating chiller one" + annotation (Placement(transformation(extent={{40,-150},{60,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{140,-50},{160,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa1(final k=50) + "Chiller load" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant yOpeParLoaRatMin1( + final k=0.7) + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{40,-100},{60,-80}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=20) + "Output the input signal with zero order hold" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1[2]( + final samplePeriod=fill(20,2)) + "Output the input signal with zero order hold" + annotation (Placement(transformation(extent={{240,40},{260,60}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) "Replicate boolean input" + annotation (Placement(transformation(extent={{140,20},{160,40}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=2) "Replicate real input" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + +equation + connect(booPul.y, limDem.u) + annotation (Line(points={{-238,100},{-222,100}}, color={255,0,255})); + connect(limDem.y, chiDemRed.uDemLim) + annotation (Line(points={{-198,100},{-180,100},{-180,119},{-102,119}}, + color={255,0,255})); + connect(chiDemRed.yChiDem[1], zerOrdHol.u) + annotation (Line(points={{-78,113.5},{-70,113.5},{-70,100},{-62,100}}, + color={0,0,127})); + connect(limDem.y, swi.u2) + annotation (Line(points={{-198,100},{-180,100},{-180,60},{-162,60}}, + color={255,0,255})); + connect(chiLoa.y, swi.u3) + annotation (Line(points={{-238,60},{-190,60},{-190,52},{-162,52}}, + color={0,0,127})); + connect(zerOrdHol.y, swi.u1) + annotation (Line(points={{-38,100},{-30,100},{-30,80},{-170,80},{-170,68}, + {-162,68}}, color={0,0,127})); + connect(swi.y, chiDemRed.uChiLoa[1]) + annotation (Line(points={{-138,60},{-130,60},{-130,114.5},{-102,114.5}}, + color={0,0,127})); + connect(zerLoa.y, chiDemRed.uChiLoa[2]) + annotation (Line(points={{-238,20},{-126,20},{-126,115.5},{-102,115.5}}, + color={0,0,127})); + connect(yOpeParLoaRatMin.y, chiDemRed.yOpeParLoaRatMin) + annotation (Line(points={{-238,-20},{-122,-20},{-122,111},{-102,111}}, + color={0,0,127})); + connect(staDow.y, chiDemRed.uStaDow) + annotation (Line(points={{-238,-60},{-118,-60},{-118,108},{-102,108}}, + color={255,0,255})); + connect(onOff.y, chiDemRed.uOnOff) + annotation (Line(points={{-238,-100},{-114,-100},{-114,105},{-102,105}}, + color={255,0,255})); + connect(chiOn.y, chiDemRed.uChi[1]) + annotation (Line(points={{-238,-140},{-110,-140},{-110,100.5},{-102,100.5}}, + color={255,0,255})); + connect(onOff.y, chiDemRed.uChi[2]) + annotation (Line(points={{-238,-100},{-106,-100},{-106,101.5},{-102,101.5}}, + color={255,0,255})); + connect(booPul1.y, limDem1.u) + annotation (Line(points={{62,100},{78,100}}, color={255,0,255})); + connect(limDem1.y, chiDemRed1.uDemLim) + annotation (Line(points={{102,100},{120,100},{120,69},{198,69}}, + color={255,0,255})); + connect(yOpeParLoaRatMin1.y, chiDemRed1.yOpeParLoaRatMin) + annotation (Line(points={{62,-90},{178,-90},{178,61},{198,61}}, + color={0,0,127})); + connect(chiDemRed1.yChiDem, zerOrdHol1.u) + annotation (Line(points={{222,64},{230,64},{230,50},{238,50}}, + color={0,0,127})); + connect(chiLoa1.y, reaRep.u) + annotation (Line(points={{62,-40},{78,-40}}, color={0,0,127})); + connect(booRep.y, swi1.u2) + annotation (Line(points={{162,30},{170,30},{170,10},{120,10},{120,-40}, + {138,-40}}, color={255,0,255})); + connect(reaRep.y, swi1.u3) + annotation (Line(points={{102,-40},{110,-40},{110,-48},{138,-48}}, + color={0,0,127})); + connect(zerOrdHol1.y, swi1.u1) + annotation (Line(points={{262,50},{270,50},{270,-10},{130,-10},{130,-32}, + {138,-32}}, color={0,0,127})); + connect(swi1.y, chiDemRed1.uChiLoa) + annotation (Line(points={{162,-40},{174,-40},{174,65},{198,65}}, + color={0,0,127})); + connect(limDem1.y, booRep.u) + annotation (Line(points={{102,100},{120,100},{120,30},{138,30}}, + color={255,0,255})); + connect(limDem1.y, chiDemRed1.uStaDow) + annotation (Line(points={{102,100},{120,100},{120,58},{198,58}}, + color={255,0,255})); + connect(limDem1.y, chiDemRed1.uOnOff) + annotation (Line(points={{102,100},{120,100},{120,55},{198,55}}, + color={255,0,255})); + connect(chiOn1.y, chiDemRed1.uChi) + annotation (Line(points={{62,-140},{182,-140},{182,51},{198,51}}, + color={255,0,255})); + +annotation ( + experiment(StopTime=600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ReduceDemand.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand. +

+

+It has two instances as below to demonstrate the process of reducing chiller demand +when the plant is in staging process. +

+

+The instance chiDemRed shows the process of reducing the chiller +demand when the plant starts staging up. +

+ + +

+The instance chiDemRed1 shows the process of reducing the chiller +demand when the plant starts staging up. The process requires enabling a large +chiller and disabling a small chiller. +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-280,-160},{280,160}}), + graphics={ + Text( + extent={{-258,152},{-184,142}}, + textColor={0,0,127}, + textString="In stage up process,"), + Text( + extent={{-258,138},{-166,128}}, + textColor={0,0,127}, + textString="enable one more chiller."), + Text( + extent={{38,136},{130,126}}, + textColor={0,0,127}, + textString="enable enabling chiller."), + Text( + extent={{42,152},{244,140}}, + textColor={0,0,127}, + textString="In stage down process that requires chiller on and off,")})); +end ReduceDemand; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo new file mode 100644 index 00000000000..c0d7ee56670 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo @@ -0,0 +1,117 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model ResetMinBypass + "Validate sequence of reseting minimum flow bypass" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass + minBypRes + "Check if the setpoint has achieved" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.15, + final period=600) "Boolean pulse" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev + "Upstream device reset status" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.2, + final period=600) "Boolean pulse" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp minFloSet( + final height=0.5, + final duration=60, + final offset=1, + final startTime=120) "Minimum chiller water flow setpoint" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp meaFlo( + final height=0.5, + final duration=80, + final offset=1, + final startTime=120) "Measured chiller water flow" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev1 + "Upstream device reset status" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + +equation + connect(booPul2.y, upStrDev.u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + connect(booPul1.y, staUp.u) + annotation (Line(points={{-58,40},{-42,40}}, color={255,0,255})); + connect(upStrDev.y, minBypRes.uUpsDevSta) + annotation (Line(points={{-18,80},{0,80},{0,8},{18,8}}, color={255,0,255})); + connect(staUp.y, minBypRes.uStaPro) annotation (Line(points={{-18,40},{-10,40}, + {-10,4},{18,4}}, color={255,0,255})); + connect(meaFlo.y, minBypRes.VChiWat_flow) + annotation (Line(points={{-18,0},{18,0}}, color={0,0,127})); + connect(minFloSet.y, minBypRes.VMinChiWat_setpoint) + annotation (Line(points={{-18,-40},{0,-40},{0,-4},{18,-4}}, color={0,0,127})); + connect(upStrDev.y, upStrDev1.u) annotation (Line(points={{-18,80},{0,80},{0,20}, + {-50,20},{-50,-80},{-42,-80}}, color={255,0,255})); + connect(upStrDev1.y, minBypRes.uSetChaPro) + annotation (Line(points={{-18,-80},{10,-80},{10,-8},{18,-8}}, color={255,0,255})); + +annotation ( + experiment(StopTime=600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass. +

+

+The instance minBypRes shows the process of changing the bypass valve +when the minimum bypass chilled water flow setpoint has been changed when the +plant is in a staging up process. +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-120},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end ResetMinBypass; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithOff.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithOff.mo new file mode 100644 index 00000000000..9c8c193d67c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithOff.mo @@ -0,0 +1,271 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model UpEndWithOff + "Validate sequence of end staging up process which requires chiller OFF" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.UpEnd + endUp1( + final nChi=2, + final chaChiWatIsoTim=300, + final byPasSetTim=300, + final minFloSet={0.5,1}, + final maxFloSet={1,1.5}) + "End staging up process which does require one chiller on and another chiller off" + annotation (Placement(transformation(extent={{60,150},{80,170}}))); + +protected + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant nexEnaChi1(final k=2) + "Next enable chiller" + annotation (Placement(transformation(extent={{-180,170},{-160,190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-180,130},{-160,150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3( + final width=0.15, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-180,80},{-160,100}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp1 "Stage up command" + annotation (Placement(transformation(extent={{-140,80},{-120,100}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev1 "Upstream device status" + annotation (Placement(transformation(extent={{-140,40},{-120,60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul4( + final width=0.20, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-180,40},{-160,60}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta1(final pre_u_start=true) + "Chiller one status" + annotation (Placement(transformation(extent={{140,120},{160,140}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta1(final pre_u_start=false) + "Chiller two status" + annotation (Placement(transformation(extent={{140,80},{160,100}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer4(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-180,-40},{-160,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant nexDisChi2(final k=1) + "Next disable chiller" + annotation (Placement(transformation(extent={{-180,0},{-160,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpe(final k=1) + "Full open" + annotation (Placement(transformation(extent={{-180,-80},{-160,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiIsoVal1 + "Chilled water isolation valve one" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1[2]( + final samplePeriod=fill(10, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{140,-20},{160,0}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant enaHeaCon(final k=true) + "Enable head pressure control" + annotation (Placement(transformation(extent={{-180,-170},{-160,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiOneHeaCon + "Chiller one head pressure control" + annotation (Placement(transformation(extent={{-100,-170},{-80,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneHea1(final pre_u_start=true) + "Chiller one head pressure control" + annotation (Placement(transformation(extent={{140,-130},{160,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlo1(final k=1) + "Chilled water flow rate" + annotation (Placement(transformation(extent={{-180,-210},{-160,-190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlo2(final k=1.667) + "Minimum chilled water flow setpoint calculated from upstream process" + annotation (Placement(transformation(extent={{-180,-250},{-160,-230}}))); + +equation + connect(booPul3.y, staUp1.u) + annotation (Line(points={{-158,90},{-142,90}}, color={255,0,255})); + connect(booPul4.y, upStrDev1.u) + annotation (Line(points={{-158,50},{-142,50}}, color={255,0,255})); + connect(nexEnaChi1.y, swi1.u1) + annotation (Line(points={{-158,180},{-140,180},{-140,168},{-102,168}}, + color={0,0,127})); + connect(zer1.y, swi1.u3) + annotation (Line(points={{-158,140},{-140,140},{-140,152},{-102,152}}, + color={0,0,127})); + connect(swi1.y, reaToInt1.u) + annotation (Line(points={{-78,160},{-62,160}}, color={0,0,127})); + connect(staUp1.y, swi1.u2) + annotation (Line(points={{-118,90},{-110,90},{-110,160},{-102,160}}, + color={255,0,255})); + connect(reaToInt1.y, endUp1.nexEnaChi) + annotation (Line(points={{-38,160},{-20,160},{-20,172},{58,172}}, + color={255,127,0})); + connect(staUp1.y, endUp1.uStaUp) + annotation (Line(points={{-118,90},{-16,90},{-16,170},{58,170}}, + color={255,0,255})); + connect(upStrDev1.y, endUp1.uEnaChiWatIsoVal) + annotation (Line(points={{-118,50},{-12,50},{-12,168},{58,168}}, + color={255,0,255})); + connect(endUp1.yChi[1], chiOneSta1.u) + annotation (Line(points={{82,168.5},{128,168.5},{128,130},{138,130}}, + color={255,0,255})); + connect(endUp1.yChi[2], chiTwoSta1.u) + annotation (Line(points={{82,169.5},{130,169.5},{130,90},{138,90}}, + color={255,0,255})); + connect(chiTwoSta1.y, endUp1.uChi[2]) + annotation (Line(points={{162,90},{176,90},{176,60},{-8,60},{-8,166.5},{58,166.5}}, + color={255,0,255})); + connect(chiOneSta1.y, endUp1.uChi[1]) + annotation (Line(points={{162,130},{180,130},{180,40},{-4,40},{-4,165.5}, + {58,165.5}}, color={255,0,255})); + connect(staUp1.y, endUp1.uOnOff) + annotation (Line(points={{-118,90},{0,90},{0,164},{58,164}}, + color={255,0,255})); + connect(nexDisChi2.y, swi3.u1) + annotation (Line(points={{-158,10},{-140,10},{-140,-2},{-102,-2}}, + color={0,0,127})); + connect(zer4.y, swi3.u3) + annotation (Line(points={{-158,-30},{-140,-30},{-140,-18},{-102,-18}}, + color={0,0,127})); + connect(staUp1.y, swi3.u2) + annotation (Line(points={{-118,90},{-110,90},{-110,-10},{-102,-10}}, + color={255,0,255})); + connect(swi3.y, reaToInt2.u) + annotation (Line(points={{-78,-10},{-62,-10}}, color={0,0,127})); + connect(reaToInt2.y, endUp1.nexDisChi) + annotation (Line(points={{-38,-10},{4,-10},{4,162},{58,162}}, + color={255,127,0})); + connect(chiTwoSta1.y, endUp1.uChiWatReq[2]) + annotation (Line(points={{162,90},{176,90},{176,60},{8,60},{8,160.5},{58,160.5}}, + color={255,0,255})); + connect(chiOneSta1.y, endUp1.uChiWatReq[1]) + annotation (Line(points={{162,130},{180,130},{180,40},{12,40},{12,159.5}, + {58,159.5}}, color={255,0,255})); + connect(fulOpe.y, chiIsoVal1.u3) + annotation (Line(points={{-158,-70},{-140,-70},{-140,-78},{-102,-78}}, + color={0,0,127})); + connect(staUp1.y, chiIsoVal1.u2) + annotation (Line(points={{-118,90},{-110,90},{-110,-70},{-102,-70}}, + color={255,0,255})); + connect(endUp1.yChiWatIsoVal, zerOrdHol1.u) + annotation (Line(points={{82,165},{124,165},{124,-10},{138,-10}}, + color={0,0,127})); + connect(zerOrdHol1[1].y, chiIsoVal1.u1) + annotation (Line(points={{162,-10},{166,-10},{166,-40},{-120,-40},{-120,-62}, + {-102,-62}}, color={0,0,127})); + connect(chiIsoVal1.y, endUp1.uChiWatIsoVal[1]) + annotation (Line(points={{-78,-70},{16,-70},{16,157.5},{58,157.5}}, + color={0,0,127})); + connect(chiOneSta1.y, endUp1.uConWatReq[1]) + annotation (Line(points={{162,130},{180,130},{180,40},{24,40},{24,155.5}, + {58,155.5}}, color={255,0,255})); + connect(chiTwoSta1.y, endUp1.uConWatReq[2]) + annotation (Line(points={{162,90},{176,90},{176,60},{28,60},{28,156.5},{58,156.5}}, + color={255,0,255})); + connect(enaHeaCon.y, chiOneHeaCon.u3) + annotation (Line(points={{-158,-160},{-140,-160},{-140,-168},{-102,-168}}, + color={255,0,255})); + connect(staUp1.y, chiOneHeaCon.u2) + annotation (Line(points={{-118,90},{-110,90},{-110,-160},{-102,-160}}, + color={255,0,255})); + connect(endUp1.yChiHeaCon[1], chiOneHea1.u) + annotation (Line(points={{82,160.5},{120,160.5},{120,-120},{138,-120}}, + color={255,0,255})); + connect(chiOneHea1.y, chiOneHeaCon.u1) + annotation (Line(points={{162,-120},{170,-120},{170,-140},{-120,-140}, + {-120,-152},{-102,-152}}, color={255,0,255})); + connect(chiOneHeaCon.y, endUp1.uChiHeaCon[1]) + annotation (Line(points={{-78,-160},{32,-160},{32,153.5},{58,153.5}}, + color={255,0,255})); + connect(chiWatFlo1.y, endUp1.VChiWat_flow) + annotation (Line(points={{-158,-200},{40,-200},{40,152},{58,152}}, + color={0,0,127})); + connect(fulOpe.y, endUp1.uChiWatIsoVal[2]) + annotation (Line(points={{-158,-70},{-140,-70},{-140,-100},{20,-100},{20,158.5}, + {58,158.5}}, color={0,0,127})); + connect(enaHeaCon.y, endUp1.uChiHeaCon[2]) + annotation (Line(points={{-158,-160},{-140,-160},{-140,-180},{36,-180},{36,154.5}, + {58,154.5}}, color={255,0,255})); + connect(chiWatFlo2.y, endUp1.VMinChiWat_setpoint) + annotation (Line(points={{-158,-240},{44,-240},{44,150},{58,150}}, color={0,0,127})); + +annotation ( + experiment(StopTime=1200, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithOff.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.UpEnd. +

+

+It shows how the staging up process ends when the process requires one chiller +being enabled and another chiller being disabled. The instance endUp1 +shows the results as below. It stages up from stage 1 which requires smaller chiller +1 being enabled, to stage 2 which requires larger chiller 2 being enabled and +chiller 1 being disabled. +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-200,-260},{200,260}}), + graphics={ + Text( + extent={{-182,250},{-150,242}}, + textColor={0,0,127}, + textString="Stage up:"), + Text( + extent={{-176,236},{-16,226}}, + textColor={0,0,127}, + textString="from stage 1 which has small chiller 1 being enabled, "), + Text( + extent={{-180,224},{82,210}}, + textColor={0,0,127}, + textString="to stage 2 which has small chiller 1 being disabled and large chiller 2 being enabled.")})); +end UpEndWithOff; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithoutOff.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithoutOff.mo new file mode 100644 index 00000000000..191ed5e8001 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithoutOff.mo @@ -0,0 +1,202 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.Validation; +model UpEndWithoutOff + "Validate sequence of end staging up process which does not require chiller OFF" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.UpEnd + endUp( + final nChi=2, + final chaChiWatIsoTim=300, + final byPasSetTim=300, + final minFloSet={0.5,1}, + final maxFloSet={1,1.5}) + "End staging up process which does not require one chiller on and another chiller off" + annotation (Placement(transformation(extent={{100,140},{120,160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + freqHz=1/1200) "Source for the trigger sampling" + annotation (Placement(transformation(extent={{80,190},{100,210}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Check if there is end staging edge " + annotation (Placement(transformation(extent={{140,190},{160,210}}))); +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.15, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,70},{-120,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant nexDisChi( + final k=0) "Next disabling chiller" + annotation (Placement(transformation(extent={{-140,-50},{-120,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff( + final k=false) "Chiller on-off command" + annotation (Placement(transformation(extent={{-140,-10},{-120,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiHea[2]( + final k=fill(true,2)) "Chiller one head pressure control" + annotation (Placement(transformation(extent={{-140,-170},{-120,-150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatFlo(final k=1.667) + "Chilled water flow rate" + annotation (Placement(transformation(extent={{-140,-250},{-120,-230}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta( + final pre_u_start=true) "Chiller one status" + annotation (Placement(transformation(extent={{140,110},{160,130}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-60,140},{-40,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant nexEnaChi( + final k=2) "Next enable chiller" + annotation (Placement(transformation(extent={{-140,160},{-120,180}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-140,120},{-120,140}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-20,140},{0,160}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.20, + final period=1200) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev "Upstream device status" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta( + final pre_u_start=false) "Chiller two status" + annotation (Placement(transformation(extent={{140,70},{160,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatIsoVal[2]( + final k=fill(1, 2)) "Constant one" + annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-118,80},{-102,80}}, color={255,0,255})); + connect(staUp.y, swi2.u2) + annotation (Line(points={{-78,80},{-70,80},{-70,150},{-62,150}}, + color={255,0,255})); + connect(nexEnaChi.y, swi2.u1) + annotation (Line(points={{-118,170},{-100,170},{-100,158},{-62,158}}, + color={0,0,127})); + connect(zer2.y, swi2.u3) + annotation (Line(points={{-118,130},{-100,130},{-100,142},{-62,142}}, + color={0,0,127})); + connect(swi2.y, reaToInt.u) + annotation (Line(points={{-38,150},{-22,150}}, color={0,0,127})); + connect(booPul1.y, upStrDev.u) + annotation (Line(points={{-118,40},{-102,40}}, color={255,0,255})); + connect(endUp.yChi[1], chiOneSta.u) + annotation (Line(points={{122,158.5},{130,158.5},{130,120},{138,120}}, + color={255,0,255})); + connect(endUp.yChi[2], chiTwoSta.u) + annotation (Line(points={{122,159.5},{130,159.5},{130,80},{138,80}}, + color={255,0,255})); + connect(reaToInt.y, endUp.nexEnaChi) + annotation (Line(points={{2,150},{20,150},{20,162},{98,162}}, + color={255,127,0})); + connect(staUp.y, endUp.uStaUp) + annotation (Line(points={{-78,80},{24,80},{24,160},{98,160}}, + color={255,0,255})); + connect(upStrDev.y, endUp.uEnaChiWatIsoVal) + annotation (Line(points={{-78,40},{28,40},{28,158},{98,158}}, + color={255,0,255})); + connect(chiOneSta.y, endUp.uChi[1]) + annotation (Line(points={{162,120},{174,120},{174,100},{32,100},{32,155.5},{ + 98,155.5}}, color={255,0,255})); + connect(chiTwoSta.y, endUp.uChi[2]) + annotation (Line(points={{162,80},{170,80},{170,60},{36,60},{36,156.5},{98,156.5}}, + color={255,0,255})); + connect(onOff.y, endUp.uOnOff) + annotation (Line(points={{-118,0},{40,0},{40,154},{98,154}}, + color={255,0,255})); + connect(nexDisChi.y, endUp.nexDisChi) + annotation (Line(points={{-118,-40},{44,-40},{44,152},{98,152}}, + color={255,127,0})); + connect(chiOneSta.y, endUp.uChiWatReq[1]) + annotation (Line(points={{162,120},{174,120},{174,100},{48,100},{48,149.5},{ + 98,149.5}}, color={255,0,255})); + connect(chiTwoSta.y, endUp.uChiWatReq[2]) + annotation (Line(points={{162,80},{170,80},{170,60},{52,60},{52,150.5},{98,150.5}}, + color={255,0,255})); + connect(chiOneSta.y, endUp.uConWatReq[1]) + annotation (Line(points={{162,120},{174,120},{174,100},{60,100},{60,145.5},{ + 98,145.5}}, color={255,0,255})); + connect(chiTwoSta.y, endUp.uConWatReq[2]) + annotation (Line(points={{162,80},{170,80},{170,60},{64,60},{64,146.5},{98,146.5}}, + color={255,0,255})); + connect(chiWatFlo.y, endUp.VChiWat_flow) + annotation (Line(points={{-118,-240},{72,-240},{72,142},{98,142}}, + color={0,0,127})); + connect(chiWatIsoVal.y, endUp.uChiWatIsoVal) + annotation (Line(points={{-118,-80},{56,-80},{56,148},{98,148}}, + color={0,0,127})); + connect(chiHea.y, endUp.uChiHeaCon) + annotation (Line(points={{-118,-160},{68,-160},{68,144},{98,144}}, + color={255,0,255})); + connect(chiWatFlo.y, endUp.VMinChiWat_setpoint) + annotation (Line(points={{-118,-240},{72,-240},{72,140},{98,140}}, + color={0,0,127})); + connect(sin.y, triSam.u) + annotation (Line(points={{102,200},{138,200}}, color={0,0,127})); + connect(endUp.yEndSta, triSam.trigger) annotation (Line(points={{122,143},{150, + 143},{150,188}}, color={255,0,255})); +annotation ( + experiment(StopTime=1200, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithoutOff.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.UpEnd. +

+

+It shows how the staging up process ends when the process does not require one chiller +being enabled and another chiller being disabled. The instance endUp +shows the results as below. It stages up from stage 1 which requires chiller 1 being +enabled, to stage 2 which requires chiller 1 and chiller 2 being enabled. +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-180,-260},{180,260}}), + graphics={ + Text( + extent={{-142,240},{-110,232}}, + textColor={0,0,127}, + textString="Stage up:"), + Text( + extent={{-138,226},{22,216}}, + textColor={0,0,127}, + textString="from stage 1 which has only chiller 1 being enabled, "), + Text( + extent={{-138,214},{16,200}}, + textColor={0,0,127}, + textString="to stage 2 which has chiller 1 and 2 being enabled.")})); +end UpEndWithoutOff; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..aace7958dd6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences; +package Validation "Collection of validation models" +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/package.order new file mode 100644 index 00000000000..673266a6037 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/package.order @@ -0,0 +1,12 @@ +CHWIsoVal +DisableChiller +DownStartWithOn +DownStartWithoutOn +EnableCWPump +EnableChiller +HeadControl +NextChiller +ReduceDemand +ResetMinBypass +UpEndWithOff +UpEndWithoutOff diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/package.mo new file mode 100644 index 00000000000..117822b0a83 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/package.mo @@ -0,0 +1,44 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes; +package Subsequences "Package of subsequences for staging up and down devices" + +annotation (preferredView="info", Documentation(info=" +

+This package contains subsequences for controlling devices when there is stage-up +or stage-down command. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/package.order new file mode 100644 index 00000000000..c5c50244d09 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/package.order @@ -0,0 +1,11 @@ +CHWIsoVal +DisableChiller +DownStart +EnableCWPump +EnableChiller +HeadControl +NextChiller +ReduceDemand +ResetMinBypass +UpEnd +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Up.mo new file mode 100644 index 00000000000..0f1c3a3f6a6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Up.mo @@ -0,0 +1,933 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes; +block Up "Sequence for control devices when there is stage-up command" + + parameter Integer nChi=2 "Total number of chillers in the plant"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Integer totSta=6 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable"; + parameter Integer nChiSta=3 + "Total number of chiller stages, including stage zero but not the stages with a WSE, if applicable"; + parameter Boolean have_WSE=true + "True: have waterside economizer"; + parameter Boolean have_ponyChiller=false + "True: have pony chiller"; + parameter Boolean have_parChi=true + "True: the plant has parallel chillers"; + parameter Boolean have_heaConWatPum=true + "True: headered condenser water pumps"; + parameter Boolean have_fixSpeConWatPum=true + "True: fixed speed condenser water pump"; + parameter Boolean need_reduceChillerDemand=false + "True: need limit chiller demand when chiller staging"; + parameter Real chiDemRedFac=0.75 + "Demand reducing factor of current operating chillers" + annotation (Dialog(group="Limit chiller demand", enable=need_reduceChillerDemand)); + parameter Real holChiDemTim( + unit="s", + displayUnit="s")=300 + "Maximum time to wait for the actual demand less than percentage of current load" + annotation (Dialog(group="Limit chiller demand", enable=need_reduceChillerDemand)); + parameter Real byPasSetTim( + unit="s", + displayUnit="s")=300 + "Time to reset minimum bypass flow" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real minFloSet[nChi]( + final unit=fill("m3/s",nChi), + displayUnit=fill("m3/s",nChi))={0.0089,0.0089} + "Minimum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real maxFloSet[nChi]( + final unit=fill("m3/s",nChi), + displayUnit=fill("m3/s",nChi))={0.025,0.025} + "Maximum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real aftByPasSetTim( + unit="s", + displayUnit="s")=60 + "Time to allow loop to stabilize after resetting minimum chilled water flow setpoint" + annotation (Dialog(group="Reset bypass")); + parameter Real staVec[totSta]={0,0.5,1,1.5,2,2.5} + "Chiller stage vector, element value like x.5 means chiller stage x plus WSE" + annotation (Dialog(group="Enable condenser water pump")); + parameter Real desConWatPumSpe[totSta]={0,0.5,0.75,0.6,0.75,0.9} + "Design condenser water pump speed setpoints, according to current chiller stage and WSE status" + annotation (Dialog(group="Enable condenser water pump")); + parameter Real desConWatPumNum[totSta]={0,1,1,2,2,2} + "Design number of condenser water pumps that should be ON, according to current chiller stage and WSE status" + annotation (Dialog(group="Enable condenser water pump")); + parameter Real desChiNum[nChiSta]={0,1,2} + "Design number of chiller that should be ON, according to current chiller stage" + annotation (Dialog(group="Enable condenser water pump", enable=have_fixSpeConWatPum)); + parameter Real thrTimEnb( + unit="s", + displayUnit="s")=10 + "Threshold time to enable head pressure control after condenser water pump being reset" + annotation (Dialog(group="Enable head pressure control")); + parameter Real waiTim( + unit="s", + displayUnit="s")=30 + "Waiting time after enabling next head pressure control" + annotation (Dialog(group="Enable head pressure control")); + parameter Real chaChiWatIsoTim( + unit="s", + displayUnit="s")=300 + "Time to slowly change isolation valve, should be determined in the field" + annotation (Dialog(group="Enable CHW isolation valve")); + parameter Real proOnTim( + unit="s", + displayUnit="s")=300 + "Threshold time to check after newly enabled chiller being operated" + annotation (Dialog(group="Enable next chiller",enable=have_ponyChiller)); + parameter Real pumSpeChe = 0.05 + "Lower threshold value to check if condenser water pump has achieved setpoint" + annotation (Dialog(tab="Advanced", group="Enable condenser water pump")); + parameter Real relFloDif=0.05 + "Relative error to the setpoint for checking if it has achieved flow rate setpoint" + annotation (Dialog(tab="Advanced", group="Reset bypass")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Chiller stage setpoint index" + annotation (Placement(transformation(extent={{-280,180},{-240,220}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiSet[nChi] + "Vector of chillers status setpoint" + annotation (Placement(transformation(extent={{-280,150},{-240,190}}), + iconTransformation(extent={{-140,140},{-100,180}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiLoa[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) + if need_reduceChillerDemand + "Current chiller load" + annotation (Placement(transformation(extent={{-280,90},{-240,130}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-280,60},{-240,100}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-280,30},{-240,70}}), + iconTransformation(extent={{-140,56},{-100,96}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiConIsoVal[nChi] + "Chiller condenser water isolation valve status" + annotation (Placement(transformation(extent={{-280,-10},{-240,30}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage, it would be the same as chiller stage setpoint when it is not in staging process" + annotation (Placement(transformation(extent={{-280,-30},{-240,10}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPlaConPum + "True: enable condenser water pump when the plant is just enabled" + annotation (Placement(transformation(extent={{-280,-56},{-240,-16}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatReq[nChi] + "Condenser water requst status for each chiller" + annotation (Placement(transformation(extent={{-280,-90},{-240,-50}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWSE if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-280,-110},{-240,-70}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpeSet( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{-280,-130},{-240,-90}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-280,-150},{-240,-110}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPlaConIso + "True: enable condenser water pump when then plant is just enabled" + annotation (Placement(transformation(extent={{-280,-180},{-240,-140}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatPum[nConWatPum] if have_fixSpeConWatPum + "Status indicating if condenser water pump is running" + annotation (Placement(transformation(extent={{-280,-210},{-240,-170}}), + iconTransformation(extent={{-140,-150},{-100,-110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-280,-240},{-240,-200}}), + iconTransformation(extent={{-140,-170},{-100,-130}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chilled water isolation valve position" + annotation (Placement(transformation(extent={{-280,-270},{-240,-230}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatReq[nChi] + "Chilled water requst status for each chiller" + annotation (Placement(transformation(extent={{-280,-300},{-240,-260}}), + iconTransformation(extent={{-140,-210},{-100,-170}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaPro + "Indicate if it is in stage-up process: true=in stage-up process" + annotation (Placement(transformation(extent={{240,190},{280,230}}), + iconTransformation(extent={{100,170},{140,210}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiDem[nChi]( + final quantity=fill("ElectricCurrent", nChi), + final unit=fill("A", nChi)) + if need_reduceChillerDemand + "Chiller demand setpoint" + annotation (Placement(transformation(extent={{240,160},{280,200}}), + iconTransformation(extent={{100,130},{140,170}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatMinFloSet( + final min=0, + final unit="m3/s", + final quantity="VolumeFlowRate") + "Chilled water minimum flow setpoint" + annotation (Placement(transformation(extent={{240,20},{280,60}}), + iconTransformation(extent={{100,90},{140,130}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowStaUp + "Tower stage up status: true=stage up cooling tower" + annotation (Placement(transformation(extent={{240,-20},{280,20}}), + iconTransformation(extent={{100,50},{140,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaPum + "Lead condenser water pump status" + annotation (Placement(transformation(extent={{240,-50},{280,-10}}), + iconTransformation(extent={{100,10},{140,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDesConWatPumSpe( + final min=0, + final max=1, + final unit="1") if not have_fixSpeConWatPum + "Condenser water pump design speed at current stage" + annotation (Placement(transformation(extent={{240,-80},{280,-40}}), + iconTransformation(extent={{100,-30},{140,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yConWatPumNum + "Number of operating condenser water pumps" + annotation (Placement(transformation(extent={{240,-110},{280,-70}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiHeaCon[nChi] + "Chiller head pressure control enabling status" + annotation (Placement(transformation(extent={{240,-150},{280,-110}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yChiWatIsoVal[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Chiller chilled water isolation valve position" + annotation (Placement(transformation(extent={{240,-210},{280,-170}}), + iconTransformation(extent={{100,-160},{140,-120}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{240,-260},{280,-220}}), + iconTransformation(extent={{100,-190},{140,-150}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEndStaTri + "Staging end trigger" + annotation (Placement(transformation(extent={{240,-320},{280,-280}}), + iconTransformation(extent={{100,-210},{140,-170}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if stage setpoint increases" + annotation (Placement(transformation(extent={{-200,140},{-180,160}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi(final nChi=nChi) "Identify next enabling chiller" + annotation (Placement(transformation(extent={{-80,180},{-60,200}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand + chiDemRed( + final nChi=nChi, + final chiDemRedFac=chiDemRedFac, + final holChiDemTim=holChiDemTim) if need_reduceChillerDemand + "Limit chiller demand" + annotation (Placement(transformation(extent={{-80,110},{-60,130}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + minChiWatFlo( + final nChi=nChi, + final have_parChi=have_parChi, + final byPasSetTim=byPasSetTim, + final minFloSet=minFloSet, + final maxFloSet=maxFloSet) "Minimum chilled water flow setpoint" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass + minBypSet( + final aftByPasSetTim=aftByPasSetTim, + final relFloDif=relFloDif) + "Check if minium bypass has been reset" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump + enaNexCWP + "Identify correct stage number for enabling next condenser water pump" + annotation (Placement(transformation(extent={{0,-20},{20,0}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller + conWatPumCon( + final have_heaPum=have_heaConWatPum, + final have_WSE=have_WSE, + final fixSpe=have_fixSpeConWatPum, + final nChi=nChi, + final totSta=totSta, + final nChiSta=nChiSta, + final staVec=staVec, + final desConWatPumSpe=desConWatPumSpe, + final desConWatPumNum=desConWatPumNum, + final desChiNum=desChiNum, + final pumSpeChe=pumSpeChe) + "Enabling next condenser water pump or change pump speed" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl + enaHeaCon( + final nChi=nChi, + final thrTimEnb=thrTimEnb, + final waiTim=waiTim, + final heaStaCha=true) + "Enabling head pressure control for next enabling chiller" + annotation (Placement(transformation(extent={{60,-150},{80,-130}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal + enaChiIsoVal( + final nChi=nChi, + final chaChiWatIsoTim=chaChiWatIsoTim, + final iniValPos=0, + final endValPos=1) + "Enable chilled water isolation valve for next enabling chiller" + annotation (Placement(transformation(extent={{60,-210},{80,-190}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.UpEnd + endUp( + final nChi=nChi, + final have_parChi=have_parChi, + final chaChiWatIsoTim=chaChiWatIsoTim, + final maxFloSet=maxFloSet, + final proOnTim=proOnTim, + final minFloSet=minFloSet, + final byPasSetTim=byPasSetTim, + final aftByPasSetTim=aftByPasSetTim, + final relFloDif=relFloDif) "End stage-up process" + annotation (Placement(transformation(extent={{20,-280},{40,-260}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(final k=false) + "False constant" + annotation (Placement(transformation(extent={{-200,20},{-180,40}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(final nin=nChi) "Multiple or" + annotation (Placement(transformation(extent={{-140,-62},{-120,-42}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1(final nin=nChi) "Multiple or" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{200,-200},{220,-180}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{140,-230},{160,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{200,-140},{220,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{200,30},{220,50}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{-140,140},{-120,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(final k=0) + if need_reduceChillerDemand + "Constant zero" + annotation (Placement(transformation(extent={{-200,80},{-180,100}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{20,-126},{40,-106}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 if need_reduceChillerDemand + "Maintain ON signal when chiller demand has been limited" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Maintain ON signal when minimum chilled water flow has been reset" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat3 + "Maintain ON signal when condenser water pump has been enabled" + annotation (Placement(transformation(extent={{120,-90},{140,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat4 + "Maintain ON signal when chiller head pressure control has been enabled" + annotation (Placement(transformation(extent={{120,-170},{140,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat5 + "Maintain ON signal when chilled water isolation valve has been open" + annotation (Placement(transformation(extent={{100,-230},{120,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 if not need_reduceChillerDemand + "Dummy or" + annotation (Placement(transformation(extent={{-20,160},{0,180}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-100,290},{-80,310}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 "Logical switch" + annotation (Placement(transformation(extent={{-40,240},{-20,260}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu + "Check if the stage setpoint is zero" + annotation (Placement(transformation(extent={{-140,270},{-120,290}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-220,290},{-200,310}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2(final k=true) + "Constant true" + annotation (Placement(transformation(extent={{-200,230},{-180,250}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=1, + final delayOnInit=true) "Check if it has passed initial time" + annotation (Placement(transformation(extent={{-140,230},{-120,250}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge when the new setpoint has been achieved" + annotation (Placement(transformation(extent={{120,70},{140,90}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical and" + annotation (Placement(transformation(extent={{100,110},{120,130}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 + "Logical and" + annotation (Placement(transformation(extent={{160,150},{180,170}}))); + +equation + connect(lat.y,chiDemRed.uDemLim) + annotation (Line(points={{-118,150},{-100,150},{-100,129},{-82,129}}, + color={255,0,255})); + connect(chiDemRed.uChiLoa, uChiLoa) + annotation (Line(points={{-82,125},{-230,125},{-230,110},{-260,110}}, + color={0,0,127})); + connect(chiDemRed.uChi, uChi) + annotation (Line(points={{-82,111},{-220,111},{-220,80},{-260,80}}, + color={255,0,255})); + connect(lat.y, minBypSet.uStaPro) annotation (Line(points={{-118,150},{-100, + 150},{-100,84},{58,84}}, color={255,0,255})); + connect(minBypSet.VChiWat_flow, VChiWat_flow) + annotation (Line(points={{58,80},{-156,80},{-156,50},{-260,50}}, + color={0,0,127})); + connect(lat.y, minChiWatFlo.uStaUp) + annotation (Line(points={{-118,150},{-100,150},{-100,49},{18,49}}, + color={255,0,255})); + connect(con.y, minChiWatFlo.uStaDow) + annotation (Line(points={{-178,30},{-96,30},{-96,31},{18,31}}, + color={255,0,255})); + connect(lat.y, enaNexCWP.uStaUp) + annotation (Line(points={{-118,150},{-100,150},{-100,-8},{-2,-8}}, + color={255,0,255})); + connect(conWatPumCon.uWSE, uWSE) + annotation (Line(points={{58,-63},{-6,-63},{-6,-90},{-260,-90}}, + color={255,0,255})); + connect(conWatPumCon.uConWatPumSpe, uConWatPumSpe) + annotation (Line(points={{58,-67},{2,-67},{2,-130},{-260,-130}}, + color={0,0,127})); + connect(enaNexCWP.yChiSta, conWatPumCon.uChiSta) + annotation (Line(points={{22,-10},{36,-10},{36,-61},{58,-61}}, + color={255,127,0})); + connect(lat.y, enaHeaCon.uStaPro) annotation (Line(points={{-118,150},{-100, + 150},{-100,-140},{58,-140}}, color={255,0,255})); + connect(nexChi.yNexEnaChi, enaHeaCon.nexChaChi) + annotation (Line(points={{-58,194},{-36,194},{-36,-144},{58,-144}}, + color={255,127,0})); + connect(nexChi.yNexEnaChi, enaChiIsoVal.nexChaChi) + annotation (Line(points={{-58,194},{-36,194},{-36,-192},{58,-192}}, + color={255,127,0})); + connect(enaChiIsoVal.uChiWatIsoVal, uChiWatIsoVal) + annotation (Line(points={{58,-195},{-96,-195},{-96,-250},{-260,-250}}, + color={0,0,127})); + connect(lat.y, enaChiIsoVal.uStaPro) annotation (Line(points={{-118,150},{-100, + 150},{-100,-208},{58,-208}}, color={255,0,255})); + connect(nexChi.yNexEnaChi, endUp.nexEnaChi) + annotation (Line(points={{-58,194},{-36,194},{-36,-258},{18,-258}}, + color={255,127,0})); + connect(lat.y, endUp.uStaUp) + annotation (Line(points={{-118,150},{-100,150},{-100,-260},{18,-260}}, + color={255,0,255})); + connect(uChi, endUp.uChi) + annotation (Line(points={{-260,80},{-220,80},{-220,-264},{18,-264}}, + color={255,0,255})); + connect(endUp.uChiWatReq, uChiWatReq) + annotation (Line(points={{18,-270},{-168,-270},{-168,-280},{-260,-280}}, + color={255,0,255})); + connect(endUp.uChiWatIsoVal, uChiWatIsoVal) + annotation (Line(points={{18,-272},{-96,-272},{-96,-250},{-260,-250}}, + color={0,0,127})); + connect(uConWatReq, endUp.uConWatReq) + annotation (Line(points={{-260,-70},{-164,-70},{-164,-274},{18,-274}}, + color={255,0,255})); + connect(VChiWat_flow, endUp.VChiWat_flow) + annotation (Line(points={{-260,50},{-156,50},{-156,-278},{18,-278}}, + color={0,0,127})); + connect(uConWatReq, mulOr1.u) + annotation (Line(points={{-260,-70},{-82,-70}}, + color={255,0,255})); + connect(uChi, mulOr.u) + annotation (Line(points={{-260,80},{-220,80},{-220,-52},{-142,-52}}, + color={255,0,255})); + connect(chiDemRed.yChiDem, yChiDem) + annotation (Line(points={{-58,124},{40,124},{40,180},{260,180}}, + color={0,0,127})); + connect(conWatPumCon.yLeaPum, yLeaPum) + annotation (Line(points={{82,-51},{120,-51},{120,-30},{260,-30}}, color={255,0,255})); + connect(endUp.yChi, yChi) + annotation (Line(points={{42,-261},{220,-261},{220,-240},{260,-240}}, + color={255,0,255})); + connect(endUp.yChiWatIsoVal, swi.u1) + annotation (Line(points={{42,-265},{184,-265},{184,-182},{198,-182}}, + color={0,0,127})); + connect(swi.y, yChiWatIsoVal) + annotation (Line(points={{222,-190},{260,-190}}, color={0,0,127})); + connect(endUp.yChiHeaCon, logSwi.u1) + annotation (Line(points={{42,-269},{172,-269},{172,-122},{198,-122}}, + color={255,0,255})); + connect(enaHeaCon.yChiHeaCon, logSwi.u3) + annotation (Line(points={{82,-146},{120,-146},{120,-138},{198,-138}}, + color={255,0,255})); + connect(logSwi.y, yChiHeaCon) + annotation (Line(points={{222,-130},{260,-130}}, color={255,0,255})); + connect(enaChiIsoVal.yEnaChiWatIsoVal, swi1.u2) + annotation (Line(points={{82,-194},{100,-194},{100,40},{198,40}}, + color={255,0,255})); + connect(endUp.yChiWatMinSet, swi1.u1) + annotation (Line(points={{42,-273},{178,-273},{178,48},{198,48}}, + color={0,0,127})); + connect(swi1.y, yChiWatMinFloSet) + annotation (Line(points={{222,40},{260,40}}, color={0,0,127})); + connect(enaChiIsoVal.yChiWatIsoVal, swi.u3) + annotation (Line(points={{82,-206},{100,-206},{100,-198},{198,-198}}, + color={0,0,127})); + connect(nexChi.yDisSmaChi, endUp.nexDisChi) + annotation (Line(points={{-58,190.8},{-40,190.8},{-40,-268},{18,-268}}, + color={255,127,0})); + connect(nexChi.yOnOff, minChiWatFlo.uOnOff) + annotation (Line(points={{-58,187},{-44,187},{-44,33},{18,33}}, + color={255,0,255})); + connect(nexChi.yOnOff, endUp.uOnOff) + annotation (Line(points={{-58,187},{-44,187},{-44,-266},{18,-266}}, + color={255,0,255})); + connect(con.y, enaNexCWP.uStaDow) + annotation (Line(points={{-178,30},{-96,30},{-96,-12},{-2,-12}}, + color={255,0,255})); + connect(lat.y, yStaPro) + annotation (Line(points={{-118,150},{-100,150},{-100,210},{260,210}}, + color={255,0,255})); + connect(and2.y, enaHeaCon.uUpsDevSta) + annotation (Line(points={{42,-116},{50,-116},{50,-136},{58,-136}}, + color={255,0,255})); + connect(con.y, chiDemRed.uStaDow) + annotation (Line(points={{-178,30},{-96,30},{-96,118},{-82,118}}, + color={255,0,255})); + connect(con1.y, chiDemRed.yOpeParLoaRatMin) + annotation (Line(points={{-178,90},{-140,90},{-140,121},{-82,121}}, + color={0,0,127})); + connect(uChi, minChiWatFlo.uChi) + annotation (Line(points={{-260,80},{-220,80},{-220,44},{18,44}}, + color={255,0,255})); + connect(nexChi.yNexEnaChi, minChiWatFlo.nexEnaChi) + annotation (Line(points={{-58,194},{-36,194},{-36,41},{18,41}}, + color={255,127,0})); + connect(nexChi.yDisSmaChi, minChiWatFlo.nexDisChi) + annotation (Line(points={{-58,190.8},{-40,190.8},{-40,39},{18,39}}, + color={255,127,0})); + connect(con.y, minChiWatFlo.uSubCha) + annotation (Line(points={{-178,30},{-96,30},{-96,36},{18,36}}, + color={255,0,255})); + connect(nexChi.yOnOff, chiDemRed.uOnOff) + annotation (Line(points={{-58,187},{-44,187},{-44,140},{-92,140},{-92,115},{ + -82,115}}, color={255,0,255})); + connect(minChiWatFlo.yChiWatMinFloSet, minBypSet.VMinChiWat_setpoint) + annotation (Line(points={{42,40},{50,40},{50,76},{58,76}}, + color={0,0,127})); + connect(minChiWatFlo.yChiWatMinFloSet, swi1.u3) + annotation (Line(points={{42,40},{50,40},{50,32},{198,32}}, + color={0,0,127})); + connect(conWatPumCon.yDesConWatPumSpe, yDesConWatPumSpe) + annotation (Line(points={{82,-57},{120,-57},{120,-60},{260,-60}}, + color={0,0,127})); + connect(conWatPumCon.uChiConIsoVal, uChiConIsoVal) + annotation (Line(points={{58,-50},{48,-50},{48,10},{-260,10}}, + color={255,0,255})); + connect(mulOr.y, conWatPumCon.uLeaChiSta) + annotation (Line(points={{-118,-52},{44,-52},{44,-54},{58,-54}}, + color={255,0,255})); + connect(mulOr.y, conWatPumCon.uLeaChiEna) + annotation (Line(points={{-118,-52},{58,-52}}, + color={255,0,255})); + connect(mulOr1.y, conWatPumCon.uLeaConWatReq) + annotation (Line(points={{-58,-70},{-10,-70},{-10,-56},{58,-56}}, + color={255,0,255})); + connect(conWatPumCon.uConWatPumSpeSet, uConWatPumSpeSet) + annotation (Line(points={{58,-65},{-2,-65},{-2,-110},{-260,-110}}, + color={0,0,127})); + connect(conWatPumCon.yConWatPumNum, yConWatPumNum) + annotation (Line(points={{82,-63},{220,-63},{220,-90},{260,-90}}, + color={255,127,0})); + connect(minChiWatFlo.yChiWatMinFloSet, endUp.VMinChiWat_setpoint) + annotation (Line(points={{42,40},{50,40},{50,20},{-92,20},{-92,-280},{18,-280}}, + color={0,0,127})); + connect(lat1.y, minBypSet.uUpsDevSta) annotation (Line(points={{2,100},{10,100}, + {10,88},{58,88}}, color={255,0,255})); + connect(lat1.y, minChiWatFlo.uUpsDevSta) annotation (Line(points={{2,100},{10, + 100},{10,47},{18,47}}, color={255,0,255})); + connect(lat2.y, yTowStaUp) annotation (Line(points={{182,70},{190,70},{190,0}, + {260,0}}, color={255,0,255})); + connect(lat2.y, enaNexCWP.uUpsDevSta) annotation (Line(points={{182,70},{190,70}, + {190,14},{-20,14},{-20,-2},{-2,-2}}, color={255,0,255})); + connect(lat2.y, and2.u2) annotation (Line(points={{182,70},{190,70},{190,14},{ + -20,14},{-20,-124},{18,-124}},color={255,0,255})); + connect(conWatPumCon.yPumSpeChe, lat3.u) annotation (Line(points={{82,-69},{110, + -69},{110,-80},{118,-80}}, color={255,0,255})); + connect(lat3.y, and2.u1) annotation (Line(points={{142,-80},{160,-80},{160,-98}, + {10,-98},{10,-116},{18,-116}}, color={255,0,255})); + connect(enaHeaCon.yEnaHeaCon, lat4.u) annotation (Line(points={{82,-134},{110, + -134},{110,-160},{118,-160}}, color={255,0,255})); + connect(lat4.y, enaChiIsoVal.uUpsDevSta) annotation (Line(points={{142,-160},{ + 160,-160},{160,-180},{40,-180},{40,-205},{58,-205}}, color={255,0,255})); + connect(enaChiIsoVal.yEnaChiWatIsoVal, lat5.u) annotation (Line(points={{82,-194}, + {90,-194},{90,-220},{98,-220}}, color={255,0,255})); + connect(lat5.y, booRep.u) + annotation (Line(points={{122,-220},{138,-220}}, color={255,0,255})); + connect(booRep.y, logSwi.u2) annotation (Line(points={{162,-220},{166,-220},{166, + -130},{198,-130}}, color={255,0,255})); + connect(booRep.y, swi.u2) annotation (Line(points={{162,-220},{166,-220},{166, + -190},{198,-190}}, color={255,0,255})); + connect(lat5.y, endUp.uEnaChiWatIsoVal) annotation (Line(points={{122,-220},{ + 130,-220},{130,-240},{0,-240},{0,-262},{18,-262}}, + color={255,0,255})); + connect(endUp.endStaTri, lat.clr) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{-160,-300},{-160,144},{-142,144}}, color={255,0,255})); + connect(endUp.endStaTri, lat1.clr) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{-160,-300},{-160,94},{-22,94}}, color={255,0,255})); + connect(endUp.endStaTri, lat2.clr) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{-160,-300},{-160,64},{158,64}}, color={255,0,255})); + connect(endUp.endStaTri, lat3.clr) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{-160,-300},{-160,-86},{118,-86}}, color={255,0,255})); + connect(endUp.endStaTri, lat4.clr) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{-160,-300},{-160,-166},{118,-166}}, color={255,0,255})); + connect(uStaSet, nexChi.uStaSet) annotation (Line(points={{-260,200},{-104,200}, + {-104,197},{-82,197}}, color={255,127,0})); + connect(nexChi.uChiSet, uChiSet) + annotation (Line(points={{-82,190},{-180,190},{-180,170},{-260,170}}, + color={255,0,255})); + connect(uStaSet, cha.u) annotation (Line(points={{-260,200},{-220,200},{-220,150}, + {-202,150}}, color={255,127,0})); + connect(uStaSet, enaNexCWP.uStaSet) annotation (Line(points={{-260,200},{-104, + 200},{-104,-19},{-2,-19}}, color={255,127,0})); + connect(uChiSta, enaNexCWP.uChiSta) annotation (Line(points={{-260,-10},{-180, + -10},{-180,-15},{-2,-15}}, color={255,127,0})); + connect(enaHeaCon.uChiHeaCon, uChiHeaCon) annotation (Line(points={{58,-148},{ + -48,-148},{-48,-220},{-260,-220}}, color={255,0,255})); + connect(uChiHeaCon, endUp.uChiHeaCon) annotation (Line(points={{-260,-220},{-48, + -220},{-48,-276},{18,-276}}, color={255,0,255})); + connect(conWatPumCon.uConWatPum, uConWatPum) annotation (Line(points={{58,-69}, + {6,-69},{6,-190},{-260,-190}}, color={255,0,255})); + connect(endUp.endStaTri, lat5.clr) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{-160,-300},{-160,-226},{98,-226}}, color={255,0,255})); + connect(lat.y, or2.u1) + annotation (Line(points={{-118,150},{-100,150},{-100,170},{-22,170}}, + color={255,0,255})); + connect(con.y, or2.u2) annotation (Line(points={{-178,30},{-96,30},{-96,162},{ + -22,162}}, color={255,0,255})); + connect(or2.y, minBypSet.uUpsDevSta) annotation (Line(points={{2,170},{6,170}, + {6,88},{58,88}}, color={255,0,255})); + connect(or2.y, minChiWatFlo.uUpsDevSta) annotation (Line(points={{2,170},{6,170}, + {6,47},{18,47}}, color={255,0,255})); + connect(intEqu.y, and1.u2) annotation (Line(points={{-118,280},{-110,280},{-110, + 292},{-102,292}}, color={255,0,255})); + connect(conInt.y, intEqu.u1) annotation (Line(points={{-198,300},{-180,300},{-180, + 280},{-142,280}}, color={255,127,0})); + connect(uStaSet, intEqu.u2) annotation (Line(points={{-260,200},{-220,200},{-220, + 272},{-142,272}}, color={255,127,0})); + connect(cha.up, and1.u1) annotation (Line(points={{-178,156},{-170,156},{-170, + 300},{-102,300}}, color={255,0,255})); + connect(and1.y, logSwi1.u3) annotation (Line(points={{-78,300},{-60,300},{-60, + 242},{-42,242}}, color={255,0,255})); + connect(cha.up, logSwi1.u1) annotation (Line(points={{-178,156},{-170,156},{-170, + 258},{-42,258}}, color={255,0,255})); + connect(logSwi1.y, lat.u) annotation (Line(points={{-18,250},{0,250},{0,220},{ + -150,220},{-150,150},{-142,150}}, color={255,0,255})); + connect(uEnaPlaConPum, conWatPumCon.uEnaPla) annotation (Line(points={{-260,-36}, + {40,-36},{40,-58},{58,-58}}, color={255,0,255})); + connect(uEnaPlaConIso, enaHeaCon.uEnaPla) annotation (Line(points={{-260,-160}, + {-52,-160},{-52,-132},{58,-132}}, color={255,0,255})); + connect(endUp.endStaTri, yEndStaTri) annotation (Line(points={{42,-279},{60,-279}, + {60,-300},{260,-300}}, color={255,0,255})); + connect(endUp.endStaTri, nexChi.endPro) annotation (Line(points={{42,-279},{60, + -279},{60,-300},{-160,-300},{-160,183},{-82,183}}, color={255,0,255})); + connect(con2.y, truDel.u) + annotation (Line(points={{-178,240},{-142,240}}, color={255,0,255})); + connect(truDel.y, logSwi1.u2) annotation (Line(points={{-118,240},{-80,240},{-80, + 250},{-42,250}}, color={255,0,255})); + connect(minChiWatFlo.yChaSet, minBypSet.uSetChaPro) annotation (Line(points={ + {42,32},{46,32},{46,72},{58,72}}, color={255,0,255})); + connect(edg.y, lat2.u) annotation (Line(points={{142,80},{150,80},{150,70},{158, + 70}}, color={255,0,255})); + connect(minBypSet.yMinBypRes, and3.u2) annotation (Line(points={{82,80},{90, + 80},{90,112},{98,112}}, + color={255,0,255})); + connect(and3.y, edg.u) annotation (Line(points={{122,120},{130,120},{130,100}, + {110,100},{110,80},{118,80}}, color={255,0,255})); + connect(lat.y, and3.u1) annotation (Line(points={{-118,150},{80,150},{80,120}, + {98,120}}, color={255,0,255})); + connect(lat.y, and4.u1) annotation (Line(points={{-118,150},{80,150},{80,160}, + {158,160}}, color={255,0,255})); + connect(chiDemRed.yChiDemRed, and4.u2) annotation (Line(points={{-58,116},{ + -32,116},{-32,152},{158,152}}, color={255,0,255})); + connect(and4.y, lat1.u) annotation (Line(points={{182,160},{190,160},{190,140}, + {-28,140},{-28,100},{-22,100}}, color={255,0,255})); + connect(or2.y, and4.u2) annotation (Line(points={{2,170},{6,170},{6,152},{158, + 152}}, color={255,0,255})); +annotation ( + defaultComponentName="upProCon", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-240,-320},{240,320}}), graphics={ + Rectangle( + extent={{-238,318},{158,202}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-40,302},{138,260}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="The Change block in default has initial input of zero. +This is to avoid the initial edge.")}), + Icon(coordinateSystem(extent={{-100,-200},{100,200}}), graphics={ + Rectangle( + extent={{-100,-200},{100,200}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + borderPattern=BorderPattern.Raised), + Text( + extent={{-120,240},{120,200}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-10,120},{10,-140}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,160},{-40,120},{0,120},{40,120},{0,160}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,198},{-58,186}}, + textColor={255,127,0}, + textString="uStaSet"), + Text( + extent={{-100,106},{-70,94}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-96,58},{-32,44}}, + textColor={255,0,255}, + textString="uChiConIsoVal"), + Text( + extent={{-96,-12},{-38,-26}}, + textColor={255,0,255}, + textString="uConWatReq"), + Text( + extent={{-100,-34},{-64,-46}}, + textColor={255,0,255}, + textString="uWSE", + visible=have_WSE), + Text( + extent={{-98,-184},{-48,-196}}, + textColor={255,0,255}, + textString="uChiWatReq"), + Text( + extent={{-96,128},{-60,116}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiLoa", + visible=need_reduceChillerDemand), + Text( + extent={{-96,84},{-40,70}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{-96,-50},{-12,-68}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uConWatPumSpeSet", + visible=not have_fixSpeConWatPum), + Text( + extent={{-96,-72},{-22,-86}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uConWatPumSpe", + visible=not have_fixSpeConWatPum), + Text( + extent={{-96,-164},{-36,-176}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uChiWatIsoVal"), + Text( + extent={{60,198},{100,186}}, + textColor={255,0,255}, + textString="yStaPro"), + Text( + extent={{52,78},{98,66}}, + textColor={255,0,255}, + textString="yTowStaUp"), + Text( + extent={{58,38},{96,26}}, + textColor={255,0,255}, + textString="yLeaPum"), + Text( + extent={{48,-82},{96,-96}}, + textColor={255,0,255}, + textString="yChiHeaCon"), + Text( + extent={{76,-162},{100,-174}}, + textColor={255,0,255}, + textString="yChi"), + Text( + extent={{60,158},{96,146}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiDem", + visible=need_reduceChillerDemand), + Text( + extent={{28,118},{98,104}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatMinFloSet"), + Text( + extent={{18,-4},{98,-14}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yDesConWatPumSpe", + visible=not have_fixSpeConWatPum), + Text( + extent={{36,-130},{96,-146}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yChiWatIsoVal"), + Text( + extent={{34,-42},{96,-56}}, + textColor={255,127,0}, + textString="yConWatPumNum"), + Text( + extent={{-100,168},{-60,156}}, + textColor={255,0,255}, + textString="uChiSet"), + Text( + extent={{-98,36},{-56,24}}, + textColor={255,127,0}, + textString="uChiSta"), + Text( + extent={{-98,-144},{-48,-156}}, + textColor={255,0,255}, + textString="uChiHeaCon"), + Text( + extent={{-96,-122},{-38,-136}}, + textColor={255,0,255}, + textString="uConWatPum", + visible=have_fixSpeConWatPum), + Text( + extent={{-96,-92},{-30,-106}}, + textColor={255,0,255}, + textString="uEnaPlaConIso"), + Text( + extent={{-96,16},{-24,2}}, + textColor={255,0,255}, + textString="uEnaPlaConPum"), + Text( + extent={{50,-182},{98,-196}}, + textColor={255,0,255}, + textString="yEndStaTri")}), +Documentation(info=" +

+Block that controls devices when there is a stage-up command. This sequence is for +water-cooled primary-only parallel chiller plants with headered chilled water pumps +and headered condenser water pumps, or air-cooled primary-only parallel chiller +plants with headered chilled water pumps. +This development is based on ASHRAE Guideline 36-2021, +section 5.20.4.16, which specifies the step-by-step control of +devices during chiller staging up process. +

+
    +
  1. +Identify the chiller(s) that should be enabled (and disabled, if have_ponyChiller=true). +This is implemented in block nexChi. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller +for more decriptions. +
  2. +
  3. +Command operating chillers to reduce demand to 75% (chiDemRedFac) of +their current load (uChiLoa). Wait until actual demand < 80% of +current load up to a maximum of 5 minutes (holChiDemTim) before proceeding. +This is implemented in block chiDemRed. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ReduceDemand +for more decriptions. +
  4. +
  5. +Reset the minimum chilled water flow setpoint, + +The minimum flow setpoint is reset in block minChiWatFlo +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint). +Block minBypSet checks if the new setpoint is achieved +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.ResetMinBypass). +
  6. +
  7. +Start the next condenser water pump and/or change condenser water pump speed +to that required of the new stage. Wait 10 seconds (thrTimEnb). +Block enaNexCWP identifies chiller stage for the condenser water pump +control +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.EnableCWPump) +and block conWatPumCon checks if the condenser water pumps have been reset +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.CondenserWater.Controller). +
  8. +
  9. +Enabled head pressure control for the chiller being enabled. Wait 30 seconds (waiTim). +This is implemented in block enaHeaCon. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.HeadControl +for more decriptions. +
  10. +
  11. +Slowly (chaChiWatIsoTim) open chilled water isolation valve of the chiller +being enabled. The valve timing should be determined in the fields. +This is implemented in block enaChiIsoVal. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.CHWIsoVal +for more decriptions. +
  12. +
  13. +End the staging up process: + +These are implemented in block endUp. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.UpEnd +for more decriptions. +
  14. +
+", revisions=" + +")); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithOnOff.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithOnOff.mo new file mode 100644 index 00000000000..f4975c754fc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithOnOff.mo @@ -0,0 +1,437 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Validation; +model DownWithOnOff + "Validate sequence of staging down process which requires enabling one chiller and disabling another chiller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Down + dowProCon( + final nChi=2, + final totSta=4, + final have_ponyChiller=true, + final need_reduceChillerDemand=true, + final chaChiWatIsoTim=300, + final staVec={0,0.5,1,2}, + final desConWatPumSpe={0,0.5,0.75,0.6}, + final desConWatPumNum={0,1,1,2}, + final byPasSetTim=300, + final minFloSet={0.5,1}, + final maxFloSet={1,1.5}) + "Stage down process when does require chiller on and off" + annotation (Placement(transformation(extent={{20,60},{40,100}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + delayTime=1, + delayOnInit=true) + "Delay the true input" + annotation (Placement(transformation(extent={{80,210},{100,230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiWatFlo1( + final height=0.5 - 5/3, + final duration=300, + final offset=5/3, + final startTime=800) "Chilled water flow rate" + annotation (Placement(transformation(extent={{-200,-100},{-180,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.05, final period=2400) + "Boolean pulse" + annotation (Placement(transformation(extent={{-200,130},{-180,150}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow1 "Stage down command" + annotation (Placement(transformation(extent={{-160,130},{-140,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa1( + final k=2) "Chiller load" + annotation (Placement(transformation(extent={{-200,-60},{-180,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant yOpeParLoaRatMin1( + final k=0.78) + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-200,20},{-180,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpe1(final k=1) + "Full open isolation valve" + annotation (Placement(transformation(extent={{-200,-260},{-180,-240}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerLoa( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-200,-20},{-180,0}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta( + final pre_u_start=false) "Chiller one status" + annotation (Placement(transformation(extent={{100,30},{120,50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiOneLoa "Chiller one load" + annotation (Placement(transformation(extent={{-120,-20},{-100,0}}))); + Buildings.Controls.OBC.CDL.Reals.Switch IsoValOne "Logical switch" + annotation (Placement(transformation(extent={{-120,-220},{-100,-200}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol3[2]( + final samplePeriod=fill(10, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-180},{120,-160}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant wseSta1( + final k=false) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-200,-300},{-180,-280}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol4( + final samplePeriod=10) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-220},{120,-200}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol5( + final samplePeriod=20) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-260},{120,-240}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiTwoLoa "Chiller two load" + annotation (Placement(transformation(extent={{-120,-60},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta( + final pre_u_start=true) "Chiller two status" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer3[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{80,80},{100,100}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol6( + final samplePeriod=10) "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{80,110},{100,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa3(final k=1) + "Chiller load" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiLoa2[2] "Chiller load" + annotation (Placement(transformation(extent={{140,110},{160,130}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol7( + final samplePeriod=10) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{180,110},{200,130}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneHea( + final pre_u_start=false) + "Chiller one head pressure control" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoHea( + final pre_u_start=true) + "Chiller two head pressure control" + annotation (Placement(transformation(extent={{100,-140},{120,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerOpe2( + final k=0) "Closed isolation valve" + annotation (Placement(transformation(extent={{-200,-220},{-180,-200}}))); + Buildings.Controls.OBC.CDL.Reals.Switch IsoValTwo "Logical switch" + annotation (Placement(transformation(extent={{-120,-260},{-100,-240}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi2[2]( + final k={false,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{-200,90},{-180,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi2[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{-200,160},{-180,180}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=2) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-120,130},{-100,150}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet2[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{-80,130},{-60,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant upSta2( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,190},{-180,210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dowSta2( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-200,230},{-180,250}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet2 + "Stage setpoint index" + annotation (Placement(transformation(extent={{-80,210},{-60,230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staOne( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-200,-140},{-180,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staTwo( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,-180},{-180,-160}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiSta "Current chiller stage" + annotation (Placement(transformation(extent={{-120,-160},{-100,-140}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger sta "Current chiller stage" + annotation (Placement(transformation(extent={{-80,-160},{-60,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal( + final k=false) + "Logical false" + annotation (Placement(transformation(extent={{120,180},{140,200}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Check if the down process has ended" + annotation (Placement(transformation(extent={{120,210},{140,230}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "True when it is not in process" + annotation (Placement(transformation(extent={{160,210},{180,230}}))); + +equation + connect(booPul1.y, staDow1.u) + annotation (Line(points={{-178,140},{-162,140}}, color={255,0,255})); + connect(staDow1.y, chiOneLoa.u2) + annotation (Line(points={{-138,140},{-130,140},{-130,-10},{-122,-10}}, + color={255,0,255})); + connect(staDow1.y, chiTwoLoa.u2) + annotation (Line(points={{-138,140},{-130,140},{-130,-50},{-122,-50}}, + color={255,0,255})); + connect(chiLoa1.y, chiTwoLoa.u3) + annotation (Line(points={{-178,-50},{-160,-50},{-160,-58},{-122,-58}}, + color={0,0,127})); + connect(zerLoa.y, chiOneLoa.u3) + annotation (Line(points={{-178,-10},{-160,-10},{-160,-18},{-122,-18}}, + color={0,0,127})); + connect(chiLoa3.y, chiLoa2[1].u1) + annotation (Line(points={{102,160},{120,160},{120,128},{138,128}}, + color={0,0,127})); + connect(zerOrdHol6.y, chiLoa2[2].u1) + annotation (Line(points={{102,120},{120,120},{120,128},{138,128}}, + color={0,0,127})); + connect(zer3.y, chiLoa2.u3) + annotation (Line(points={{102,90},{120,90},{120,112},{138,112}}, + color={0,0,127})); + connect(dowProCon.yChiDem[2], zerOrdHol6.u) + annotation (Line(points={{42,95.5},{60,95.5},{60,120},{78,120}}, + color={0,0,127})); + connect(dowProCon.yChi[1], chiOneSta.u) + annotation (Line(points={{42,91.5},{60,91.5},{60,40},{98,40}}, + color={255,0,255})); + connect(dowProCon.yChi[2], chiTwoSta.u) + annotation (Line(points={{42,92.5},{62,92.5},{62,0},{98,0}}, color={255,0,255})); + connect(chiOneSta.y, chiLoa2[1].u2) + annotation (Line(points={{122,40},{130,40},{130,120},{138,120}}, + color={255,0,255})); + connect(chiTwoSta.y, chiLoa2[2].u2) + annotation (Line(points={{122,0},{132,0},{132,120},{138,120}}, + color={255,0,255})); + connect(chiLoa2[2].y, chiTwoLoa.u1) + annotation (Line(points={{162,120},{170,120},{170,-70},{-140,-70},{-140,-42}, + {-122,-42}}, color={0,0,127})); + connect(chiLoa2[1].y, zerOrdHol7.u) + annotation (Line(points={{162,120},{178,120}}, color={0,0,127})); + connect(zerOrdHol7.y, chiOneLoa.u1) + annotation (Line(points={{202,120},{210,120},{210,-30},{-140,-30},{-140,-2}, + {-122,-2}}, color={0,0,127})); + connect(yOpeParLoaRatMin1.y, dowProCon.yOpeParLoaRatMin) + annotation (Line(points={{-178,30},{-126,30},{-126,93},{18,93}}, + color={0,0,127})); + connect(chiOneLoa.y, dowProCon.uChiLoa[1]) + annotation (Line(points={{-98,-10},{-90,-10},{-90,90.5},{18,90.5}}, + color={0,0,127})); + connect(chiTwoLoa.y, dowProCon.uChiLoa[2]) + annotation (Line(points={{-98,-50},{-88,-50},{-88,91.5},{18,91.5}}, + color={0,0,127})); + connect(chiOneSta.y, dowProCon.uChi[1]) + annotation (Line(points={{122,40},{130,40},{130,20},{-80,20},{-80,88.5}, + {18,88.5}}, color={255,0,255})); + connect(chiTwoSta.y, dowProCon.uChi[2]) + annotation (Line(points={{122,0},{132,0},{132,-20},{-78,-20},{-78,89.5}, + {18,89.5}}, color={255,0,255})); + connect(chiWatFlo1.y, dowProCon.VChiWat_flow) + annotation (Line(points={{-178,-90},{-76,-90},{-76,87},{18,87}}, + color={0,0,127})); + connect(dowProCon.yChiHeaCon[1], chiOneHea.u) + annotation (Line(points={{42,76.5},{58,76.5},{58,-90},{98,-90}}, + color={255,0,255})); + connect(dowProCon.yChiHeaCon[2], chiTwoHea.u) + annotation (Line(points={{42,77.5},{56,77.5},{56,-130},{98,-130}}, + color={255,0,255})); + connect(chiOneHea.y, dowProCon.uChiHeaCon[1]) + annotation (Line(points={{122,-90},{140,-90},{140,-60},{-32,-60},{-32,80.5}, + {18,80.5}}, color={255,0,255})); + connect(chiTwoHea.y, dowProCon.uChiHeaCon[2]) + annotation (Line(points={{122,-130},{140,-130},{140,-112},{-34,-112},{-34,81.5}, + {18,81.5}}, color={255,0,255})); + connect(zerOpe2.y, IsoValOne.u3) + annotation (Line(points={{-178,-210},{-160,-210},{-160,-218},{-122,-218}}, + color={0,0,127})); + connect(fulOpe1.y, IsoValTwo.u3) + annotation (Line(points={{-178,-250},{-160,-250},{-160,-258},{-122,-258}}, + color={0,0,127})); + connect(staDow1.y, IsoValOne.u2) + annotation (Line(points={{-138,140},{-130,140},{-130,-210},{-122,-210}}, + color={255,0,255})); + connect(staDow1.y, IsoValTwo.u2) + annotation (Line(points={{-138,140},{-130,140},{-130,-250},{-122,-250}}, + color={255,0,255})); + connect(dowProCon.yChiWatIsoVal, zerOrdHol3.u) + annotation (Line(points={{42,84},{72,84},{72,-170},{98,-170}}, + color={0,0,127})); + connect(zerOrdHol3[1].y, IsoValOne.u1) + annotation (Line(points={{122,-170},{140,-170},{140,-190},{-140,-190}, + {-140, -202},{-122,-202}}, color={0,0,127})); + connect(zerOrdHol3[2].y, IsoValTwo.u1) + annotation (Line(points={{122,-170},{140,-170},{140,-190},{-140,-190}, + {-140,-242},{-122,-242}}, color={0,0,127})); + connect(IsoValOne.y, dowProCon.uChiWatIsoVal[1]) + annotation (Line(points={{-98,-210},{-44,-210},{-44,77.5},{18,77.5}}, + color={0,0,127})); + connect(IsoValTwo.y, dowProCon.uChiWatIsoVal[2]) + annotation (Line(points={{-98,-250},{-42,-250},{-42,78.5},{18,78.5}}, + color={0,0,127})); + connect(chiOneSta.y, dowProCon.uChiWatReq[1]) + annotation (Line(points={{122,40},{130,40},{130,20},{-30,20},{-30,74.5}, + {18,74.5}}, color={255,0,255})); + connect(chiTwoSta.y, dowProCon.uChiWatReq[2]) + annotation (Line(points={{122,0},{132,0},{132,-20},{-28,-20},{-28,75.5}, + {18,75.5}}, color={255,0,255})); + connect(chiOneSta.y, dowProCon.uConWatReq[1]) + annotation (Line(points={{122,40},{130,40},{130,20},{-26,20},{-26,72.5}, + {18,72.5}}, color={255,0,255})); + connect(chiTwoSta.y, dowProCon.uConWatReq[2]) + annotation (Line(points={{122,0},{132,0},{132,-20},{-24,-20},{-24,73.5}, + {18,73.5}}, color={255,0,255})); + connect(chiOneSta.y, dowProCon.uChiConIsoVal[1]) + annotation (Line(points={{122,40},{130,40},{130,20},{-22,20},{-22,69.5}, + {18,69.5}}, color={255,0,255})); + connect(chiTwoSta.y, dowProCon.uChiConIsoVal[2]) + annotation (Line(points={{122,0},{132,0},{132,-20},{-20,-20},{-20,70.5}, + {18,70.5}}, color={255,0,255})); + connect(wseSta1.y, dowProCon.uWSE) + annotation (Line(points={{-178,-290},{-10,-290},{-10,67},{18,67}}, + color={255,0,255})); + connect(dowProCon.yDesConWatPumSpe, zerOrdHol4.u) + annotation (Line(points={{42,69},{78,69},{78,-210},{98,-210}}, + color={0,0,127})); + connect(zerOrdHol4.y, zerOrdHol5.u) + annotation (Line(points={{122,-210},{140,-210},{140,-230},{80,-230},{80,-250}, + {98,-250}}, color={0,0,127})); + connect(zerOrdHol4.y, dowProCon.uConWatPumSpeSet) + annotation (Line(points={{122,-210},{140,-210},{140,-230},{-8,-230},{-8,65}, + {18,65}}, color={0,0,127})); + connect(zerOrdHol5.y, dowProCon.uConWatPumSpe) + annotation (Line(points={{122,-250},{140,-250},{140,-270},{-6,-270},{-6,63}, + {18,63}}, color={0,0,127})); + connect(staDow1.y, booRep2.u) + annotation (Line(points={{-138,140},{-122,140}}, color={255,0,255})); + connect(staTwoChi2.y, chiSet2.u3) annotation (Line(points={{-178,100},{-90,100}, + {-90,132},{-82,132}}, color={255,0,255})); + connect(booRep2.y, chiSet2.u2) + annotation (Line(points={{-98,140},{-82,140}}, color={255,0,255})); + connect(staOneChi2.y, chiSet2.u1) annotation (Line(points={{-178,170},{-90,170}, + {-90,148},{-82,148}}, color={255,0,255})); + connect(dowSta2.y, swi2.u1) annotation (Line(points={{-178,240},{-140,240},{-140, + 228},{-122,228}}, color={0,0,127})); + connect(upSta2.y, swi2.u3) annotation (Line(points={{-178,200},{-140,200},{-140, + 212},{-122,212}}, color={0,0,127})); + connect(staDow1.y, swi2.u2) annotation (Line(points={{-138,140},{-130,140},{-130, + 220},{-122,220}}, color={255,0,255})); + connect(swi2.y, staSet2.u) + annotation (Line(points={{-98,220},{-82,220}}, color={0,0,127})); + connect(chiSet2.y, dowProCon.uChiSet) annotation (Line(points={{-58,140},{-40, + 140},{-40,97},{18,97}}, color={255,0,255})); + connect(staSet2.y, dowProCon.uStaSet) annotation (Line(points={{-58,220},{-36, + 220},{-36,99},{18,99}}, color={255,127,0})); + connect(staOne.y, chiSta.u1) annotation (Line(points={{-178,-130},{-160,-130}, + {-160,-142},{-122,-142}}, color={0,0,127})); + connect(staTwo.y, chiSta.u3) annotation (Line(points={{-178,-170},{-160,-170}, + {-160,-158},{-122,-158}}, color={0,0,127})); + connect(chiSta.y, sta.u) + annotation (Line(points={{-98,-150},{-82,-150}}, color={0,0,127})); + connect(falEdg.y, lat.u) + annotation (Line(points={{142,220},{158,220}}, color={255,0,255})); + connect(fal.y, lat.clr) annotation (Line(points={{142,190},{150,190},{150,214}, + {158,214}}, color={255,0,255})); + connect(lat.y, chiSta.u2) annotation (Line(points={{182,220},{214,220},{214,-104}, + {-140,-104},{-140,-150},{-122,-150}}, color={255,0,255})); + connect(sta.y, dowProCon.uChiSta) annotation (Line(points={{-58,-150},{-50, + -150},{-50,84},{18,84}}, color={255,127,0})); + connect(dowProCon.yStaPro, truDel.u) annotation (Line(points={{42,99},{50,99}, + {50,220},{78,220}}, color={255,0,255})); + connect(truDel.y, falEdg.u) + annotation (Line(points={{102,220},{118,220}}, color={255,0,255})); +annotation ( + experiment(StopTime=2400, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithOnOff.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Down. +

+

+It shows a process of staging down from stage 2 which requires large chiller 2 +being enabled to stage 1 which requires small chiller 1 being enabled and chiller +2 being disabled. +

+ +

+It demonstrates process as below: +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-320},{220,320}}), + graphics={ + Text( + extent={{-194,276},{-4,260}}, + textColor={0,0,127}, + textString="to stage 1 which only has small chiller enabled (chiller 1)."), + Text( + extent={{-194,288},{-6,278}}, + textColor={0,0,127}, + textString="from stage 2 which only has large chiller enabled (chiller 2), "), + Text( + extent={{-204,300},{-156,292}}, + textColor={0,0,127}, + textString="Stage down:")})); +end DownWithOnOff; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithoutOnOff.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithoutOnOff.mo new file mode 100644 index 00000000000..63d67bf79c6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithoutOnOff.mo @@ -0,0 +1,304 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Validation; +model DownWithoutOnOff + "Validate sequence of staging down process which does require chiller ON" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Down + dowProCon( + final nChi=2, + final totSta=4, + final need_reduceChillerDemand=true, + final chaChiWatIsoTim=300, + final staVec={0,0.5,1,2}, + final desConWatPumSpe={0,0.5,0.75,0.6}, + final desConWatPumNum={0,1,1,2}, + final byPasSetTim=300, + final minFloSet={1,1}, + final maxFloSet={1.5,1.5}) + "Stage down process when does not require chiller on and off" + annotation (Placement(transformation(extent={{40,50},{60,90}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiWatFlo( + final height=-1, + final duration=300, + final offset=2, + final startTime=800) "Chilled water flow rate" + annotation (Placement(transformation(extent={{-140,-110},{-120,-90}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,-210},{-40,-190}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul(final width=0.05, + final period=1500) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,120},{-120,140}}))); + Buildings.Controls.OBC.CDL.Logical.Not staDow "Stage down command" + annotation (Placement(transformation(extent={{-100,120},{-80,140}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa[2]( + final k=fill(2, 2)) + "Chiller load" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant yOpeParLoaRatMin( + final k=0.78) "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpe[2]( + final k=fill(1, 2)) "Full open isolation valve" + annotation (Placement(transformation(extent={{-140,-240},{-120,-220}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{-140,-70},{-120,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre2[2]( + final pre_u_start=fill(true,2)) "Break algebraic loop" + annotation (Placement(transformation(extent={{100,30},{120,50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch IsoVal[2] "Logical switch" + annotation (Placement(transformation(extent={{-20,-240},{0,-220}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2]( + final samplePeriod=fill(10, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant wseSta(final k=false) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-140,-280},{-120,-260}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=10) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2( + final samplePeriod=20) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-130},{120,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi2[2](final k={ + true,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{-140,90},{-120,110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi2[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{-140,150},{-120,170}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2(final nout=2) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,120},{-40,140}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet2[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{-20,120},{0,140}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet2 + "Stage setpoint index" + annotation (Placement(transformation(extent={{-20,200},{0,220}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-60,200},{-40,220}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant upSta2(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,180},{-120,200}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dowSta2(final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-140,220},{-120,240}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staOne(final k=1) "Stage one" + annotation (Placement(transformation(extent={{-140,-150},{-120,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staTwo(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,-190},{-120,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiSta "Current chiller stage" + annotation (Placement(transformation(extent={{-60,-170},{-40,-150}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger sta "Current chiller stage" + annotation (Placement(transformation(extent={{-20,-170},{0,-150}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Check if the down process has ended" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal(final k=false) + "Logical false" + annotation (Placement(transformation(extent={{80,100},{100,120}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "True when it is not in process" + annotation (Placement(transformation(extent={{120,130},{140,150}}))); + +equation + connect(booPul.y,staDow. u) + annotation (Line(points={{-118,130},{-102,130}}, color={255,0,255})); + connect(yOpeParLoaRatMin.y, dowProCon.yOpeParLoaRatMin) + annotation (Line(points={{-118,20},{-58,20},{-58,83},{38,83}}, + color={0,0,127})); + connect(dowProCon.yChi, pre2.u) + annotation (Line(points={{62,82},{94,82},{94,40},{98,40}}, + color={255,0,255})); + connect(pre2.y, swi1.u2) + annotation (Line(points={{122,40},{140,40},{140,0},{-80,0},{-80,-40},{-62,-40}}, + color={255,0,255})); + connect(chiLoa.y, swi1.u1) + annotation (Line(points={{-118,-20},{-100,-20},{-100,-32},{-62,-32}}, + color={0,0,127})); + connect(zer1.y, swi1.u3) + annotation (Line(points={{-118,-60},{-100,-60},{-100,-48},{-62,-48}}, + color={0,0,127})); + connect(swi1.y, dowProCon.uChiLoa) + annotation (Line(points={{-38,-40},{-30,-40},{-30,81},{38,81}}, + color={0,0,127})); + connect(pre2.y, dowProCon.uChi) + annotation (Line(points={{122,40},{140,40},{140,0},{-28,0},{-28,79},{38,79}}, + color={255,0,255})); + connect(chiWatFlo.y, dowProCon.VChiWat_flow) + annotation (Line(points={{-118,-100},{-26,-100},{-26,77},{38,77}}, + color={0,0,127})); + connect(pre2.y, dowProCon.uChiHeaCon) + annotation (Line(points={{122,40},{140,40},{140,0},{12,0},{12,71},{38,71}}, + color={255,0,255})); + connect(staDow.y, booRep.u) + annotation (Line(points={{-78,130},{-70,130},{-70,-200},{-62,-200}}, + color={255,0,255})); + connect(booRep.y, IsoVal.u2) + annotation (Line(points={{-38,-200},{-30,-200},{-30,-230},{-22,-230}}, + color={255,0,255})); + connect(fulOpe.y, IsoVal.u3) + annotation (Line(points={{-118,-230},{-100,-230},{-100,-238},{-22,-238}}, + color={0,0,127})); + connect(dowProCon.yChiWatIsoVal, zerOrdHol.u) + annotation (Line(points={{62,74},{88,74},{88,-30},{98,-30}}, + color={0,0,127})); + connect(zerOrdHol.y, IsoVal.u1) + annotation (Line(points={{122,-30},{150,-30},{150,-190},{-26,-190},{-26,-222}, + {-22,-222}}, color={0,0,127})); + connect(IsoVal.y, dowProCon.uChiWatIsoVal) + annotation (Line(points={{2,-230},{14,-230},{14,68},{38,68}}, + color={0,0,127})); + connect(pre2.y, dowProCon.uChiWatReq) + annotation (Line(points={{122,40},{140,40},{140,0},{16,0},{16,65},{38,65}}, + color={255,0,255})); + connect(pre2.y, dowProCon.uConWatReq) + annotation (Line(points={{122,40},{140,40},{140,0},{18,0},{18,63},{38,63}}, + color={255,0,255})); + connect(pre2.y, dowProCon.uChiConIsoVal) + annotation (Line(points={{122,40},{140,40},{140,0},{20,0},{20,60},{38,60}}, + color={255,0,255})); + connect(wseSta.y, dowProCon.uWSE) + annotation (Line(points={{-118,-270},{22,-270},{22,57},{38,57}}, + color={255,0,255})); + connect(dowProCon.yDesConWatPumSpe, zerOrdHol1.u) + annotation (Line(points={{62,59},{80,59},{80,-80},{98,-80}}, + color={0,0,127})); + connect(zerOrdHol1.y, dowProCon.uConWatPumSpeSet) + annotation (Line(points={{122,-80},{140,-80},{140,-160},{24,-160},{24,55},{ + 38,55}}, + color={0,0,127})); + connect(zerOrdHol1.y, zerOrdHol2.u) + annotation (Line(points={{122,-80},{140,-80},{140,-100},{80,-100},{80,-120}, + {98,-120}}, color={0,0,127})); + connect(zerOrdHol2.y, dowProCon.uConWatPumSpe) + annotation (Line(points={{122,-120},{130,-120},{130,-140},{26,-140},{26,53}, + {38,53}}, color={0,0,127})); + connect(staDow.y, booRep2.u) + annotation (Line(points={{-78,130},{-62,130}}, color={255,0,255})); + connect(staTwoChi2.y, chiSet2.u3) annotation (Line(points={{-118,100},{-30,100}, + {-30,122},{-22,122}}, color={255,0,255})); + connect(booRep2.y, chiSet2.u2) + annotation (Line(points={{-38,130},{-22,130}}, color={255,0,255})); + connect(staOneChi2.y, chiSet2.u1) annotation (Line(points={{-118,160},{-30,160}, + {-30,138},{-22,138}}, color={255,0,255})); + connect(upSta2.y, swi2.u3) annotation (Line(points={{-118,190},{-100,190},{-100, + 202},{-62,202}}, color={0,0,127})); + connect(dowSta2.y, swi2.u1) annotation (Line(points={{-118,230},{-100,230},{-100, + 218},{-62,218}}, color={0,0,127})); + connect(swi2.y, staSet2.u) + annotation (Line(points={{-38,210},{-22,210}}, color={0,0,127})); + connect(staDow.y, swi2.u2) annotation (Line(points={{-78,130},{-70,130},{-70,210}, + {-62,210}}, color={255,0,255})); + connect(chiSet2.y, dowProCon.uChiSet) annotation (Line(points={{2,130},{12, + 130},{12,87},{38,87}}, color={255,0,255})); + connect(staSet2.y, dowProCon.uStaSet) annotation (Line(points={{2,210},{20, + 210},{20,89},{38,89}}, color={255,127,0})); + connect(staOne.y, chiSta.u1) annotation (Line(points={{-118,-140},{-100,-140}, + {-100,-152},{-62,-152}}, color={0,0,127})); + connect(staTwo.y, chiSta.u3) annotation (Line(points={{-118,-180},{-100,-180}, + {-100,-168},{-62,-168}}, color={0,0,127})); + connect(chiSta.y, sta.u) + annotation (Line(points={{-38,-160},{-22,-160}}, color={0,0,127})); + connect(dowProCon.yStaPro, falEdg.u) annotation (Line(points={{62,89},{70,89}, + {70,140},{78,140}}, color={255,0,255})); + connect(falEdg.y, lat.u) + annotation (Line(points={{102,140},{118,140}}, color={255,0,255})); + connect(fal.y, lat.clr) annotation (Line(points={{102,110},{110,110},{110,134}, + {118,134}}, color={255,0,255})); + connect(lat.y, chiSta.u2) annotation (Line(points={{142,140},{154,140},{154,-180}, + {-80,-180},{-80,-160},{-62,-160}}, color={255,0,255})); + connect(sta.y, dowProCon.uChiSta) annotation (Line(points={{2,-160},{10,-160}, + {10,74},{38,74}}, color={255,127,0})); + +annotation ( + experiment(StopTime=1500, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithoutOnOff.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Down. +

+

+It shows a process of staging down from stage 2 which requires chiller 1 and chiller 2 +being enabled to stage 1 which requires only chiller 1 being enabled. +

+ +

+It demonstrates process as below: +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-300},{160,300}}), + graphics={ + Text( + extent={{-144,294},{-96,286}}, + textColor={0,0,127}, + textString="Stage down:"), + Text( + extent={{-134,282},{26,272}}, + textColor={0,0,127}, + textString="from stage 2 which has chiller one and two enabled, "), + Text( + extent={{-138,270},{-36,256}}, + textColor={0,0,127}, + textString="to stage 1 which only has chiller 1.")})); +end DownWithoutOnOff; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithOnOff.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithOnOff.mo new file mode 100644 index 00000000000..941a3e5a8c5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithOnOff.mo @@ -0,0 +1,392 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Validation; +model UpWithOnOff + "Validate sequence of staging up process which does require chiller OFF" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Up upProCon( + final nChi=2, + final totSta=4, + final have_ponyChiller=true, + final have_fixSpeConWatPum=false, + final need_reduceChillerDemand=true, + final chaChiWatIsoTim=300, + final staVec={0,0.5,1,2}, + final desConWatPumSpe={0,0.5,0.75,0.6}, + final desConWatPumNum={0,1,1,2}, + final byPasSetTim=300, + final minFloSet={0.5,1}, + final maxFloSet={1,1.5}) + "Stage up process when does not require chiller off" + annotation (Placement(transformation(extent={{20,80},{40,120}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiWatFlo( + final height=5/3 - 0.5, + final duration=300, + final offset=0.5, + final startTime=500) "Chilled water flow rate" + annotation (Placement(transformation(extent={{-200,-70},{-180,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.075, + final period=2000) "Boolean pulse" + annotation (Placement(transformation(extent={{-200,110},{-180,130}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-160,110},{-140,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulLoa(final k=2) + "Full load" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerLoa( + final k=0) + "Zero load" + annotation (Placement(transformation(extent={{-200,-30},{-180,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta( + final pre_u_start=true) + "Break algebraic loop" + annotation (Placement(transformation(extent={{80,60},{100,80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch loaOne "Chiller load one" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2]( + final samplePeriod=fill(10, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{80,-190},{100,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant wseSta( + final k=false) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-200,-190},{-180,-170}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold conPumSpeSet( + final samplePeriod=10) "Design condenser water pump speed setpoint" + annotation (Placement(transformation(extent={{80,-30},{100,-10}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold conPumSpe( + final samplePeriod=20) "Condenser water pump speed" + annotation (Placement(transformation(extent={{80,-70},{100,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch loaTwo "Chiller load two" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer3[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{80,100},{100,120}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold chiTwoDem( + final samplePeriod=10) "Chiller two limited demand" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa3(final k=2) + "Chiller load" + annotation (Placement(transformation(extent={{80,160},{100,180}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiLoa[2] "Limited chiller load" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold chiTwoDem1( + final samplePeriod=10) "Limited chiller two demand" + annotation (Placement(transformation(extent={{180,130},{200,150}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta( + final pre_u_start=false) "Chiller two status" + annotation (Placement(transformation(extent={{80,20},{100,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerOpe( + final k=0) "Closed isolation valve" + annotation (Placement(transformation(extent={{-200,-270},{-180,-250}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant fulOpe( + final k=1) "Full open isolation valve" + annotation (Placement(transformation(extent={{-200,-230},{-180,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Switch IsoValOne "Logical switch" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Switch IsoValTwo "Logical switch" + annotation (Placement(transformation(extent={{-120,-270},{-100,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneHea( + final pre_u_start=true) + "Chiller one head pressure control" + annotation (Placement(transformation(extent={{80,-110},{100,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoHea( + final pre_u_start=false) + "Chiller two head pressure control" + annotation (Placement(transformation(extent={{80,-150},{100,-130}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol3( + final samplePeriod=20) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{80,-230},{100,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiWatFlo1 "Chilled water flow rate" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneHea1( + final pre_u_start=false) + "Chiller one head pressure control" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{-200,70},{-180,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi[2]( + final k={false,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{-200,150},{-180,170}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-120,110},{-100,130}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{-80,130},{-60,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dowSta( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-200,190},{-180,210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant upSta( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,220},{-180,240}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-120,200},{-100,220}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet + "Stage setpoint index" + annotation (Placement(transformation(extent={{-80,200},{-60,220}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staOne( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-200,-150},{-180,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staTwo( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,-110},{-180,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiSta "Current chiller stage" + annotation (Placement(transformation(extent={{-120,-130},{-100,-110}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger sta "Current chiller stage" + annotation (Placement(transformation(extent={{-80,-130},{-60,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal( + final k=false) + "Logical false" + annotation (Placement(transformation(extent={{140,170},{160,190}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Check if the up process has ended" + annotation (Placement(transformation(extent={{80,190},{100,210}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "True when it is not in process" + annotation (Placement(transformation(extent={{180,190},{200,210}}))); + +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-178,120},{-162,120}}, color={255,0,255})); + connect(fulLoa.y, loaOne.u3) annotation (Line(points={{-178,20},{-160,20},{-160, + 12},{-122,12}}, color={0,0,127})); + connect(zerLoa.y, loaTwo.u3) annotation (Line(points={{-178,-20},{-160,-20},{-160, + -28},{-122,-28}}, color={0,0,127})); + connect(staUp.y, loaOne.u2) annotation (Line(points={{-138,120},{-130,120},{-130, + 20},{-122,20}}, color={255,0,255})); + connect(staUp.y, loaTwo.u2) annotation (Line(points={{-138,120},{-130,120},{-130, + -20},{-122,-20}}, color={255,0,255})); + connect(upProCon.yChi[1], chiOneSta.u) annotation (Line(points={{42,82.5},{60, + 82.5},{60,70},{78,70}}, color={255,0,255})); + connect(upProCon.yChi[2], chiTwoSta.u) annotation (Line(points={{42,83.5},{58, + 83.5},{58,30},{78,30}}, color={255,0,255})); + connect(chiOneSta.y, chiLoa[1].u2) annotation (Line(points={{102,70},{130,70}, + {130,140},{138,140}}, color={255,0,255})); + connect(chiTwoSta.y, chiLoa[2].u2) annotation (Line(points={{102,30},{132,30}, + {132,140},{138,140}}, color={255,0,255})); + connect(upProCon.yChiDem[2], chiTwoDem.u) annotation (Line(points={{42,115.5}, + {60,115.5},{60,140},{78,140}}, color={0,0,127})); + connect(chiLoa3.y, chiLoa[1].u1) annotation (Line(points={{102,170},{120,170}, + {120,148},{138,148}}, color={0,0,127})); + connect(zer3.y, chiLoa.u3) annotation (Line(points={{102,110},{120,110},{120,132}, + {138,132}}, color={0,0,127})); + connect(chiLoa[2].y, chiTwoDem1.u) + annotation (Line(points={{162,140},{178,140}}, color={0,0,127})); + connect(chiLoa[1].y, loaOne.u1) annotation (Line(points={{162,140},{170,140},{ + 170,46},{-140,46},{-140,28},{-122,28}}, color={0,0,127})); + connect(chiTwoDem1.y, loaTwo.u1) annotation (Line(points={{202,140},{210,140}, + {210,0},{-140,0},{-140,-12},{-122,-12}}, color={0,0,127})); + connect(loaOne.y, upProCon.uChiLoa[1]) annotation (Line(points={{-98,20},{-60, + 20},{-60,111.5},{18,111.5}}, color={0,0,127})); + connect(loaTwo.y, upProCon.uChiLoa[2]) annotation (Line(points={{-98,-20},{-58, + -20},{-58,112.5},{18,112.5}}, color={0,0,127})); + connect(chiOneSta.y, upProCon.uChi[1]) annotation (Line(points={{102,70},{130, + 70},{130,50},{-56,50},{-56,109.5},{18,109.5}}, color={255,0,255})); + connect(chiTwoSta.y, upProCon.uChi[2]) annotation (Line(points={{102,30},{132, + 30},{132,10},{-54,10},{-54,110.5},{18,110.5}}, color={255,0,255})); + connect(zerOpe.y, IsoValTwo.u3) annotation (Line(points={{-178,-260},{-160,-260}, + {-160,-268},{-122,-268}}, color={0,0,127})); + connect(fulOpe.y, IsoValOne.u3) annotation (Line(points={{-178,-220},{-160,-220}, + {-160,-228},{-122,-228}}, color={0,0,127})); + connect(staUp.y, IsoValOne.u2) annotation (Line(points={{-138,120},{-130,120}, + {-130,-220},{-122,-220}}, color={255,0,255})); + connect(staUp.y, IsoValTwo.u2) annotation (Line(points={{-138,120},{-130,120}, + {-130,-260},{-122,-260}}, color={255,0,255})); + connect(upProCon.yChiWatIsoVal, zerOrdHol.u) annotation (Line(points={{42,86}, + {56,86},{56,-180},{78,-180}}, color={0,0,127})); + connect(zerOrdHol[1].y, IsoValOne.u1) annotation (Line(points={{102,-180},{120, + -180},{120,-200},{-140,-200},{-140,-212},{-122,-212}}, color={0,0,127})); + connect(zerOrdHol[2].y, IsoValTwo.u1) annotation (Line(points={{102,-180},{120, + -180},{120,-200},{-140,-200},{-140,-252},{-122,-252}}, color={0,0,127})); + connect(chiOneSta.y, upProCon.uChiConIsoVal[1]) annotation (Line(points={{102,70}, + {130,70},{130,50},{-50,50},{-50,104.5},{18,104.5}}, color={255,0,255})); + connect(chiTwoSta.y, upProCon.uChiConIsoVal[2]) annotation (Line(points={{102,30}, + {132,30},{132,10},{-48,10},{-48,105.5},{18,105.5}}, color={255,0,255})); + connect(chiOneSta.y, upProCon.uConWatReq[1]) annotation (Line(points={{102,70}, + {130,70},{130,50},{-44,50},{-44,97.5},{18,97.5}},color={255,0,255})); + connect(chiTwoSta.y, upProCon.uConWatReq[2]) annotation (Line(points={{102,30}, + {132,30},{132,10},{-42,10},{-42,98.5},{18,98.5}}, color={255,0,255})); + connect(wseSta.y, upProCon.uWSE) annotation (Line(points={{-178,-180},{-40,-180}, + {-40,96},{18,96}}, color={255,0,255})); + connect(upProCon.yDesConWatPumSpe, conPumSpeSet.u) annotation (Line(points={{42,99}, + {54,99},{54,-20},{78,-20}}, color={0,0,127})); + connect(conPumSpeSet.y, conPumSpe.u) annotation (Line(points={{102,-20},{120,-20}, + {120,-40},{60,-40},{60,-60},{78,-60}}, color={0,0,127})); + connect(conPumSpeSet.y, upProCon.uConWatPumSpeSet) annotation (Line(points={{102,-20}, + {120,-20},{120,-40},{-38,-40},{-38,94},{18,94}}, color={0,0,127})); + connect(conPumSpe.y, upProCon.uConWatPumSpe) annotation (Line(points={{102,-60}, + {120,-60},{120,-80},{-36,-80},{-36,92},{18,92}}, color={0,0,127})); + connect(chiOneHea.y, upProCon.uChiHeaCon[1]) annotation (Line(points={{102,-100}, + {120,-100},{120,-116},{-32,-116},{-32,84.5},{18,84.5}}, color={255,0,255})); + connect(chiTwoHea.y, upProCon.uChiHeaCon[2]) annotation (Line(points={{102,-140}, + {120,-140},{120,-124},{-34,-124},{-34,85.5},{18,85.5}}, color={255,0,255})); + connect(upProCon.yChiHeaCon[1], chiOneHea.u) annotation (Line(points={{42,90.5}, + {50,90.5},{50,-100},{78,-100}}, color={255,0,255})); + connect(upProCon.yChiHeaCon[2], chiTwoHea.u) annotation (Line(points={{42,91.5}, + {52,91.5},{52,-140},{78,-140}}, color={255,0,255})); + connect(IsoValOne.y, upProCon.uChiWatIsoVal[1]) annotation (Line(points={{-98, + -220},{-30,-220},{-30,82.5},{18,82.5}}, color={0,0,127})); + connect(IsoValTwo.y, upProCon.uChiWatIsoVal[2]) annotation (Line(points={{-98, + -260},{-28,-260},{-28,83.5},{18,83.5}}, color={0,0,127})); + connect(chiOneSta.y, upProCon.uChiWatReq[1]) annotation (Line(points={{102,70}, + {130,70},{130,50},{-26,50},{-26,80.5},{18,80.5}},color={255,0,255})); + connect(chiTwoSta.y, upProCon.uChiWatReq[2]) annotation (Line(points={{102,30}, + {132,30},{132,10},{-24,10},{-24,81.5},{18,81.5}}, color={255,0,255})); + connect(upProCon.yChiWatMinFloSet, zerOrdHol3.u) annotation (Line(points={{42,111}, + {48,111},{48,-220},{78,-220}}, color={0,0,127})); + connect(chiWatFlo.y, chiWatFlo1.u3) annotation (Line(points={{-178,-60},{-160, + -60},{-160,-68},{-122,-68}}, color={0,0,127})); + connect(zerOrdHol3.y, chiWatFlo1.u1) annotation (Line(points={{102,-220},{120, + -220},{120,-240},{-90,-240},{-90,-40},{-140,-40},{-140,-52},{-122,-52}}, + color={0,0,127})); + connect(chiWatFlo1.y, upProCon.VChiWat_flow) annotation (Line(points={{-98,-60}, + {-52,-60},{-52,107.6},{18,107.6}}, color={0,0,127})); + connect(upProCon.yTowStaUp, chiOneHea1.u) annotation (Line(points={{42,107},{46, + 107},{46,20},{-20,20},{-20,-20},{-2,-20}}, color={255,0,255})); + connect(chiOneHea1.y, chiWatFlo1.u2) annotation (Line(points={{22,-20},{40,-20}, + {40,-34},{-150,-34},{-150,-60},{-122,-60}}, color={255,0,255})); + connect(upSta.y, swi.u1) annotation (Line(points={{-178,230},{-160,230},{-160, + 218},{-122,218}}, color={0,0,127})); + connect(dowSta.y, swi.u3) annotation (Line(points={{-178,200},{-160,200},{-160, + 202},{-122,202}}, color={0,0,127})); + connect(swi.y, staSet.u) + annotation (Line(points={{-98,210},{-82,210}}, color={0,0,127})); + connect(booRep.y, chiSet.u2) annotation (Line(points={{-98,120},{-92,120},{-92, + 140},{-82,140}}, color={255,0,255})); + connect(staUp.y, booRep.u) + annotation (Line(points={{-138,120},{-122,120}}, color={255,0,255})); + connect(staOneChi.y, chiSet.u3) annotation (Line(points={{-178,80},{-88,80},{-88, + 132},{-82,132}}, color={255,0,255})); + connect(staTwoChi.y, chiSet.u1) annotation (Line(points={{-178,160},{-90,160}, + {-90,148},{-82,148}}, color={255,0,255})); + connect(staUp.y, swi.u2) annotation (Line(points={{-138,120},{-130,120},{-130, + 210},{-122,210}}, color={255,0,255})); + connect(staSet.y, upProCon.uStaSet) annotation (Line(points={{-58,210},{0,210}, + {0,119},{18,119}}, color={255,127,0})); + connect(chiSet.y, upProCon.uChiSet) annotation (Line(points={{-58,140},{-4,140}, + {-4,116},{18,116}}, color={255,0,255})); + connect(staTwo.y, chiSta.u1) annotation (Line(points={{-178,-100},{-160,-100}, + {-160,-112},{-122,-112}}, color={0,0,127})); + connect(staOne.y, chiSta.u3) annotation (Line(points={{-178,-140},{-160,-140}, + {-160,-128},{-122,-128}}, color={0,0,127})); + connect(chiSta.y, sta.u) + annotation (Line(points={{-98,-120},{-82,-120}}, color={0,0,127})); + connect(sta.y, upProCon.uChiSta) annotation (Line(points={{-58,-120},{-46,-120}, + {-46,103},{18,103}}, color={255,127,0})); + connect(upProCon.yStaPro, falEdg.u) annotation (Line(points={{42,119},{56,119}, + {56,200},{78,200}}, color={255,0,255})); + connect(falEdg.y, lat.u) + annotation (Line(points={{102,200},{178,200}}, color={255,0,255})); + connect(fal.y, lat.clr) annotation (Line(points={{162,180},{170,180},{170,194}, + {178,194}}, color={255,0,255})); + connect(lat.y, chiSta.u2) annotation (Line(points={{202,200},{214,200},{214,-84}, + {-140,-84},{-140,-120},{-122,-120}}, color={255,0,255})); + connect(wseSta.y, upProCon.uEnaPlaConPum) annotation (Line(points={{-178,-180}, + {-40,-180},{-40,101},{18,101}}, color={255,0,255})); + connect(wseSta.y, upProCon.uEnaPlaConIso) annotation (Line(points={{-178,-180}, + {-40,-180},{-40,90},{18,90}}, color={255,0,255})); + connect(chiLoa3.y, chiLoa[2].u1) annotation (Line(points={{102,170},{120,170}, + {120,148},{138,148}}, color={0,0,127})); +annotation ( + experiment(StopTime=2000, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithOnOff.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Up. +

+

+It shows a process of staging up from stage 1 which only requires small chiller 1 +being enabled, to stage 2 which only requires large chiller 2 being enabled. In +stage 1 and 2, the required minimum chilled water flow setpoints are 0.5 m3/s and +1.0 m3/s respectively. The process are below: +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-300},{220,300}}), + graphics={ + Text( + extent={{-208,294},{-160,286}}, + textColor={0,0,127}, + textString="Stage up:"), + Text( + extent={{-196,280},{-50,272}}, + textColor={0,0,127}, + textString="from stage 1 which has small chiller one been enabled, "), + Text( + extent={{-196,268},{-70,254}}, + textColor={0,0,127}, + textString="to stage 2 which has large chiller 2 been enabled.")})); +end UpWithOnOff; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithoutOnOff.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithoutOnOff.mo new file mode 100644 index 00000000000..0a52393dd5b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithoutOnOff.mo @@ -0,0 +1,281 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Validation; +model UpWithoutOnOff + "Validate sequence of staging up process which does not require chiller OFF" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Up upProCon( + final nChi=2, + final totSta=4, + final have_fixSpeConWatPum=false, + final need_reduceChillerDemand=true, + final chaChiWatIsoTim=300, + final staVec={0,0.5,1,2}, + final desConWatPumSpe={0,0.5,0.75,0.6}, + final desConWatPumNum={0,1,1,2}, + final byPasSetTim=300, + final minFloSet={1,1}, + final maxFloSet={1.5,1.5}) + "Stage up process when does not require chiller off" + annotation (Placement(transformation(extent={{40,48},{60,88}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiWatFlo( + final height=1, + final duration=300, + final offset=1, + final startTime=500) "Chilled water flow rate" + annotation (Placement(transformation(extent={{-140,-50},{-120,-30}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,-230},{-40,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.075, + final period=2000) + "Boolean pulse" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLoa[2]( + final k=fill(2, 2)) + "Chiller load" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant iniChiIsoVal[2]( + final k={1,0}) "Initial chilled water solation valve" + annotation (Placement(transformation(extent={{-140,-260},{-120,-240}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{-140,-10},{-120,10}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiStaRet[2]( + final pre_u_start={true,false}) "Chiller status return value" + annotation (Placement(transformation(extent={{100,60},{120,80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch IsoVal[2] "Logical switch" + annotation (Placement(transformation(extent={{-20,-260},{0,-240}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2]( + final samplePeriod=fill(10, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant wseSta(final k=false) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-140,-180},{-120,-160}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=10) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-70},{120,-50}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2( + final samplePeriod=20) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{100,-120},{120,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staOneChi[2]( + final k={true,false}) + "Vector of chillers status setpoint at stage one" + annotation (Placement(transformation(extent={{-140,62},{-120,82}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoChi[2]( + final k={true,true}) + "Vector of chillers status setpoint at stage two" + annotation (Placement(transformation(extent={{-140,140},{-120,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dowSta(final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-140,170},{-120,190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant upSta(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,210},{-120,230}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-60,190},{-40,210}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet + "Stage setpoint index" + annotation (Placement(transformation(extent={{-20,190},{0,210}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1(final nout=2) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,100},{-40,120}}))); + Buildings.Controls.OBC.CDL.Logical.Switch chiSet[2] + "Chiller status setpoint" + annotation (Placement(transformation(extent={{-20,100},{0,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staOne(final k=1) "Stage one" + annotation (Placement(transformation(extent={{-140,-140},{-120,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staTwo(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,-100},{-120,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiSta "Current chiller stage" + annotation (Placement(transformation(extent={{-60,-120},{-40,-100}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger sta "Current chiller stage" + annotation (Placement(transformation(extent={{-20,-120},{0,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal(final k=false) + "Logical false" + annotation (Placement(transformation(extent={{80,100},{100,120}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Check if the up process has ended" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "True when it is not in process" + annotation (Placement(transformation(extent={{120,130},{140,150}}))); + +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-118,110},{-102,110}}, color={255,0,255})); + connect(chiLoa.y, swi1.u1) + annotation (Line(points={{-118,40},{-100,40},{-100,28},{-62,28}}, + color={0,0,127})); + connect(zer1.y, swi1.u3) + annotation (Line(points={{-118,0},{-100,0},{-100,12},{-62,12}}, + color={0,0,127})); + connect(iniChiIsoVal.y, IsoVal.u3) + annotation (Line(points={{-118,-250},{-100,-250},{-100,-258},{-22,-258}}, + color={0,0,127})); + connect(upProCon.yChi, chiStaRet.u) annotation (Line(points={{62,51},{94,51},{ + 94,70},{98,70}}, color={255,0,255})); + connect(chiStaRet.y, swi1.u2) annotation (Line(points={{122,70},{140,70},{140, + 40},{-80,40},{-80,20},{-62,20}}, color={255,0,255})); + connect(swi1.y, upProCon.uChiLoa) annotation (Line(points={{-38,20},{-30,20},{ + -30,80},{38,80}}, color={0,0,127})); + connect(chiStaRet.y, upProCon.uChi) annotation (Line(points={{122,70},{140,70}, + {140,40},{-28,40},{-28,78},{38,78}}, color={255,0,255})); + connect(chiWatFlo.y, upProCon.VChiWat_flow) annotation (Line(points={{-118,-40}, + {-26,-40},{-26,75.6},{38,75.6}}, color={0,0,127})); + connect(chiStaRet.y, upProCon.uChiConIsoVal) annotation (Line(points={{122,70}, + {140,70},{140,40},{-24,40},{-24,73},{38,73}}, color={255,0,255})); + connect(chiStaRet.y, upProCon.uConWatReq) annotation (Line(points={{122,70},{ + 140,70},{140,40},{12,40},{12,66},{38,66}}, color={255,0,255})); + connect(wseSta.y, upProCon.uWSE) annotation (Line(points={{-118,-170},{14, + -170},{14,64},{38,64}}, color={255,0,255})); + connect(upProCon.yDesConWatPumSpe, zerOrdHol1.u) annotation (Line(points={{62,67}, + {80,67},{80,-60},{98,-60}}, color={0,0,127})); + connect(zerOrdHol1.y, upProCon.uConWatPumSpeSet) annotation (Line(points={{122,-60}, + {140,-60},{140,-140},{16,-140},{16,62},{38,62}}, color={0,0,127})); + connect(zerOrdHol1.y, zerOrdHol2.u) annotation (Line(points={{122,-60},{140,-60}, + {140,-90},{80,-90},{80,-110},{98,-110}}, color={0,0,127})); + connect(zerOrdHol2.y, upProCon.uConWatPumSpe) annotation (Line(points={{122, + -110},{130,-110},{130,-134},{18,-134},{18,60},{38,60}}, color={0,0,127})); + connect(chiStaRet.y, upProCon.uChiHeaCon) annotation (Line(points={{122,70},{ + 140,70},{140,40},{20,40},{20,53},{38,53}}, color={255,0,255})); + connect(staUp.y, booRep.u) annotation (Line(points={{-78,110},{-70,110},{-70,-220}, + {-62,-220}}, color={255,0,255})); + connect(booRep.y, IsoVal.u2) annotation (Line(points={{-38,-220},{-30,-220},{-30, + -250},{-22,-250}}, color={255,0,255})); + connect(upProCon.yChiWatIsoVal, zerOrdHol.u) annotation (Line(points={{62,54}, + {88,54},{88,-20},{98,-20}},color={0,0,127})); + connect(zerOrdHol.y, IsoVal.u1) annotation (Line(points={{122,-20},{150,-20},{ + 150,-190},{-80,-190},{-80,-242},{-22,-242}}, color={0,0,127})); + connect(IsoVal.y, upProCon.uChiWatIsoVal) annotation (Line(points={{2,-250},{22, + -250},{22,51},{38,51}}, color={0,0,127})); + connect(chiStaRet.y, upProCon.uChiWatReq) annotation (Line(points={{122,70},{ + 140,70},{140,40},{24,40},{24,49},{38,49}}, color={255,0,255})); + connect(staUp.y, booRep1.u) + annotation (Line(points={{-78,110},{-62,110}}, color={255,0,255})); + connect(staOneChi.y, chiSet.u3) annotation (Line(points={{-118,72},{-60,72},{-60, + 90},{-30,90},{-30,102},{-22,102}}, color={255,0,255})); + connect(booRep1.y, chiSet.u2) + annotation (Line(points={{-38,110},{-22,110}}, color={255,0,255})); + connect(staTwoChi.y, chiSet.u1) annotation (Line(points={{-118,150},{-30,150}, + {-30,118},{-22,118}}, color={255,0,255})); + connect(upSta.y, swi.u1) annotation (Line(points={{-118,220},{-80,220},{-80,208}, + {-62,208}}, color={0,0,127})); + connect(dowSta.y, swi.u3) annotation (Line(points={{-118,180},{-80,180},{-80,192}, + {-62,192}}, color={0,0,127})); + connect(staUp.y, swi.u2) annotation (Line(points={{-78,110},{-70,110},{-70,200}, + {-62,200}}, color={255,0,255})); + connect(swi.y, staSet.u) + annotation (Line(points={{-38,200},{-22,200}}, color={0,0,127})); + connect(staSet.y, upProCon.uStaSet) annotation (Line(points={{2,200},{30,200}, + {30,87},{38,87}}, color={255,127,0})); + connect(chiSet.y, upProCon.uChiSet) annotation (Line(points={{2,110},{20,110}, + {20,84},{38,84}}, color={255,0,255})); + connect(staTwo.y, chiSta.u1) annotation (Line(points={{-118,-90},{-100,-90},{-100, + -102},{-62,-102}}, color={0,0,127})); + connect(staOne.y, chiSta.u3) annotation (Line(points={{-118,-130},{-100,-130}, + {-100,-118},{-62,-118}}, color={0,0,127})); + connect(chiSta.y, sta.u) + annotation (Line(points={{-38,-110},{-22,-110}}, color={0,0,127})); + connect(sta.y, upProCon.uChiSta) annotation (Line(points={{2,-110},{8,-110},{ + 8,71},{38,71}}, color={255,127,0})); + connect(upProCon.yStaPro, falEdg.u) annotation (Line(points={{62,87},{70,87},{ + 70,140},{78,140}}, color={255,0,255})); + connect(falEdg.y, lat.u) + annotation (Line(points={{102,140},{118,140}}, color={255,0,255})); + connect(fal.y, lat.clr) annotation (Line(points={{102,110},{110,110},{110,134}, + {118,134}}, color={255,0,255})); + connect(lat.y, chiSta.u2) annotation (Line(points={{142,140},{150,140},{150,0}, + {-80,0},{-80,-110},{-62,-110}}, color={255,0,255})); + connect(wseSta.y, upProCon.uEnaPlaConPum) annotation (Line(points={{-118,-170}, + {14,-170},{14,69},{38,69}}, color={255,0,255})); + connect(wseSta.y, upProCon.uEnaPlaConIso) annotation (Line(points={{-118,-170}, + {14,-170},{14,58},{38,58}}, color={255,0,255})); +annotation ( + experiment(StopTime=2000, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithoutOnOff.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Up. +

+

+It shows a process of staging up from stage 1 which requires only chiller 1 being +enabled, to stage 2 which requires both chiller 1 and 2 being enabled. In stage 1 +and 2, the required minimum chilled water flow setpoints are 1.0 m3/s and 2.0 m3/s +respectively. The process are below: +

+ +", revisions=" + +"), +Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-300},{160,300}}), + graphics={ + Text( + extent={{-148,290},{-100,282}}, + textColor={0,0,127}, + textString="Stage up:"), + Text( + extent={{-138,274},{-8,264}}, + textColor={0,0,127}, + textString="from stage 1 which has chiller 1 enabled, "), + Text( + extent={{-136,262},{-10,248}}, + textColor={0,0,127}, + textString="to stage 2 which has chiller 1 and 2 enabled.")})); +end UpWithoutOnOff; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/package.mo new file mode 100644 index 00000000000..846bf37c7f5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes; +package Validation "Collection of validation models" +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/package.order new file mode 100644 index 00000000000..fd9062ca55c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/package.order @@ -0,0 +1,4 @@ +DownWithOnOff +DownWithoutOnOff +UpWithOnOff +UpWithoutOnOff diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/package.mo new file mode 100644 index 00000000000..3543a331612 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging; +package Processes "Package of sequences for controlling devices when there is a chiller stage change command" + annotation (preferredView="info", Documentation(info=" +

+This package contains sequences for controlling devices when there is stage-up +or stage-down command. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Processes; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/package.order new file mode 100644 index 00000000000..95417cff338 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/package.order @@ -0,0 +1,4 @@ +Down +Up +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/SetpointController.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/SetpointController.mo new file mode 100644 index 00000000000..f3de506b7e0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/SetpointController.mo @@ -0,0 +1,844 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints; +block SetpointController + "Calculates the chiller stage status setpoint signal" + + parameter Boolean have_WSE = false + "true = plant has a WSE, false = plant does not have WSE" + annotation (Dialog(tab="General", group="Plant configuration parameters")); + + parameter Boolean have_serChi = false + "true = series chillers plant; false = parallel chillers plant" + annotation (Dialog(tab="General", group="Plant configuration parameters")); + + parameter Boolean have_locSen=false + "Flag of local DP sensor: true=local DP sensor hardwired to controller" + annotation (Dialog(tab="General", group="Plant configuration parameters", enable=not have_serChi)); + + parameter Integer nRemSen=2 + "Total number of remote differential pressure sensors" + annotation (Dialog(tab="General", group="Plant configuration parameters", enable=not have_serChi)); + + parameter Boolean anyVsdCen=false + "Plant contains at least one variable speed centrifugal chiller" + annotation (Dialog(tab="General", group="Plant configuration parameters")); + + parameter Integer nChi = 2 + "Number of chillers" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Real chiDesCap[nChi]( + final unit=fill("W",nChi), + displayUnit=fill("W",nChi)) + "Design chiller capacities vector" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Real chiMinCap[nChi]( + final unit=fill("W",nChi), + displayUnit=fill("W",nChi)) + "Chiller minimum cycling loads vector" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Integer chiTyp[nChi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal} + "Chiller type. Recommended staging order: positive displacement, variable speed centrifugal, constant speed centrifugal" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Integer nSta = 3 + "Number of chiller stages, does not include zero stage" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Integer staMat[nSta, nChi] = {{1,0},{0,1},{1,1}} + "Staging matrix with stage as row index and chiller as column index" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Real avePer(unit="s")=300 + "Time period for the capacity requirement rolling average" + annotation (Dialog(tab="Time parameters", group="Hold and delay parameters")); + + parameter Real delayStaCha( + unit="s", + displayUnit="h")=900 + "Hold period for each stage change" + annotation (Dialog(tab="Time parameters", group="Hold and delay parameters")); + + parameter Real parLoaRatDelay( + unit="s", + displayUnit="h")=900 + "Enable delay for operating and staging part load ratio condition" + annotation (Dialog(tab="Time parameters", group="Hold and delay parameters")); + + parameter Real faiSafTruDelay( + unit="s", + displayUnit="h")=900 + "Enable delay for failsafe condition" + annotation (Dialog(tab="Time parameters", group="Hold and delay parameters")); + + parameter Real effConTruDelay( + unit="s", + displayUnit="h")=900 + "Enable delay for efficiency condition" + annotation (Dialog(tab="Time parameters", group="Hold and delay parameters")); + + parameter Real shortTDelay( + unit="s", + displayUnit="h")=600 + "Short enable delay for staging from zero to first available stage up" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Time parameters", group="Hold and delay parameters")); + + parameter Real longTDelay( + unit="s", + displayUnit="h")=1200 + "Long enable delay for staging from zero to first available stage up" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Time parameters", group="Hold and delay parameters")); + + parameter Real posDisMult(unit="1")=0.8 + "Positive displacement chiller type staging multiplier" + annotation (Dialog(tab="Conditionals", group="Staging part load ratio parameters")); + + parameter Real conSpeCenMult(unit="1")=0.9 + "Constant speed centrifugal chiller type staging multiplier" + annotation (Dialog(tab="Conditionals", group="Staging part load ratio parameters")); + + parameter Real anyOutOfScoMult(unit="1")=0.9 + "Outside of G36 recommended staging order chiller type SPLR multiplier" + annotation(Evaluate=true, __cdl(ValueInReference=False), Dialog(tab="Conditionals", group="Staging part load ratio parameters")); + + parameter Real varSpeStaMin(unit="1")=0.45 + "Minimum stage up or down part load ratio for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen, tab="Conditionals", group="Staging part load ratio parameters")); + + parameter Real varSpeStaMax(unit="1")=0.9 + "Maximum stage up or down part load ratio for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen, tab="Conditionals", group="Staging part load ratio parameters")); + + parameter Real smallTDif( + unit="K", + displayUnit="degC")=1 + "Offset between the chilled water supply temperature and its setpoint for the long condition" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Conditionals", group="Value comparison parameters")); + + parameter Real largeTDif( + unit="K", + displayUnit="degC")=2 + "Offset between the chilled water supply temperature and its setpoint for the short condition" + annotation(Evaluate=true, Dialog(enable=have_WSE, tab="Conditionals", group="Value comparison parameters")); + + parameter Real faiSafTDif( + unit="K", + displayUnit="degC")=1 + "Offset between the chilled water supply temperature and its setpoint for the failsafe condition" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + parameter Real dpDif( + unit="Pa", + displayUnit="Pa")=2*6895 + "Offset between the chilled water pump diferential static pressure and its setpoint" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + parameter Real TDif( + unit="K", + displayUnit="degC")=1 + "Offset between the chilled water supply temperature and its setpoint for staging down to WSE only" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + parameter Real TDifHys( + unit="K", + displayUnit="degC")=1 + "Hysteresis deadband for temperature" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + parameter Real faiSafDpDif( + unit="Pa", + displayUnit="Pa")=2*6895 + "Offset between the chilled water differential pressure and its setpoint" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + parameter Real dpDifHys( + unit="Pa", + displayUnit="Pa")=0.5*6895 + "Pressure difference hysteresis deadband" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + parameter Real effConSigDif(unit="1")=0.05 + "Signal hysteresis deadband" + annotation (Dialog(tab="Conditionals", group="Value comparison parameters")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla "Plant enable signal" + annotation (Placement( + transformation(extent={{-440,-120},{-400,-80}}), iconTransformation( + extent={{-140,110},{-100,150}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro "Stage change process status signal" + annotation (Placement(transformation(extent={{-440,-160},{-400,-120}}), + iconTransformation(extent={{-140,150},{-100,190}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWseSta if have_WSE + "WSE status" + annotation (Placement(transformation(extent={{-440,-280},{-400,-240}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiAva[nChi] + "Chiller availability status vector" + annotation (Placement(transformation(extent={{-440,-220},{-400,-180}}), + iconTransformation(extent={{-140,130},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uSta( + final min=0, + final max=nSta) + "Chiller stage" + annotation (Placement(transformation(extent={{-440, + -80},{-400,-40}}), iconTransformation(extent={{-140,80},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TWsePre( + final quantity="ThermodynamicTemperature", + final unit="K") if have_WSE + "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{-440,70},{-400,110}}), + iconTransformation(extent={{-140,-210},{-100,-170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTowFanSpeMax if have_WSE + "Maximum cooling tower fan speed" + annotation (Placement(transformation(extent={{-440,40},{-400,80}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uLifMin( + final unit="K", + final quantity="TemperatureDifference") if anyVsdCen + "Minimum chiller lift" + annotation (Placement(transformation(extent={{-440,-30},{-400,10}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uLifMax( + final unit="K", + final quantity="TemperatureDifference") if anyVsdCen + "Maximum chiller lift" + annotation (Placement(transformation(extent={{-440,0},{-400,40}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-442,350},{-402,390}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water return temperature" + annotation (Placement(transformation(extent={{-440,280},{-400,320}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s") "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-440,250},{-400,290}}), + iconTransformation(extent={{-140,-230},{-100,-190}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_local( + final unit="Pa", + final quantity="PressureDifference") + if (not have_serChi) and have_locSen + "Chilled water pump differential static pressure setpoint for local sensor" + annotation (Placement(transformation(extent={{-440,220},{-400,260}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_local( + final unit="Pa", + final quantity="PressureDifference") if (not have_serChi) and have_locSen + "Chilled water pump differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-440,190},{-400,230}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference",nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure setpoint for remote sensor" + annotation (Placement(transformation(extent={{-440,160},{-400,200}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference",nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure from remote sensor" + annotation (Placement(transformation(extent={{-440,130},{-400,170}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-442,320},{-402,360}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTunPar if have_WSE + "Tuning parameter as at last plant disable" + annotation (Placement(transformation(extent={{-440,100},{-400,140}}), + iconTransformation(extent={{-140,-140},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutWet( + final unit="K", + final quantity="ThermodynamicTemperature") if have_WSE + "Outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-440,380},{-400,420}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiSet[nChi] + "Chiller status setpoint vector for the current chiller stage setpoint" + annotation (Placement(transformation(extent={{120,-280},{160,-240}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaEdg + "Chiller stage change edge signal" + annotation (Placement(transformation(extent={{120,-160},{160,-120}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaUpEdg + "Chiller stage up change edge signal" + annotation (Placement(transformation(extent={{120,-120},{160,-80}}), + iconTransformation(extent={{100,70},{140,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaDowEdg + "Chiller stage down change edge signal" + annotation (Placement(transformation(extent={{120,-220},{160,-180}}), + iconTransformation(extent={{100,10},{140,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yIni + "Initial chiller plant stage" + annotation (Placement(transformation(extent={{120,280},{160,320}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput ySta( + final min=0, + final max=nSta) + "Chiller stage integer setpoint" + annotation (Placement(transformation(extent={{120,220},{160,260}}), + iconTransformation(extent={{100,-130},{140,-90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yUp + "Stage up signal" + annotation (Placement(transformation(extent={{120,60},{160,100}}), + iconTransformation(extent={{100,160},{140,200}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDow + "Stage down signal" + annotation (Placement(transformation(extent={{120,22},{156,58}}), + iconTransformation(extent={{100,130},{140,170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOpeParLoaRatMin( + final unit="1", + final min=0) + "Minimum operating part load ratio at current stage" + annotation (Placement(transformation(extent={{120,320},{160,360}}), + iconTransformation(extent={{100,-202},{140,-162}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCapReq( + final quantity="HeatFlowRate", + final unit="W") + "Chilled water cooling capacity requirement" + annotation (Placement(transformation(extent={{120,370},{160,410}}), + iconTransformation(extent={{100,-230},{140,-190}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Up staUp( + final have_WSE=have_WSE, + final have_serChi=have_serChi, + final have_locSen=have_locSen, + final nRemSen=nRemSen, + final effConTruDelay=effConTruDelay, + final faiSafTruDelay=faiSafTruDelay, + final shortTDelay=shortTDelay, + final longTDelay=longTDelay, + final faiSafTDif=faiSafTDif, + final TDifHys=TDifHys, + final smallTDif=smallTDif, + final largeTDif=largeTDif, + final faiSafDpDif=faiSafDpDif, + final dpDifHys=dpDifHys, + final effConSigDif=effConSigDif) "Stage up conditions" + annotation (Placement(transformation(extent={{-100,-120},{-80,-100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Down staDow( + final have_WSE=have_WSE, + final have_serChi=have_serChi, + final have_locSen=have_locSen, + final nRemSen=nRemSen, + final parLoaRatDelay=parLoaRatDelay, + final faiSafTruDelay=faiSafTruDelay, + final faiSafTDif=faiSafTDif, + final faiSafDpDif=faiSafDpDif, + final TDif=TDif, + final TDifHys=TDifHys) "Stage down conditions" + annotation (Placement(transformation(extent={{-100,-240},{-80,-220}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.CapacityRequirement capReq( + final avePer = avePer, + final holPer = delayStaCha) "Capacity requirement" + annotation (Placement(transformation(extent={{-320,300},{-300,320}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities cap( + final nSta=nSta) "Design and minimum capacities for relevant chiller stages" + annotation (Placement(transformation(extent={{-270,-180},{-250,-160}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial iniSta( + final have_WSE=have_WSE) "Initia stage" + annotation (Placement(transformation(extent={{-80,100},{-60,120}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf( + final nSta = nSta, + final nChi = nChi, + final chiTyp = chiTyp, + final chiDesCap = chiDesCap, + final chiMinCap = chiMinCap, + final staMat = staMat) + "Configures chiller staging variables such as capacity and stage type vectors" + annotation (Placement(transformation(extent={{-360,-180},{-340,-160}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta( + final nSta=nSta, + final nChi=nChi, + final staMat=staMat) "First higher and lower available stage index, end stage boolean flags and chiller status setpoints" + annotation (Placement(transformation(extent={{-320,-220},{-300,-200}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs( + final anyVsdCen=anyVsdCen, + final nSta=nSta, + final posDisMult=posDisMult, + final conSpeCenMult=conSpeCenMult, + final anyOutOfScoMult=anyOutOfScoMult, + final varSpeStaMin=varSpeStaMin, + final varSpeStaMax=varSpeStaMax) "Operative and staging part load ratios" + annotation (Placement(transformation(extent={{-182,-200},{-162,-160}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Change cha( + final nSta=nSta, + final delayStaCha=delayStaCha) "Stage change assignment" + annotation (Placement(transformation(extent={{-20,-180},{0,-160}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd( + final nSta=nSta, + final nChi=nChi, + final staMat=staMat) "Calculates chiller status setpoint vector" + annotation (Placement(transformation(extent={{40,-240},{60,-220}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract lift if anyVsdCen + "Calculates chiller lift for variable speed centrifugal chiller containing configurations" + annotation (Placement(transformation(extent={{-260,30},{-240,50}}))); + +equation + connect(uChiAva, conf.uChiAva) + annotation (Line(points={{-420,-200},{-380,-200},{-380,-170},{-362,-170}}, + color={255,0,255})); + connect(conf.yAva, sta.uAva) annotation (Line(points={{-338,-178},{-332,-178}, + {-332,-216},{-322,-216}},color={255,0,255})); + connect(TChiWatSupSet, capReq.TChiWatSupSet) annotation (Line(points={{-422,370}, + {-360,370},{-360,319},{-322,319}}, color={0,0,127})); + connect(TChiWatRet, capReq.TChiWatRet) annotation (Line(points={{-420,300},{-374, + 300},{-374,314},{-322,314}}, color={0,0,127})); + connect(VChiWat_flow, capReq.VChiWat_flow) annotation (Line(points={{-420,270}, + {-370,270},{-370,309},{-322,309}}, color={0,0,127})); + connect(conf.yDesCap, cap.uDesCap) annotation (Line(points={{-338,-162},{-322, + -162},{-322,-161},{-272,-161}}, color={0,0,127})); + connect(conf.yMinCap, cap.uMinCap) annotation (Line(points={{-338,-166},{-312, + -166},{-312,-164},{-272,-164}}, color={0,0,127})); + connect(sta.yAvaUp, cap.uUp) annotation (Line(points={{-298,-203},{-286,-203}, + {-286,-170},{-272,-170}}, color={255,127,0})); + connect(sta.yAvaDow, cap.uDown) annotation (Line(points={{-298,-206},{-282,-206}, + {-282,-173},{-272,-173}}, color={255,127,0})); + connect(sta.yHig, cap.uHig) annotation (Line(points={{-298,-211},{-280,-211}, + {-280,-176},{-272,-176}},color={255,0,255})); + connect(capReq.y, PLRs.uCapReq) annotation (Line(points={{-298,310},{-194,310}, + {-194,-166},{-184,-166}}, + color={0,0,127})); + connect(cap.yDes, PLRs.uCapDes) annotation (Line(points={{-248,-162},{-234, + -162},{-234,-168},{-184,-168}}, + color={0,0,127})); + connect(cap.yUpDes, PLRs.uUpCapDes) annotation (Line(points={{-248,-166},{ + -236,-166},{-236,-170},{-184,-170}}, + color={0,0,127})); + connect(cap.yDowDes, PLRs.uDowCapDes) annotation (Line(points={{-248,-170},{ + -238,-170},{-238,-172},{-184,-172}}, + color={0,0,127})); + connect(cap.yMin, PLRs.uCapMin) annotation (Line(points={{-248,-174},{-240, + -174},{-240,-175},{-184,-175}}, + color={0,0,127})); + connect(cap.yUpMin, PLRs.uUpCapMin) annotation (Line(points={{-248,-178},{ + -242,-178},{-242,-177},{-184,-177}}, + color={0,0,127})); + connect(uLifMax, PLRs.uLifMax) annotation (Line(points={{-420,20},{-212,20},{ + -212,-182},{-184,-182}}, + color={0,0,127})); + connect(uLifMin, PLRs.uLifMin) annotation (Line(points={{-420,-10},{-222,-10}, + {-222,-184},{-184,-184}}, + color={0,0,127})); + connect(conf.yTyp, PLRs.uTyp) annotation (Line(points={{-338,-174},{-302,-174}, + {-302,-188},{-184,-188}}, color={255,127,0})); + connect(sta.yAvaUp, PLRs.uUp) annotation (Line(points={{-298,-203},{-242,-203}, + {-242,-194},{-184,-194}}, color={255,127,0})); + connect(sta.yAvaDow, PLRs.uDown) + annotation (Line(points={{-298,-206},{-242,-206},{-242,-196},{-184,-196}}, + color={255,127,0})); + connect(sta.yLow, cap.uLow) annotation (Line(points={{-298,-214},{-278,-214}, + {-278,-179},{-272,-179}},color={255,0,255})); + connect(PLRs.yOpe, staUp.uOpe) annotation (Line(points={{-160,-172},{-136, + -172},{-136,-99},{-102,-99}}, + color={0,0,127})); + connect(PLRs.yStaUp, staUp.uStaUp) annotation (Line(points={{-160,-181},{-134, + -181},{-134,-101},{-102,-101}}, + color={0,0,127})); + connect(TChiWatSupSet, staUp.TChiWatSupSet) annotation (Line(points={{-422, + 370},{-162,370},{-162,-103},{-102,-103}}, + color={0,0,127})); + connect(TChiWatSup, staUp.TChiWatSup) annotation (Line(points={{-422,340},{ + -386,340},{-386,284},{-164,284},{-164,-105},{-102,-105}}, + color={0,0,127})); + connect(dpChiWatPumSet_local, staUp.dpChiWatPumSet_local) annotation (Line( + points={{-420,240},{-144,240},{-144,-107},{-102,-107}}, color={0,0,127})); + connect(dpChiWatPum_local, staUp.dpChiWatPum_local) annotation (Line(points={{-420, + 210},{-146,210},{-146,-109},{-102,-109}}, color={0,0,127})); + connect(PLRs.yOpeDow, staDow.uOpeDow) annotation (Line(points={{-160,-176},{ + -142,-176},{-142,-219},{-102,-219}}, + color={0,0,127})); + connect(staDow.uStaDow, PLRs.yStaDow) annotation (Line(points={{-102,-221},{ + -144,-221},{-144,-183},{-160,-183}}, + color={0,0,127})); + connect(dpChiWatPumSet_local, staDow.dpChiWatPumSet_local) annotation (Line( + points={{-420,240},{-144,240},{-144,-223},{-102,-223}}, color={0,0,127})); + connect(dpChiWatPum_local, staDow.dpChiWatPum_local) annotation (Line(points={ + {-420,210},{-146,210},{-146,-225},{-102,-225}}, color={0,0,127})); + connect(TChiWatSupSet, staDow.TChiWatSupSet) annotation (Line(points={{-422,370}, + {-152,370},{-152,-231.2},{-102,-231.2}}, + color={0,0,127})); + connect(TChiWatSup, staDow.TChiWatSup) annotation (Line(points={{-422,340},{-386, + 340},{-386,284},{-154,284},{-154,-233.2},{-102,-233.2}}, + color={0,0,127})); + connect(TWsePre, staDow.TWsePre) annotation (Line(points={{-420,90},{-156,90}, + {-156,-235.2},{-102,-235.2}}, + color={0,0,127})); + connect(uTowFanSpeMax, staDow.uTowFanSpeMax) annotation (Line(points={{-420,60}, + {-158,60},{-158,-237.2},{-102,-237.2}}, + color={0,0,127})); + connect(staDow.uWseSta, uWseSta) annotation (Line(points={{-102,-241},{-340, + -241},{-340,-260},{-420,-260}}, + color={255,0,255})); + connect(uSta, sta.u) annotation (Line(points={{-420,-60},{-328,-60},{-328,-204}, + {-322,-204}}, color={255,127,0})); + connect(sta.yAvaCur, staUp.uAvaCur) annotation (Line(points={{-298,-217},{ + -242,-217},{-242,-210},{-122,-210},{-122,-117},{-102,-117}}, + color={255,0,255})); + connect(uSta, cap.u) annotation (Line(points={{-420,-60},{-328,-60},{-328,-167}, + {-272,-167}}, color={255,127,0})); + connect(uSta, PLRs.u) annotation (Line(points={{-420,-60},{-232,-60},{-232, + -192},{-184,-192}}, + color={255,127,0})); + connect(uSta, staUp.u) annotation (Line(points={{-420,-60},{-112,-60},{-112, + -115},{-102,-115}}, + color={255,127,0})); + connect(uSta, staDow.u) annotation (Line(points={{-420,-60},{-328,-60},{-328,-239}, + {-102,-239}}, color={255,127,0})); + connect(chaPro, capReq.chaPro) annotation (Line(points={{-420,-140},{-350, + -140},{-350,302},{-322,302}}, color={255,0,255})); + connect(sta.yAvaUp, cha.uAvaUp) annotation (Line(points={{-298,-203},{-292,-203}, + {-292,-148},{-40,-148},{-40,-164},{-22,-164}}, color={255,127,0})); + connect(sta.yAvaDow, cha.uAvaDow) annotation (Line(points={{-298,-206},{-290,-206}, + {-290,-150},{-44,-150},{-44,-168},{-22,-168}}, color={255,127,0})); + connect(staUp.y, cha.uUp) annotation (Line(points={{-78,-110},{-50,-110},{-50, + -172},{-22,-172}}, color={255,0,255})); + connect(staDow.y, cha.uDow) annotation (Line(points={{-78,-230},{-60,-230},{ + -60,-176},{-22,-176}}, + color={255,0,255})); + connect(uPla, cha.uPla) annotation (Line(points={{-420,-100},{-280,-100},{ + -280,-140},{-70,-140},{-70,-180},{-22,-180}}, + color={255,0,255})); + connect(cha.ySta, ySta) annotation (Line(points={{2,-166},{20,-166},{20,240},{ + 140,240}}, color={255,127,0})); + connect(cha.yChaEdg, yChaEdg) annotation (Line(points={{2,-174},{80,-174},{80, + -140},{140,-140}}, color={255,0,255})); + connect(chiInd.yChi, yChiSet) annotation (Line(points={{62,-230},{80,-230},{ + 80,-260},{140,-260}}, color={255,0,255})); + connect(cha.ySta, chiInd.u) annotation (Line(points={{2,-166},{20,-166},{20, + -230},{38,-230}}, color={255,127,0})); + connect(TChiWatSupSet, iniSta.TChiWatSupSet) annotation (Line(points={{-422,370}, + {-100,370},{-100,113},{-82,113}}, color={0,0,127})); + connect(uTunPar, iniSta.uTunPar) annotation (Line(points={{-420,120},{-104,120}, + {-104,116},{-82,116}}, color={0,0,127})); + connect(iniSta.yIni, cha.uIni) annotation (Line(points={{-59,110},{-30,110},{-30, + -160},{-22,-160}}, color={255,127,0})); + connect(TOutWet, iniSta.TOutWet) annotation (Line(points={{-420,400},{-96,400}, + {-96,119},{-82,119}}, color={0,0,127})); + connect(sta.yAvaUp, iniSta.uUp) annotation (Line(points={{-298,-203},{-294,-203}, + {-294,110},{-82,110}}, color={255,127,0})); + connect(uPla, iniSta.uPla) annotation (Line(points={{-420,-100},{-280,-100},{-280, + 104},{-82,104}}, color={255,0,255})); + connect(cha.yChaUpEdg, yChaUpEdg) annotation (Line(points={{2,-170},{60,-170}, + {60,-100},{140,-100}}, + color={255,0,255})); + connect(cha.yChaDowEdg, yChaDowEdg) annotation (Line(points={{2,-178},{60, + -178},{60,-200},{140,-200}}, + color={255,0,255})); + connect(PLRs.yOpeMin, yOpeParLoaRatMin) annotation (Line(points={{-160,-187}, + {-130,-187},{-130,340},{140,340}}, + color={0,0,127})); + connect(staUp.y, yUp) annotation (Line(points={{-78,-110},{-50,-110},{-50,80}, + {140,80}}, color={255,0,255})); + connect(staDow.y, yDow) annotation (Line(points={{-78,-230},{-60,-230},{-60, + 40},{138,40}}, color={255,0,255})); + connect(TChiWatRet, lift.u1) annotation (Line(points={{-420,300},{-388,300},{-388, + 46},{-262,46}}, color={0,0,127})); + connect(TChiWatSupSet, lift.u2) annotation (Line(points={{-422,370},{-360,370}, + {-360,34},{-262,34}}, color={0,0,127})); + connect(PLRs.uLif, lift.y) annotation (Line(points={{-184,-180},{-202,-180},{ + -202,40},{-238,40}}, + color={0,0,127})); + connect(capReq.y, yCapReq) annotation (Line(points={{-298,310},{-194,310},{-194, + 390},{140,390}}, color={0,0,127})); + connect(dpChiWatPumSet_remote, staUp.dpChiWatPumSet_remote) annotation (Line( + points={{-420,180},{-148,180},{-148,-111},{-102,-111}}, color={0,0,127})); + connect(dpChiWatPumSet_remote, staDow.dpChiWatPumSet_remote) annotation (Line( + points={{-420,180},{-148,180},{-148,-227},{-102,-227}}, color={0,0,127})); + connect(dpChiWatPum_remote, staUp.dpChiWatPum_remote) annotation (Line(points={{-420, + 150},{-150,150},{-150,-113},{-102,-113}}, color={0,0,127})); + connect(dpChiWatPum_remote, staDow.dpChiWatPum_remote) annotation (Line( + points={{-420,150},{-150,150},{-150,-229},{-102,-229}}, color={0,0,127})); + connect(iniSta.yIni, yIni) annotation (Line(points={{-59,110},{-30,110},{-30,300}, + {140,300}}, color={255,127,0})); + connect(uPla, staUp.uPla) annotation (Line(points={{-420,-100},{-280,-100},{ + -280,-119},{-102,-119}}, color={255,0,255})); + annotation (defaultComponentName = "staSetCon", + Icon(coordinateSystem(extent={{-100,-220},{100,200}}, initialScale=0.2), + graphics={ + Rectangle( + extent={{-100,-220},{100,200}}, + lineColor={0,0,127}, + fillColor={255,255,85}, + fillPattern=FillPattern.Solid), + Text( + extent={{-112,244},{108,206}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-96,88},{-8,54}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="TChiWatSupSet"), + Text( + extent={{-96,66},{-24,34}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="TChiWatSup"), + Text( + extent={{-96,-182},{-40,-198}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="TWsePre"), + Text( + extent={{-98,-160},{-24,-178}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="TChiWatRet"), + Text( + extent={{-98,-196},{-14,-222}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{-96,-128},{8,-152}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uTowFanSpeMax"), + Text( + extent={{-94,-10},{0,-32}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatPumSet_local", + visible=(not have_serChi) and have_locSen), + Text( + extent={{-96,-28},{-10,-48}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatPum_local", + visible=(not have_serChi) and have_locSen), + Text( + extent={{-96,8},{-48,-10}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uLifMin", + visible=anyVsdCen), + Text( + extent={{-96,32},{-46,14}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uLifMax", + visible=anyVsdCen), + Text( + extent={{-98,112},{-68,92}}, + textColor={244,125,35}, + pattern=LinePattern.Dash, + textString="uSta"), + Text( + extent={{-98,200},{-46,180}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="uWseSta"), + Text( + extent={{-100,180},{-50,164}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="chaPro"), + Text( + extent={{-96,142},{-68,120}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="uPla"), + Text( + extent={{-96,160},{-44,142}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="uChiAva"), + Text( + extent={{62,-116},{94,-100}}, + textColor={244,125,35}, + pattern=LinePattern.Dash, + textString="ySta"), + Text( + extent={{42,74},{94,50}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="yChaEdg"), + Text( + extent={{40,-24},{92,-52}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="yChiSet[]"), + Text( + extent={{-98,-110},{-48,-126}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uTunPar"), + Text( + extent={{-98,-90},{-46,-108}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="TOutWet"), + Text( + extent={{28,112},{94,70}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="yChaUpEdg"), + Text( + extent={{16,50},{94,14}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="yChaDowEdg"), + Text( + extent={{-12,-154},{96,-200}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yOpeParLoaRatMin"), + Text( + extent={{54,194},{98,170}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="yUp"), + Text( + extent={{52,164},{100,140}}, + textColor={217,67,180}, + pattern=LinePattern.Dash, + textString="yDow"), + Text( + extent={{42,-198},{94,-220}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yCapReq"), + Text( + extent={{-96,-48},{8,-72}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatPumSet_remote", + visible=(not have_serChi) and (not have_locSen)), + Text( + extent={{-96,-68},{8,-92}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpChiWatPum_remote", + visible=(not have_serChi) and (not have_locSen)), + Text( + extent={{62,-98},{94,-82}}, + textColor={244,125,35}, + pattern=LinePattern.Dash, + textString="yIni")}), Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-400,-300},{120,420}})), +Documentation(info=" +

+The sequence is a chiller stage status setpoint controller that outputs the +chiller stage integer index ySta, chiller stage change trigger signal +y and a chiller status vector for the current stage yChi. +

+

+It is implemented according to ASHRAE Guideline36-2021, section 5.20.4.1 - 15. +

+

+The controller contains the following subsequences: +

+ +", +revisions=" + +")); +end SetpointController; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Capacities.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Capacities.mo new file mode 100644 index 00000000000..e31bd037bc6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Capacities.mo @@ -0,0 +1,335 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Capacities + "Returns design and minimal stage capacities for current and next available higher and lower stage" + + parameter Integer nSta = 3 + "Number of chiller stages, does not include zero stage"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLow + "Current stage is the lowest available stage" + annotation (Placement(transformation(extent={{-240,-80},{-200,-40}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHig + "Current stage is the highest available stage" + annotation (Placement(transformation(extent={{-240,-110},{-200,-70}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta) "Chiller stage" + annotation (Placement(transformation(extent={{-240,100},{-200,140}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uUp( + final min=0, + final max=nSta) "Next available higher stage" + annotation (Placement(transformation(extent={{-240,40},{-200,80}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uDown( + final min=0, + final max=nSta) "Next available lower stage" + annotation (Placement(transformation(extent={{-240,-40},{-200,0}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uDesCap[nSta]( + final quantity=fill("HeatFlowRate", nSta), + final unit=fill("W", nSta)) "Design stage capacities" + annotation (Placement(transformation(extent={{-240,160},{-200,200}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMinCap[nSta]( + final quantity=fill("HeatFlowRate", nSta), + final unit=fill("W", nSta)) "Unload stage capacities" + annotation (Placement(transformation(extent={{-240,-200},{-200,-160}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDes( + final unit="W", + final quantity="HeatFlowRate") "Design capacity of the current stage" + annotation (Placement(transformation(extent={{200,160},{240,200}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDowDes( + final unit="W", + final quantity="HeatFlowRate") "Design capacity of the next available lower stage" + annotation (Placement(transformation(extent={{200,0},{240,40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yUpDes( + final unit="W", + final quantity="HeatFlowRate") "Design capacity of the next available higher stage" + annotation (Placement(transformation(extent={{200,40},{240,80}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMin( + final unit="W", + final quantity="HeatFlowRate") "Minimum capacity of the current stage" + annotation (Placement(transformation(extent={{200,-40},{240,0}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yUpMin( + final unit="W", + final quantity="HeatFlowRate") "Minimum capacity of the next available higher stage" + annotation (Placement(transformation(extent={{200,-110},{240,-70}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + final parameter Real larGai = 10 + "Large gain"; + + Buildings.Controls.OBC.CDL.Routing.RealExtractor cap( + final nin=nSta) + "Extracts the design capacity at the current stage" + annotation (Placement(transformation(extent={{-10,170},{10,190}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor dowCap( + final nin=nSta) + "Extracts the design capacity of one stage lower than the current stage" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor upCapMin( + final nin=nSta) + "Extracts minimal capacity of the next higher stage" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor upCap( + final nin=nSta) + "Extracts the design capacity of the next stage" + annotation (Placement(transformation(extent={{0,80},{20,100}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor capMin( + final nin=nSta) + "Extracts the minimum capacity of the current stage" + annotation (Placement(transformation(extent={{0,-150},{20,-130}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Switch" + annotation (Placement(transformation(extent={{160,50},{180,70}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi4 "Switch" + annotation (Placement(transformation(extent={{160,-100},{180,-80}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Outputs minimum current stage capacity as design stage down capacity if operating in the lowest available stage" + annotation (Placement(transformation(extent={{160,10},{180,30}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai( + final k=larGai) + "Ouputs a very large and unachievable staging up capacity when current is the highest available stage" + annotation (Placement(transformation(extent={{80,110},{100,130}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[3] + "Convert boolean to real" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{30,140},{50,160}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul1 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,-130},{80,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul2 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul3 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul4 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr[3]( + final t=fill(1, 3)) "Check if index is in the range" + annotation (Placement(transformation(extent={{-160,70},{-140,90}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr[3]( + final t=fill(nSta, 3)) "Check if index is in the range" + annotation (Placement(transformation(extent={{-160,-10},{-140,10}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[3]( + final k=fill(1, 3)) + "Dummy index so the extractor will not have out of range index" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Logical.And and2[3] + "Check if index is in the range" + annotation (Placement(transformation(extent={{-120,70},{-100,90}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi[3] "Valid index" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); +equation + connect(swi2.y, yUpDes) annotation (Line(points={{182,60},{220,60}}, color={0,0,127})); + connect(swi4.y, yUpMin) annotation (Line(points={{182,-90},{220,-90}}, color={0,0,127})); + connect(uMinCap, upCapMin.u) annotation (Line(points={{-220,-180},{-20,-180},{ + -20,-60},{-2,-60}}, color={0,0,127})); + connect(uMinCap, capMin.u) annotation (Line(points={{-220,-180},{-20,-180},{-20, + -140},{-2,-140}}, color={0,0,127})); + connect(uDesCap, cap.u) annotation (Line(points={{-220,180},{-12,180}}, + color={0,0,127})); + connect(uDesCap, dowCap.u) annotation (Line(points={{-220,180},{-20,180},{-20, + 0},{-2,0}}, color={0,0,127})); + connect(uDesCap, upCap.u) annotation (Line(points={{-220,180},{-20,180},{-20,90}, + {-2,90}}, color={0,0,127})); + connect(uLow, swi1.u2) annotation (Line(points={{-220,-60},{-50,-60},{-50,20}, + {158,20}}, color={255,0,255})); + connect(uHig, swi2.u2) annotation (Line(points={{-220,-90},{140,-90},{140,60}, + {158,60}}, color={255,0,255})); + connect(uHig, swi4.u2) annotation (Line(points={{-220,-90},{158,-90}}, + color={255,0,255})); + connect(gai.y, swi2.u1) annotation (Line(points={{102,120},{120,120},{120,68}, + {158,68}}, color={0,0,127})); + connect(gai.y, swi4.u1) annotation (Line(points={{102,120},{120,120},{120,-82}, + {158,-82}},color={0,0,127})); + connect(swi1.y, yDowDes) annotation (Line(points={{182,20},{220,20}}, color={0,0,127})); + connect(cap.y, yDes) annotation (Line(points={{12,180},{220,180}}, + color={0,0,127})); + connect(intGreEquThr.y, and2.u1) + annotation (Line(points={{-138,80},{-122,80}}, color={255,0,255})); + connect(intLesEquThr.y, and2.u2) annotation (Line(points={{-138,0},{-130,0},{-130, + 72},{-122,72}}, color={255,0,255})); + connect(and2.y, intSwi.u2) annotation (Line(points={{-98,80},{-90,80},{-90,30}, + {-82,30}}, color={255,0,255})); + connect(conInt.y, intSwi.u3) annotation (Line(points={{-98,0},{-90,0},{-90,22}, + {-82,22}}, color={255,127,0})); + connect(and2.y, booToRea.u) + annotation (Line(points={{-98,80},{-82,80}}, color={255,0,255})); + connect(cap.y, mul.u1) annotation (Line(points={{12,180},{20,180},{20,156},{28, + 156}}, color={0,0,127})); + connect(mul.y, gai.u) annotation (Line(points={{52,150},{60,150},{60,120},{78, + 120}}, color={0,0,127})); + connect(capMin.y, mul1.u2) annotation (Line(points={{22,-140},{40,-140},{40,-126}, + {58,-126}}, color={0,0,127})); + connect(mul1.y, yMin) annotation (Line(points={{82,-120},{130,-120},{130,-20}, + {220,-20}}, color={0,0,127})); + connect(mul1.y, swi1.u1) annotation (Line(points={{82,-120},{130,-120},{130,28}, + {158,28}}, color={0,0,127})); + connect(u, intGreEquThr[1].u) annotation (Line(points={{-220,120},{-190,120},{ + -190,80},{-162,80}}, color={255,127,0})); + connect(u, intLesEquThr[1].u) annotation (Line(points={{-220,120},{-190,120},{ + -190,0},{-162,0}}, color={255,127,0})); + connect(u, intSwi[1].u1) annotation (Line(points={{-220,120},{-190,120},{-190, + 38},{-82,38}}, color={255,127,0})); + connect(booToRea[1].y, mul1.u1) annotation (Line(points={{-58,80},{-30,80},{-30, + -114},{58,-114}}, color={0,0,127})); + connect(booToRea[1].y, mul.u2) annotation (Line(points={{-58,80},{-30,80},{-30, + 144},{28,144}}, color={0,0,127})); + connect(intSwi[1].y, cap.index) annotation (Line(points={{-58,30},{-40,30},{-40, + 160},{0,160},{0,168}}, color={255,127,0})); + connect(intSwi[1].y, capMin.index) annotation (Line(points={{-58,30},{-40,30}, + {-40,-160},{10,-160},{10,-152}}, color={255,127,0})); + connect(mul2.y, swi4.u3) annotation (Line(points={{82,-40},{100,-40},{100,-98}, + {158,-98}}, color={0,0,127})); + connect(upCapMin.y, mul2.u2) annotation (Line(points={{22,-60},{40,-60},{40,-46}, + {58,-46}}, color={0,0,127})); + connect(booToRea[2].y, mul2.u1) annotation (Line(points={{-58,80},{-30,80},{-30, + -34},{58,-34}}, color={0,0,127})); + connect(intSwi[2].y, upCapMin.index) annotation (Line(points={{-58,30},{-40,30}, + {-40,-80},{10,-80},{10,-72}}, color={255,127,0})); + connect(upCap.y, mul3.u1) annotation (Line(points={{22,90},{40,90},{40,76},{58, + 76}}, color={0,0,127})); + connect(mul3.y, swi2.u3) annotation (Line(points={{82,70},{100,70},{100,52},{158, + 52}}, color={0,0,127})); + connect(booToRea[2].y, mul3.u2) annotation (Line(points={{-58,80},{-10,80},{ + -10,64},{58,64}}, + color={0,0,127})); + connect(intSwi[2].y, upCap.index) + annotation (Line(points={{-58,30},{10,30},{10,78}}, color={255,127,0})); + connect(mul4.y, swi1.u3) annotation (Line(points={{82,40},{100,40},{100,12},{158, + 12}}, color={0,0,127})); + connect(dowCap.y, mul4.u2) + annotation (Line(points={{22,0},{40,0},{40,34},{58,34}}, color={0,0,127})); + connect(booToRea[3].y, mul4.u1) annotation (Line(points={{-58,80},{-30,80},{-30, + 46},{58,46}}, color={0,0,127})); + connect(intSwi[3].y, dowCap.index) annotation (Line(points={{-58,30},{-40,30}, + {-40,-20},{10,-20},{10,-12}}, color={255,127,0})); + connect(uUp, intGreEquThr[2].u) annotation (Line(points={{-220,60},{-180,60},{ + -180,80},{-162,80}}, color={255,127,0})); + connect(uUp, intLesEquThr[2].u) annotation (Line(points={{-220,60},{-180,60},{ + -180,0},{-162,0}}, color={255,127,0})); + connect(uUp, intSwi[2].u1) annotation (Line(points={{-220,60},{-180,60},{-180, + 38},{-82,38}}, color={255,127,0})); + connect(uDown, intGreEquThr[3].u) annotation (Line(points={{-220,-20},{-170,-20}, + {-170,80},{-162,80}}, color={255,127,0})); + connect(uDown, intLesEquThr[3].u) annotation (Line(points={{-220,-20},{-170,-20}, + {-170,0},{-162,0}}, color={255,127,0})); + connect(uDown, intSwi[3].u1) annotation (Line(points={{-220,-20},{-170,-20},{-170, + 38},{-82,38}}, color={255,127,0})); +annotation (defaultComponentName = "cap", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-200,-200},{200,200}})), +Documentation(info=" +

+This subsequence is not directly specified in Guideline36 as it provides +a side calculation pertaining to generalization of the staging +sequences for any number of chillers and stages provided by the +user. +

+

+Based on: +

+ +

+the subsequence selects from the design stage capacity uDesCap +and the minimal stage capacity uMinCap vectors +the following variables and outputs them: +

+ +

+for the purpose of calculating the operative part load ratios +(OPLR) up and down, respectively. The OPLR is defined in 1711 March 2020 draft section 5.2.4.6. +

+

+For numerical reasons and to ensure expected behavior in corner cases such as +when the plant operates at the highest or the lowest available stage, the +sequence implements the following: +

+ +", +revisions=" + +")); +end Capacities; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/CapacityRequirement.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/CapacityRequirement.mo new file mode 100644 index 00000000000..e2fc87c5ca6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/CapacityRequirement.mo @@ -0,0 +1,190 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block CapacityRequirement + "Cooling capacity requirement" + + parameter Real avePer( + final unit="s", + final quantity="Time")=300 + "Time period for the rolling average"; + + parameter Real holPer( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Time period for the value hold at stage change"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "Stage change process status, true = on, false = off" + annotation (Placement(transformation(extent={{-180,90},{-140,130}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-180,-10},{-140,30}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water return temperature" + annotation (Placement(transformation(extent={{-180,-70},{-140,-30}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s") "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-180,-150},{-140,-110}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput y( + final quantity="HeatFlowRate", + final unit="W") "Chilled water cooling capacity requirement" + annotation (Placement(transformation(extent={{140,110},{180,150}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + constant Real rhoWat( + final unit="kg/m3", + final quantity="Density", + displayUnit="kg/m3")=1000 "Water density"; + + constant Real cpWat( + final unit="J/(kg.K)", + final quantity="SpecificEntropy", + displayUnit="J/(kg.K)")=4184 + "Specific heat capacity of water"; + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Triggered sampler" + annotation (Placement(transformation(extent={{-40,120},{-20,140}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi "Switch" + annotation (Placement(transformation(extent={{80,120},{100,140}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg "Edge" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=holPer, + final falseHoldDuration=0) "True hold" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant density( + final k = rhoWat) + "Water density" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant speHeaCap( + final k = cpWat) + "Specific heat capacity of water" + annotation (Placement(transformation(extent={{-120,-160},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minLim( + final k=0) + "Minimum capacity requirement limit" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 + "Find input difference" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.MovingAverage movMea( + final delta=avePer) + "Moving average" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro "Product" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro1 "Product" + annotation (Placement(transformation(extent={{-80,-130},{-60,-110}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro2 "Product" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max "Maximum of two inputs" + annotation (Placement(transformation(extent={{100,-80},{120,-60}}))); + +equation + connect(sub1.y, pro.u1) annotation (Line(points={{-58,-20},{10,-20},{10,-64}, + {18,-64}},color={0,0,127})); + connect(pro.y, movMea.u) + annotation (Line(points={{42,-70},{58,-70}}, color={0,0,127})); + connect(speHeaCap.y, pro1.u2) annotation (Line(points={{-98,-150},{-90,-150},{ + -90,-126},{-82,-126}}, color={0,0,127})); + connect(pro1.y, pro2.u2) annotation (Line(points={{-58,-120},{-50,-120},{-50,-86}, + {-22,-86}}, color={0,0,127})); + connect(pro.u2, pro2.y) annotation (Line(points={{18,-76},{10,-76},{10,-80},{2, + -80}}, color={0,0,127})); + connect(pro1.u1, density.y) annotation (Line(points={{-82,-114},{-90,-114},{-90, + -100},{-98,-100}}, color={0,0,127})); + connect(VChiWat_flow, pro2.u1) annotation (Line(points={{-160,-130},{-130,-130}, + {-130,-74},{-22,-74}}, color={0,0,127})); + connect(max.u1, minLim.y) annotation (Line(points={{98,-64},{90,-64},{90,-20}, + {82,-20}}, color={0,0,127})); + connect(movMea.y, max.u2) annotation (Line(points={{82,-70},{90,-70},{90,-76}, + {98,-76}}, color={0,0,127})); + connect(max.y, triSam.u) annotation (Line(points={{122,-70},{130,-70},{130,20}, + {-60,20},{-60,130},{-42,130}}, color={0,0,127})); + connect(chaPro, edg.u) + annotation (Line(points={{-160,110},{-102,110}}, color={255,0,255})); + connect(edg.y, triSam.trigger) annotation (Line(points={{-78,110},{-30,110},{-30, + 118}}, color={255,0,255})); + connect(triSam.y, swi.u1) annotation (Line(points={{-18,130},{10,130},{10,138}, + {78,138}}, color={0,0,127})); + connect(max.y, swi.u3) annotation (Line(points={{122,-70},{130,-70},{130,60},{ + 60,60},{60,122},{78,122}}, color={0,0,127})); + connect(swi.y, y) + annotation (Line(points={{102,130},{160,130}},color={0,0,127})); + connect(chaPro, truFalHol.u) annotation (Line(points={{-160,110},{-120,110},{ + -120,80},{-42,80}}, color={255,0,255})); + connect(truFalHol.y, swi.u2) annotation (Line(points={{-18,80},{40,80},{40, + 130},{78,130}}, color={255,0,255})); + connect(TChiWatSupSet, sub1.u2) annotation (Line(points={{-160,10},{-120,10},{ + -120,-26},{-82,-26}}, color={0,0,127})); + connect(TChiWatRet, sub1.u1) annotation (Line(points={{-160,-50},{-100,-50},{-100, + -14},{-82,-14}}, color={0,0,127})); + + annotation (defaultComponentName = "capReq", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-62,88},{60,-76}}, + textColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + textString="Load")}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-140,-180},{140,160}})), +Documentation(info=" +

+Calculates cooling capacity requirement based on the measured chilled water return temperature TChiWatRet, +calculated chilled water supply temperature setpoint +TChiWatSupSet and the measured chilled water flow VChiWat_flow.
+The calculation is according to Guideline36-2021, section 5.20.4.8. +

+

+When a stage change process is in progress, as indicated by a boolean input +chaPro, the capacity requirement is kept constant for the longer of +holPer and the duration of the change process.
+The calculation is according to Guideline36-2021, section 5.20.4.9. +

+", +revisions=" + +")); +end CapacityRequirement; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Change.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Change.mo new file mode 100644 index 00000000000..2b4def86f65 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Change.mo @@ -0,0 +1,467 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Change "Calculates the chiller stage signal" + + parameter Integer nSta = 3 + "Number of chiller stages, does not include zero stage"; + + parameter Real delayStaCha( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Hold period for each stage change"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-480,150},{-440,190}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUp + "Stage up status" + annotation (Placement(transformation(extent={{-480,-60},{-440,-20}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDow + "Stage down signal" + annotation (Placement(transformation(extent={{-480,-160},{-440,-120}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uIni( + final min=0, + final max=nSta) + "Initial chiller stage (at plant enable)" + annotation (Placement(transformation(extent={{-480,220},{-440,260}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAvaUp( + final min=0, + final max=nSta) + "Next available stage up" + annotation (Placement(transformation(extent={{-480,90},{-440,130}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAvaDow( + final min=0, + final max=nSta) + "Next available stage down" + annotation (Placement(transformation(extent={{-480,10},{-440,50}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaEdg + "Chiller stage change edge signal" + annotation (Placement(transformation(extent={{440,-102},{480,-62}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaUpEdg + "Chiller stage up change edge signal" + annotation (Placement(transformation(extent={{440,-62},{480,-22}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaDowEdg + "Chiller stage down change edge signal" + annotation (Placement(transformation(extent={{440,-142},{480,-102}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput ySta( + final min=0, + final max = nSta) + "Chiller stage integer setpoint" + annotation (Placement(transformation(extent={{440,150},{480,190}}), + iconTransformation(extent={{100,20},{140,60}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{-380,-90},{-360,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Boolean signal change" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam "Triggered sampler" + annotation (Placement(transformation(extent={{110,60},{130,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch switch1 "Switch" + annotation (Placement(transformation(extent={{-240,60},{-220,80}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea "Type converter" + annotation (Placement(transformation(extent={{-320,20},{-300,40}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt "Type converter" + annotation (Placement(transformation(extent={{200,190},{220,210}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 "Type converter" + annotation (Placement(transformation(extent={{-320,100},{-300,120}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea2 + "Integer to real conversion" + annotation (Placement(transformation(extent={{-40,230},{-20,250}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold holIniSta( + final trueHoldDuration=delayStaCha, + final falseHoldDuration=0) + "Holds stage switched to initial upon plant start" + annotation (Placement(transformation(extent={{-320,160},{-300,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch switch2 "Switch" + annotation (Placement(transformation(extent={{160,190},{180,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 "Logical or" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Ensures the stage is changed at high load increases/decreases where a stage up or a stage down signal is uninterrupted after a single stage change as an another one is needed right away" + annotation (Placement(transformation(extent={{0,-140},{20,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim "Timer" + annotation (Placement(transformation(extent={{-80,-240},{-60,-220}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical andEnsures the stage is changed at high load increases/decreases where a stage up or a stage down signal is uninterrupted after a single stage change as an another one is needed right away" + annotation (Placement(transformation(extent={{-140,-200},{-120,-180}}))); + + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesEquThr( + final t=delayStaCha) "Less equal threshold" + annotation (Placement(transformation(extent={{-40,-240},{-20,-220}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam1 + "Triggered sampler" + annotation (Placement(transformation(extent={{180,0},{200,20}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea "Type conveter" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=0.5) "Greater than a threshold" + annotation (Placement(transformation(extent={{-20,80},{0,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Ensures initial stage is held until the first stage change signal after the initial stage phase is over" + annotation (Placement(transformation(extent={{100,190},{120,210}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 "And" + annotation (Placement(transformation(extent={{40,110},{60,130}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staChaHol1( + final trueHoldDuration=delayStaCha, + final falseHoldDuration=0) + "Ensures stage change delay is kept at long stage up or down signals that cause multiple consecutive stage changes " + annotation (Placement(transformation(extent={{-80,-180},{-60,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Detects plant start" + annotation (Placement(transformation(extent={{-380,160},{-360,180}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not" + annotation (Placement(transformation(extent={{-260,-70},{-240,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.And and6 "Logical and" + annotation (Placement(transformation(extent={{-180,-90},{-160,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or3 "Logical or" + annotation (Placement(transformation(extent={{160,-60},{180,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Detects plant start" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staChaHol2( + final trueHoldDuration=delayStaCha, + final falseHoldDuration=0) + "Stage change hold" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staChaHol3( + final trueHoldDuration=delayStaCha, + final falseHoldDuration=0) + "Stage change hold" + annotation (Placement(transformation(extent={{340,-260},{360,-240}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{372,-260},{392,-240}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if there is stage change" + annotation (Placement(transformation(extent={{300,90},{320,110}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 + "Consider staging up only if stage down signal is not on" + annotation (Placement(transformation(extent={{-320,60},{-300,80}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-380,40},{-360,60}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{180,-170},{200,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu + "Check if the stage setpoint is zero" + annotation (Placement(transformation(extent={{240,-170},{260,-150}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 "Logical and" + annotation (Placement(transformation(extent={{280,-140},{300,-120}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 "Logical switch" + annotation (Placement(transformation(extent={{380,-132},{400,-112}}))); + Buildings.Controls.OBC.CDL.Logical.And and7 "Logical and" + annotation (Placement(transformation(extent={{280,-100},{300,-80}}))); + Buildings.Controls.OBC.CDL.Logical.And and8 "Logical and" + annotation (Placement(transformation(extent={{280,-60},{300,-40}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2 "Logical switch" + annotation (Placement(transformation(extent={{380,-92},{400,-72}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3 "Logical switch" + annotation (Placement(transformation(extent={{380,-52},{400,-32}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt + "Convert boolean input to integer output" + annotation (Placement(transformation(extent={{-120,140},{-100,160}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply mulInt + "Stage zero when the plant is not enabled" + annotation (Placement(transformation(extent={{240,160},{260,180}}))); + Buildings.Controls.OBC.CDL.Logical.And and9 + "Logical and" + annotation (Placement(transformation(extent={{-220,-90},{-200,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2(final k=true) + "Constant true" + annotation (Placement(transformation(extent={{180,-220},{200,-200}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=1, + final delayOnInit=true) + "Check if it has passed initial time" + annotation (Placement(transformation(extent={{240,-220},{260,-200}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Previous value" + annotation (Placement(transformation(extent={{380,-190},{400,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Previous value" + annotation (Placement(transformation(extent={{0,-240},{20,-220}}))); +equation + connect(switch1.y,triSam. u) + annotation (Line(points={{-218,70},{108,70}}, color={0,0,127})); + connect(intToRea1.y,switch1. u1) annotation (Line(points={{-298,110},{-260,110}, + {-260,78},{-242,78}}, color={0,0,127})); + connect(intToRea.y,switch1. u3) annotation (Line(points={{-298,30},{-260,30},{ + -260,62},{-242,62}}, color={0,0,127})); + connect(edg.y,holIniSta. u) + annotation (Line(points={{-358,170},{-322,170}}, color={255,0,255})); + connect(triSam.y,switch2. u3) annotation (Line(points={{132,70},{140,70},{140, + 192},{158,192}}, color={0,0,127})); + connect(uIni,intToRea2. u) annotation (Line(points={{-460,240},{-42,240}}, + color={255,127,0})); + connect(intToRea2.y,switch2. u1) annotation (Line(points={{-18,240},{140,240}, + {140,208},{158,208}}, color={0,0,127})); + connect(tim.y,lesEquThr. u) annotation (Line(points={{-58,-230},{-42,-230}}, + color={0,0,127})); + connect(triSam1.u,booToRea. y) + annotation (Line(points={{178,10},{82,10}}, color={0,0,127})); + connect(edg.y,lat1. u) annotation (Line(points={{-358,170},{-340,170},{-340, + 200},{98,200}}, color={255,0,255})); + connect(switch2.y,reaToInt. u) + annotation (Line(points={{182,200},{198,200}}, color={0,0,127})); + connect(and3.y,lat1. clr) annotation (Line(points={{62,120},{80,120},{80,194}, + {98,194}}, color={255,0,255})); + connect(and1.y,staChaHol1. u) annotation (Line(points={{-118,-190},{-100,-190}, + {-100,-170},{-82,-170}}, color={255,0,255})); + connect(uUp, or2.u1) annotation (Line(points={{-460,-40},{-410,-40},{-410,-80}, + {-382,-80}}, color={255,0,255})); + connect(uDow, or2.u2) annotation (Line(points={{-460,-140},{-400,-140},{-400,-88}, + {-382,-88}}, color={255,0,255})); + connect(uAvaUp, intToRea1.u) + annotation (Line(points={{-460,110},{-322,110}}, color={255,127,0})); + connect(uAvaDow, intToRea.u) + annotation (Line(points={{-460,30},{-322,30}}, color={255,127,0})); + connect(holIniSta.y, not3.u) annotation (Line(points={{-298,170},{-280,170},{ + -280,-60},{-262,-60}}, color={255,0,255})); + connect(and6.y, and1.u1) annotation (Line(points={{-158,-80},{-150,-80},{-150, + -190},{-142,-190}}, color={255,0,255})); + connect(and6.y, edg1.u) + annotation (Line(points={{-158,-80},{-82,-80}},color={255,0,255})); + connect(uPla, booToRea.u) annotation (Line(points={{-460,170},{-420,170},{ + -420,10},{58,10}}, color={255,0,255})); + connect(uPla, falEdg.u) annotation (Line(points={{-460,170},{-420,170},{-420, + -20},{-82,-20}}, color={255,0,255})); + connect(falEdg.y, or3.u1) annotation (Line(points={{-58,-20},{140,-20},{140,-50}, + {158,-50}}, color={255,0,255})); + connect(uPla, edg.u) + annotation (Line(points={{-460,170},{-382,170}}, color={255,0,255})); + connect(and3.u1, and6.y) annotation (Line(points={{38,120},{-150,120},{-150, + -80},{-158,-80}}, color={255,0,255})); + connect(or1.y, staChaHol2.u) annotation (Line(points={{62,-50},{78,-50}}, + color={255,0,255})); + connect(staChaHol2.y, triSam.trigger) annotation (Line(points={{102,-50},{120, + -50},{120,58}}, color={255,0,255})); + connect(edg1.y, or3.u2) annotation (Line(points={{-58,-80},{140,-80},{140,-58}, + {158,-58}}, color={255,0,255})); + connect(staChaHol3.y, not1.u) + annotation (Line(points={{362,-250},{370,-250}}, color={255,0,255})); + connect(uUp, and4.u1) annotation (Line(points={{-460,-40},{-410,-40},{-410,70}, + {-322,70}}, color={255,0,255})); + connect(uDow, not2.u) annotation (Line(points={{-460,-140},{-400,-140},{-400,50}, + {-382,50}}, color={255,0,255})); + connect(not2.y, and4.u2) annotation (Line(points={{-358,50},{-340,50},{-340,62}, + {-322,62}}, color={255,0,255})); + connect(and4.y, switch1.u2) annotation (Line(points={{-298,70},{-242,70}}, + color={255,0,255})); + connect(conInt.y, intEqu.u1) annotation (Line(points={{202,-160},{238,-160}}, + color={255,127,0})); + connect(intEqu.y, and5.u2) annotation (Line(points={{262,-160},{270,-160},{ + 270,-138},{278,-138}}, color={255,0,255})); + connect(and5.y,logSwi1. u3) annotation (Line(points={{302,-130},{378,-130}}, + color={255,0,255})); + connect(and6.y, and2.u1) annotation (Line(points={{-158,-80},{-150,-80},{-150, + -130},{-2,-130}}, color={255,0,255})); + connect(and7.y, logSwi2.u3) annotation (Line(points={{302,-90},{378,-90}}, + color={255,0,255})); + connect(and8.y, logSwi3.u3) annotation (Line(points={{302,-50},{378,-50}}, + color={255,0,255})); + connect(intEqu.y, and7.u2) annotation (Line(points={{262,-160},{270,-160},{ + 270,-98},{278,-98}}, color={255,0,255})); + connect(intEqu.y, and8.u2) annotation (Line(points={{262,-160},{270,-160},{ + 270,-58},{278,-58}}, color={255,0,255})); + connect(or3.y, triSam1.trigger) annotation (Line(points={{182,-50},{190,-50},{ + 190,-2}}, color={255,0,255})); + connect(triSam1.y, greThr1.u) annotation (Line(points={{202,10},{210,10},{210, + 40},{-40,40},{-40,90},{-22,90}}, color={0,0,127})); + connect(greThr1.y, and3.u2) annotation (Line(points={{2,90},{20,90},{20,112},{ + 38,112}}, color={255,0,255})); + connect(cha.down, and5.u1) annotation (Line(points={{322,94},{350,94},{350,20}, + {240,20},{240,-130},{278,-130}}, color={255,0,255})); + connect(cha.y, and7.u1) annotation (Line(points={{322,100},{360,100},{360,10}, + {250,10},{250,-90},{278,-90}}, color={255,0,255})); + connect(cha.up, and8.u1) annotation (Line(points={{322,106},{370,106},{370,0}, + {260,0},{260,-50},{278,-50}}, color={255,0,255})); + connect(cha.up, logSwi3.u1) annotation (Line(points={{322,106},{370,106},{370, + -34},{378,-34}}, color={255,0,255})); + connect(cha.y, logSwi2.u1) annotation (Line(points={{322,100},{360,100},{360, + -74},{378,-74}}, color={255,0,255})); + connect(cha.down, logSwi1.u1) annotation (Line(points={{322,94},{350,94},{350, + -114},{378,-114}}, color={255,0,255})); + connect(logSwi1.y, yChaDowEdg) + annotation (Line(points={{402,-122},{460,-122}}, color={255,0,255})); + connect(logSwi2.y, yChaEdg) + annotation (Line(points={{402,-82},{460,-82}}, color={255,0,255})); + connect(logSwi3.y, yChaUpEdg) + annotation (Line(points={{402,-42},{460,-42}}, color={255,0,255})); + connect(uPla, booToInt.u) annotation (Line(points={{-460,170},{-420,170},{ + -420,150},{-122,150}}, color={255,0,255})); + connect(booToInt.y, mulInt.u2) annotation (Line(points={{-98,150},{200,150},{ + 200,164},{238,164}}, color={255,127,0})); + connect(reaToInt.y, mulInt.u1) annotation (Line(points={{222,200},{230,200},{ + 230,176},{238,176}}, color={255,127,0})); + connect(mulInt.y, ySta) + annotation (Line(points={{262,170},{460,170}}, color={255,127,0})); + connect(mulInt.y, cha.u) annotation (Line(points={{262,170},{280,170},{280, + 100},{298,100}}, color={255,127,0})); + connect(mulInt.y, intEqu.u2) annotation (Line(points={{262,170},{280,170},{ + 280,100},{220,100},{220,-168},{238,-168}}, color={255,127,0})); + connect(and9.y, and6.u1) + annotation (Line(points={{-198,-80},{-182,-80}}, color={255,0,255})); + connect(not3.y, and9.u2) annotation (Line(points={{-238,-60},{-232,-60},{-232, + -88},{-222,-88}}, color={255,0,255})); + connect(or2.y, and9.u1) + annotation (Line(points={{-358,-80},{-222,-80}}, color={255,0,255})); + connect(con2.y, truDel.u) + annotation (Line(points={{202,-210},{238,-210}}, color={255,0,255})); + connect(truDel.y, logSwi3.u2) annotation (Line(points={{262,-210},{340,-210},{ + 340,-42},{378,-42}}, color={255,0,255})); + connect(truDel.y, logSwi2.u2) annotation (Line(points={{262,-210},{340,-210},{ + 340,-82},{378,-82}}, color={255,0,255})); + connect(truDel.y, logSwi1.u2) annotation (Line(points={{262,-210},{340,-210},{ + 340,-122},{378,-122}}, color={255,0,255})); + connect(edg1.y, or1.u1) annotation (Line(points={{-58,-80},{-20,-80},{-20,-50}, + {38,-50}}, color={255,0,255})); + connect(lat1.y, switch2.u2) + annotation (Line(points={{122,200},{158,200}}, color={255,0,255})); + connect(logSwi2.y, pre2.u) annotation (Line(points={{402,-82},{420,-82},{420, + -98},{320,-98},{320,-180},{378,-180}}, color={255,0,255})); + connect(pre2.y, staChaHol3.u) annotation (Line(points={{402,-180},{420,-180}, + {420,-220},{320,-220},{320,-250},{338,-250}}, color={255,0,255})); + connect(not1.y, and6.u2) annotation (Line(points={{394,-250},{420,-250},{420, + -280},{-190,-280},{-190,-88},{-182,-88}}, color={255,0,255})); + connect(and2.y, or1.u2) annotation (Line(points={{22,-130},{30,-130},{30,-58}, + {38,-58}}, color={255,0,255})); + connect(and1.y, tim.u) annotation (Line(points={{-118,-190},{-100,-190},{-100, + -230},{-82,-230}}, color={255,0,255})); + connect(lesEquThr.y, pre1.u) + annotation (Line(points={{-18,-230},{-2,-230}}, color={255,0,255})); + connect(pre1.y, and1.u2) annotation (Line(points={{22,-230},{30,-230},{30, + -260},{-150,-260},{-150,-198},{-142,-198}}, color={255,0,255})); + connect(staChaHol1.y, and2.u2) annotation (Line(points={{-58,-170},{-48,-170}, + {-48,-138},{-2,-138}}, color={255,0,255})); + annotation (defaultComponentName = "cha", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-112,150},{108,112}}, + textColor={0,0,255}, + textString="%name")}), Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-440,-300},{440,300}})), +Documentation(info=" +

+This subsequence is not directly specified in Guideline36 as it provides a side +calculation pertaining to generalization of the staging sequences for any number +of chillers and stages provided by the user. +

+

+This subsequence is used to generate the chiller stage setpoint +ySta and a boolean vector of +chiller status setpoint indices y +for the ySta stage. +

+

+The inputs to the subsequece are: +

+ +

+If stage down and stage up happen at the same time for any faulty reason the staging down is performed. +

+

+If stage down or stage up signal is held for a time longer than delayStaCha +multiple consecutive stage change signals are issued. +

+

+At plant enable the intial stage uIni is held for at least delayStaCha +and until any stage up or down signal is generated. +

+

+Per Guideline36-2021, section 5.20.4.15.a. Each stage shall have a minimum runtime +of delayStaCha. +

+", +revisions=" + +")); +end Change; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/ChillerIndices.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/ChillerIndices.mo new file mode 100644 index 00000000000..32245e0326c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/ChillerIndices.mo @@ -0,0 +1,136 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block ChillerIndices "Returns chiller indices for the current stage" + + parameter Integer nSta = 3 + "Number of chiller stages"; + + parameter Integer nChi = 2 + "Number of chillers"; + + parameter Integer staMat[nSta, nChi] = {{1,0},{0,1},{1,1}} + "Staging matrix with stages in rows and chillers in columns"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta, + final start=0) "Current chiller stage" + annotation (Placement(transformation(extent={{-160,40},{-120,80}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller status setpoint vector for the current stage" + annotation (Placement(transformation(extent={{120,-60},{160,-20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + final parameter Integer staInd[nSta] = {i for i in 1:nSta} + "Stage index vector"; + + final parameter Integer staIndMat[nSta, nChi] = {j for i in 1:nChi, j in 1:nSta} + "Matrix of staging matrix dimensions with stage indices in each column"; + + final parameter Integer lowDia[nSta, nSta] = {if i<=j then 1 else 0 for i in 1:nSta, j in 1:nSta} + "Lower diagonal unit matrix"; + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nSta) "Replicates signal to a length equal the stage count" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1[nSta]( + final nout=fill(nChi, nSta)) "Replicates signal to dimensions of the staging matrix" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staIndMatr[nSta,nChi]( + final k=staIndMat) "Matrix with stage index in each column" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nSta,nChi] + "Outputs a zero matrix populated with ones in the current stage index row" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiStaMatr[nSta,nChi]( + final k=staMat) "Staging matrix" + annotation (Placement(transformation(extent={{-80,-56},{-60,-36}}))); + + Buildings.Controls.OBC.CDL.Reals.MatrixMax matMax( + final nRow=nSta, + final nCol=nChi, + final rowMax=false) "Column-wise matrix maximum" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold chiInSta[nChi](t=fill(0.5, nChi)) + "Identifies chillers designated to operate in a given stage" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt[nSta,nChi] + "Outputs a zero matrix populated with ones for any available chiller in the current stage" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nSta,nChi]( + final integerTrue=fill(1, nSta, nChi), + final integerFalse=fill(0, nSta, nChi)) + "Type converter" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta,nChi] + "Type converter" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + +equation + connect(intRep.y, intRep1.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,127,0})); + connect(intRep1.y, intEqu1.u1) + annotation (Line(points={{-38,60},{-2,60}}, color={255,127,0})); + connect(matMax.y, chiInSta.u) + annotation (Line(points={{62,-40},{78,-40}}, color={0,0,127})); + connect(staIndMatr.y, intEqu1.u2) annotation (Line(points={{-38,20},{-20,20},{ + -20,52},{-2,52}}, color={255,127,0})); + connect(chiInSta.y, yChi) + annotation (Line(points={{102,-40},{140,-40}}, color={255,0,255})); + connect(proInt.y, intToRea.u) + annotation (Line(points={{-18,-40},{-2,-40}}, color={255,127,0})); + connect(intToRea.y, matMax.u) + annotation (Line(points={{22,-40},{38,-40}}, color={0,0,127})); + connect(intEqu1.y, booToInt.u) + annotation (Line(points={{22,60},{38,60}}, color={255,0,255})); + connect(chiStaMatr.y, proInt.u2) annotation (Line(points={{-58,-46},{-42,-46}}, + color={255,127,0})); + connect(u, intRep.u) annotation (Line(points={{-140,60},{-102,60}}, + color={255,127,0})); + connect(booToInt.y, proInt.u1) annotation (Line(points={{62,60},{80,60},{80,-10}, + {-50,-10},{-50,-34},{-42,-34}}, color={255,127,0})); + annotation (defaultComponentName = "chiInd", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-120,-100},{120,100}})), +Documentation(info=" +

+This subsequence is not directly specified in Guideline36-2021 as it provides +a side calculation pertaining to generalization of the staging +sequences for any number of chillers and stages provided by the +user. +

+

+The subsequence outputs a vector of chiller indices yChi +for a stage index input u given a staging matrix staMat. +

+", +revisions=" + +")); +end ChillerIndices; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Configurator.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Configurator.mo new file mode 100644 index 00000000000..47217def7f9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Configurator.mo @@ -0,0 +1,311 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Configurator "Configures chiller staging" + + parameter Integer nSta = 3 + "Number of chiller stages, does not include zero stage"; + + parameter Integer nChi = 2 + "Number of chillers"; + + parameter Real chiDesCap[nChi]( + final unit=fill("W",nChi), + final quantity=fill("HeatFlowRate",nChi), + displayUnit=fill("W",nChi)) + "Design chiller capacities vector" + annotation (Evaluate=true); + + parameter Real chiMinCap[nChi]( + final unit=fill("W",nChi), + final quantity=fill("HeatFlowRate",nChi), + displayUnit=fill("W",nChi)) + "Chiller minimum cycling loads vector" + annotation (Evaluate=true); + + parameter Integer chiTyp[nChi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal} + "Chiller type. Recommended staging order: positive displacement, variable speed centrifugal, constant speed centrifugal"; + + parameter Integer staMat[nSta, nChi] = {{1,0},{0,1},{1,1}} + "Staging matrix with stage as row index and chiller as column index"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiAva[nChi] + "Chiller availability status vector. Chiller may be deemend unavailable due to unavailability of a dedicated chilled or condenser water pump" + annotation (Placement(transformation(extent={{-260,-60},{-220,-20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yAva[nSta] + "Stage availability status vector" + annotation (Placement(transformation(extent={{220,-100},{260,-60}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yTyp[nSta]( + final max=fill(nSta, nSta)) "Chiller stage types vector" + annotation (Placement(transformation(extent={{220,-140},{260,-100}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDesCap[nSta]( + final unit=fill("W", nSta), + final quantity=fill("HeatFlowRate", nSta)) "Stage design capacities vector" + annotation (Placement(transformation(extent={{220,0},{260,40}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinCap[nSta]( + final unit=fill("W", nSta), + final quantity=fill("HeatFlowRate", nSta)) "Unload stage capacities vector" + annotation (Placement(transformation(extent={{220,-40},{260,0}}), + iconTransformation(extent={{100,20},{140,60}}))); + +protected + final parameter Integer chiTypMat[nSta, nChi] = {chiTyp[i] for i in 1:nChi, j in 1:nSta} + "Chiller type array expanded to allow for element-wise multiplication with the staging matrix"; + + Buildings.Controls.OBC.CDL.Utilities.Assert assMes1( + final message="The chillers must be tagged in order of design capacity if unequally sized") + "Asserts whether chillers are tagged in ascending order with regards to capacity" + annotation (Placement(transformation(extent={{60,160},{80,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Sort sort1( + final nin=nChi) "Ascending sort" + annotation (Placement(transformation(extent={{-140,160},{-120,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1[nChi] + "Subtracts signals" + annotation (Placement(transformation(extent={{-100,160},{-80,180}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax( + final nin=nChi) "Maximum value in a vector input" + annotation (Placement(transformation(extent={{-60,160},{-40,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Abs abs "Absolute values" + annotation (Placement(transformation(extent={{-20,160},{0,180}}))); + + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr1( + final t=0.5) "Less threshold" + annotation (Placement(transformation(extent={{20,160},{40,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiDesCaps[nChi]( + final k=chiDesCap) "Design chiller capacities vector" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiMinCaps[nChi]( + final k=chiMinCap) "Chiller unload capacities vector" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Reals.MatrixGain staDesCaps( + final K=staMat) "Matrix gain for design capacities" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Reals.MatrixGain staMinCaps( + final K=staMat) "Matrix gain from minimal capacities" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Reals.MatrixGain sumNumChi( + final K=staMat) + "Outputs the total chiller count per stage vector" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + + Buildings.Controls.OBC.CDL.Reals.MatrixGain sumNumAvaChi( + final K=staMat) + "Outputs the available chiller count per stage vector" + annotation (Placement(transformation(extent={{-140,-50},{-120,-30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant oneVec[nChi]( + final k=fill(1, nChi)) "Mocks a case with all chillers available" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] + "Type converter" + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub2[nSta] + "Subtracts count of available chillers from the design count, at each stage" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + + Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr[nSta]( + final t=fill(0.5, nSta)) + "Checks if the count of available chillers in each stage equals the design count" + annotation (Placement(transformation(extent={{-40,-20},{-20,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiStaMat[nSta,nChi]( + final k=staMat) "Staging matrix" + annotation (Placement(transformation(extent={{-200,-170},{-180,-150}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staType[nSta,nChi]( + final k=chiTypMat) "Chiller stage type matrix" + annotation (Placement(transformation(extent={{-200,-110},{-180,-90}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply pro[nSta,nChi] + "Element-wise product" + annotation (Placement(transformation(extent={{-140,-130},{-120,-110}}))); + + Buildings.Controls.OBC.CDL.Reals.MatrixMax matMax( + final nRow=nSta, + final nCol=nChi) "Row-wise matrix maximum" + annotation (Placement(transformation(extent={{-100,-130},{-80,-110}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt[nSta] + "Type converter" + annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); + + Buildings.Controls.OBC.CDL.Reals.Sort sort( + final nin=nSta) "Vector sort" + annotation (Placement(transformation(extent={{20,-180},{40,-160}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1[nSta] + "Type converter" + annotation (Placement(transformation(extent={{-20,-180},{0,-160}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1[nSta] + "Type converter" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nSta] "Integer equality" + annotation (Placement(transformation(extent={{100,-160},{120,-140}}))); + + Buildings.Controls.OBC.CDL.Utilities.Assert assMes( + final message="It could be that the chillers are not being staged in an order + recommended by ASHRAE RP1711 or Guideline 36. + Please make sure to follow the recommendation that is: + any positive displacement machines first, + any variable speed centrifugal next and any constant speed centrifugal last.") + "Assert block" + annotation (Placement(transformation(extent={{180,-160},{200,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=nSta) "Logical and with a vector input" + annotation (Placement(transformation(extent={{140,-160},{160,-140}}))); + +equation + connect(chiDesCaps.y, staDesCaps.u) annotation (Line(points={{-178,110},{-142, + 110}}, color={0,0,127})); + connect(chiMinCaps.y, staMinCaps.u) annotation (Line(points={{-178,70},{-142,70}}, + color={0,0,127})); + connect(uChiAva, booToRea.u) + annotation (Line(points={{-240,-40},{-202,-40}}, color={255,0,255})); + connect(booToRea.y, sumNumAvaChi.u) + annotation (Line(points={{-178,-40},{-142,-40}}, color={0,0,127})); + connect(sumNumChi.y, sub2.u1) annotation (Line(points={{-118,20},{-100,20},{-100, + -4},{-82,-4}}, color={0,0,127})); + connect(sumNumAvaChi.y, sub2.u2) annotation (Line(points={{-118,-40},{-100.5,-40}, + {-100.5,-16},{-82,-16}}, color={0,0,127})); + connect(sub2.y,lesThr. u) + annotation (Line(points={{-58,-10},{-42,-10}}, color={0,0,127})); + connect(lesThr.y, yAva) annotation (Line(points={{-18,-10},{60,-10},{60,-80},{ + 240,-80}}, color={255,0,255})); + connect(chiStaMat.y,pro. u2) annotation (Line(points={{-178,-160},{-160,-160}, + {-160,-126},{-142,-126}}, color={0,0,127})); + connect(pro.y,matMax. u) + annotation (Line(points={{-118,-120},{-102,-120}}, color={0,0,127})); + connect(matMax.y,reaToInt. u) + annotation (Line(points={{-78,-120},{-62,-120}}, color={0,0,127})); + connect(reaToInt.y, yTyp) annotation (Line(points={{-38,-120},{240,-120}}, + color={255,127,0})); + connect(reaToInt.y, intToRea1.u) annotation (Line(points={{-38,-120},{-30, + -120},{-30,-170},{-22,-170}}, + color={255,127,0})); + connect(intToRea1.y, sort.u) + annotation (Line(points={{2,-170},{18,-170}}, color={0,0,127})); + connect(sort.y, reaToInt1.u) + annotation (Line(points={{42,-170},{58,-170}}, color={0,0,127})); + connect(reaToInt.y,intEqu. u1) annotation (Line(points={{-38,-120},{90,-120},{ + 90,-150},{98,-150}}, color={255,127,0})); + connect(reaToInt1.y,intEqu. u2) annotation (Line(points={{82,-170},{90,-170},{ + 90,-158},{98,-158}}, color={255,127,0})); + connect(mulAnd.y, assMes.u) + annotation (Line(points={{162,-150},{178,-150}}, color={255,0,255})); + connect(intEqu.y, mulAnd.u) annotation (Line(points={{122,-150},{138,-150}}, + color={255,0,255})); + connect(staType.y, pro.u1) annotation (Line(points={{-178,-100},{-160,-100},{-160, + -114},{-142,-114}}, color={0,0,127})); + connect(staDesCaps.y, yDesCap) annotation (Line(points={{-118,110},{100,110},{ + 100,20},{240,20}}, color={0,0,127})); + connect(staMinCaps.y, yMinCap) annotation (Line(points={{-118,70},{80,70},{80, + -20},{240,-20}}, color={0,0,127})); + connect(oneVec.y, sumNumChi.u) + annotation (Line(points={{-178,20},{-142,20}}, color={0,0,127})); + connect(sort1.u, chiDesCaps.y) annotation (Line(points={{-142,170},{-160, + 170},{-160,110},{-178,110}}, color={0,0,127})); + connect(sort1.y, sub1.u1) annotation (Line(points={{-118,170},{-110,170},{-110, + 176},{-102,176}}, color={0,0,127})); + connect(chiDesCaps.y, sub1.u2) annotation (Line(points={{-178,110},{-160,110}, + {-160,150},{-110,150},{-110,164},{-102,164}}, color={0,0,127})); + connect(sub1.y, multiMax.u) + annotation (Line(points={{-78,170},{-62,170}}, color={0,0,127})); + connect(multiMax.y, abs.u) + annotation (Line(points={{-38,170},{-22,170}}, color={0,0,127})); + connect(abs.y, lesThr1.u) + annotation (Line(points={{2,170},{18,170}}, color={0,0,127})); + connect(lesThr1.y, assMes1.u) + annotation (Line(points={{42,170},{58,170}}, color={255,0,255})); + annotation (defaultComponentName = "conf", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-220,-200},{220,200}})), +Documentation(info=" +

+This subsequence is not directly specified in Guideline36-2021 as it provides +a side calculation pertaining to generalization of the staging +sequences for any number of chillers and stages provided by the +user. +

+

+Given the staging matrix input parameter staMat the staging configurator calculates: +

+ +", +revisions=" + +")); +end Configurator; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Down.mo new file mode 100644 index 00000000000..a8935b61597 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Down.mo @@ -0,0 +1,338 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Down "Generates a stage down signal" + + parameter Boolean have_WSE = true + "true = plant has a WSE, false = plant does not have WSE"; + + parameter Boolean have_serChi = false + "true = series chillers plant; false = parallel chillers plant"; + + parameter Boolean have_locSen=false + "Flag of local DP sensor: true=local DP sensor hardwired to controller" + annotation (Dialog(enable=not have_serChi)); + + parameter Integer nRemSen=2 + "Total number of remote differential pressure sensors" + annotation (Dialog(enable=not have_serChi)); + + parameter Real parLoaRatDelay( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Enable delay for operating and staging part load ratio condition"; + + parameter Real faiSafTruDelay( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Enable delay for failsafe condition"; + + parameter Real faiSafTDif( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=1 + "Offset between the chilled water supply temperature and its setpoint for the failsafe condition"; + + parameter Real TDif( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=1 + "Offset between the chilled water supply temperature and its setpoint" + annotation(Evaluate=true, Dialog(enable=have_WSE)); + + parameter Real TDifHys( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=1 + "Hysteresis deadband for temperature" + annotation(Evaluate=true, Dialog(enable=have_WSE)); + + parameter Real faiSafDpDif( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa")=2 * 6895 + "Offset between the chilled water pump differential static pressure and its setpoint"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWseSta if have_WSE + "WSE status" + annotation (Placement(transformation(extent={{-220,-150},{-180,-110}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u + "Chiller stage" + annotation (Placement(transformation(extent={{-220,-180},{-180,-140}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uOpeDow(final unit="1") + "Next available stage down operating part load ratio (OPLR)" + annotation (Placement( + transformation(extent={{-220,190},{-180,230}}), iconTransformation( + extent={{-140,90},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uStaDow(final unit="1") + "Next available stage down staging part load ratio (SPLR)" + annotation (Placement(transformation(extent={{-220,150},{-180,190}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-220,-60},{-180,-20}}), + iconTransformation(extent={{-140,-32},{-100,8}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-220,110},{-180,150}}), + iconTransformation(extent={{-140,-52},{-100,-12}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_local( + final unit="Pa", + final quantity="PressureDifference") + if (not have_serChi) and have_locSen + "Chilled water pump differential static pressure setpoint for local pressure sensor" + annotation (Placement(transformation(extent={{-220,80},{-180,120}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_local( + final unit="Pa", + final quantity="PressureDifference") if (not have_serChi) and have_locSen + "Chilled water pump differential static pressure" + annotation (Placement(transformation(extent={{-220,50},{-180,90}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference",nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure setpoint for remote sensor" + annotation (Placement(transformation(extent={{-220,10},{-180,50}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference",nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure from remote sensor" + annotation (Placement(transformation(extent={{-220,-20},{-180,20}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TWsePre( + final quantity="ThermodynamicTemperature", + final unit="K") if have_WSE + "Predicted waterside economizer outlet temperaturePredicted WSE outlet temperature" + annotation (Placement(transformation(extent={{-220,-90},{-180,-50}}), + iconTransformation(extent={{-140,-72},{-100,-32}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTowFanSpeMax if have_WSE + "Maximum cooling tower fan speed" + annotation (Placement(transformation(extent={{-220,-120},{-180,-80}}), + iconTransformation(extent={{-140,-92},{-100,-52}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y + "Stage down signal" + annotation (Placement(transformation(extent={{180,-10},{200,10}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.FailsafeCondition faiSafCon( + final have_serChi=have_serChi, + final have_locSen=have_locSen, + final nRemSen=nRemSen, + final faiSafTruDelay=faiSafTruDelay, + final TDif=TDif, + final dpDif=faiSafDpDif) + "Failsafe condition of the next lower stage" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.CDL.Logical.And and0 "And for staging down" + annotation (Placement(transformation(extent={{20,80},{40,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi "Logical switch" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr( + final t=1) + "Switches staging down rules" + annotation (Placement(transformation(extent={{-120,-170},{-100,-150}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTSup( + final uLow=TDif - TDifHys, + final uHigh=TDif) if have_WSE + "Checks if the predicted downstream WSE chilled water supply temperature is higher than its setpoint plus an offset" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 if have_WSE + "Or for staging up" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not0 if have_WSE + "Outputs true if signal is below maximum" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 if have_WSE + "Temperature difference" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys( + final uHigh=0.99, + final uLow=0.98) if have_WSE + "Checks if the signal is at its maximum" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=parLoaRatDelay, + final delayOnInit=true) + "Delays a true signal" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysDow( + final uLow=0, + final uHigh=0.05) + "Checks if the operating PLR of the next available stage down exceeds the staging down PLR for that stage" + annotation (Placement(transformation(extent={{-80,180},{-60,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub2 + "Subtracts part load ratios" + annotation (Placement(transformation(extent={{-120,180},{-100,200}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noWSEcoSig( + final k=false) if not have_WSE + "Staging from 1 to 0 for plants without a WSE is depends on the plant disable sequence" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if have_WSE + "Logical and" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + +equation + connect(TChiWatSupSet, faiSafCon.TChiWatSupSet) annotation (Line(points={{-200, + -40},{-160,-40},{-160,59},{-82,59}},color={0,0,127})); + connect(dpChiWatPumSet_local, faiSafCon.dpChiWatPumSet_local) annotation ( + Line(points={{-200,100},{-130,100},{-130,51},{-82,51}}, color={0,0,127})); + connect(dpChiWatPum_local, faiSafCon.dpChiWatPum_local) annotation (Line( + points={{-200,70},{-140,70},{-140,48},{-82,48}}, color={0,0,127})); + connect(u, intGreThr.u) + annotation (Line(points={{-200,-160},{-122,-160}}, color={255,127,0})); + connect(sub1.y,hysTSup. u) + annotation (Line(points={{-58,-60},{-42,-60}}, color={0,0,127})); + connect(TChiWatSup, faiSafCon.TChiWatSup) annotation (Line(points={{-200,130}, + {-120,130},{-120,56},{-82,56}}, color={0,0,127})); + connect(hys.y, not0.u) + annotation (Line(points={{-98,-100},{-82,-100}}, color={255,0,255})); + connect(uTowFanSpeMax, hys.u) annotation ( + Line(points={{-200,-100},{-122,-100}},color={0,0,127})); + connect(hysTSup.y, and1.u1) annotation (Line(points={{-18,-60},{-2,-60}}, + color={255,0,255})); + connect(not1.y, and0.u2) annotation (Line(points={{-18,50},{0,50},{0,82},{18,82}}, + color={255,0,255})); + connect(intGreThr.y, logSwi.u2) annotation (Line(points={{-98,-160},{90,-160}, + {90,0},{98,0}}, color={255,0,255})); + connect(not0.y, and1.u2) annotation (Line(points={{-58,-100},{-10,-100},{-10,-68}, + {-2,-68}}, color={255,0,255})); + connect(sub2.y, hysDow.u) + annotation (Line(points={{-98,190},{-82,190}}, color={0,0,127})); + connect(TChiWatSupSet, sub1.u1) annotation (Line(points={{-200,-40},{-160,-40}, + {-160,-54},{-82,-54}}, color={0,0,127})); + connect(TWsePre, sub1.u2) annotation (Line(points={{-200,-70},{-140,-70},{-140, + -66},{-82,-66}}, color={0,0,127})); + connect(noWSEcoSig.y, logSwi.u3) annotation (Line(points={{42,-10},{70,-10},{70, + -8},{98,-8}}, color={255,0,255})); + connect(hysDow.y, truDel1.u) + annotation (Line(points={{-58,190},{-42,190}}, color={255,0,255})); + connect(truDel1.y, and0.u1) annotation (Line(points={{-18,190},{0,190},{0,90}, + {18,90}}, color={255,0,255})); + connect(and0.y, logSwi.u1) annotation (Line(points={{42,90},{70,90},{70,8},{98, + 8}}, color={255,0,255})); + connect(logSwi.y, y) + annotation (Line(points={{122,0},{190,0}}, color={255,0,255})); + connect(faiSafCon.y, not1.u) + annotation (Line(points={{-58,50},{-42,50}}, color={255,0,255})); + connect(dpChiWatPumSet_remote, faiSafCon.dpChiWatPumSet_remote) annotation ( + Line(points={{-200,30},{-130,30},{-130,44},{-82,44}}, color={0,0,127})); + connect(dpChiWatPum_remote, faiSafCon.dpChiWatPum_remote) annotation (Line( + points={{-200,0},{-120,0},{-120,41},{-82,41}}, color={0,0,127})); + connect(uOpeDow, sub2.u2) annotation (Line(points={{-200,210},{-160,210},{-160, + 184},{-122,184}}, color={0,0,127})); + connect(uStaDow, sub2.u1) annotation (Line(points={{-200,170},{-140,170},{-140, + 196},{-122,196}}, color={0,0,127})); + connect(and1.y, and2.u1) + annotation (Line(points={{22,-60},{38,-60}}, color={255,0,255})); + connect(uWseSta, and2.u2) annotation (Line(points={{-200,-130},{30,-130},{30,-68}, + {38,-68}}, color={255,0,255})); + connect(and2.y, logSwi.u3) annotation (Line(points={{62,-60},{80,-60},{80,-8}, + {98,-8}}, color={255,0,255})); + annotation (defaultComponentName = "staDow", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name"), + Rectangle(extent={{-80,-10},{-20,-22}}, lineColor={0,0,127}), + Rectangle(extent={{-80,-28},{-20,-40}}, lineColor={0,0,127}), + Rectangle(extent={{-76,-22},{-72,-28}}, lineColor={0,0,127}), + Rectangle(extent={{-28,-22},{-24,-28}}, lineColor={0,0,127}), + Rectangle(extent={{20,-10},{80,-22}}, lineColor={0,0,127}), + Rectangle(extent={{20,-28},{80,-40}}, lineColor={0,0,127}), + Rectangle(extent={{24,-22},{28,-28}}, lineColor={0,0,127}), + Rectangle(extent={{72,-22},{76,-28}}, lineColor={0,0,127}), + Rectangle(extent={{-80,30},{-20,18}}, lineColor={0,0,127}), + Rectangle(extent={{-80,12},{-20,0}}, lineColor={0,0,127}), + Rectangle(extent={{-76,18},{-72,12}}, lineColor={0,0,127}), + Rectangle(extent={{-28,18},{-24,12}}, lineColor={0,0,127})}), + Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-180,-200},{180,240}})), +Documentation(info=" +

+Outputs a boolean stage down signal y when: +

+ +

+If the plant has a WSE, staging from the lowest available chiller stage to +WSE stage occurs when: +

+

+The implementation is according to ASHRAE Guideline36-2021, section 5.20.4.15. +and can be used for both primary-only plants with and without a WSE. +

+", +revisions=" + +")); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo new file mode 100644 index 00000000000..d8190ebcde8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo @@ -0,0 +1,89 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block EfficiencyCondition + "Efficiency condition used in staging up and down" + + parameter Real effConTruDelay( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Enable delay"; + + parameter Real sigDif = 0.05 + "Signal hysteresis deadband"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uOpe( + final unit="1") + "Operative part load ratio of the current stage" + annotation (Placement(transformation(extent={{-140,0},{-100,40}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uStaUp( + final unit="1") + "Staging part load ratio of the next stage up" + annotation (Placement(transformation(extent={{-140,-40},{-100,0}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y + "Efficiency condition for chiller staging" + annotation (Placement(transformation(extent={{80,-20},{120,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=effConTruDelay, + final delayOnInit=true) + "Delays a true signal" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysOpe( + final uLow=0, + final uHigh=sigDif) + "Checks if the current stage operating part load ratio exceeds the stage up part load ratio" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub + "Subtracts part load ratios" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + +equation + connect(truDel.y, y) + annotation (Line(points={{42,0},{100,0}},color={255,0,255})); + connect(hysOpe.y, truDel.u) + annotation (Line(points={{2,0},{18,0}}, color={255,0,255})); + connect(sub.y, hysOpe.u) + annotation (Line(points={{-38,0},{-22,0}}, color={0,0,127})); + connect(uOpe, sub.u1) annotation (Line(points={{-120,20},{-80,20},{-80,6},{-62, + 6}}, color={0,0,127})); + connect(uStaUp, sub.u2) annotation (Line(points={{-120,-20},{-80,-20},{-80,-6}, + {-62,-6}}, color={0,0,127})); + +annotation (defaultComponentName = "effCon", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-100,-60},{80,60}})), +Documentation(info=" +

+Efficiency condition used in staging up and down for plants primary-only and +primary-secondary plants, both with and without a water side economizer. +It is implemented according to the specification provided in section 5.20.4.15 of +Guideline36-2021. +

+", +revisions=" + +")); +end EfficiencyCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo new file mode 100644 index 00000000000..dd5de59cf94 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo @@ -0,0 +1,230 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block FailsafeCondition + "Failsafe condition used in staging up and down" + + parameter Boolean have_serChi = false + "true = series chillers plant; false = parallel chillers plant"; + + parameter Boolean have_locSen = false + "Flag of local DP sensor: true=local DP sensor hardwired to controller" + annotation (Dialog(enable=not have_serChi)); + + parameter Integer nRemSen=2 + "Total number of remote differential pressure sensors" + annotation (Dialog(enable=not have_serChi)); + + parameter Real faiSafTruDelay( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Enable delay"; + + parameter Real TDif( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=1 + "Offset between the chilled water supply temperature and its setpoint"; + + parameter Real TDifHys( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=1 + "Temperature hysteresis deadband"; + + parameter Real dpDif( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa")=2 * 6895 + "Offset between the chilled water differential pressure and its setpoint"; + + parameter Real dpDifHys( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa")=0.5 * 6895 + "Pressure difference hysteresis deadband"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-180,70},{-140,110}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-180,30},{-140,70}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_local( + final unit="Pa", + final quantity="PressureDifference") + if (not have_serChi) and have_locSen + "Chilled water differential pressure setpoint for local pressure sensor" + annotation (Placement(transformation(extent={{-180,0},{-140,40}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_local( + final unit="Pa", + final quantity="PressureDifference") if (not have_serChi) and have_locSen + "Chilled water differential pressure from local pressure sensor" + annotation (Placement(transformation(extent={{-180,-40},{-140,0}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference", nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure setpoint for remote sensor" + annotation (Placement(transformation(extent={{-180,-80},{-140,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference", nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure from remote sensor" + annotation (Placement(transformation(extent={{-180,-120},{-140,-80}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y + "Failsafe condition for chiller staging" + annotation (Placement(transformation(extent={{140,-20},{180,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysdpSup( + final uLow=dpDif - dpDifHys, + final uHigh=dpDif) if (not have_serChi) and have_locSen + "Checks how closely the chilled water pump differential pressure aproaches its setpoint from below" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTSup( + final uLow=TDif - TDifHys, + final uHigh=TDif) + "Checks if the chilled water supply temperature is higher than its setpoint plus an offset" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysdpSup1[nRemSen]( + final uLow=fill(dpDif - dpDifHys, nRemSen), + final uHigh=fill(dpDif, nRemSen)) + if (not have_serChi) and (not have_locSen) + "Checks how closely the chilled water pump differential pressure aproaches its setpoint from below" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) if have_serChi + "Virtual signal for series chiller plants" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=faiSafTruDelay, + final delayOnInit=false) + "Delays a true signal" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 "Logical or" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub0 + "Adder for temperatures" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 + if (not have_serChi) and have_locSen + "Subtracts differential pressures" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nRemSen) + if (not have_serChi) and (not have_locSen) + "Check if there is any true input" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub2[nRemSen] + if (not have_serChi) and (not have_locSen) + "Subtracts differential pressures" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1[nRemSen]( + final delayTime=fill(faiSafTruDelay,nRemSen), + final delayOnInit=fill(false, nRemSen)) + if (not have_serChi) and (not have_locSen) "Delays a true signal" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2( + final delayTime=faiSafTruDelay, + final delayOnInit=false) + if (not have_serChi) and have_locSen "Delays a true signal" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + +equation + connect(sub1.y, hysdpSup.u) + annotation (Line(points={{-78,0},{-62,0}}, color={0,0,127})); + connect(dpChiWatPumSet_local, sub1.u1) annotation (Line(points={{-160,20},{-120, + 20},{-120,6},{-102,6}}, color={0,0,127})); + connect(dpChiWatPum_local, sub1.u2) annotation (Line(points={{-160,-20},{-120, + -20},{-120,-6},{-102,-6}}, color={0,0,127})); + connect(sub0.y, hysTSup.u) + annotation (Line(points={{-78,80},{-62,80}}, color={0,0,127})); + connect(sub2.y, hysdpSup1.u) + annotation (Line(points={{-78,-80},{-62,-80}}, color={0,0,127})); + connect(dpChiWatPumSet_remote, sub2.u1) annotation (Line(points={{-160,-60},{-120, + -60},{-120,-74},{-102,-74}}, color={0,0,127})); + connect(dpChiWatPum_remote, sub2.u2) annotation (Line(points={{-160,-100},{-120, + -100},{-120,-86},{-102,-86}}, color={0,0,127})); + connect(or1.y, y) + annotation (Line(points={{122,0},{160,0}}, color={255,0,255})); + connect(hysTSup.y, truDel.u) + annotation (Line(points={{-38,80},{-22,80}}, color={255,0,255})); + connect(hysdpSup1.y, truDel1.u) + annotation (Line(points={{-38,-80},{-22,-80}}, color={255,0,255})); + connect(hysdpSup.y, truDel2.u) + annotation (Line(points={{-38,0},{-22,0}}, color={255,0,255})); + connect(truDel.y, or1.u1) annotation (Line(points={{2,80},{80,80},{80,0},{98,0}}, + color={255,0,255})); + connect(truDel2.y, or1.u2) annotation (Line(points={{2,0},{60,0},{60,-8},{98,-8}}, + color={255,0,255})); + connect(con.y, or1.u2) annotation (Line(points={{2,-40},{60,-40},{60,-8},{98,-8}}, + color={255,0,255})); + connect(mulOr.y, or1.u2) annotation (Line(points={{42,-80},{60,-80},{60,-8},{98, + -8}}, color={255,0,255})); + connect(truDel1.y, mulOr.u) + annotation (Line(points={{2,-80},{18,-80}}, color={255,0,255})); + connect(TChiWatSupSet, sub0.u2) annotation (Line(points={{-160,90},{-130,90},{ + -130,74},{-102,74}}, color={0,0,127})); + connect(TChiWatSup, sub0.u1) annotation (Line(points={{-160,50},{-120,50},{-120, + 86},{-102,86}}, color={0,0,127})); + +annotation (defaultComponentName = "faiSafCon", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-140,-120},{140,120}})), +Documentation(info=" +

+Failsafe condition used in staging up and down, implemented according to the +specification provided in section 5.20.4.15 of Guideline36-2021. The subsequence +applies to primary-only plants with and without a WSE. The sequence contains a +boolean flag to differentiate between parallel and series chiller plants. +

+", +revisions=" + +")); +end FailsafeCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Initial.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Initial.mo new file mode 100644 index 00000000000..bf44985915a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Initial.mo @@ -0,0 +1,240 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Initial "Outputs the initial stage" + + parameter Boolean have_WSE = true + "true = plant has a WSE, false = plant does not have WSE"; + + parameter Real wseDt = 1 + "Offset for checking waterside economizer leaving water temperature" + annotation (Dialog(tab="Advanced", enable=have_WSE)); + + parameter Real heaExcAppDes( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=2 + "Design heat exchanger approach" + annotation (Dialog(group="Waterside economizer", enable=have_WSE)); + + parameter Real cooTowAppDes( + final unit="K", + final quantity="TemperatureDifference", + displayUnit="degC")=2 + "Design cooling tower approach" + annotation (Dialog(group="Waterside economizer", enable=have_WSE)); + + parameter Real TOutWetDes( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Design outdoor air wet bulb temperature" + annotation (Dialog(group="Waterside economizer", enable=have_WSE)); + + parameter Real VHeaExcDes_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.01 + "Desing heat exchanger chilled water flow rate" + annotation (Dialog(group="Waterside economizer", enable=have_WSE)); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uUp + "First higher available chiller stage" + annotation (Placement(transformation(extent={{-280,-60},{-240,-20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutWet( + final unit="K", + final quantity="ThermodynamicTemperature") if have_WSE + "Outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-280,50},{-240,90}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTunPar if have_WSE + "Tuning parameter as at last plant disable" + annotation (Placement(transformation(extent={{-280,-20},{-240,20}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") if have_WSE + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{-280,90},{-240,130}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yIni + "Initial chiller plant stage" + annotation (Placement(transformation(extent={{240,-10},{260,10}}), + iconTransformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-280,-110},{-240,-70}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Samples first available stage up at plant enable" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg( + final pre_u_start=false) "Rising edge" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + +//protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Economizers.Subsequences.PredictedOutletTemperature + wseTOut( + final heaExcAppDes=heaExcAppDes, + final cooTowAppDes=cooTowAppDes, + final TOutWetDes=TOutWetDes, + final VHeaExcDes_flow=VHeaExcDes_flow) if have_WSE + "Waterside economizer outlet temperature predictor" + annotation (Placement(transformation(extent={{-160,20},{-140,40}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea "Type converter" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt "Type converter" + annotation (Placement(transformation(extent={{160,30},{180,50}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant staZer( + final k=0) + "Zero stage" + annotation (Placement(transformation(extent={{0,100},{20,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys1( + final uLow=0, + final uHigh=wseDt) if have_WSE + "Check if the initial predicted heat exchange leaving water temperature is greater than chilled water supply temperature setpoint less offset" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 if have_WSE + "Difference between predicted heat exchanger leaving water temperature and chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-100,80},{-80,100}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{60,80},{80,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noWSE( + final k=false) if not have_WSE "Replacement signal for no WSE case" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con3( + final k=VHeaExcDes_flow) if have_WSE + "Design heat exchanger chiller water flow rate" + annotation (Placement(transformation(extent={{-220,20},{-200,40}}))); + +equation + connect(reaToInt.y, yIni) + annotation (Line(points={{182,40},{200,40},{200,0},{250,0}}, color={255,127,0})); + connect(sub1.y,hys1. u) + annotation (Line(points={{-78,90},{-62,90}}, color={0,0,127})); + connect(noWSE.y,swi. u2) + annotation (Line(points={{-38,50},{-20,50},{-20,90},{58,90}}, + color={255,0,255})); + connect(hys1.y,swi. u2) + annotation (Line(points={{-38,90},{58,90}}, color={255,0,255})); + connect(wseTOut.TOutWet,TOutWet) + annotation (Line(points={{-162,38},{-180,38},{-180,70},{-260,70}}, + color={0,0,127})); + connect(con3.y,wseTOut. VChiWat_flow) + annotation (Line(points={{-198,30},{-162,30}}, + color={0,0,127})); + connect(wseTOut.uTunPar,uTunPar) + annotation (Line(points={{-162,22},{-180,22},{-180,0},{-260,0}}, + color={0,0,127})); + connect(TChiWatSupSet,sub1. u1) + annotation (Line(points={{-260,110},{-170,110},{-170,96},{-102,96}}, + color={0,0,127})); + connect(staZer.y,swi. u1) + annotation (Line(points={{22,110},{40,110},{40,98},{58,98}}, color={0,0,127})); + connect(uUp, intToRea.u) annotation (Line(points={{-260,-40},{-100,-40},{-100, + 0},{-62,0}}, color={255,127,0})); + connect(swi.y, reaToInt.u) annotation (Line(points={{82,90},{140,90},{140,40}, + {158,40}}, color={0,0,127})); + connect(intToRea.y, triSam.u) + annotation (Line(points={{-38,0},{-12,0}}, color={0,0,127})); + connect(triSam.y, swi.u3) + annotation (Line(points={{12,0},{40,0},{40,82},{58,82}}, color={0,0,127})); + connect(uPla, edg.u) + annotation (Line(points={{-260,-90},{-62,-90}}, color={255,0,255})); + connect(edg.y, triSam.trigger) + annotation (Line(points={{-38,-90},{0,-90},{0,-12}}, color={255,0,255})); + connect(wseTOut.y, sub1.u2) annotation (Line(points={{-138,30},{-120,30},{ + -120,84},{-102,84}}, color={0,0,127})); +annotation (defaultComponentName = "iniSta", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Line( + points={{-54,-50},{-2,-50},{-2,54},{50,54}}, + color={244,125,35}, + thickness=0.5), + Text( + extent={{-68,-44},{58,-114}}, + textColor={0,0,0}, + lineThickness=0.5, + textString="At Enable")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-240,-140},{240,140}})), +Documentation(info=" +

+This subsequence is not directly specified in Guideline36-2021 as it provides a side +calculation pertaining to generalization of the staging sequences for any +number of chillers and stages provided by the user. +

+

+Determines the initial stage upon plant startup for both plants with and +without a WSE. It is implemented according to section 5.20.4.15 of Guideline36-2021, +under part g. (primary-only) and part p. (primary-secondary) plants. +

+

+The initial stage yIni is defined as: +

+

+When the plant is enabled and the plant has no waterside economizer +(have_WSE=false), the initial stage will be the lowest available +stage uUp. +

+

+When the plant is enabled and the plant has waterside economizer +(have_WSE=true), the initial stage will be: +

+ +

+The following state machine chart illustrates the initial stage selection for plants with a waterside economizer: +

+

+\"Image +

+", +revisions=" + +")); +end Initial; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/PartLoadRatios.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/PartLoadRatios.mo new file mode 100644 index 00000000000..a08aadfb269 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/PartLoadRatios.mo @@ -0,0 +1,731 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block PartLoadRatios + "Operating and staging part load ratios with chiller type reset" + + parameter Boolean anyVsdCen = true + "Plant contains at least one variable speed centrifugal chiller"; + + parameter Integer nSta = 3 + "Number of chiller stages, does not include zero stage"; + + parameter Real posDisMult( + final unit = "1", + final min = 0, + final max = 1)=0.8 + "Positive displacement chiller type staging multiplier"; + + parameter Real conSpeCenMult( + final unit = "1", + final min = 0, + final max = 1)=0.9 + "Constant speed centrifugal chiller type staging multiplier"; + + parameter Real anyOutOfScoMult( + final unit = "1", + final min = 0, + final max = 1)=0.9 + "Outside of G36 recommended staging order chiller type SPLR multiplier" + annotation(Evaluate=true, __cdl(ValueInReference=False)); + + parameter Real varSpeStaMin( + final unit = "1", + final min = 0.1, + final max = 1)=0.45 + "Minimum stage up or down part load ratio for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen)); + + parameter Real varSpeStaMax( + final unit = "1", + final min = varSpeStaMin, + final max = 1)=0.9 + "Maximum stage up or down part load ratio for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen)); + + parameter Real avePer( + final unit="s", + final quantity="Time")=300 + "Moving mean time period for staging multiplier calculation for variable speed centrifugal stage types" + annotation(Evaluate=true, Dialog(enable=anyVsdCen)); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta) "Chiller stage" + annotation (Placement(transformation(extent={{-420,220},{-380,260}}), + iconTransformation(extent={{-140,-140},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uUp( + final min=0, + final max=nSta) "Next available stage up" + annotation ( + Placement(transformation(extent={{-420,180},{-380,220}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uDown( + final min=0, + final max=nSta) "Next available stage down" + annotation ( + Placement(transformation(extent={{-420,20},{-380,60}}), + iconTransformation(extent={{-140,-180},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uTyp[nSta]( + final min=fill(1, nSta), + final max=fill(3, nSta)) "Design chiller stage types" + annotation (Placement( + transformation(extent={{-420,280},{-380,320}}), iconTransformation( + extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uUpCapDes( + final unit="W", + final quantity="HeatFlowRate") + "Design capacity of the next available stage up" + annotation (Placement(transformation(extent={{-420,-200},{-380,-160}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapReq( + final unit="W", + final quantity="HeatFlowRate") + "Chilled water cooling capacity requirement" + annotation (Placement(transformation(extent={{-420,-30},{-380,10}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapDes( + final unit="W", + final quantity="HeatFlowRate") + "Design capacity of the current stage" + annotation (Placement(transformation(extent={{-420,-100},{-380,-60}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uUpCapMin( + final unit="W", + final quantity="HeatFlowRate") + "Minimal capacity of the next available stage up" + annotation (Placement(transformation(extent={{-420,-300},{-380,-260}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uDowCapDes( + final unit="W", + final quantity="HeatFlowRate") + "Design capacity of next available stage down" + annotation (Placement(transformation(extent={{-420,-150},{-380,-110}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uLifMin( + final unit="K", + final quantity="TemperatureDifference") if anyVsdCen + "Minimum chiller lift" + annotation (Placement(transformation(extent={{-420,-450},{-380,-410}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uLifMax( + final unit="K", + final quantity="TemperatureDifference") if anyVsdCen + "Maximum chiller lift" + annotation (Placement(transformation(extent={{-420,-380},{-380,-340}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uLif( + final unit="K", + final quantity="TemperatureDifference") if anyVsdCen + "Chiller lift" + annotation (Placement(transformation(extent={{-420,-590},{-380,-550}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapMin( + final unit="W", + final quantity="HeatFlowRate") + "Minimal capacity of the current stage" + annotation (Placement(transformation(extent={{-420,-240},{-380,-200}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOpeUp(final unit="1", + final min=0) "Operating part load ratio of the next higher stage" + annotation (Placement(transformation(extent={{380,-140},{420,-100}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOpeDow(final unit="1", + final min=0) "Operating part load ratio of the next stage down" + annotation (Placement(transformation(extent={{380,-100},{420,-60}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOpeMin(final unit="1", + final min=0) "Minimum operating part load ratio at current stage" + annotation (Placement(transformation(extent={{380,-220},{420,-180}}), + iconTransformation(extent={{100,-90},{140,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOpe( + final unit="1", + final min=0) "Operating part load ratio of the current stage" + annotation ( + Placement(transformation(extent={{380,-60},{420,-20}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yStaDow( + final unit="1", + final min = 0) + "Staging down part load ratio" + annotation (Placement(transformation(extent={{380,-180},{420,-140}}), + iconTransformation(extent={{100,-50},{140,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yStaUp( + final unit="1", + final min = 0) + "Staging up part load ratio" + annotation (Placement(transformation(extent={{380,-20},{420,20}}), + iconTransformation(extent={{100,-30},{140,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOpeUpMin( + final unit="1", + final min=0) + "Minimum operating part load ratio of the next available stage up" + annotation (Placement(transformation(extent={{380,-260},{420,-220}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + +protected + final parameter Real small = Buildings.Controls.OBC.CDL.Constants.small + "Small number to avoid division with zero"; + + Buildings.Controls.OBC.CDL.Reals.Divide opePlrSta + "Calculates operating part load ratio at the current stage" + annotation (Placement(transformation(extent={{-200,-60},{-180,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerExtractor extCurTyp( + final nin=nSta) "Extract current stage type" + annotation (Placement(transformation(extent={{-120,290},{-100,310}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant one( + final k=1) "Stage 1" + annotation (Placement(transformation(extent={{-360,130},{-340,150}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerExtractor extUpTyp( + final nin=nSta) + "Extract stage type for the first higher available stage" + annotation (Placement(transformation(extent={{-120,200},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerExtractor extDowTyp( + final nin=nSta) + "Extract stage type for the first lower available stage" + annotation (Placement(transformation(extent={{-120,110},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{200,140},{220,160}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conSpeCenTyp( + final k=Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal) + "Stage type with any constant speed centrifugal chillers" + annotation (Placement(transformation(extent={{-20,130},{0,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant posDisTyp( + final k=Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement) + "Stage type with none but positive displacement chillers" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu "Equality" + annotation (Placement(transformation(extent={{60,160},{80,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant posDisTypMult( + final k=posDisMult) + "Positive displacement chiller type SPLR multiplier" + annotation (Placement(transformation(extent={{-140,-120},{-120,-100}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conSpeCenTypMult( + final k=conSpeCenMult) + "Constant speed centrifugal chiller type SPLR multiplier" + annotation (Placement(transformation(extent={{-140,-40},{-120,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{100,-190},{120,-170}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{60,-240},{80,-220}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1 "Logical equality" + annotation (Placement(transformation(extent={{60,100},{80,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu2 "Logical equality" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Divide minOpePlrUp + "Calculates minimum OPLR of one stage up" + annotation (Placement(transformation(extent={{-200,-200},{-180,-180}}))); + + Buildings.Controls.OBC.CDL.Reals.Divide opePlrUp + "Calculates operating part load ratio at the next stage up" + annotation (Placement(transformation(extent={{-200,-150},{-180,-130}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant const( + final k=0.9) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{-200,-360},{-180,-340}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub2 + if anyVsdCen "Subtract" + annotation (Placement(transformation(extent={{-80,-420},{-60,-400}}))); + + Buildings.Controls.OBC.CDL.Reals.Divide div if anyVsdCen + "Division" + annotation (Placement(transformation(extent={{-20,-370},{0,-350}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant const1( + final k=0.4) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{-200,-480},{-180,-460}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant const2( + final k=1.4) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{-200,-560},{-180,-540}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 + if anyVsdCen "Subtract" + annotation (Placement(transformation(extent={{-80,-500},{-60,-480}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply mult0 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{-140,-460},{-120,-440}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply mult1 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{-140,-540},{-120,-520}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply mult2 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{40,-440},{60,-420}}))); + + Buildings.Controls.OBC.CDL.Reals.Multiply mult3 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{100,-510},{120,-490}}))); + + Buildings.Controls.OBC.CDL.Reals.Add add3 if anyVsdCen "Add" + annotation (Placement(transformation(extent={{160,-482},{180,-462}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant const3( + final k=-1) if not anyVsdCen + "Constant" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant const4( + final k=-1) if not anyVsdCen + "Constant" + annotation (Placement(transformation(extent={{0,-260},{20,-240}}))); + + Buildings.Controls.OBC.CDL.Utilities.Assert cheStaTyp( + final message="Recommended staging order got violated or an unlisted chiller type got provided when staging up") + "Chiller type outside of recommenation when staging up" + annotation (Placement(transformation(extent={{300,280},{320,300}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr( + final t=-0.5) + "Less than threshold" + annotation (Placement(transformation(extent={{260,200},{280,220}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=-0.5) "Less than threshold" + annotation (Placement(transformation(extent={{200,-110},{220,-90}}))); + + Buildings.Controls.OBC.CDL.Reals.Divide opePlrDow + "Calculates operating part load ratio of the next stage down" + annotation (Placement(transformation(extent={{-200,-90},{-180,-70}}))); + + Buildings.Controls.OBC.CDL.Reals.Divide minOpePlr + "Calculates minimum OPLR of the current stage" + annotation (Placement(transformation(extent={{-200,-240},{-180,-220}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu3 "Integer equal" + annotation (Placement(transformation(extent={{60,240},{80,260}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi4 "Switch" + annotation (Placement(transformation(extent={{160,-170},{180,-150}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant const5( + final k=1) + "If staging down to stage 0 set staging down part load to 1" + annotation (Placement(transformation(extent={{100,-150},{120,-130}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu4 "Equality" + annotation (Placement(transformation(extent={{-140,0},{-120,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxInt "Maximum" + annotation (Placement(transformation(extent={{-300,260},{-280,280}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxIntUp "Maximum" + annotation (Placement(transformation(extent={{-300,170},{-280,190}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxIntDown "Maximum" + annotation (Placement(transformation(extent={{-300,60},{-280,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max if anyVsdCen "Maximum" + annotation (Placement(transformation(extent={{220,-420},{240,-400}}))); + + Buildings.Controls.OBC.CDL.Reals.Min min if anyVsdCen "Minimum" + annotation (Placement(transformation(extent={{260,-380},{280,-360}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxLim( + final k=varSpeStaMax) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{160,-360},{180,-340}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minLim( + final k=varSpeStaMin) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{160,-420},{180,-400}}))); + + Buildings.Controls.OBC.CDL.Utilities.Assert cheStaTyp1( + final message="Recommended staging order got violated or an unlisted chiller type got provided when staging down") + "Chiller type outside of recommenation when staging down" + annotation (Placement(transformation(extent={{260,-20},{280,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conSpeCenTypMult1( + final k=anyOutOfScoMult) + "Outside of G36 recommended staging order chiller type SPLR multiplier" + annotation (Placement(transformation(extent={{200,20},{220,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi5 + "Logical switch" + annotation (Placement(transformation(extent={{320,220},{340,240}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch swi6 + "Logical switch" + annotation (Placement(transformation(extent={{260,-110},{280,-90}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant smaNum( + final k=small) "Small constant" + annotation (Placement(transformation(extent={{-360,-54},{-340,-34}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max1 + "Maximum output to avoid zero denominator in downstream" + annotation (Placement(transformation(extent={{-300,-60},{-280,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max2 + "Maximum output to avoid zero denominator in downstream" + annotation (Placement(transformation(extent={{-300,-110},{-280,-90}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max3 + "Maximum output to avoid zero denominator in downstream" + annotation (Placement(transformation(extent={{-300,-170},{-280,-150}}))); + + Buildings.Controls.OBC.CDL.Reals.MovingAverage movMea( + final delta=avePer) if anyVsdCen "Moving mean" + annotation (Placement(transformation(extent={{300,-330},{320,-310}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr[3]( + final t=fill(nSta, 3)) + "Check if index is out of the range" + annotation (Placement(transformation(extent={{-240,140},{-220,160}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi[3] + "Valid index" + annotation (Placement(transformation(extent={{-180,80},{-160,100}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[3]( + final k=fill(nSta, 3)) + "Dummy index so the extractor will not have out of range index" + annotation (Placement(transformation(extent={{-240,230},{-220,250}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1[3] + "Valid value" + annotation (Placement(transformation(extent={{-80,140},{-60,160}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant con[3]( + final k=fill(-1, 3)) "Dummy stage" + annotation (Placement(transformation(extent={{-180,160},{-160,180}}))); + +equation + connect(intEqu.u2, conSpeCenTyp.y) annotation (Line(points={{58,162},{10,162}, + {10,140},{2,140}}, color={255,127,0})); + connect(opePlrSta.y, yOpe) annotation (Line(points={{-178,-50},{0,-50},{0,-40}, + {400,-40}}, color={0,0,127})); + connect(posDisTyp.y, intEqu1.u2) annotation (Line(points={{2,80},{10,80},{10,102}, + {58,102}}, color={255,127,0})); + connect(intEqu1.y, swi1.u2) annotation (Line(points={{82,110},{140,110},{140,70}, + {158,70}},color={255,0,255})); + connect(swi1.y, swi.u3) annotation (Line(points={{182,70},{190,70},{190,142},{ + 198,142}}, color={0,0,127})); + connect(posDisTyp.y, intEqu2.u2) annotation (Line(points={{2,80},{10,80},{10,22}, + {18,22}}, color={255,127,0})); + connect(swi3.y, swi2.u3) annotation (Line(points={{82,-230},{90,-230},{90,-188}, + {98,-188}}, color={0,0,127})); + connect(intEqu2.y, swi3.u2) annotation (Line(points={{42,30},{50,30},{50,-230}, + {58,-230}}, color={255,0,255})); + connect(opePlrUp.y, yOpeUp) annotation (Line(points={{-178,-140},{0,-140},{0,-120}, + {400,-120}}, color={0,0,127})); + connect(minOpePlrUp.y, yOpeUpMin) annotation (Line(points={{-178,-190},{-60,-190}, + {-60,-280},{240,-280},{240,-240},{400,-240}}, color={0,0,127})); + connect(uLifMin, sub2.u2) annotation (Line(points={{-400,-430},{-240,-430},{-240, + -416},{-82,-416}}, color={0,0,127})); + connect(const.y, div.u1) annotation (Line(points={{-178,-350},{-40,-350},{-40, + -354},{-22,-354}}, color={0,0,127})); + connect(sub2.y, div.u2) annotation (Line(points={{-58,-410},{-40,-410},{-40,-366}, + {-22,-366}}, color={0,0,127})); + connect(const1.y, mult0.u2) annotation (Line(points={{-178,-470},{-160,-470},{ + -160,-456},{-142,-456}}, color={0,0,127})); + connect(uLifMax, mult0.u1) annotation (Line(points={{-400,-360},{-220,-360},{-220, + -444},{-142,-444}}, color={0,0,127})); + connect(uLifMin, mult1.u1) annotation (Line(points={{-400,-430},{-240,-430},{-240, + -524},{-142,-524}}, + color={0,0,127})); + connect(const2.y, mult1.u2) annotation (Line(points={{-178,-550},{-160,-550},{ + -160,-536},{-142,-536}}, color={0,0,127})); + connect(mult0.y, sub1.u1) annotation (Line(points={{-118,-450},{-110,-450},{-110, + -484},{-82,-484}}, color={0,0,127})); + connect(mult1.y, sub1.u2) annotation (Line(points={{-118,-530},{-108,-530},{-108, + -496},{-82,-496}}, color={0,0,127})); + connect(div.y, mult2.u1) annotation (Line(points={{2,-360},{20,-360},{20,-424}, + {38,-424}}, color={0,0,127})); + connect(sub1.y, mult2.u2) annotation (Line(points={{-58,-490},{20,-490},{20,-436}, + {38,-436}}, color={0,0,127})); + connect(div.y, mult3.u1) annotation (Line(points={{2,-360},{80,-360},{80,-494}, + {98,-494}}, + color={0,0,127})); + connect(uLif, mult3.u2) annotation (Line(points={{-400,-570},{80,-570},{80,-506}, + {98,-506}}, color={0,0,127})); + connect(mult3.y, add3.u2) annotation (Line(points={{122,-500},{130,-500},{130, + -478},{158,-478}}, color={0,0,127})); + connect(mult2.y, add3.u1) annotation (Line(points={{62,-430},{140,-430},{140,-466}, + {158,-466}}, color={0,0,127})); + connect(swi.y,greThr. u) annotation (Line(points={{222,150},{248,150},{248,210}, + {258,210}}, color={0,0,127})); + connect(uLifMax, sub2.u1) annotation (Line(points={{-400,-360},{-220,-360},{-220, + -404},{-82,-404}}, color={0,0,127})); + connect(opePlrDow.y, yOpeDow) + annotation (Line(points={{-178,-80},{400,-80}}, color={0,0,127})); + connect(minOpePlr.y, yOpeMin) annotation (Line(points={{-178,-230},{-40,-230}, + {-40,-200},{400,-200}}, color={0,0,127})); + connect(conSpeCenTypMult.y, swi.u1) annotation (Line(points={{-118,-30},{0,-30}, + {0,-20},{96,-20},{96,158},{198,158}}, color={0,0,127})); + connect(posDisTypMult.y, swi1.u1) annotation (Line(points={{-118,-110},{-20,-110}, + {-20,50},{40,50},{40,78},{158,78}}, color={0,0,127})); + connect(posDisTypMult.y, swi3.u1) annotation (Line(points={{-118,-110},{-20,-110}, + {-20,-222},{58,-222}}, color={0,0,127})); + connect(conSpeCenTypMult.y, swi2.u1) annotation (Line(points={{-118,-30},{40,-30}, + {40,-172},{98,-172}},color={0,0,127})); + connect(conSpeCenTyp.y, intEqu3.u2) annotation (Line(points={{2,140},{10,140}, + {10,242},{58,242}}, color={255,127,0})); + connect(intEqu3.y, swi2.u2) annotation (Line(points={{82,250},{90,250},{90,-180}, + {98,-180}},color={255,0,255})); + connect(uCapMin, minOpePlr.u1) annotation (Line(points={{-400,-220},{-300,-220}, + {-300,-224},{-202,-224}}, color={0,0,127})); + connect(uUpCapMin, minOpePlrUp.u1) annotation (Line(points={{-400,-280},{-220, + -280},{-220,-184},{-202,-184}}, color={0,0,127})); + connect(intEqu.y, swi.u2) annotation (Line(points={{82,170},{160,170},{160,150}, + {198,150}}, color={255,0,255})); + connect(const4.y, swi3.u3) annotation (Line(points={{22,-250},{40,-250},{40,-238}, + {58,-238}}, color={0,0,127})); + connect(const3.y, swi1.u3) annotation (Line(points={{122,30},{140,30},{140,62}, + {158,62}}, color={0,0,127})); + connect(swi2.y, swi4.u3) annotation (Line(points={{122,-180},{140,-180},{140,-168}, + {158,-168}}, color={0,0,127})); + connect(const5.y, swi4.u1) annotation (Line(points={{122,-140},{140,-140},{140, + -152},{158,-152}}, color={0,0,127})); + connect(u, intEqu4.u2) annotation (Line(points={{-400,240},{-330,240},{-330,2}, + {-142,2}}, color={255,127,0})); + connect(one.y, intEqu4.u1) annotation (Line(points={{-338,140},{-320,140},{-320, + 10},{-142,10}}, color={255,127,0})); + connect(intEqu4.y, swi4.u2) annotation (Line(points={{-118,10},{20,10},{20,-160}, + {158,-160}}, color={255,0,255})); + connect(one.y, maxInt.u2) annotation (Line(points={{-338,140},{-320,140},{-320, + 264},{-302,264}}, color={255,127,0})); + connect(u, maxInt.u1) annotation (Line(points={{-400,240},{-330,240},{-330,276}, + {-302,276}}, color={255,127,0})); + connect(one.y, maxIntUp.u2) annotation (Line(points={{-338,140},{-320,140},{-320, + 174},{-302,174}}, color={255,127,0})); + connect(uUp, maxIntUp.u1) annotation (Line(points={{-400,200},{-340,200},{-340, + 186},{-302,186}}, color={255,127,0})); + connect(one.y, maxIntDown.u1) annotation (Line(points={{-338,140},{-320,140},{ + -320,76},{-302,76}}, color={255,127,0})); + connect(uDown, maxIntDown.u2) annotation (Line(points={{-400,40},{-340,40},{-340, + 64},{-302,64}}, color={255,127,0})); + connect(add3.y, max.u2) annotation (Line(points={{182,-472},{200,-472},{200,-416}, + {218,-416}}, color={0,0,127})); + connect(minLim.y, max.u1) annotation (Line(points={{182,-410},{200,-410},{200, + -404},{218,-404}}, color={0,0,127})); + connect(max.y, min.u2) annotation (Line(points={{242,-410},{250,-410},{250,-376}, + {258,-376}}, color={0,0,127})); + connect(maxLim.y, min.u1) annotation (Line(points={{182,-350},{220,-350},{220, + -364},{258,-364}}, color={0,0,127})); + connect(swi4.y, greThr1.u) annotation (Line(points={{182,-160},{192,-160},{192, + -100},{198,-100}}, color={0,0,127})); + connect(swi.y, swi5.u1) annotation (Line(points={{222,150},{240,150},{240,238}, + {318,238}}, color={0,0,127})); + connect(greThr.y, swi5.u2) annotation (Line(points={{282,210},{290,210},{290,230}, + {318,230}}, color={255,0,255})); + connect(greThr.y, cheStaTyp.u) annotation (Line(points={{282,210},{290,210},{290, + 290},{298,290}}, color={255,0,255})); + connect(conSpeCenTypMult1.y, swi5.u3) annotation (Line(points={{222,30},{300,30}, + {300,222},{318,222}}, color={0,0,127})); + connect(swi5.y, yStaUp) annotation (Line(points={{342,230},{354,230},{354,0}, + {400,0}},color={0,0,127})); + connect(swi6.y, yStaDow) annotation (Line(points={{282,-100},{290,-100},{290,-160}, + {400,-160}}, color={0,0,127})); + connect(greThr1.y, swi6.u2) + annotation (Line(points={{222,-100},{258,-100}}, color={255,0,255})); + connect(swi4.y, swi6.u1) annotation (Line(points={{182,-160},{240,-160},{240,-92}, + {258,-92}}, color={0,0,127})); + connect(conSpeCenTypMult1.y, swi6.u3) annotation (Line(points={{222,30},{250,30}, + {250,-108},{258,-108}}, color={0,0,127})); + connect(greThr1.y, cheStaTyp1.u) annotation (Line(points={{222,-100},{230,-100}, + {230,-10},{258,-10}}, color={255,0,255})); + connect(max1.y, opePlrSta.u2) annotation (Line(points={{-278,-50},{-240,-50}, + {-240,-56},{-202,-56}}, color={0,0,127})); + connect(smaNum.y, max1.u1) annotation (Line(points={{-338,-44},{-302,-44}}, + color={0,0,127})); + connect(max1.y, minOpePlr.u2) annotation (Line(points={{-278,-50},{-260,-50},{ + -260,-236},{-202,-236}}, color={0,0,127})); + connect(max2.y, opePlrDow.u2) annotation (Line(points={{-278,-100},{-240,-100}, + {-240,-86},{-202,-86}}, color={0,0,127})); + connect(smaNum.y, max2.u1) annotation (Line(points={{-338,-44},{-320,-44},{-320, + -94},{-302,-94}}, color={0,0,127})); + connect(uDowCapDes, max2.u2) annotation (Line(points={{-400,-130},{-330,-130}, + {-330,-106},{-302,-106}}, color={0,0,127})); + connect(max3.y, opePlrUp.u2) annotation (Line(points={{-278,-160},{-240,-160}, + {-240,-146},{-202,-146}}, color={0,0,127})); + connect(max3.y, minOpePlrUp.u2) annotation (Line(points={{-278,-160},{-240, + -160},{-240,-196},{-202,-196},{-202,-196}}, color={0,0,127})); + connect(smaNum.y, max3.u1) annotation (Line(points={{-338,-44},{-320,-44},{-320, + -154},{-302,-154}}, color={0,0,127})); + connect(uUpCapDes, max3.u2) annotation (Line(points={{-400,-180},{-320,-180},{ + -320,-166},{-302,-166}}, color={0,0,127})); + connect(uCapDes, max1.u2) annotation (Line(points={{-400,-80},{-330,-80},{-330, + -56},{-302,-56}}, color={0,0,127})); + connect(uCapReq, opePlrSta.u1) annotation (Line(points={{-400,-10},{-220,-10}, + {-220,-44},{-202,-44}}, color={0,0,127})); + connect(uCapReq, opePlrDow.u1) annotation (Line(points={{-400,-10},{-220,-10}, + {-220,-74},{-202,-74}}, color={0,0,127})); + connect(uCapReq, opePlrUp.u1) annotation (Line(points={{-400,-10},{-220,-10},{ + -220,-134},{-202,-134}}, color={0,0,127})); + connect(min.y, movMea.u) annotation (Line(points={{282,-370},{290,-370},{290,-320}, + {298,-320}}, color={0,0,127})); + connect(movMea.y, swi3.u3) annotation (Line(points={{322,-320},{340,-320},{340, + -300},{50,-300},{50,-238},{58,-238}}, color={0,0,127})); + connect(movMea.y, swi1.u3) annotation (Line(points={{322,-320},{340,-320},{340, + -260},{150,-260},{150,62},{158,62}}, color={0,0,127})); + connect(uTyp, extCurTyp.u) + annotation (Line(points={{-400,300},{-122,300}}, color={255,127,0})); + connect(uTyp, extUpTyp.u) annotation (Line(points={{-400,300},{-140,300},{ + -140,210},{-122,210}}, color={255,127,0})); + connect(uTyp, extDowTyp.u) annotation (Line(points={{-400,300},{-140,300},{-140, + 120},{-122,120}}, color={255,127,0})); + connect(maxInt.y, intGreThr[1].u) annotation (Line(points={{-278,270},{-260,270}, + {-260,150},{-242,150}}, color={255,127,0})); + connect(intGreThr.y, intSwi.u2) annotation (Line(points={{-218,150},{-190,150}, + {-190,90},{-182,90}}, color={255,0,255})); + connect(maxInt.y, intSwi[1].u3) annotation (Line(points={{-278,270},{-200,270}, + {-200,82},{-182,82}}, color={255,127,0})); + connect(intSwi[1].y, extCurTyp.index) annotation (Line(points={{-158,90},{-150, + 90},{-150,280},{-110,280},{-110,288}}, color={255,127,0})); + connect(maxIntUp.y, intGreThr[2].u) annotation (Line(points={{-278,180},{-260, + 180},{-260,150},{-242,150}}, color={255,127,0})); + connect(conInt.y, intSwi.u1) annotation (Line(points={{-218,240},{-210,240},{-210, + 98},{-182,98}}, color={255,127,0})); + connect(intSwi[2].y, extUpTyp.index) annotation (Line(points={{-158,90},{-150, + 90},{-150,190},{-110,190},{-110,198}}, color={255,127,0})); + connect(maxIntDown.y, intGreThr[3].u) annotation (Line(points={{-278,70},{-260, + 70},{-260,150},{-242,150}}, color={255,127,0})); + connect(maxIntUp.y, intSwi[2].u3) annotation (Line(points={{-278,180},{-200,180}, + {-200,82},{-182,82}}, color={255,127,0})); + connect(intSwi[3].y, extDowTyp.index) annotation (Line(points={{-158,90},{-110, + 90},{-110,108}}, color={255,127,0})); + connect(maxIntDown.y, intSwi[3].u3) annotation (Line(points={{-278,70},{-200,70}, + {-200,82},{-182,82}}, color={255,127,0})); + connect(intGreThr.y, intSwi1.u2) + annotation (Line(points={{-218,150},{-82,150}}, color={255,0,255})); + connect(con.y, intSwi1.u1) annotation (Line(points={{-158,170},{-100,170},{-100, + 158},{-82,158}}, color={255,127,0})); + connect(extCurTyp.y, intSwi1[1].u3) annotation (Line(points={{-98,300},{-90,300}, + {-90,142},{-82,142}}, color={255,127,0})); + connect(extUpTyp.y, intSwi1[2].u3) annotation (Line(points={{-98,210},{-90,210}, + {-90,142},{-82,142}}, color={255,127,0})); + connect(extDowTyp.y, intSwi1[3].u3) annotation (Line(points={{-98,120},{-90,120}, + {-90,142},{-82,142}}, color={255,127,0})); + connect(intSwi1[1].y, intEqu3.u1) annotation (Line(points={{-58,150},{-50,150}, + {-50,250},{58,250}}, color={255,127,0})); + connect(intSwi1[1].y, intEqu1.u1) annotation (Line(points={{-58,150},{-50,150}, + {-50,110},{58,110}}, color={255,127,0})); + connect(intSwi1[2].y, intEqu.u1) annotation (Line(points={{-58,150},{-40,150}, + {-40,170},{58,170}}, color={255,127,0})); + connect(intSwi1[3].y, intEqu2.u1) annotation (Line(points={{-58,150},{-40,150}, + {-40,30},{18,30}}, color={255,127,0})); + annotation (defaultComponentName = "PLRs", + Icon(coordinateSystem(extent={{-100,-200},{100,200}}), graphics={ + Text( + extent={{-100,240},{100,200}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-200},{100,200}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-60,36},{64,-42}}, + textColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + textString="PLR")}), Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-380,-600},{380,340}})), +Documentation(info=" +

+Calculates operative part load ratios (OPLR) per sections 5.20.4.5, section 5.20.4.9, +section 5.20.4.10 and stage part load ratios (SPLR, up or down) per section 5.20.4.14 +of Guideline36-2021. +

+

+OPLR is a ratio of the current capacity requirement to a given design or minimal +stage capacity, such as: +

+ +

+SPLRup yStaUp or SPLRdown yStaDown value depends on the +stage type staTyp as indicated in the table below. +Note that the rules are prioritized by stage type column, from left to right +

+

+The stage type is determined by the + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator +subsequence based on the type of chillers staged. +

+ + + + + + + + + + + + + + + + + + + + + + + + +
Row: Stage / Column: Stage TypeAny Constant Speed CentrifugalAll Positive DisplacementAny Variable Speed and no Constant Speed Centrifugal
Next Available UpyStaUp=conSpeCenMultN/A>N/A
CurrentyStaDown=conSpeCenMultyStaUp=posDisMultyStaUp=f(uLif, uLifMin, uLifMax)
Next Available DownN/AyStaDown=posDisMultyStaDown=f(uLif, uLifMin, uLifMax)
+

+For operation outside of the recommended staging order as provided in the table +above a constant SPLRup and SPLRdown value anyOutOfScoMult is set to prevent +simulation interruption, accompanied with a warning. +

+", +revisions=" + +")); +end PartLoadRatios; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Status.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Status.mo new file mode 100644 index 00000000000..05ac2491338 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Status.mo @@ -0,0 +1,377 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Status + "Outputs current stage chiller index vector, current, next available lower and higher stage index and whether curent stage is the lowest and/or the highest available stage" + + parameter Integer nSta = 3 + "Number of chiller stages, does not include zero stage"; + + parameter Integer nChi = 2 + "Number of chillers"; + + parameter Integer staMat[nSta, nChi] = {{1,0},{0,1},{1,1}} + "Staging matrix with stages in rows and chillers in columns"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uAva[nSta]( + final start = fill(true, nSta)) "Stage availability status" + annotation (Placement(transformation(extent={{-460,-100},{-420,-60}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta, + final start = 0) "Current chiller stage" + annotation (Placement(transformation(extent={{-460,60},{-420,100}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yHig + "If true current stage is the highest available stage" + annotation (Placement(transformation(extent={{440,20},{480,60}}), + iconTransformation(extent={{100,-30},{140,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLow + "If true current stage is the lowest available stage" + annotation (Placement(transformation(extent={{440,-110},{480,-70}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yAvaCur + "Current stage availability status" + annotation (Placement(transformation(extent={{440,-260},{480,-220}}), + iconTransformation(extent={{100,-90},{140,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yAvaUp( + final min=0, + final max=nSta) + "Next available higher stage" + annotation (Placement(transformation(extent={{440,60},{480,100}}), + iconTransformation(extent={{100,50},{140,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yAvaDow( + final min=0, + final max=nSta) + "Next available lower stage" + annotation (Placement(transformation(extent={{440,-60},{480,-20}}), + iconTransformation(extent={{100,20},{140,60}}))); + +protected + final parameter Integer staInd[nSta] = {i for i in 1:nSta} + "Stage index vector"; + + final parameter Integer staIndMat[nSta, nChi] = {j for i in 1:nChi, j in 1:nSta} + "Matrix of staging matrix dimensions with stage indices in each column"; + + final parameter Integer lowDia[nSta, nSta] = {if i<=j then 1 else 0 for i in 1:nSta, j in 1:nSta} + "Lower diagonal unit matrix"; + + Buildings.Controls.OBC.CDL.Logical.Not not1 "Not unavailable" + annotation (Placement(transformation(extent={{-60,-180},{-40,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 "Switch" + annotation (Placement(transformation(extent={{260,-220},{280,-200}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi3 "Switch" + annotation (Placement(transformation(extent={{360,70},{380,90}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nSta) "Replicates signal to a length equal the stage count" + annotation (Placement(transformation(extent={{-300,190},{-280,210}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt1[nSta] + "Outputs a vector of stage indices for any available stage above the current stage" + annotation (Placement(transformation(extent={{-60,100},{-40,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staIndx[nSta]( + final k=staInd) "Stage index vector" + annotation (Placement(transformation(extent={{-240,120},{-220,140}}))); + + Buildings.Controls.OBC.CDL.Integers.Greater intGre[nSta] + "Identifies stages that are above the current stage" + annotation (Placement(transformation(extent={{-180,80},{-160,100}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nSta]( + final integerTrue=fill(1, nSta), + final integerFalse=fill(nSta + 1, nSta)) + "Type converter that outputs a value larger than the stage count for any false input" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2[nSta] + "Identifies any available stages above the current stage" + annotation (Placement(transformation(extent={{-140,70},{-120,90}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMin multiMin( + final nin=nSta) + "Minimum of a vector input" + annotation (Placement(transformation(extent={{20,100},{40,120}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1[nSta] + "Type converter" + annotation (Placement(transformation(extent={{-20,100},{0,120}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Type converter" + annotation (Placement(transformation(extent={{60,100},{80,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Less intLes[nSta] + "Identifies stages that are below the current stage" + annotation (Placement(transformation(extent={{-180,-80},{-160,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1[nSta] + "Identifies any available stage below the current stage" + annotation (Placement(transformation(extent={{-140,-100},{-120,-80}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt2[nSta]( + integerTrue=fill(1, nSta), integerFalse=fill(0, nSta)) + "Type converter that outputs zero for any false input" + annotation (Placement(transformation(extent={{-100,-100},{-80,-80}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt2[nSta] + "Outputs vector of stage indices for any available stage below the current stage" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea3[nSta] + "Type converter" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax( + final nin=nSta) + "Maximum of a vector input" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Type converter" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr( + final t=nSta) "True if there are no higher available stages" + annotation (Placement(transformation(extent={{100,100},{120,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "If no higher stage is available, output current stage" + annotation (Placement(transformation(extent={{180,100},{200,120}}))); + + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr( + final t=0) + "If the current stage is the lowest available the input value equals 0" + annotation (Placement(transformation(extent={{100,-80},{120,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 "Logical switch" + annotation (Placement(transformation(extent={{180,-80},{200,-60}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanExtractor extStaAva( + final nin=nSta) "Extracts stage availability for the current stage" + annotation (Placement(transformation(extent={{-200,-140},{-180,-120}}))); + + Buildings.Controls.OBC.CDL.Utilities.Assert cheStaAva1( + final message="There are no available chiller stages. The staging cannot be performed.") + "Checks if any stage is available" + annotation (Placement(transformation(extent={{-320,-50},{-300,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nSta) "Logical or" + annotation (Placement(transformation(extent={{-360,-50},{-340,-30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) "Zero" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4 "Logical and" + annotation (Placement(transformation(extent={{220,70},{240,90}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr( + final t=1) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-380,-120},{-360,-100}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr1( + final t=nSta) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-380,-200},{-360,-180}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Check if index is in the range" + annotation (Placement(transformation(extent={{-320,-120},{-300,-100}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Dummy index so the extractor will not have out of range index" + annotation (Placement(transformation(extent={{-320,-200},{-300,-180}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi4 "Valid index" + annotation (Placement(transformation(extent={{-260,-160},{-240,-140}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 "Chiller availability" + annotation (Placement(transformation(extent={{-140,-180},{-120,-160}}))); + +equation + connect(staIndx.y, intGre.u1) annotation (Line(points={{-218,130},{-200,130},{ + -200,90},{-182,90}}, color={255,127,0})); + connect(intRep.y, intGre.u2) annotation (Line(points={{-278,200},{-260,200},{ + -260,82},{-182,82}}, color={255,127,0})); + connect(intGre.y, and2.u1) annotation (Line(points={{-158,90},{-150,90},{-150, + 80},{-142,80}},color={255,0,255})); + connect(uAva, and2.u2) annotation (Line(points={{-440,-80},{-220,-80},{-220,72}, + {-142,72}}, color={255,0,255})); + connect(staIndx.y, proInt1.u1) annotation (Line(points={{-218,130},{-70,130},{ + -70,116},{-62,116}}, color={255,127,0})); + connect(booToInt1.y, proInt1.u2) annotation (Line(points={{-78,80},{-70,80},{-70, + 104},{-62,104}}, color={255,127,0})); + connect(proInt1.y, intToRea1.u) + annotation (Line(points={{-38,110},{-22,110}}, color={255,127,0})); + connect(intToRea1.y, multiMin.u) annotation (Line(points={{2,110},{18,110}}, + color={0,0,127})); + connect(intRep.y, intLes.u2) annotation (Line(points={{-278,200},{-260,200},{ + -260,-78},{-182,-78}}, color={255,127,0})); + connect(staIndx.y, intLes.u1) annotation (Line(points={{-218,130},{-200,130},{ + -200,-70},{-182,-70}}, color={255,127,0})); + connect(uAva, and1.u2) annotation (Line(points={{-440,-80},{-220,-80},{-220,-98}, + {-142,-98}}, color={255,0,255})); + connect(intLes.y, and1.u1) annotation (Line(points={{-158,-70},{-150,-70},{-150, + -90},{-142,-90}}, color={255,0,255})); + connect(proInt2.y, intToRea3.u) + annotation (Line(points={{-38,-70},{-22,-70}}, color={255,127,0})); + connect(intToRea3.y, multiMax.u) annotation (Line(points={{2,-70},{18,-70}}, + color={0,0,127})); + connect(staIndx.y, proInt2.u1) annotation (Line(points={{-218,130},{-200,130}, + {-200,-40},{-70,-40},{-70,-64},{-62,-64}}, color={255,127,0})); + connect(booToInt2.y, proInt2.u2) annotation (Line(points={{-78,-90},{-70,-90}, + {-70,-76},{-62,-76}}, color={255,127,0})); + connect(multiMax.y, reaToInt1.u) + annotation (Line(points={{42,-70},{58,-70}}, color={0,0,127})); + connect(multiMin.y, reaToInt.u) + annotation (Line(points={{42,110},{58,110}}, color={0,0,127})); + connect(reaToInt.y, intGreThr.u) + annotation (Line(points={{82,110},{98,110}}, color={255,127,0})); + connect(intGreThr.y, intSwi.u2) + annotation (Line(points={{122,110},{178,110}}, color={255,0,255})); + connect(intGreThr.y, yHig) annotation (Line(points={{122,110},{140,110},{140,40}, + {460,40}}, color={255,0,255})); + connect(reaToInt1.y, intLesEquThr.u) + annotation (Line(points={{82,-70},{98,-70}}, color={255,127,0})); + connect(intLesEquThr.y, intSwi1.u2) + annotation (Line(points={{122,-70},{178,-70}}, color={255,0,255})); + connect(intLesEquThr.y, yLow) annotation (Line(points={{122,-70},{140,-70},{140, + -90},{460,-90}}, color={255,0,255})); + connect(and2.y, booToInt1.u) + annotation (Line(points={{-118,80},{-102,80}}, color={255,0,255})); + connect(intGreThr.y, and4.u1) + annotation (Line(points={{122,110},{140,110},{140,80},{218,80}}, + color={255,0,255})); + connect(and4.y, intSwi3.u2) + annotation (Line(points={{242,80},{358,80}}, color={255,0,255})); + connect(uAva, mulOr.u) annotation (Line(points={{-440,-80},{-380,-80},{-380,-40}, + {-362,-40}}, color={255,0,255})); + connect(mulOr.y, cheStaAva1.u) + annotation (Line(points={{-338,-40},{-322,-40}}, color={255,0,255})); + connect(and1.y, booToInt2.u) + annotation (Line(points={{-118,-90},{-102,-90}}, color={255,0,255})); + connect(u, intRep.u) annotation (Line(points={{-440,80},{-400,80},{-400,200},{ + -302,200}}, color={255,127,0})); + connect(conInt.y, intSwi1.u1) annotation (Line(points={{122,-30},{160,-30},{160, + -62},{178,-62}}, color={255,127,0})); + connect(intSwi1.y, yAvaDow) annotation (Line(points={{202,-70},{320,-70},{320, + -40},{460,-40}}, color={255,127,0})); + connect(intSwi1.y, intSwi2.u1) annotation (Line(points={{202,-70},{220,-70},{220, + -202},{258,-202}}, color={255,127,0})); + connect(intSwi2.y, intSwi3.u1) annotation (Line(points={{282,-210},{350,-210}, + {350,88},{358,88}}, color={255,127,0})); + connect(u, intSwi2.u3) annotation (Line(points={{-440,80},{-400,80},{-400,-218}, + {258,-218}}, color={255,127,0})); + connect(intSwi.y, intSwi3.u3) annotation (Line(points={{202,110},{340,110},{340, + 72},{358,72}}, color={255,127,0})); + connect(u, intSwi.u1) annotation (Line(points={{-440,80},{-400,80},{-400,160}, + {160,160},{160,118},{178,118}}, color={255,127,0})); + connect(reaToInt.y, intSwi.u3) annotation (Line(points={{82,110},{90,110},{90, + 90},{160,90},{160,102},{178,102}}, color={255,127,0})); + connect(reaToInt1.y, intSwi1.u3) annotation (Line(points={{82,-70},{90,-70},{90, + -100},{170,-100},{170,-78},{178,-78}}, color={255,127,0})); + connect(intSwi3.y, yAvaUp) + annotation (Line(points={{382,80},{460,80}}, color={255,127,0})); + connect(uAva, extStaAva.u) annotation (Line(points={{-440,-80},{-220,-80},{-220, + -130},{-202,-130}}, color={255,0,255})); + connect(not1.y, intSwi2.u2) annotation (Line(points={{-38,-170},{210,-170},{210, + -210},{258,-210}},color={255,0,255})); + connect(not1.y, and4.u2) annotation (Line(points={{-38,-170},{210,-170},{210,72}, + {218,72}}, color={255,0,255})); + connect(u, intGreEquThr.u) annotation (Line(points={{-440,80},{-400,80},{-400, + -110},{-382,-110}}, color={255,127,0})); + connect(u, intLesEquThr1.u) annotation (Line(points={{-440,80},{-400,80},{-400, + -190},{-382,-190}}, color={255,127,0})); + connect(intGreEquThr.y, and3.u1) + annotation (Line(points={{-358,-110},{-322,-110}}, color={255,0,255})); + connect(intLesEquThr1.y, and3.u2) annotation (Line(points={{-358,-190},{-340,-190}, + {-340,-118},{-322,-118}}, color={255,0,255})); + connect(intSwi4.y, extStaAva.index) annotation (Line(points={{-238,-150},{-190, + -150},{-190,-142}}, color={255,127,0})); + connect(and3.y, intSwi4.u2) annotation (Line(points={{-298,-110},{-280,-110},{ + -280,-150},{-262,-150}}, color={255,0,255})); + connect(u, intSwi4.u1) annotation (Line(points={{-440,80},{-400,80},{-400,-142}, + {-262,-142}}, color={255,127,0})); + connect(conInt1.y, intSwi4.u3) annotation (Line(points={{-298,-190},{-290,-190}, + {-290,-158},{-262,-158}}, color={255,127,0})); + connect(extStaAva.y, and5.u1) annotation (Line(points={{-178,-130},{-160,-130}, + {-160,-170},{-142,-170}}, color={255,0,255})); + connect(and5.y, not1.u) + annotation (Line(points={{-118,-170},{-62,-170}}, color={255,0,255})); + connect(and5.y, yAvaCur) annotation (Line(points={{-118,-170},{-100,-170},{-100, + -240},{460,-240}}, color={255,0,255})); + connect(and3.y, and5.u2) annotation (Line(points={{-298,-110},{-280,-110},{-280, + -178},{-142,-178}}, color={255,0,255})); + annotation (defaultComponentName = "sta", + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-420,-280},{440,280}})), +Documentation(info=" +

+This subsequence is not directly specified in Guideline36-2021 as it provides a +side calculation pertaining to generalization of the staging sequences for any +number of chillers and stages provided by the user. +

+

+Based on the current stage u and stage availability vector +uAva the sequence outputs: +

+ +

+The purpose of this sequence is to: +

+ +", +revisions=" + +")); +end Status; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Up.mo new file mode 100644 index 00000000000..f78f6447f97 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Up.mo @@ -0,0 +1,383 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +block Up "Generates a stage up signal" + parameter Boolean have_WSE = true + "true = plant has a WSE, false = plant does not have WSE"; + + parameter Boolean have_serChi = false + "true = series chillers plant; false = parallel chillers plant"; + + parameter Boolean have_locSen=false + "Flag of local DP sensor: true=local DP sensor hardwired to controller" + annotation (Dialog(enable=not have_serChi)); + + parameter Integer nRemSen=2 + "Total number of remote differential pressure sensors" + annotation (Dialog(enable=not have_serChi)); + + parameter Real effConTruDelay( + final unit="s", + final quantity="Time")=900 + "Enable delay for efficiency condition"; + + parameter Real faiSafTruDelay( + final unit="s", + final quantity="Time")=900 + "Enable delay for failsafe condition"; + + parameter Real shortTDelay( + final unit="s", + final quantity="Time")=600 + "Short enable delay for staging from zero to first available stage up" + annotation(Evaluate=true, Dialog(enable=have_WSE)); + + parameter Real longTDelay( + final unit="s", + final quantity="Time")=1200 + "Long enable delay for staging from zero to first available stage up" + annotation(Evaluate=true, Dialog(enable=have_WSE)); + + parameter Real faiSafTDif( + final unit="K", + final quantity="TemperatureDifference")=1 + "Offset between the chilled water supply temperature and its setpoint"; + + parameter Real TDifHys( + final unit="K", + final quantity="TemperatureDifference")=1 + "Hysteresis deadband for temperature"; + + parameter Real smallTDif( + final unit="K", + final quantity="TemperatureDifference")=1 + "Offset between the chilled water supply temperature and its setpoint for the long condition" + annotation(Evaluate=true, Dialog(enable=have_WSE)); + + parameter Real largeTDif( + final unit="K", + final quantity="TemperatureDifference")=2 + "Offset between the chilled water supply temperature and its setpoint for the short condition" + annotation(Evaluate=true, Dialog(enable=have_WSE)); + + parameter Real faiSafDpDif( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa")=2 * 6895 + "Offset between the chilled water differential pressure and its setpoint"; + + parameter Real dpDifHys( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa")=0.5 * 6895 + "Pressure difference hysteresis deadband"; + + parameter Real effConSigDif( + final min=0, + final max=1, + final unit="1") = 0.05 + "Signal hysteresis deadband"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uAvaCur + "Current stage availability status" + annotation (Placement(transformation(extent={{-200,0},{-160,40}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u + "Chiller stage" + annotation (Placement(transformation(extent={{-200,-120},{-160,-80}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uOpe( + final unit="1") + "Operating part load ratio of the current stage" + annotation (Placement(transformation(extent={{-200,180},{-160,220}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uStaUp( + final unit="1") + "Staging part load ratio of the next stage up" + annotation (Placement(transformation(extent={{-200,150},{-160,190}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_local( + final unit="Pa", + final quantity="PressureDifference") + if (not have_serChi) and have_locSen + "Chilled water pump Diferential static pressure setpoint for local sensor" + annotation (Placement(transformation(extent={{-200,120},{-160,160}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_local( + final unit="Pa", + final quantity="PressureDifference") if (not have_serChi) and have_locSen + "Chilled water pump Diferential static pressure" + annotation (Placement(transformation(extent={{-200,90},{-160,130}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPumSet_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference",nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure setpoint for remote sensor" + annotation (Placement(transformation(extent={{-200,60},{-160,100}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatPum_remote[nRemSen]( + final unit=fill("Pa", nRemSen), + final quantity=fill("PressureDifference",nRemSen)) + if (not have_serChi) and (not have_locSen) + "Chilled water differential pressure from remote sensor" + annotation (Placement(transformation(extent={{-200,30},{-160,70}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-200,-50},{-160,-10}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-200,-90},{-160,-50}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-200,-200},{-160,-160}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y "Stage up signal" + annotation (Placement(transformation(extent={{160,-200},{200,-160}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.FailsafeCondition faiSafCon( + final have_serChi=have_serChi, + final faiSafTruDelay=faiSafTruDelay, + final have_locSen=have_locSen, + final nRemSen=nRemSen, + final TDif=faiSafTDif, + final TDifHys=TDifHys, + final dpDif=faiSafDpDif, + final dpDifHys=dpDifHys) + "Failsafe condition of the current stage" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition effCon( + final effConTruDelay = effConTruDelay, + final sigDif=effConSigDif) + "Efficiency condition of the current stage" + annotation (Placement(transformation(extent={{-100,170},{-80,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Or orStaUp + "Or for staging up" + annotation (Placement(transformation(extent={{20,110},{40,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Or for staging up" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi "Logical switch" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr if have_WSE + "Switches staging up rules" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTSup( + final uLow=smallTDif - TDifHys, + final uHigh=smallTDif, + final pre_y_start=false) if have_WSE + "Checks if the chilled water supply temperature is higher than its setpoint plus an offset" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTSup1( + final uLow=largeTDif - TDifHys, + final uHigh=largeTDif, + final pre_y_start=false) if have_WSE + "Checks if the chilled water supply temperature is higher than its setpoint plus an offset" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Or orStaUp1 if have_WSE + "Or for staging up" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 if have_WSE + "Temperature difference" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=longTDelay, + final delayOnInit=true) + if have_WSE + "Delays a true signal" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=shortTDelay, + final delayOnInit=true) + if have_WSE + "Delays a true signal" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noWSE( + final k=true) if not have_WSE + "Replacement signal for when a plant does not have a WSE" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 + "Logical switch" + annotation (Placement(transformation(extent={{120,-190},{140,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noUp( + final k=false) + "No stage up signal when it is in initial stage" + annotation (Placement(transformation(extent={{40,-150},{60,-130}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "If it is in initial stage, there will be stage up signal when enabling plant" + annotation (Placement(transformation(extent={{40,-190},{60,-170}}))); + +equation + connect(uOpe, effCon.uOpe) annotation (Line(points={{-180,200},{-150,200},{-150, + 185},{-102,185}},color={0,0,127})); + connect(uStaUp, effCon.uStaUp) annotation (Line(points={{-180,170},{-150,170}, + {-150,175},{-102,175}},color={0,0,127})); + connect(TChiWatSupSet, faiSafCon.TChiWatSupSet) annotation (Line(points={{-180, + -30},{-140,-30},{-140,109},{-102,109}}, color={0,0,127})); + connect(TChiWatSup, faiSafCon.TChiWatSup) annotation (Line(points={{-180,-70}, + {-130,-70},{-130,106},{-102,106}}, color={0,0,127})); + connect(dpChiWatPumSet_local, faiSafCon.dpChiWatPumSet_local) annotation ( + Line(points={{-180,140},{-120,140},{-120,101},{-102,101}}, color={0,0,127})); + connect(dpChiWatPum_local, faiSafCon.dpChiWatPum_local) annotation (Line( + points={{-180,110},{-150,110},{-150,98},{-102,98}}, color={0,0,127})); + connect(intGreThr.y, logSwi.u2) annotation (Line(points={{-98,-100},{20,-100}, + {20,80},{78,80}}, color={255,0,255})); + connect(orStaUp.y, logSwi.u1) annotation (Line(points={{42,120},{60,120},{60,88}, + {78,88}}, color={255,0,255})); + connect(sub1.y, hysTSup1.u) + annotation (Line(points={{-98,-30},{-80,-30},{-80,-60},{-62,-60}}, color={0,0,127})); + connect(hysTSup.y, truDel.u) + annotation (Line(points={{-38,0},{-22,0}}, color={255,0,255})); + connect(hysTSup1.y, truDel1.u) + annotation (Line(points={{-38,-60},{-22,-60}}, color={255,0,255})); + connect(truDel.y, orStaUp1.u1) annotation (Line(points={{2,0},{38,0}}, + color={255,0,255})); + connect(truDel1.y, orStaUp1.u2) annotation (Line(points={{2,-60},{10,-60},{10, + -8},{38,-8}}, color={255,0,255})); + connect(orStaUp1.y, logSwi.u3) annotation (Line(points={{62,0},{70,0},{70,72}, + {78,72}}, color={255,0,255})); + connect(noWSE.y, logSwi.u2) + annotation (Line(points={{2,80},{78,80}}, color={255,0,255})); + connect(noWSE.y, logSwi.u3) annotation (Line(points={{2,80},{30,80},{30,72},{78, + 72}}, color={255,0,255})); + connect(u, intGreThr.u) + annotation (Line(points={{-180,-100},{-122,-100}}, color={255,127,0})); + connect(sub1.y, hysTSup.u) annotation (Line(points={{-98,-30},{-80,-30},{-80, + 0},{-62,0}}, + color={0,0,127})); + connect(TChiWatSup, sub1.u1) annotation (Line(points={{-180,-70},{-130,-70},{ + -130,-24},{-122,-24}}, + color={0,0,127})); + connect(TChiWatSupSet, sub1.u2) annotation (Line(points={{-180,-30},{-140,-30}, + {-140,-36},{-122,-36}}, color={0,0,127})); + connect(uAvaCur, not1.u) + annotation (Line(points={{-180,20},{-122,20}}, color={255,0,255})); + connect(dpChiWatPumSet_remote, faiSafCon.dpChiWatPumSet_remote) annotation ( + Line(points={{-180,80},{-150,80},{-150,94},{-102,94}}, color={0,0,127})); + connect(dpChiWatPum_remote, faiSafCon.dpChiWatPum_remote) annotation (Line( + points={{-180,50},{-120,50},{-120,91},{-102,91}}, color={0,0,127})); + connect(lat.y, logSwi1.u2) + annotation (Line(points={{62,-180},{118,-180}}, color={255,0,255})); + connect(logSwi.y, logSwi1.u3) annotation (Line(points={{102,80},{110,80},{110, + -188},{118,-188}}, color={255,0,255})); + connect(logSwi1.y, y) + annotation (Line(points={{142,-180},{180,-180}}, color={255,0,255})); + connect(noUp.y, logSwi1.u1) annotation (Line(points={{62,-140},{100,-140},{100, + -172},{118,-172}}, color={255,0,255})); + connect(logSwi.y, lat.clr) annotation (Line(points={{102,80},{110,80},{110,-110}, + {20,-110},{20,-186},{38,-186}}, color={255,0,255})); + connect(not1.y, orStaUp.u2) annotation (Line(points={{-98,20},{10,20},{10,112}, + {18,112}}, color={255,0,255})); + connect(faiSafCon.y, or2.u2) annotation (Line(points={{-78,100},{-60,100},{-60, + 112},{-42,112}}, color={255,0,255})); + connect(effCon.y, or2.u1) annotation (Line(points={{-78,180},{-60,180},{-60,120}, + {-42,120}}, color={255,0,255})); + connect(or2.y, orStaUp.u1) + annotation (Line(points={{-18,120},{18,120}}, color={255,0,255})); + connect(uPla, lat.u) + annotation (Line(points={{-180,-180},{38,-180}}, color={255,0,255})); + annotation (defaultComponentName = "staUp", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name"), + Rectangle(extent={{-80,-10},{-20,-22}}, lineColor={0,0,127}), + Rectangle(extent={{-80,-28},{-20,-40}}, lineColor={0,0,127}), + Rectangle(extent={{-76,-22},{-72,-28}}, lineColor={0,0,127}), + Rectangle(extent={{-28,-22},{-24,-28}}, lineColor={0,0,127}), + Rectangle(extent={{20,-10},{80,-22}}, lineColor={0,0,127}), + Rectangle(extent={{20,-28},{80,-40}}, lineColor={0,0,127}), + Rectangle(extent={{24,-22},{28,-28}}, lineColor={0,0,127}), + Rectangle(extent={{72,-22},{76,-28}}, lineColor={0,0,127}), + Rectangle(extent={{20,30},{80,18}}, lineColor={0,0,127}), + Rectangle(extent={{20,12},{80,0}}, lineColor={0,0,127}), + Rectangle(extent={{24,18},{28,12}}, lineColor={0,0,127}), + Rectangle(extent={{72,18},{76,12}}, lineColor={0,0,127}), + Line(points={{130,-48}}, color={0,0,127})}), Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-160,-220},{160,220}})), +Documentation(info=" +

+Outputs a boolean stage up signal y based on the various plant +operation conditions that get provided as input signals. +It is implemented according to Guideline36-2021, section 5.20.4.15 and applies to +primary-only plant with and without a WSE. +

+

+The stage up signal becomes true when: +

+ +

+If have_WSE boolean flag is true, staging up from WSE only to the first +available stage occurs when the chilled water supply temperature is sufficienctly +above its setpoint for either a shorter or a longer time period +

+

+Note that when the plant is enabled in chiller mode, the stage up signal will keep +false. The plant will control by the + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.Enable. +

+", +revisions=" + +")); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_u.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_u.mo new file mode 100644 index 00000000000..495d658e2d5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_u.mo @@ -0,0 +1,162 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Capacities_u + "Validate stage capacities subsequence for chiller stage inputs" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap0(final nSta=3) + "Outputs design capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap1(final nSta=3) + "Outputs design capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap2(final nSta=3) + "Outputs design capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap3(final nSta=3) + "Outputs design capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{140,0},{160,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant desStaCap[3]( + final k={2e5,1e6,1.5e6}) "Design stage capacities" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minStaCap[3]( + final k={4e4,2e5,3e5}) "Minimum stage capacities" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage0(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{-140,20},{-120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage1(final k=1) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage2(final k=2) + "Chiller stage" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(final k=true) + "Boolean signal" + annotation (Placement(transformation(extent={{-140,-100},{-120,-80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage3(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage4(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{100,-20},{120,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage5(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage6(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage7(final k=1) + "Chiller stage" + annotation (Placement(transformation(extent={{-140,-20},{-120,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Boolean signal" + annotation (Placement(transformation(extent={{-140,-60},{-120,-40}}))); + +equation + connect(stage0.y, staCap0.u) + annotation (Line(points={{-118,30},{-110,30},{-110,13},{-102,13}}, + color={255,127,0})); + connect(stage1.y, staCap1.u) + annotation (Line(points={{-38,30},{-30,30},{-30,13},{-22,13}}, + color={255,127,0})); + connect(stage2.y, staCap2.u) + annotation (Line(points={{42,30},{50,30},{50,13},{58,13}}, color={255,127,0})); + connect(stage3.y, staCap3.u) annotation (Line(points={{122,30},{130,30},{130,13}, + {138,13}}, color={255,127,0})); + connect(stage0.y, staCap0.uDown) annotation (Line(points={{-118,30},{-110,30}, + {-110,7},{-102,7}}, color={255,127,0})); + connect(staCap0.uUp, stage7.y) annotation (Line(points={{-102,10},{-116,10},{-116, + -10},{-118,-10}}, color={255,127,0})); + connect(stage0.y, staCap1.uDown) annotation (Line(points={{-118,30},{-70,30},{ + -70,7},{-22,7}}, color={255,127,0})); + connect(stage6.y, staCap1.uUp) annotation (Line(points={{-38,-10},{-30,-10},{-30, + 10},{-22,10}}, color={255,127,0})); + connect(stage1.y, staCap2.uDown) annotation (Line(points={{-38,30},{10,30},{10, + 7},{58,7}}, color={255,127,0})); + connect(staCap2.uUp, stage5.y) annotation (Line(points={{58,10},{50,10},{50,-10}, + {42,-10}}, color={255,127,0})); + connect(stage2.y, staCap3.uDown) annotation (Line(points={{42,30},{90,30},{90, + 7},{138,7}}, color={255,127,0})); + connect(staCap3.uUp, stage4.y) annotation (Line(points={{138,10},{130,10},{130, + -10},{122,-10}}, color={255,127,0})); + connect(desStaCap.y, staCap0.uDesCap) annotation (Line(points={{-118,110},{ + -106,110},{-106,19},{-102,19}}, color={0,0,127})); + connect(minStaCap.y, staCap0.uMinCap) annotation (Line(points={{-118,70},{-108, + 70},{-108,16},{-102,16}}, color={0,0,127})); + connect(desStaCap.y, staCap1.uDesCap) annotation (Line(points={{-118,110},{ + -24,110},{-24,19},{-22,19}}, color={0,0,127})); + connect(minStaCap.y, staCap1.uMinCap) annotation (Line(points={{-118,70},{-26, + 70},{-26,16},{-22,16}}, color={0,0,127})); + connect(desStaCap.y, staCap2.uDesCap) annotation (Line(points={{-118,110},{54, + 110},{54,19},{58,19}}, color={0,0,127})); + connect(minStaCap.y, staCap2.uMinCap) annotation (Line(points={{-118,70},{52,70}, + {52,16},{58,16}}, color={0,0,127})); + connect(desStaCap.y, staCap3.uDesCap) annotation (Line(points={{-118,110},{ + 134,110},{134,19},{138,19}}, color={0,0,127})); + connect(staCap3.uMinCap, minStaCap.y) annotation (Line(points={{138,16},{132,16}, + {132,70},{-118,70}}, color={0,0,127})); + connect(con1.y, staCap1.uHig) annotation (Line(points={{-118,-50},{-28,-50},{-28, + 4},{-22,4}}, color={255,0,255})); + connect(con.y, staCap1.uLow) annotation (Line(points={{-118,-90},{-26,-90},{-26, + 1},{-22,1}}, color={255,0,255})); + connect(staCap0.uHig, con1.y) annotation (Line(points={{-102,4},{-110,4},{-110, + -50},{-118,-50}}, color={255,0,255})); + connect(staCap0.uLow, con.y) annotation (Line(points={{-102,1},{-108,1},{-108, + -90},{-118,-90}}, color={255,0,255})); + connect(con1.y, staCap2.uHig) annotation (Line(points={{-118,-50},{52,-50},{52, + 4},{58,4}}, color={255,0,255})); + connect(con1.y, staCap2.uLow) annotation (Line(points={{-118,-50},{54,-50},{54, + 1},{58,1}}, color={255,0,255})); + connect(con.y, staCap3.uHig) annotation (Line(points={{-118,-90},{132,-90},{132, + 4},{138,4}}, color={255,0,255})); + connect(con1.y, staCap3.uLow) annotation (Line(points={{-118,-50},{134,-50},{134, + 1},{138,1}}, color={255,0,255})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_u.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-180,-120},{180,140}}))); +end Capacities_u; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_uLow_uHig.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_uLow_uHig.mo new file mode 100644 index 00000000000..d55254e547e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_uLow_uHig.mo @@ -0,0 +1,126 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Capacities_uLow_uHig + "Validate stage capacities subsequence for highest and lowest available stage inputs" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap0(final nSta=3) + "Nominal capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap1(final nSta=3) + "Nominal capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{20,0},{40,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities + staCap2(final nSta=3) + "Nominal capacitites at the current and stage one lower" + annotation (Placement(transformation(extent={{100,0},{120,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant desStaCap[3]( + final k={2e5,1e6,1.5e6}) "Design stage capacities" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minStaCap[3]( + final k={4e4,2e5,3e5}) "Minimum stage capacities" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage0(final k=2) + "Chiller stage" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage2(final k=2) + "Chiller stage" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(final k=true) + "Boolean signal" + annotation (Placement(transformation(extent={{-100,-100},{-80,-80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage6(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{-20,-20},{0,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage7(final k=1) + "Chiller stage" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Boolean signal" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + +equation + connect(stage0.y, staCap0.u) + annotation (Line(points={{-78,30},{-70,30},{-70,13},{-62,13}}, + color={255,127,0})); + connect(stage2.y, staCap2.u) + annotation (Line(points={{82,30},{90,30},{90,13},{98,13}}, color={255,127,0})); + connect(stage0.y, staCap1.uDown) annotation (Line(points={{-78,30},{-20,30},{-20, + 7},{18,7}}, color={255,127,0})); + connect(stage6.y, staCap1.uUp) annotation (Line(points={{2,-10},{10,-10},{10,10}, + {18,10}}, color={255,127,0})); + connect(desStaCap.y, staCap0.uDesCap) annotation (Line(points={{-78,110},{-66, + 110},{-66,19},{-62,19}}, color={0,0,127})); + connect(minStaCap.y, staCap0.uMinCap) annotation (Line(points={{-78,70},{-68,70}, + {-68,16},{-62,16}}, color={0,0,127})); + connect(desStaCap.y, staCap1.uDesCap) annotation (Line(points={{-78,110},{16, + 110},{16,19},{18,19}}, color={0,0,127})); + connect(minStaCap.y, staCap1.uMinCap) annotation (Line(points={{-78,70},{14,70}, + {14,16},{18,16}}, color={0,0,127})); + connect(desStaCap.y, staCap2.uDesCap) annotation (Line(points={{-78,110},{94, + 110},{94,19},{98,19}}, color={0,0,127})); + connect(minStaCap.y, staCap2.uMinCap) annotation (Line(points={{-78,70},{92,70}, + {92,16},{98,16}}, color={0,0,127})); + connect(con1.y, staCap1.uHig) annotation (Line(points={{-78,-50},{12,-50},{12, + 4},{18,4}}, color={255,0,255})); + connect(con.y, staCap1.uLow) annotation (Line(points={{-78,-90},{14,-90},{14,1}, + {18,1}}, color={255,0,255})); + connect(staCap0.uUp, stage0.y) annotation (Line(points={{-62,10},{-70,10},{-70, + 30},{-78,30}}, color={255,127,0})); + connect(stage7.y, staCap0.uDown) annotation (Line(points={{-78,-10},{-70,-10}, + {-70,7},{-62,7}}, color={255,127,0})); + connect(con1.y, staCap0.uLow) annotation (Line(points={{-78,-50},{-66,-50},{-66, + 1},{-62,1}}, color={255,0,255})); + connect(con.y, staCap0.uHig) annotation (Line(points={{-78,-90},{-68,-90},{-68, + 4},{-62,4}}, color={255,0,255})); + connect(con.y, staCap2.uHig) annotation (Line(points={{-78,-90},{92,-90},{92,4}, + {98,4}}, color={255,0,255})); + connect(con.y, staCap2.uLow) annotation (Line(points={{-78,-90},{94,-90},{94,1}, + {98,1}}, color={255,0,255})); + connect(stage2.y, staCap2.uUp) annotation (Line(points={{82,30},{90,30},{90,10}, + {98,10}}, color={255,127,0})); + connect(stage2.y, staCap2.uDown) annotation (Line(points={{82,30},{90,30},{90, + 7},{98,7}}, color={255,127,0})); + connect(stage0.y, staCap1.u) annotation (Line(points={{-78,30},{0,30},{0,13},{ + 18,13}}, color={255,127,0})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Capacities_uLow_uHig.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Capacities. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{140,140}}))); +end Capacities_uLow_uHig; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mo new file mode 100644 index 00000000000..0cce8f4d09f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mo @@ -0,0 +1,155 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model CapacityRequirement + "Validates the cooling capacity requirement calculation" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq "Capacity requirement when no stage chage occurs" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq1 "Capacity requirement when stage change occurs and the process is shorter than 15 minutes" + annotation (Placement(transformation(extent={{20,0},{40,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq2 "Capacity requirement when stage change occurs and the process is longer than 15 minutes" + annotation (Placement(transformation(extent={{120,0},{140,20}}))); + +protected + parameter Real TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=285.15 + "Chilled water supply set temperature"; + + parameter Real aveTChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Average measured chilled water return temperature"; + + parameter Real aveVChiWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s") = 0.02 + "Average measured chilled water flow rate"; + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet( + final k=TChiWatSupSet) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet( + final amplitude=2, + final freqHz=1/300, + final offset=aveTChiWatRet) "Chilled water return temeprature" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow( + final freqHz=1/600, + final offset=aveVChiWat_flow, + final amplitude=0.01) "Chilled water flow" + annotation (Placement(transformation(extent={{-140,-70},{-120,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chaPro(final k=false) + "Stage change is not in process" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet1( + final k=TChiWatSupSet) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet1( + final amplitude=2, + final freqHz=1/300, + final offset=aveTChiWatRet) "Chilled water return temeprature" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow1( + final freqHz=1/600, + final offset=aveVChiWat_flow, + final amplitude=0.01) "Chilled water flow" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chaPro1( + final period=24*60, + final shift=5*60) + "Stage change process status signal" + annotation (Placement(transformation(extent={{-40,60},{-20,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet2( + final k= TChiWatSupSet) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet2( + final amplitude=2, + final freqHz=1/300, + final offset=aveTChiWatRet) "Chilled water return temeprature" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow2( + final freqHz=1/600, + final offset=aveVChiWat_flow, + final amplitude=0.01) "Chilled water flow" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chaPro2( + final period=32*60, + final shift=5*60) + "Stage change process status signal" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + +equation + connect(TCWSupSet.y, capReq.TChiWatSupSet) annotation (Line(points={{-118,20}, + {-90,20},{-90,19},{-82,19}}, color={0,0,127})); + connect(TChiWatRet.y, capReq.TChiWatRet) annotation (Line(points={{-118,-20}, + {-100,-20},{-100,14},{-82,14}}, + color={0,0,127})); + connect(chiWatFlow.y, capReq.VChiWat_flow) annotation (Line(points={{-118,-60}, + {-88,-60},{-88,9},{-82,9}},color={0,0,127})); + connect(chaPro.y, capReq.chaPro) annotation (Line(points={{-118,70},{-86,70}, + {-86,2},{-82,2}}, color={255,0,255})); + connect(TCWSupSet1.y, capReq1.TChiWatSupSet) annotation (Line(points={{-18,20}, + {10,20},{10,19},{18,19}}, color={0,0,127})); + connect(TChiWatRet1.y, capReq1.TChiWatRet) annotation (Line(points={{-18,-20}, + {0,-20},{0,14},{18,14}}, + color={0,0,127})); + connect(chiWatFlow1.y, capReq1.VChiWat_flow) annotation (Line(points={{-18,-60}, + {12,-60},{12,9},{18,9}}, color={0,0,127})); + connect(chaPro1.y, capReq1.chaPro) annotation (Line(points={{-18,70},{14,70}, + {14,2},{18,2}}, color={255,0,255})); + connect(TCWSupSet2.y, capReq2.TChiWatSupSet) annotation (Line(points={{82,20}, + {110,20},{110,19},{118,19}}, color={0,0,127})); + connect(TChiWatRet2.y, capReq2.TChiWatRet) annotation (Line(points={{82,-20}, + {100,-20},{100,14},{118,14}}, + color={0,0,127})); + connect(chiWatFlow2.y, capReq2.VChiWat_flow) annotation (Line(points={{82,-60}, + {112,-60},{112,9},{118,9}}, color={0,0,127})); + connect(chaPro2.y, capReq2.chaPro) annotation (Line(points={{82,70},{114,70}, + {114,2},{118,2}}, color={255,0,255})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.CapacityRequirement. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-100},{160,100}}))); +end CapacityRequirement; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo new file mode 100644 index 00000000000..dab6ca7b8f7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo @@ -0,0 +1,345 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Change + "Validates chiller stage status setpoint signal generation for plants with WSE" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Change + cha(final nSta=10) + "Controls for stage up signal variations" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Change + cha1(final nSta=10) + "Controls for stage down signal variations" + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Change + cha2 + "Controls for stage up/stage down signal interaction" + annotation (Placement(transformation(extent={{-40,-180},{-20,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{0,120},{20,140}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{0,-240},{20,-220}}))); + +protected + parameter Real TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=285.15 + "Chilled water supply set temperature"; + + parameter Real aveTChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Average measured chilled water return temperature"; + + parameter Real minStaRuntime( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Minimum stage runtime"; + + parameter Real aveVChiWat_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.05 + "Average measured chilled water flow rate"; + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timeTable( + final table=[0,0; 600,0; 600,1; 1200,1; 1200,0; 2500,0; 2500,1; 3700,1; 3700,0; 4300, + 0; 4300,1; 4500,1; 4500,0; 6000,0; 6000,1; 9200,1; 9200,0; 12000,0; + 12000,1; 14000,1; 14000,0]) + "Stage up signal for the first exampe and stage down signal for the second example from the top" + annotation (Placement(transformation(extent={{-160,220},{-140,240}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr( + final t=0.5) "Greater than threshold" + annotation (Placement(transformation(extent={{-120,220},{-100,240}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Type converter" + annotation (Placement(transformation(extent={{20,180},{40,200}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=1) "Zero order hold" + annotation (Placement(transformation(extent={{60,180},{80,200}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Type converter" + annotation (Placement(transformation(extent={{100,180},{120,200}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt + "Adder" + annotation (Placement(transformation(extent={{140,200},{160,220}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract addInt1 "Adder" + annotation (Placement(transformation(extent={{140,160},{160,180}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Type converter" + annotation (Placement(transformation(extent={{20,0},{40,20}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=1) "Zero order hold" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Type converter" + annotation (Placement(transformation(extent={{100,0},{120,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt2 "Adder" + annotation (Placement(transformation(extent={{140,20},{160,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract addInt3 "Addder" + annotation (Placement(transformation(extent={{140,-20},{160,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timeTable2( + final table=[0,0; 800,0; 800,1; 2700,1; 2700,0; 4500,0; 4500,1; 5200,1; 5200,0; + 6000,0; 6000,1; 6900,1; 6900,0; 7800,0; 7800,1; 8700,1; 8700,0; 12000,0; + 12000,1; 14000,1; 14000,0]) + "Stage up signal, if simultaneous stage up and down signals are generated the plant will stage down" + annotation (Placement(transformation(extent={{-160,-140},{-140,-120}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr2( + final t=0.5) "Greater threshold" + annotation (Placement(transformation(extent={{-120,-140},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea2 + "Type converter" + annotation (Placement(transformation(extent={{20,-180},{40,-160}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2( + final samplePeriod=1) "Zero order hold" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Type converter" + annotation (Placement(transformation(extent={{100,-180},{120,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt4 "Adder" + annotation (Placement(transformation(extent={{140,-160},{160,-140}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract addInt5 "Adder" + annotation (Placement(transformation(extent={{140,-200},{160,-180}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr3( + final t=0.5) "Greater than threshold" + annotation (Placement(transformation(extent={{-120,-180},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noStaChaSig( + final k=false) + "No stage change signal" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timeTable1( + final table=[0,0; 1600,0; 1600,1; 2400,1; 2400,0; 3700,0; 3700,1; 5900,1; 5900, + 0; 6900,0; 6900,1; 7800,1; 7800,0; 12000,0; 12000,1; 14000,1; 14000,0]) + "Stage down signal" + annotation (Placement(transformation(extent={{-160,-180},{-140,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxInt "Maximum" + annotation (Placement(transformation(extent={{180,140},{200,160}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxInt1 "Maximum" + annotation (Placement(transformation(extent={{180,-40},{200,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Max maxInt2 "Maximum" + annotation (Placement(transformation(extent={{180,-220},{200,-200}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant uIni(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{-120,260},{-100,280}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant step(final k=1) + "Assuming that the next available stage is always the next stage" + annotation (Placement(transformation(extent={{100,220},{120,240}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant uIni1(final k=7) + "Chiller stage" + annotation (Placement(transformation(extent={{-120,80},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant step1(final k=1) + "Assuming that the next available stage is always the next stage" + annotation (Placement(transformation(extent={{100,40},{120,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant uIni2(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{-120,-100},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant step2(final k=1) + "Assuming that the next available stage is always the next stage" + annotation (Placement(transformation(extent={{100,-140},{120,-120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u3(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{140,120},{160,140}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u4(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{140,-60},{160,-40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u5(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{140,-240},{160,-220}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timeTable3( + final table=[0,0; 10,0; 10,1; 11000,1; 11000,0; 12000,0; 12000,1; 14000,1; + 14000,0]) "Plant enable" + annotation (Placement(transformation(extent={{-200,20},{-180,40}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=0.5) "Greater than threshold" + annotation (Placement(transformation(extent={{-160,20},{-140,40}}))); + +equation + connect(cha.uIni, uIni.y) annotation (Line(points={{-42,200},{-60,200},{-60, + 270},{-98,270}}, color={255,127,0})); + connect(timeTable.y[1], greThr.u) + annotation (Line(points={{-138,230},{-122,230}}, color={0,0,127})); + connect(cha.ySta, intToRea.u) annotation (Line(points={{-18,194},{0,194},{0, + 190},{18,190}}, color={255,127,0})); + connect(intToRea.y, zerOrdHol.u) + annotation (Line(points={{42,190},{58,190}}, color={0,0,127})); + connect(zerOrdHol.y, reaToInt.u) + annotation (Line(points={{82,190},{98,190}}, color={0,0,127})); + connect(reaToInt.y, addInt.u2) annotation (Line(points={{122,190},{130,190},{ + 130,204},{138,204}}, color={255,127,0})); + connect(reaToInt.y, addInt1.u1) annotation (Line(points={{122,190},{130,190},{ + 130,176},{138,176}}, color={255,127,0})); + connect(step.y, addInt.u1) annotation (Line(points={{122,230},{130,230},{130, + 216},{138,216}}, color={255,127,0})); + connect(step.y, addInt1.u2) annotation (Line(points={{122,230},{126,230},{126, + 164},{138,164}}, color={255,127,0})); + connect(addInt.y, cha.uAvaUp) annotation (Line(points={{162,210},{170,210},{ + 170,250},{-50,250},{-50,196},{-42,196}}, color={255,127,0})); + connect(cha1.uIni, uIni1.y) annotation (Line(points={{-42,20},{-60,20},{-60, + 90},{-98,90}}, color={255,127,0})); + connect(cha1.ySta, intToRea1.u) annotation (Line(points={{-18,14},{0,14},{0, + 10},{18,10}}, color={255,127,0})); + connect(intToRea1.y, zerOrdHol1.u) + annotation (Line(points={{42,10},{58,10}}, color={0,0,127})); + connect(zerOrdHol1.y, reaToInt1.u) + annotation (Line(points={{82,10},{98,10}}, color={0,0,127})); + connect(reaToInt1.y, addInt2.u2) annotation (Line(points={{122,10},{130,10},{ + 130,24},{138,24}},color={255,127,0})); + connect(reaToInt1.y, addInt3.u1) annotation (Line(points={{122,10},{130,10},{ + 130,-4},{138,-4}}, color={255,127,0})); + connect(step1.y, addInt2.u1) annotation (Line(points={{122,50},{130,50},{130, + 36},{138,36}}, color={255,127,0})); + connect(step1.y, addInt3.u2) annotation (Line(points={{122,50},{126,50},{126, + -16},{138,-16}}, color={255,127,0})); + connect(addInt2.y, cha1.uAvaUp) annotation (Line(points={{162,30},{170,30},{ + 170,70},{-50,70},{-50,16},{-42,16}}, color={255,127,0})); + connect(timeTable2.y[1], greThr2.u) + annotation (Line(points={{-138,-130},{-122,-130}}, color={0,0,127})); + connect(cha2.uIni, uIni2.y) annotation (Line(points={{-42,-160},{-60,-160},{-60, + -90},{-98,-90}}, color={255,127,0})); + connect(cha2.ySta, intToRea2.u) annotation (Line(points={{-18,-166},{0,-166}, + {0,-170},{18,-170}},color={255,127,0})); + connect(intToRea2.y, zerOrdHol2.u) + annotation (Line(points={{42,-170},{58,-170}}, color={0,0,127})); + connect(zerOrdHol2.y, reaToInt2.u) + annotation (Line(points={{82,-170},{98,-170}}, color={0,0,127})); + connect(reaToInt2.y, addInt4.u2) annotation (Line(points={{122,-170},{130, + -170},{130,-156},{138,-156}}, color={255,127,0})); + connect(reaToInt2.y, addInt5.u1) annotation (Line(points={{122,-170},{130, + -170},{130,-184},{138,-184}}, color={255,127,0})); + connect(step2.y, addInt4.u1) annotation (Line(points={{122,-130},{130,-130},{ + 130,-144},{138,-144}}, color={255,127,0})); + connect(step2.y, addInt5.u2) annotation (Line(points={{122,-130},{126,-130},{ + 126,-196},{138,-196}}, color={255,127,0})); + connect(addInt4.y, cha2.uAvaUp) annotation (Line(points={{162,-150},{170,-150}, + {170,-110},{-50,-110},{-50,-164},{-42,-164}}, color={255,127,0})); + connect(noStaChaSig.y, cha.uDow) annotation (Line(points={{-178,110},{-170, + 110},{-170,184},{-42,184}}, color={255,0,255})); + connect(noStaChaSig.y, cha1.uUp) annotation (Line(points={{-178,110},{-170, + 110},{-170,60},{-80,60},{-80,8},{-42,8}},color={255,0,255})); + connect(greThr.y, cha.uUp) annotation (Line(points={{-98,230},{-70,230},{-70, + 188},{-42,188}}, color={255,0,255})); + connect(greThr2.y, cha2.uUp) annotation (Line(points={{-98,-130},{-80,-130},{ + -80,-172},{-42,-172}}, color={255,0,255})); + connect(greThr3.y, cha2.uDow) annotation (Line(points={{-98,-170},{-90,-170}, + {-90,-176},{-42,-176}},color={255,0,255})); + connect(greThr.y, cha1.uDow) annotation (Line(points={{-98,230},{-64,230},{ + -64,4},{-42,4}}, color={255,0,255})); + connect(timeTable1.y[1], greThr3.u) + annotation (Line(points={{-138,-170},{-122,-170}}, color={0,0,127})); + connect(cha.yChaEdg, truFalHol.u) annotation (Line(points={{-18,186},{-10,186}, + {-10,130},{-2,130}}, color={255,0,255})); + connect(cha1.yChaEdg, truFalHol1.u) annotation (Line(points={{-18,6},{-10,6}, + {-10,-50},{-2,-50}}, color={255,0,255})); + connect(cha2.yChaEdg, truFalHol2.u) annotation (Line(points={{-18,-174},{-10, + -174},{-10,-230},{-2,-230}}, color={255,0,255})); + connect(maxInt.u2, u3.y) annotation (Line(points={{178,144},{170,144},{170,130}, + {162,130}}, color={255,127,0})); + connect(maxInt.y, cha.uAvaDow) annotation (Line(points={{202,150},{210,150},{210, + 110},{-50,110},{-50,192},{-42,192}}, color={255,127,0})); + connect(u4.y, maxInt1.u2) annotation (Line(points={{162,-50},{170,-50},{170, + -36},{178,-36}}, color={255,127,0})); + connect(maxInt1.y, cha1.uAvaDow) annotation (Line(points={{202,-30},{208,-30}, + {208,-70},{-50,-70},{-50,12},{-42,12}}, color={255,127,0})); + connect(u5.y, maxInt2.u2) annotation (Line(points={{162,-230},{170,-230},{170, + -216},{178,-216}}, color={255,127,0})); + connect(maxInt2.y, cha2.uAvaDow) annotation (Line(points={{202,-210},{208, + -210},{208,-252},{-50,-252},{-50,-168},{-42,-168}}, color={255,127,0})); + connect(timeTable3.y[1], greThr1.u) + annotation (Line(points={{-178,30},{-162,30}}, color={0,0,127})); + connect(greThr1.y, cha.uPla) annotation (Line(points={{-138,30},{-130,30},{ + -130,180},{-42,180}}, color={255,0,255})); + connect(greThr1.y, cha1.uPla) annotation (Line(points={{-138,30},{-130,30},{ + -130,0},{-42,0}}, color={255,0,255})); + connect(greThr1.y, cha2.uPla) annotation (Line(points={{-138,30},{-88,30},{ + -88,-180},{-42,-180}}, color={255,0,255})); + connect(addInt3.y, maxInt1.u1) annotation (Line(points={{162,-10},{170,-10},{ + 170,-24},{178,-24}}, + color={255,127,0})); + connect(addInt5.y, maxInt2.u1) annotation (Line(points={{162,-190},{170,-190}, + {170,-204},{178,-204}}, color={255,127,0})); + connect(addInt1.y, maxInt.u1) annotation (Line(points={{162,170},{170,170},{ + 170,156},{178,156}}, + color={255,127,0})); +annotation ( + experiment(StopTime=14000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Change.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Change. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-280},{220,300}}))); +end Change; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/ChillerIndices_u.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/ChillerIndices_u.mo new file mode 100644 index 00000000000..5dce93390e1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/ChillerIndices_u.mo @@ -0,0 +1,125 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model ChillerIndices_u + "Validates extraction of chiller indices in a given stage" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd( + final nSta=3, + final nChi=2, + staMat={{1,0},{0,1},{1,1}}) + "Setup with two chillers and three stages" + annotation (Placement(transformation(extent={{0,80},{20,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd1( + final nSta=3, + final nChi=2, + staMat={{1,0},{0,1},{1,1}}) + "Setup with two chillers and three stages" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd2( + final nSta=3, + final nChi=2, + staMat={{1,0},{0,1},{1,1}}) + "Setup with two chillers and three stages" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd4( + final nSta=5, + final nChi=3, + staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Setup with three chillers and five stages" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd5( + final nSta=5, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Setup with three chillers and five stages" + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd6( + final nSta=5, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Setup with three chillers and five stages" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd7( + final nSta=5, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Setup with three chillers and five stages" + annotation (Placement(transformation(extent={{40,-100},{60,-80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices chiInd3 + "Setup with default settings that is two chillers and three stages" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u1(final k=1) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u2(final k=2) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u3(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u4(final k=5) + "Chiller stage" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + +equation + connect(u.y, chiInd.u) + annotation (Line(points={{-38,90},{-2,90}}, color={255,127,0})); + connect(u1.y, chiInd1.u) + annotation (Line(points={{-38,50},{-2,50}}, color={255,127,0})); + connect(u2.y, chiInd2.u) + annotation (Line(points={{-38,10},{-2,10}}, color={255,127,0})); + connect(u3.y, chiInd3.u) + annotation (Line(points={{-38,-30},{-2,-30}}, color={255,127,0})); + connect(u.y, chiInd4.u) annotation (Line(points={{-38,90},{-20,90},{-20,70},{ + 38,70}}, color={255,127,0})); + connect(u1.y, chiInd5.u) annotation (Line(points={{-38,50},{-20,50},{-20,30}, + {38,30}}, color={255,127,0})); + connect(u3.y, chiInd6.u) annotation (Line(points={{-38,-30},{-20,-30},{-20,-50}, + {38,-50}}, color={255,127,0})); + connect(u4.y,chiInd7. u) annotation (Line(points={{-38,-70},{0,-70},{0,-90},{38, + -90}}, color={255,127,0})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/ChillerIndices_u.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.ChillerIndices. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-80,-120},{80,120}}))); +end ChillerIndices_u; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Configurator_uChiAva.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Configurator_uChiAva.mo new file mode 100644 index 00000000000..cfce38c0a6a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Configurator_uChiAva.mo @@ -0,0 +1,149 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Configurator_uChiAva "Validate chiller staging configurator subsequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,0,1},{0,1,1},{1,1,1}}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}, + final chiDesCap={1e6,1.5e6,2e6}, + final chiMinCap={2e5,3e5,4e5}) + "Stage configurator" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf1( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,0,1},{0,1,1},{1,1,1}}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}, + final chiDesCap={1e6,1.5e6,2e6}, + final chiMinCap={2e5,3e5,4e5}) + "Stage configurator" + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf3( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,0,1},{0,1,1},{1,1,1}}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}, + final chiDesCap={1e6,1.5e6,2e6}, + final chiMinCap={2e5,3e5,4e5}) + "Stage configurator" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf4( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,0,1},{0,1,1},{1,1,1}}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}, + final chiDesCap={1e6,1.5e6,2e6}, + final chiMinCap={2e5,3e5,4e5}) + "Stage configurator" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf5( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,0,1},{0,1,1},{1,1,1}}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}, + final chiDesCap={1e6,1.5e6,2e6}, + final chiMinCap={2e5,3e5,4e5}) + "Stage configurator" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator conf2( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,0,1},{0,1,1},{1,1,1}}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}, + final chiDesCap={1e6,1.5e6,2e6}, + final chiMinCap={2e5,3e5,4e5}) + "Stage configurator" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva[3]( + final k={true,true,true}) + "Chiller availability array" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva1[3]( + final k={false,true,true}) + "Chiller availability array" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva3[3]( + final k={true,true,false}) + "Chiller availability array" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva4[3]( + final k={true,false,false}) + "Chiller availability array" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva5[3]( + final k={false,false,false}) + "Chiller availability array" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva2[3]( + final k={false,false,true}) + "Chiller availability array" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + +equation + connect(chiAva.y, conf.uChiAva) + annotation (Line(points={{-18,100},{18,100}},color={255,0,255})); + connect(chiAva1.y, conf1.uChiAva) + annotation (Line(points={{-18,60},{18,60}}, color={255,0,255})); + connect(chiAva3.y, conf3.uChiAva) + annotation (Line(points={{-18,-20},{18,-20}}, color={255,0,255})); + connect(chiAva4.y, conf4.uChiAva) + annotation (Line(points={{-18,-60},{18,-60}}, color={255,0,255})); + connect(chiAva5.y, conf5.uChiAva) + annotation (Line(points={{-18,-100},{18,-100}}, color={255,0,255})); + connect(chiAva2.y, conf2.uChiAva) + annotation (Line(points={{-18,20},{18,20}}, color={255,0,255})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Configurator_uChiAva.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Configurator. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-60,-120},{60,120}}))); +end Configurator_uChiAva; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Down.mo new file mode 100644 index 00000000000..f87c6684c54 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Down.mo @@ -0,0 +1,226 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Down "Validate change stage down condition sequence" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Down + withWSE(have_locSen=true) + "Generates stage down signal" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Down + withWSE1(have_locSen=true) + "Generates stage down signal" + annotation (Placement(transformation(extent={{140,40},{160,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Down + noWSE(have_WSE=false, have_locSen=true) + "Generates stage down signal for a plant with a WSE" + annotation (Placement(transformation(extent={{-40,80},{-20,100}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage2( + final k=2) + "Second stage" + annotation (Placement(transformation(extent={{-160,-100},{-140,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant WSESta( + final k=true) + "Waterside economizer status" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage1( + final k=1) "2nd stage" + annotation (Placement(transformation(extent={{20,-100},{40,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant WSESta1( + final k=true) "WSE status" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet( + final k=273.15 + 14) "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-160,-20},{-140,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet( + final k=65*6895) "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,0},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSup( + final k=273.15 + 14) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-160,-60},{-140,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant splrDown( + final k=0.8) + "Staging down part load ratio" + annotation (Placement(transformation(extent={{-160,100},{-140,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin oplrDown( + final amplitude=0.1, + final startTime=0, + final freqHz=1/4800, + final phase(displayUnit="deg") = -1.5707963267949, + final offset=0.75) "Operating part load ratio of the next stage down" + annotation (Placement(transformation(extent={{-120,120},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TWsePre( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-160,20},{-140,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TowFanSpeMax( + final k=0.9) + "Maximum cooling tower speed signal" + annotation (Placement(transformation(extent={{-120,40},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet1( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSup1( + final k=273.15 + 14) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat1( + final k=62*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant oplrDown1(final k=1) + "Operating part load ratio of stage 0" + annotation (Placement(transformation(extent={{60,120},{80,140}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TowFanSpeMax1( + final k=0.9) + "Maximum cooling tower speed signal" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TWsePre1( + final amplitude=4, + final freqHz=1/2100, + final offset=273.15 + 12.5) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + CDL.Reals.Sources.Constant splrDown1(final k=1) + "Staging down part load ratio" + annotation (Placement(transformation(extent={{40,80},{60,100}}))); +equation + + connect(TCWSupSet.y, withWSE.TChiWatSupSet) annotation (Line(points={{-138, + -10},{-70,-10},{-70,48.8},{-42,48.8}}, + color={0,0,127})); + connect(TCWSup.y, withWSE.TChiWatSup) annotation (Line(points={{-138,-50},{ + -68,-50},{-68,46.8},{-42,46.8}}, + color={0,0,127})); + connect(dpChiWatSet.y, withWSE.dpChiWatPumSet_local) annotation (Line(points= + {{-98,10},{-76,10},{-76,57},{-42,57}}, color={0,0,127})); + connect(dpChiWat.y, withWSE.dpChiWatPum_local) annotation (Line(points={{-98, + -30},{-72,-30},{-72,55},{-42,55}}, color={0,0,127})); + connect(oplrDown.y, withWSE.uOpeDow) annotation (Line(points={{-98,130},{-70, + 130},{-70,61},{-42,61}}, color={0,0,127})); + connect(splrDown.y, withWSE.uStaDow) annotation (Line(points={{-138,110},{-72, + 110},{-72,59},{-42,59}}, color={0,0,127})); + connect(WSESta.y, withWSE.uWseSta) annotation (Line(points={{-98,-70},{-66, + -70},{-66,39},{-42,39}}, color={255,0,255})); + connect(stage2.y, withWSE.u) annotation (Line(points={{-138,-90},{-62,-90},{ + -62,41},{-42,41}}, color={255,127,0})); + connect(TWsePre.y, withWSE.TWsePre) annotation (Line(points={{-138,30},{-80, + 30},{-80,44.8},{-42,44.8}}, + color={0,0,127})); + connect(TowFanSpeMax.y, withWSE.uTowFanSpeMax) annotation (Line(points={{-98,50}, + {-90,50},{-90,42.8},{-42,42.8}}, color={0,0,127})); + connect(TCWSupSet1.y, withWSE1.TChiWatSupSet) annotation (Line(points={{42,-10}, + {110,-10},{110,48.8},{138,48.8}}, color={0,0,127})); + connect(TCWSup1.y, withWSE1.TChiWatSup) annotation (Line(points={{42,-50},{ + 112,-50},{112,46.8},{138,46.8}}, + color={0,0,127})); + connect(dpChiWatSet1.y, withWSE1.dpChiWatPumSet_local) annotation (Line( + points={{82,10},{104,10},{104,57},{138,57}}, color={0,0,127})); + connect(dpChiWat1.y, withWSE1.dpChiWatPum_local) annotation (Line(points={{82, + -30},{108,-30},{108,55},{138,55}}, color={0,0,127})); + connect(oplrDown1.y, withWSE1.uOpeDow) annotation (Line(points={{82,130},{110, + 130},{110,61},{138,61}}, color={0,0,127})); + connect(WSESta1.y, withWSE1.uWseSta) annotation (Line(points={{82,-70},{114, + -70},{114,39},{138,39}}, color={255,0,255})); + connect(stage1.y, withWSE1.u) annotation (Line(points={{42,-90},{116,-90},{ + 116,41},{138,41}}, color={255,127,0})); + connect(TowFanSpeMax1.y, withWSE1.uTowFanSpeMax) annotation (Line(points={{82,50}, + {90,50},{90,42.8},{138,42.8}}, color={0,0,127})); + connect(TWsePre1.y, withWSE1.TWsePre) annotation (Line(points={{42,30},{106, + 30},{106,44.8},{138,44.8}}, + color={0,0,127})); + connect(oplrDown.y, noWSE.uOpeDow) annotation (Line(points={{-98,130},{-70, + 130},{-70,101},{-42,101}}, color={0,0,127})); + connect(splrDown.y, noWSE.uStaDow) annotation (Line(points={{-138,110},{-72, + 110},{-72,99},{-42,99}}, color={0,0,127})); + connect(dpChiWatSet.y, noWSE.dpChiWatPumSet_local) annotation (Line(points={{ + -98,10},{-82,10},{-82,86},{-56,86},{-56,97},{-42,97}}, color={0,0,127})); + connect(dpChiWat.y, noWSE.dpChiWatPum_local) annotation (Line(points={{-98, + -30},{-86,-30},{-86,84},{-54,84},{-54,95},{-42,95}}, color={0,0,127})); + connect(TCWSup.y, noWSE.TChiWatSup) annotation (Line(points={{-138,-50},{-88, + -50},{-88,82},{-50,82},{-50,86.8},{-42,86.8}}, + color={0,0,127})); + connect(TCWSupSet.y, noWSE.TChiWatSupSet) annotation (Line(points={{-138,-10}, + {-84,-10},{-84,80},{-52,80},{-52,88.8},{-42,88.8}}, + color={0,0,127})); + connect(stage2.y, noWSE.u) annotation (Line(points={{-138,-90},{-64,-90},{-64, + 81},{-42,81}}, color={255,127,0})); + connect(splrDown1.y, withWSE1.uStaDow) annotation (Line(points={{62,90},{100, + 90},{100,59},{138,59}}, color={0,0,127})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Down.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Generic.Down. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-180,-160},{180,180}}), + graphics={ + Text( + extent={{-136,-120},{-76,-142}}, + textColor={0,0,127}, + textString="Tests stage down from stages higher than stage 1. + +The tests assumes a false output of the failsafe condition and +checks functionality for the next available stage down SPLR and OPLR inputs."), + Text( + extent={{38,-120},{98,-142}}, + textColor={0,0,127}, + textString="Tests stage down from stage 1. + +Test assumes WSE is on and +maximum tower fan speed signal +is less than 1. The test ensures stage down gets initiated as the +cooling capacity of the first stage exceeds the demand +given the presence of WSE.")})); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mo new file mode 100644 index 00000000000..3a26615ff9f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mo @@ -0,0 +1,57 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model EfficiencyCondition "Validate efficiency condition sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition + effCon + "Failsafe condition to test for the operating part load ratio input" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Sin oplr( + final amplitude=0.1, + final phase(displayUnit="rad"), + final startTime=0, + final offset=0.85, + final freqHz=1/2100) "Operating part load ratio of the current stage" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant splrUp( + final k=0.8) + "Staging part load ratio of the next stage up" + annotation (Placement(transformation(extent={{-40,-20},{-20,0}}))); + +equation + connect(oplr.y, effCon.uOpe) annotation (Line(points={{-18,30},{-10,30},{-10, + 15},{-2,15}}, color={0,0,127})); + connect(splrUp.y, effCon.uStaUp) annotation (Line(points={{-18,-10},{-10,-10}, + {-10,5},{-2,5}}, color={0,0,127})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Generic.EfficiencyCondition. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-60,-40},{40,60}}))); +end EfficiencyCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mo new file mode 100644 index 00000000000..0011a15d02d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mo @@ -0,0 +1,127 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model FailsafeCondition "Validate failsafe condition sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon0(have_locSen=true) + "Failsafe condition to test for the current stage availability input" + annotation (Placement(transformation(extent={{-40,80},{-20,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon1(have_locSen=true) + "Failsafe condition to test for the chilled water supply temperature and differential pressure inputs" + annotation (Placement(transformation(extent={{120,80},{140,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon2(final have_serChi=true) + "Failsafe condition to test for the chilled water supply temperature input for series chillers plant" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSup( + final k=273.15 + 18) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat( + final k=64.1*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet1( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{20,100},{40,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TCWSup1( + final amplitude=1.5, + final offset=273.15 + 15.5, + final freqHz=1/900) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{20,60},{40,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin dpChiWat2( + final amplitude=6895, + final offset=63*6895, + final freqHz=1/1500, + final startTime=0, + phase=0.78539816339745) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet2( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-140,-40},{-120,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TCWSup2( + final amplitude=1.5, + final offset=273.15 + 15.5, + final freqHz=1/2100) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + +equation + connect(TCWSup.y, faiSafCon0.TChiWatSup) annotation (Line(points={{-118,70},{ + -110,70},{-110,96},{-42,96}}, color={0,0,127})); + connect(TCWSupSet.y, faiSafCon0.TChiWatSupSet) annotation (Line(points={{-118, + 110},{-60,110},{-60,99},{-42,99}}, color={0,0,127})); + connect(dpChiWatSet.y, faiSafCon0.dpChiWatPumSet_local) annotation (Line( + points={{-78,70},{-60,70},{-60,91},{-42,91}}, color={0,0,127})); + connect(dpChiWat.y, faiSafCon0.dpChiWatPum_local) annotation (Line(points={{ + -78,30},{-56,30},{-56,88},{-42,88}}, color={0,0,127})); + connect(TCWSupSet1.y, faiSafCon1.TChiWatSupSet) annotation (Line(points={{42,110}, + {100,110},{100,99},{118,99}}, color={0,0,127})); + connect(dpChiWatSet1.y, faiSafCon1.dpChiWatPumSet_local) annotation (Line( + points={{82,70},{90,70},{90,91},{118,91}}, color={0,0,127})); + connect(TCWSup1.y, faiSafCon1.TChiWatSup) annotation (Line(points={{42,70},{ + 50,70},{50,96},{118,96}}, color={0,0,127})); + connect(dpChiWat2.y, faiSafCon1.dpChiWatPum_local) annotation (Line(points={{ + 82,30},{100,30},{100,88},{118,88}}, color={0,0,127})); + connect(TCWSupSet2.y,faiSafCon2. TChiWatSupSet) annotation (Line(points={{-118, + -30},{-100,-30},{-100,-21},{-42,-21}}, color={0,0,127})); + connect(TCWSup2.y,faiSafCon2. TChiWatSup) annotation (Line(points={{-118,-70}, + {-100,-70},{-100,-40},{-60,-40},{-60,-24},{-42,-24}}, color={0,0,127})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Generic.FailsafeCondition. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-140},{160,140}}))); +end FailsafeCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_WSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_WSE.mo new file mode 100644 index 00000000000..0f0e00c2f52 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_WSE.mo @@ -0,0 +1,109 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Initial_WSE "Validate initial stage sequence for a plant with WSE" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial iniStaCol( + final have_WSE=true) "Initial stage is the WSE only stage" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial iniStaHot( + final have_WSE=true) + "Initial stage is the lowest available chiller stage" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant lowAvaSta( + final k=1) + "Lowest chiller stage that is available " + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin outTemHot( + final amplitude=8, + final freqHz=1/(24*3600), + final phase=-1.5707963267949, + final offset=298.15) + "Measured outdoor air wet bulb temperature on a hot day" + annotation (Placement(transformation(extent={{20,40},{40,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin outTemCol( + final amplitude=8, + final freqHz=1/(24*3600), + final phase=-1.5707963267949, + final offset=278.15) + "Measured outdoor air wet bulb temperature on a cold day" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant tunPar( + final k=0.06) + "Assume a constant tuning parameter" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet( + final k=285.15) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta( + final k=true) + "Plant status" + annotation (Placement(transformation(extent={{-120,-60},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=600, + final delayOnInit=true) "True delay" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + +equation + connect(lowAvaSta.y,iniStaCol. uUp) annotation (Line(points={{-18,-50},{-10,-50}, + {-10,0},{-2,0}}, color={255,127,0})); + connect(TChiWatSupSet.y,iniStaCol. TChiWatSupSet) annotation (Line(points={{-18, + 50},{-10,50},{-10,3},{-2,3}}, color={0,0,127})); + connect(TChiWatSupSet.y, iniStaHot.TChiWatSupSet) annotation (Line(points={{-18, + 50},{-10,50},{-10,20},{50,20},{50,3},{58,3}}, color={0,0,127})); + connect(tunPar.y,iniStaCol. uTunPar) annotation (Line(points={{-58,50},{-50,50}, + {-50,6},{-2,6}}, color={0,0,127})); + connect(tunPar.y, iniStaHot.uTunPar) annotation (Line(points={{-58,50},{-50,50}, + {-50,16},{46,16},{46,6},{58,6}}, color={0,0,127})); + connect(outTemHot.y, iniStaHot.TOutWet) + annotation (Line(points={{42,50},{54,50},{54,9},{58,9}}, color={0,0,127})); + connect(outTemCol.y, iniStaCol.TOutWet) annotation (Line(points={{-58,-10},{-30, + -10},{-30,9},{-2,9}}, color={0,0,127})); + connect(lowAvaSta.y, iniStaHot.uUp) annotation (Line(points={{-18,-50},{50,-50}, + {50,0},{58,0}}, color={255,127,0})); + connect(plaSta.y, truDel.u) + annotation (Line(points={{-98,-50},{-82,-50}}, color={255,0,255})); + connect(truDel.y, iniStaCol.uPla) annotation (Line(points={{-58,-50},{-50,-50}, + {-50,-20},{-20,-20},{-20,-6},{-2,-6}}, color={255,0,255})); + connect(truDel.y, iniStaHot.uPla) annotation (Line(points={{-58,-50},{-50,-50}, + {-50,-20},{40,-20},{40,-6},{58,-6}}, color={255,0,255})); + +annotation ( + experiment(StopTime=86400.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_WSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial +for chiller plants with WSE. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-140,-80},{140,80}}))); +end Initial_WSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_noWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_noWSE.mo new file mode 100644 index 00000000000..9d599f9662e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_noWSE.mo @@ -0,0 +1,77 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Initial_noWSE + "Validate initial stage sequence in case of no WSE" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial iniSta( + final have_WSE=false) + "Tests if initial stage is the lowest available stage" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial iniSta1( + final have_WSE=false) + "Tests if initial stage is the lowest available stage" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant lowAvaSta( + final k=2) + "Lowest chiller stage that is available" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant lowAvaSta1( + final k=2) + "Lowest chiller stage that is available" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=10, + final delayOnInit=true) + "True signal delay" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta( + final k=true) "Plant status" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + +equation + connect(lowAvaSta.y, iniSta.uUp) + annotation (Line(points={{-18,30},{18,30}},color={255,127,0})); + connect(lowAvaSta1.y, iniSta1.uUp) + annotation (Line(points={{-18,-40},{18,-40}}, color={255,127,0})); + connect(plaSta.y, truDel.u) + annotation (Line(points={{-38,0},{-22,0}}, color={255,0,255})); + connect(truDel.y, iniSta.uPla) annotation (Line(points={{2,0},{10,0},{10,24},{ + 18,24}}, color={255,0,255})); + connect(plaSta.y, iniSta1.uPla) annotation (Line(points={{-38,0},{-30,0},{-30, + -20},{0,-20},{0,-46},{18,-46}}, color={255,0,255})); +annotation ( + experiment(StopTime=100.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Initial_noWSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Initial + for chiller plants without WSE. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-80,-60},{80,60}}))); +end Initial_noWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/PartLoadRatios_u_uTyp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/PartLoadRatios_u_uTyp.mo new file mode 100644 index 00000000000..ff92e214274 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/PartLoadRatios_u_uTyp.mo @@ -0,0 +1,600 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model PartLoadRatios_u_uTyp + "Validates the operating and stage part load ratios calculation for chiller stage and stage type inputs" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs0( + final anyVsdCen=false, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{-260,170},{-240,210}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs1( + final anyVsdCen=false, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{-40,170},{-20,210}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs2( + final anyVsdCen=false, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{180,170},{200,210}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs3( + final anyVsdCen=false, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{420,170},{440,210}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs4( + final anyVsdCen=true, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{-260,-170},{-240,-130}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs5( + final anyVsdCen=true, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{-40,-170},{-20,-130}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs6( + final anyVsdCen=true, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{180,-170},{200,-130}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios PLRs7( + final anyVsdCen=true, + final nSta=3) + "Stage and operative part load ratios" + annotation (Placement(transformation(extent={{420,-170},{440,-130}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staTyp[3](final k={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}) + "Stage types" + annotation (Placement(transformation(extent={{-420,220},{-400,240}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staTyp4[3](final k={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.variableSpeedCentrifugal, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}) + "Stage types" + annotation (Placement(transformation(extent={{-420,-270},{-400,-250}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max "Maximum" + annotation (Placement(transformation(extent={{-340,360},{-320,380}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max1 "Maximum" + annotation (Placement(transformation(extent={{-120,360},{-100,380}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max2 "Maximum" + annotation (Placement(transformation(extent={{100,360},{120,380}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max3 "Maximum" + annotation (Placement(transformation(extent={{340,360},{360,380}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max4 "Maximum" + annotation (Placement(transformation(extent={{-340,0},{-320,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max5 "Maximum" + annotation (Placement(transformation(extent={{-120,0},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max6 "Maximum" + annotation (Placement(transformation(extent={{100,0},{120,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max7 "Maximum" + annotation (Placement(transformation(extent={{340,0},{360,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta( + final k=1) "Current chiller stage" + annotation (Placement(transformation(extent={{-420,180},{-400,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq3( + final amplitude=6e5, + final freqHz=1/1800, + final offset=9e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-420,380},{-400,400}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp( + final k=2) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{-420,140},{-400,160}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown( + final k=0) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{-420,100},{-400,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant lowLim( + final k=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-420,340},{-400,360}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant capDes[3]( + final k={10e5,15e5,25e5}) + "Stage design capacities" + annotation (Placement(transformation(extent={{-380,300},{-360,320}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant capMin[3]( + final k={2e5,3e5,5e5}) + "Stage unload capacities" + annotation (Placement(transformation(extent={{-380,260},{-360,280}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta1( + final k=2) + "Current chiller stage" + annotation (Placement(transformation(extent={{-200,180},{-180,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq1( + final amplitude=6e5, + final freqHz=1/1800, + final offset=14e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-200,380},{-180,400}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp1( + final k=3) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{-200,140},{-180,160}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown1( + final k=1) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta2( + final k=3) + "Current chiller stage" + annotation (Placement(transformation(extent={{20,180},{40,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq2( + final amplitude=6e5, + final freqHz=1/1800, + final offset=19e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{20,380},{40,400}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp2( + final k=3) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{20,140},{40,160}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown2(final k=2) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{20,100},{40,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta3( + final k=0) + "Current chiller stage" + annotation (Placement(transformation(extent={{260,180},{280,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq4( + final amplitude=6e5, + final freqHz=1/1800, + final offset=5e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{260,380},{280,400}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp3( + final k=1) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{260,140},{280,160}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown3( + final k=0) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{260,100},{280,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta4( + final k=1) + "Current chiller stage" + annotation (Placement(transformation(extent={{-420,-310},{-400,-290}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq5( + final amplitude=6e5, + final freqHz=1/1800, + final offset=9e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-420,20},{-400,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp4( + final k=2) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{-420,-350},{-400,-330}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown4( + final k=0) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{-420,-390},{-400,-370}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant lowLim4( + final k=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-420,-20},{-400,0}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant capDes1[3]( + final k={10e5,15e5,25e5}) "Stage design capacities" + annotation (Placement(transformation(extent={{-380,-60},{-360,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant capMin1[3]( + final k={2e5,3e5,5e5}) + "Stage unload capacities" + annotation (Placement(transformation(extent={{-380,-100},{-360,-80}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta5( + final k=2) + "Current chiller stage" + annotation (Placement(transformation(extent={{-200,-310},{-180,-290}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq6( + final amplitude=6e5, + final freqHz=1/1800, + final offset=14e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-200,20},{-180,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp5( + final k=3) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{-200,-350},{-180,-330}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown5( + final k=1) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{-200,-390},{-180,-370}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta6( + final k=3) + "Current chiller stage" + annotation (Placement(transformation(extent={{20,-310},{40,-290}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq7( + final amplitude=6e5, + final freqHz=1/1800, + final offset=19e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp6( + final k=3) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{20,-350},{40,-330}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown6( + final k=2) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{20,-390},{40,-370}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curSta7( + final k=0) + "Current chiller stage" + annotation (Placement(transformation(extent={{260,-310},{280,-290}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin capReq8( + final amplitude=6e5, + final freqHz=1/1800, + final offset=5e5, + final startTime=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{260,20},{280,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staUp7( + final k=1) + "Next available chiller stage up" + annotation (Placement(transformation(extent={{260,-350},{280,-330}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staDown7( + final k=0) + "Next available chiller stage down" + annotation (Placement(transformation(extent={{260,-390},{280,-370}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant Lift( + final k=16) "Chiller lift" + annotation (Placement(transformation(extent={{-420,-130},{-400,-110}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant LiftMin( + final k=10) "Minimum chiller lift" + annotation (Placement(transformation(extent={{-420,-220},{-400,-200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant LiftMax( + final k=20) "Maximum chiller lift" + annotation (Placement(transformation(extent={{-420,-180},{-400,-160}}))); + +equation + + connect(curSta.y, PLRs0.u) annotation (Line(points={{-398,190},{-330,190},{-330, + 178},{-262,178}}, + color={255,127,0})); + connect(staUp.y, PLRs0.uUp) annotation (Line(points={{-398,150},{-320,150},{-320, + 176},{-262,176}}, color={255,127,0})); + connect(staDown.y, PLRs0.uDown) annotation (Line(points={{-398,110},{-310,110}, + {-310,174},{-262,174}}, color={255,127,0})); + connect(max.y, PLRs0.uCapReq) annotation (Line(points={{-318,370},{-290,370},{ + -290,204},{-262,204}}, color={0,0,127})); + connect(capReq3.y, max.u1) annotation (Line(points={{-398,390},{-360,390},{-360, + 376},{-342,376}}, color={0,0,127})); + connect(lowLim.y, max.u2) annotation (Line(points={{-398,350},{-360,350},{-360, + 364},{-342,364}}, color={0,0,127})); + connect(capDes[1].y, PLRs0.uCapDes) annotation (Line(points={{-358,310},{-292, + 310},{-292,202},{-262,202}}, color={0,0,127})); + connect(capDes[2].y, PLRs0.uUpCapDes) annotation (Line(points={{-358,310},{-292, + 310},{-292,200},{-262,200}}, color={0,0,127})); + connect(capMin[1].y, PLRs0.uDowCapDes) annotation (Line(points={{-358,270},{-294, + 270},{-294,198},{-262,198}}, color={0,0,127})); + connect(capMin[1].y, PLRs0.uCapMin) annotation (Line(points={{-358,270},{-294, + 270},{-294,195},{-262,195}}, color={0,0,127})); + connect(capMin[2].y, PLRs0.uUpCapMin) annotation (Line(points={{-358,270},{-296, + 270},{-296,193},{-262,193}}, color={0,0,127})); + connect(staTyp.y, PLRs0.uTyp) annotation (Line(points={{-398,230},{-310,230},{ + -310,182},{-262,182}}, color={255,127,0})); + connect(curSta1.y, PLRs1.u) + annotation (Line(points={{-178,190},{-110,190},{-110,178},{-42,178}}, + color={255,127,0})); + connect(staUp1.y, PLRs1.uUp) annotation (Line(points={{-178,150},{-100,150},{-100, + 176},{-42,176}}, color={255,127,0})); + connect(staDown1.y, PLRs1.uDown) annotation (Line(points={{-178,110},{-90,110}, + {-90,174},{-42,174}}, color={255,127,0})); + connect(max1.y, PLRs1.uCapReq) annotation (Line(points={{-98,370},{-70,370},{-70, + 204},{-42,204}}, color={0,0,127})); + connect(capReq1.y, max1.u1) annotation (Line(points={{-178,390},{-140,390},{-140, + 376},{-122,376}}, color={0,0,127})); + connect(curSta2.y,PLRs2. u) + annotation (Line(points={{42,190},{110,190},{110,178},{178,178}}, + color={255,127,0})); + connect(staUp2.y,PLRs2.uUp) annotation (Line(points={{42,150},{120,150},{120,176}, + {178,176}}, color={255,127,0})); + connect(staDown2.y,PLRs2.uDown) annotation (Line(points={{42,110},{130,110},{130, + 174},{178,174}}, color={255,127,0})); + connect(max2.y,PLRs2.uCapReq) annotation (Line(points={{122,370},{150,370},{150, + 204},{178,204}}, color={0,0,127})); + connect(capReq2.y,max2.u1) annotation (Line(points={{42,390},{80,390},{80,376}, + {98,376}}, color={0,0,127})); + connect(curSta3.y,PLRs3. u) + annotation (Line(points={{282,190},{350,190},{350,178},{418,178}}, + color={255,127,0})); + connect(staUp3.y,PLRs3.uUp) annotation (Line(points={{282,150},{360,150},{360, + 176},{418,176}}, color={255,127,0})); + connect(staDown3.y,PLRs3.uDown) annotation (Line(points={{282,110},{370,110},{ + 370,174},{418,174}}, color={255,127,0})); + connect(max3.y,PLRs3.uCapReq) annotation (Line(points={{362,370},{410,370},{410, + 204},{418,204}}, color={0,0,127})); + connect(capReq4.y,max3.u1) annotation (Line(points={{282,390},{320,390},{320,376}, + {338,376}}, color={0,0,127})); + connect(curSta4.y, PLRs4.u) annotation (Line(points={{-398,-300},{-330,-300},{ + -330,-162},{-262,-162}}, color={255,127,0})); + connect(staUp4.y, PLRs4.uUp) annotation (Line(points={{-398,-340},{-320,-340}, + {-320,-164},{-262,-164}}, color={255,127,0})); + connect(staDown4.y, PLRs4.uDown) annotation (Line(points={{-398,-380},{-310,-380}, + {-310,-166},{-262,-166}}, color={255,127,0})); + connect(max4.y, PLRs4.uCapReq) annotation (Line(points={{-318,10},{-290,10},{-290, + -136},{-262,-136}}, color={0,0,127})); + connect(capReq5.y, max4.u1) annotation (Line(points={{-398,30},{-360,30},{-360, + 16},{-342,16}}, color={0,0,127})); + connect(lowLim4.y, max4.u2) annotation (Line(points={{-398,-10},{-360,-10},{-360, + 4},{-342,4}}, color={0,0,127})); + connect(capDes1[1].y, PLRs4.uCapDes) annotation (Line(points={{-358,-50},{-292, + -50},{-292,-138},{-262,-138}}, color={0,0,127})); + connect(capDes1[2].y, PLRs4.uUpCapDes) annotation (Line(points={{-358,-50},{-292, + -50},{-292,-140},{-262,-140}}, color={0,0,127})); + connect(capMin1[1].y, PLRs4.uDowCapDes) annotation (Line(points={{-358,-90},{-294, + -90},{-294,-142},{-262,-142}}, color={0,0,127})); + connect(capMin1[1].y, PLRs4.uCapMin) annotation (Line(points={{-358,-90},{-294, + -90},{-294,-145},{-262,-145}}, color={0,0,127})); + connect(capMin1[2].y, PLRs4.uUpCapMin) annotation (Line(points={{-358,-90},{-296, + -90},{-296,-147},{-262,-147}}, color={0,0,127})); + connect(staTyp4.y, PLRs4.uTyp) annotation (Line(points={{-398,-260},{-340,-260}, + {-340,-158},{-262,-158}}, color={255,127,0})); + connect(curSta5.y,PLRs5. u) + annotation (Line(points={{-178,-300},{-110,-300},{-110,-162},{-42,-162}}, + color={255,127,0})); + connect(staUp5.y,PLRs5. uUp) annotation (Line(points={{-178,-340},{-100,-340}, + {-100,-164},{-42,-164}}, color={255,127,0})); + connect(staDown5.y,PLRs5. uDown) annotation (Line(points={{-178,-380},{-90, + -380},{-90,-166},{-42,-166}}, + color={255,127,0})); + connect(max5.y,PLRs5. uCapReq) annotation (Line(points={{-98,10},{-70,10},{ + -70,-136},{-42,-136}},color={0,0,127})); + connect(capReq6.y,max5. u1) annotation (Line(points={{-178,30},{-140,30},{-140, + 16},{-122,16}}, color={0,0,127})); + connect(curSta6.y,PLRs6. u) + annotation (Line(points={{42,-300},{110,-300},{110,-162},{178,-162}}, + color={255,127,0})); + connect(staUp6.y,PLRs6.uUp) annotation (Line(points={{42,-340},{120,-340},{ + 120,-164},{178,-164}}, + color={255,127,0})); + connect(staDown6.y,PLRs6.uDown) annotation (Line(points={{42,-380},{130,-380}, + {130,-166},{178,-166}}, color={255,127,0})); + connect(max6.y,PLRs6.uCapReq) annotation (Line(points={{122,10},{150,10},{150, + -136},{178,-136}}, color={0,0,127})); + connect(capReq7.y,max6.u1) annotation (Line(points={{42,30},{80,30},{80,16},{98, + 16}}, color={0,0,127})); + connect(curSta7.y,PLRs7. u) + annotation (Line(points={{282,-300},{350,-300},{350,-162},{418,-162}}, + color={255,127,0})); + connect(staUp7.y,PLRs7.uUp) annotation (Line(points={{282,-340},{360,-340},{ + 360,-164},{418,-164}}, + color={255,127,0})); + connect(staDown7.y,PLRs7.uDown) annotation (Line(points={{282,-380},{370,-380}, + {370,-166},{418,-166}}, color={255,127,0})); + connect(max7.y,PLRs7.uCapReq) annotation (Line(points={{362,10},{390,10},{390, + -136},{418,-136}}, color={0,0,127})); + connect(capReq8.y,max7.u1) annotation (Line(points={{282,30},{320,30},{320,16}, + {338,16}}, color={0,0,127})); + connect(capMin1[1].y,PLRs7.uCapDes) annotation (Line(points={{-358,-90},{388, + -90},{388,-138},{418,-138}}, + color={0,0,127})); + connect(capDes1[1].y,PLRs7.uUpCapDes) annotation (Line(points={{-358,-50},{ + 388,-50},{388,-140},{418,-140}}, + color={0,0,127})); + connect(capMin1[1].y,PLRs7.uDowCapDes) annotation (Line(points={{-358,-90},{ + 386,-90},{386,-142},{418,-142}}, + color={0,0,127})); + connect(capMin1[1].y,PLRs7.uCapMin) annotation (Line(points={{-358,-90},{386, + -90},{386,-145},{418,-145}}, + color={0,0,127})); + connect(capMin1[1].y,PLRs7.uUpCapMin) annotation (Line(points={{-358,-90},{ + 384,-90},{384,-147},{418,-147}}, + color={0,0,127})); + connect(staTyp.y, PLRs1.uTyp) annotation (Line(points={{-398,230},{-90,230},{-90, + 182},{-42,182}}, color={255,127,0})); + connect(staTyp.y, PLRs2.uTyp) annotation (Line(points={{-398,230},{130,230},{130, + 182},{178,182}}, color={255,127,0})); + connect(staTyp4.y, PLRs5.uTyp) annotation (Line(points={{-398,-260},{-120, + -260},{-120,-158},{-42,-158}}, + color={255,127,0})); + connect(staTyp4.y, PLRs6.uTyp) annotation (Line(points={{-398,-260},{100,-260}, + {100,-158},{178,-158}}, color={255,127,0})); + connect(staTyp4.y, PLRs7.uTyp) annotation (Line(points={{-398,-260},{340,-260}, + {340,-158},{418,-158}}, color={255,127,0})); + connect(Lift.y, PLRs4.uLif) annotation (Line(points={{-398,-120},{-360,-120}, + {-360,-150},{-262,-150}},color={0,0,127})); + connect(LiftMax.y, PLRs4.uLifMax) annotation (Line(points={{-398,-170},{-380,-170}, + {-380,-152},{-262,-152}}, color={0,0,127})); + connect(LiftMin.y, PLRs4.uLifMin) annotation (Line(points={{-398,-210},{-360,-210}, + {-360,-154},{-262,-154}}, color={0,0,127})); + connect(Lift.y, PLRs5.uLif) annotation (Line(points={{-398,-120},{-140,-120}, + {-140,-150},{-42,-150}},color={0,0,127})); + connect(LiftMax.y, PLRs5.uLifMax) annotation (Line(points={{-398,-170},{-380, + -170},{-380,-180},{-140,-180},{-140,-152},{-42,-152}}, + color={0,0,127})); + connect(LiftMin.y, PLRs5.uLifMin) annotation (Line(points={{-398,-210},{-130, + -210},{-130,-154},{-42,-154}}, + color={0,0,127})); + connect(Lift.y, PLRs6.uLif) annotation (Line(points={{-398,-120},{80,-120},{ + 80,-150},{178,-150}}, + color={0,0,127})); + connect(Lift.y, PLRs7.uLif) annotation (Line(points={{-398,-120},{320,-120},{ + 320,-150},{418,-150}}, + color={0,0,127})); + connect(LiftMax.y, PLRs6.uLifMax) annotation (Line(points={{-398,-170},{-380, + -170},{-380,-180},{80,-180},{80,-152},{178,-152}}, + color={0,0,127})); + connect(LiftMax.y, PLRs7.uLifMax) annotation (Line(points={{-398,-170},{-380, + -170},{-380,-180},{320,-180},{320,-152},{418,-152}}, + color={0,0,127})); + connect(LiftMin.y, PLRs6.uLifMin) annotation (Line(points={{-398,-210},{92, + -210},{92,-154},{178,-154}}, + color={0,0,127})); + connect(PLRs7.uLifMin, LiftMin.y) annotation (Line(points={{418,-154},{332, + -154},{332,-210},{-398,-210}}, + color={0,0,127})); + connect(staTyp.y, PLRs3.uTyp) annotation (Line(points={{-398,230},{372,230},{372, + 182},{418,182}}, color={255,127,0})); + connect(lowLim.y, max1.u2) annotation (Line(points={{-398,350},{-140,350},{-140, + 364},{-122,364}}, color={0,0,127})); + connect(lowLim.y, max2.u2) annotation (Line(points={{-398,350},{80,350},{80,364}, + {98,364}}, color={0,0,127})); + connect(lowLim.y, max3.u2) annotation (Line(points={{-398,350},{320,350},{320, + 364},{338,364}}, color={0,0,127})); + connect(lowLim4.y, max5.u2) annotation (Line(points={{-398,-10},{-140,-10},{-140, + 4},{-122,4}}, color={0,0,127})); + connect(lowLim4.y, max6.u2) annotation (Line(points={{-398,-10},{80,-10},{80,4}, + {98,4}}, color={0,0,127})); + connect(lowLim4.y, max7.u2) annotation (Line(points={{-398,-10},{320,-10},{320, + 4},{338,4}}, color={0,0,127})); + connect(capDes[2].y, PLRs1.uCapDes) annotation (Line(points={{-358,310},{-72,310}, + {-72,202},{-42,202}}, color={0,0,127})); + connect(capDes[3].y, PLRs1.uUpCapDes) annotation (Line(points={{-358,310},{-72, + 310},{-72,200},{-42,200}}, color={0,0,127})); + connect(capDes[1].y, PLRs1.uDowCapDes) annotation (Line(points={{-358,310},{-72, + 310},{-72,198},{-42,198}}, color={0,0,127})); + connect(capMin[2].y, PLRs1.uCapMin) annotation (Line(points={{-358,270},{-74,270}, + {-74,195},{-42,195}}, color={0,0,127})); + connect(capMin[3].y, PLRs1.uUpCapMin) annotation (Line(points={{-358,270},{-74, + 270},{-74,193},{-42,193}}, color={0,0,127})); + connect(capDes1[2].y, PLRs5.uCapDes) annotation (Line(points={{-358,-50},{-80, + -50},{-80,-138},{-42,-138}}, color={0,0,127})); + connect(capDes1[3].y, PLRs5.uUpCapDes) annotation (Line(points={{-358,-50},{ + -80,-50},{-80,-140},{-42,-140}}, + color={0,0,127})); + connect(capDes1[1].y, PLRs5.uDowCapDes) annotation (Line(points={{-358,-50},{ + -80,-50},{-80,-142},{-42,-142}}, + color={0,0,127})); + connect(capMin1[2].y, PLRs5.uCapMin) annotation (Line(points={{-358,-90},{-90, + -90},{-90,-145},{-42,-145}}, color={0,0,127})); + connect(capMin1[1].y, PLRs5.uUpCapMin) annotation (Line(points={{-358,-90},{ + -90,-90},{-90,-147},{-42,-147}}, + color={0,0,127})); + connect(capDes[3].y, PLRs2.uCapDes) annotation (Line(points={{-358,310},{140,310}, + {140,202},{178,202}}, color={0,0,127})); + connect(capDes[3].y, PLRs2.uUpCapDes) annotation (Line(points={{-358,310},{140, + 310},{140,200},{178,200}}, color={0,0,127})); + connect(capDes[2].y, PLRs2.uDowCapDes) annotation (Line(points={{-358,310},{140, + 310},{140,198},{178,198}}, color={0,0,127})); + connect(capMin[3].y, PLRs2.uCapMin) annotation (Line(points={{-358,270},{138,270}, + {138,195},{178,195}}, color={0,0,127})); + connect(capMin[3].y, PLRs2.uUpCapMin) annotation (Line(points={{-358,270},{138, + 270},{138,193},{178,193}}, color={0,0,127})); + connect(capDes1[3].y, PLRs6.uCapDes) annotation (Line(points={{-358,-50},{140, + -50},{140,-138},{178,-138}}, color={0,0,127})); + connect(capDes1[3].y, PLRs6.uUpCapDes) annotation (Line(points={{-358,-50},{ + 140,-50},{140,-140},{178,-140}}, + color={0,0,127})); + connect(capDes1[2].y, PLRs6.uDowCapDes) annotation (Line(points={{-358,-50},{ + 140,-50},{140,-142},{178,-142}}, + color={0,0,127})); + connect(capMin1[3].y, PLRs6.uCapMin) annotation (Line(points={{-358,-90},{130, + -90},{130,-145},{178,-145}}, color={0,0,127})); + connect(capMin1[3].y, PLRs6.uUpCapMin) annotation (Line(points={{-358,-90},{ + 130,-90},{130,-147},{178,-147}}, + color={0,0,127})); + connect(capMin[1].y, PLRs3.uCapDes) annotation (Line(points={{-358,270},{398,270}, + {398,202},{418,202}}, color={0,0,127})); + connect(capDes[1].y, PLRs3.uUpCapDes) annotation (Line(points={{-358,310},{400, + 310},{400,200},{418,200}}, color={0,0,127})); + connect(capMin[1].y, PLRs3.uDowCapDes) annotation (Line(points={{-358,270},{398, + 270},{398,198},{418,198}}, color={0,0,127})); + connect(capMin[1].y, PLRs3.uCapMin) annotation (Line(points={{-358,270},{398,270}, + {398,195},{418,195}}, color={0,0,127})); + connect(capMin[1].y, PLRs3.uUpCapMin) annotation (Line(points={{-358,270},{398, + 270},{398,193},{418,193}}, color={0,0,127})); +annotation ( + experiment(StopTime=1200.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/PartLoadRatios_u_uTyp.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.PartLoadRatios. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-480,-420},{480,420}}), + graphics={Text( + extent={{-232,102},{252,40}}, + textColor={127,127,127}, + textString="Stage types: 1 - positive displacement, 2 and 3 - constant speed centrifugal"), + Text( + extent={{-256,-372},{308,-446}}, + textColor={127,127,127}, + textString="Stage types: 1 - positive displacement, 2 - variable speed centrifugal, 3 - constant speed centrifugal")})); +end PartLoadRatios_u_uTyp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Status_u_uAva.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Status_u_uAva.mo new file mode 100644 index 00000000000..29852fd256a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Status_u_uAva.mo @@ -0,0 +1,200 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Status_u_uAva "Validates chiller stage status subsequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests chiller stage status" + annotation (Placement(transformation(extent={{-40,120},{-20,140}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta1( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests chiller stage status at the first stage" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta2( + final nSta=4, + final nChi=3, + final staMat={{0,1,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests chiller stage status with no higher stages available" + annotation (Placement(transformation(extent={{120,120},{140,140}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta3( + final nSta=4, + final nChi=3, + final staMat={{0,1,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests chiller stage status with no lower stages available" + annotation (Placement(transformation(extent={{120,40},{140,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta4( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests chiller stage status at the highest stage" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta6( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests for unavailable current stage input" + annotation (Placement(transformation(extent={{120,-60},{140,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta7( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests for unavailable current stage input, with no higher stages available" + annotation (Placement(transformation(extent={{120,-130},{140,-110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status sta5( + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests chiller stage status at zero current stage" + annotation (Placement(transformation(extent={{-40,-140},{-20,-120}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u1(final k=2) + "Chiller stage" + annotation (Placement(transformation(extent={{-140,20},{-120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u2(final k=3) + "Chiller stage" + annotation (Placement(transformation(extent={{20,100},{40,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u3(final k=1) + "Chiller stage" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u4(final k=4) + "Chiller stage" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u5(final k=2) + "Chiller stage" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u7(final k=0) + "Chiller stage" + annotation (Placement(transformation(extent={{-140,-160},{-120,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant ava[4]( + final k={true,true,true,true}) "Stage availability array" + annotation (Placement(transformation(extent={{-140,140},{-120,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant ava1[4]( + final k={false,true,true,true}) "Stage availability array" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant ava2[4]( + final k={true,false,true,false}) "Stage availability array" + annotation (Placement(transformation(extent={{20,140},{40,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant ava3[4]( + final k={true,false,true,false}) "Stage availability array" + annotation (Placement(transformation(extent={{20,60},{40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant ava6[4]( + final k={true,true,false,false}) "Stage availability array" + annotation (Placement(transformation(extent={{20,-120},{40,-100}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea "Type converter" + annotation (Placement(transformation(extent={{20,-160},{40,-140}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt "Type converter" + annotation (Placement(transformation(extent={{80,-160},{100,-140}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel( + final samplePeriod=1, + final y_start=3) "Unit delay" + annotation (Placement(transformation(extent={{50,-160},{70,-140}}))); + +equation + connect(ava.y, sta.uAva) annotation (Line(points={{-118,150},{-80,150},{-80, + 124},{-42,124}}, + color={255,0,255})); + connect(u.y, sta.u) annotation (Line(points={{-118,110},{-60,110},{-60,136},{ + -42,136}}, + color={255,127,0})); + connect(ava1.y, sta1.uAva) annotation (Line(points={{-118,70},{-80,70},{-80, + 44},{-42,44}}, + color={255,0,255})); + connect(u1.y, sta1.u) annotation (Line(points={{-118,30},{-60,30},{-60,56},{ + -42,56}}, + color={255,127,0})); + connect(ava2.y, sta2.uAva) annotation (Line(points={{42,150},{80,150},{80,124}, + {118,124}}, color={255,0,255})); + connect(u2.y, sta2.u) annotation (Line(points={{42,110},{100,110},{100,136},{ + 118,136}}, + color={255,127,0})); + connect(ava3.y, sta3.uAva) annotation (Line(points={{42,70},{80,70},{80,44},{ + 118,44}}, + color={255,0,255})); + connect(u3.y, sta3.u) annotation (Line(points={{42,30},{100,30},{100,56},{118, + 56}}, color={255,127,0})); + connect(u4.y, sta4.u) annotation (Line(points={{-118,-70},{-80,-70},{-80,-44}, + {-42,-44}}, color={255,127,0})); + connect(u5.y, sta6.u) annotation (Line(points={{42,-70},{100,-70},{100,-44},{ + 118,-44}}, + color={255,127,0})); + connect(ava6.y, sta7.uAva) annotation (Line(points={{42,-110},{80,-110},{80, + -126},{118,-126}}, + color={255,0,255})); + connect(u7.y, sta5.u) annotation (Line(points={{-118,-150},{-80,-150},{-80, + -124},{-42,-124}}, + color={255,127,0})); + connect(ava.y, sta4.uAva) annotation (Line(points={{-118,150},{-100,150},{ + -100,-56},{-42,-56}}, + color={255,0,255})); + connect(ava.y, sta5.uAva) annotation (Line(points={{-118,150},{-100,150},{ + -100,-136},{-42,-136}}, + color={255,0,255})); + connect(ava3.y, sta6.uAva) annotation (Line(points={{42,70},{60,70},{60,-56}, + {118,-56}},color={255,0,255})); + connect(intToRea.y, uniDel.u) + annotation (Line(points={{42,-150},{48,-150}}, color={0,0,127})); + connect(uniDel.y, reaToInt.u) + annotation (Line(points={{72,-150},{78,-150}}, color={0,0,127})); + connect(reaToInt.y, sta7.u) annotation (Line(points={{102,-150},{110,-150},{ + 110,-114},{118,-114}}, + color={255,127,0})); + connect(sta7.yAvaUp, intToRea.u) annotation (Line(points={{142,-113},{148,-113}, + {148,-168},{8,-168},{8,-150},{18,-150}}, color={255,127,0})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Status_u_uAva.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Status. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-180},{160,180}}))); +end Status_u_uAva; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Up.mo new file mode 100644 index 00000000000..a30a0485f89 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Up.mo @@ -0,0 +1,198 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Validation; +model Up "Validate change stage up condition sequence" + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Up + staUp(have_locSen=true, effConTruDelay=900) + "Generates stage up signal" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Up + staUp1(final have_WSE=true, have_locSen=true) + "Generates stage up signal" + annotation (Placement(transformation(extent={{140,50},{160,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant avaCur( + final k=true) + "Current stage availability" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant avaCur1( + final k=true) + "Current stage availability" + annotation (Placement(transformation(extent={{80,-70},{100,-50}}))); + + CDL.Logical.Sources.Pulse booPul(final width=0.1, + final period=3600) + "Enabled plant" + annotation (Placement(transformation(extent={{-160,-100},{-140,-80}}))); + CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{-120,-100},{-100,-80}}))); +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage0( + final k=0) "0th stage" + annotation (Placement(transformation(extent={{-160,110},{-140,130}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage1( + final k=1) "1st stage" + annotation (Placement(transformation(extent={{20,110},{40,130}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet( + final k=273.15 + 14) "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-160,-10},{-140,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet( + final k=65*6895) "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TCWSup( + final amplitude=3, + final freqHz=1/3600, + final offset=273.15 + 16) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-160,-50},{-140,-30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin dpChiWat( + final amplitude=6895, + final startTime=300, + final freqHz=1/1200, + final offset=63*6895) "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin Ope( + final phase(displayUnit="rad"), + final startTime=0, + final offset=0.85, + final freqHz=1/2100, + final amplitude=0.05) "Operating part load ratio of the current stage" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant StaUp( + final k=0.8) + "Staging part load ratio of the next stage up" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet1( + final k=273.15 + 14) "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TCWSup1( + final amplitude=3, + final offset=273.15 + 15.5, + final freqHz=1/3600) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin dpChiWat1( + final amplitude=6895, + phase=-0.78539816339745, + final startTime=300, + final freqHz=1/1200, + final offset=63*6895) "Chilled water differential pressure" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin Ope1( + final amplitude=0.1, + final phase(displayUnit="rad"), + final startTime=0, + final offset=0.85, + final freqHz=1/2100) "Operating part load ratio of the current stage" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant StaUp1( + final k=0.8) + "Staging part load ratio of the next stage up" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + +equation + + connect(StaUp.y, staUp.uStaUp) annotation (Line(points={{-98,60},{-88,60},{ + -88,69},{-42,69}}, color={0,0,127})); + connect(Ope.y, staUp.uOpe) annotation (Line(points={{-98,100},{-80,100},{-80, + 71},{-42,71}}, + color={0,0,127})); + connect(TCWSupSet.y, staUp.TChiWatSupSet) annotation (Line(points={{-138,0},{ + -80,0},{-80,67},{-42,67}}, color={0,0,127})); + connect(TCWSup.y, staUp.TChiWatSup) annotation (Line(points={{-138,-40},{-74, + -40},{-74,65},{-42,65}},color={0,0,127})); + connect(dpChiWatSet.y, staUp.dpChiWatPumSet_local) annotation (Line(points={{-98,20}, + {-68,20},{-68,63},{-42,63}}, color={0,0,127})); + connect(dpChiWat.y, staUp.dpChiWatPum_local) annotation (Line(points={{-98,-20}, + {-62,-20},{-62,61},{-42,61}}, color={0,0,127})); + connect(stage0.y, staUp.u) annotation (Line(points={{-138,120},{-56,120},{-56, + 55},{-42,55}}, color={255,127,0})); + connect(StaUp1.y, staUp1.uStaUp) annotation (Line(points={{82,60},{92,60},{92, + 69},{138,69}}, color={0,0,127})); + connect(Ope1.y, staUp1.uOpe) annotation (Line(points={{82,100},{100,100},{100, + 71},{138,71}}, color={0,0,127})); + connect(TCWSupSet1.y, staUp1.TChiWatSupSet) annotation (Line(points={{42,0},{ + 100,0},{100,67},{138,67}}, color={0,0,127})); + connect(TCWSup1.y, staUp1.TChiWatSup) annotation (Line(points={{42,-40},{106, + -40},{106,65},{138,65}}, color={0,0,127})); + connect(dpChiWatSet1.y, staUp1.dpChiWatPumSet_local) annotation (Line(points={{82,20}, + {112,20},{112,63},{138,63}}, color={0,0,127})); + connect(dpChiWat1.y, staUp1.dpChiWatPum_local) annotation (Line(points={{82,-20}, + {118,-20},{118,61},{138,61}}, color={0,0,127})); + connect(stage1.y, staUp1.u) annotation (Line(points={{42,120},{124,120},{124, + 55},{138,55}}, + color={255,127,0})); + connect(avaCur.y, staUp.uAvaCur) annotation (Line(points={{-78,-60},{-56,-60}, + {-56,53},{-42,53}}, color={255,0,255})); + connect(avaCur1.y, staUp1.uAvaCur) annotation (Line(points={{102,-60},{124, + -60},{124,53},{138,53}}, color={255,0,255})); + connect(booPul.y, not1.u) + annotation (Line(points={{-138,-90},{-122,-90}}, color={255,0,255})); + connect(not1.y, staUp.uPla) annotation (Line(points={{-98,-90},{-50,-90},{-50, + 51},{-42,51}}, color={255,0,255})); + connect(avaCur1.y, staUp1.uPla) annotation (Line(points={{102,-60},{124,-60}, + {124,51},{138,51}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Up.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences.Up. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-180,-140},{180, + 140}}), + graphics={ + Text( + extent={{-138,-110},{-76,-134}}, + textColor={0,0,127}, + textString="Tests stage 0 to stage 1 enable +based on chilled water supply +temperature. + +Other inputs are kept the same +as in the example on the right."), + Text( + extent={{46,-108},{106,-130}}, + textColor={0,0,127}, + textString="Tests stage up enable for any stage above +and including stage 1. In this test the plant has a WSE. +The same applies for any stage in case the plant does not have a WSE.")})); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..c33089f4696 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences; +package Validation "Collection of validation models" + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/package.order new file mode 100644 index 00000000000..ee24e61ea07 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/package.order @@ -0,0 +1,14 @@ +Capacities_u +Capacities_uLow_uHig +CapacityRequirement +Change +ChillerIndices_u +Configurator_uChiAva +Down +EfficiencyCondition +FailsafeCondition +Initial_WSE +Initial_noWSE +PartLoadRatios_u_uTyp +Status_u_uAva +Up diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/package.mo new file mode 100644 index 00000000000..97309c02001 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/package.mo @@ -0,0 +1,40 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints; +package Subsequences "Chiller staging subsequences" +annotation (preferredView="info", Documentation(info=" +

This package contains chiller stage setpoint control subsequences.

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/package.order new file mode 100644 index 00000000000..420994352a2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/package.order @@ -0,0 +1,13 @@ +Capacities +CapacityRequirement +Change +ChillerIndices +Configurator +Down +EfficiencyCondition +FailsafeCondition +Initial +PartLoadRatios +Status +Up +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_WSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_WSE.mo new file mode 100644 index 00000000000..6d634ed35cb --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_WSE.mo @@ -0,0 +1,434 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Validation; +model SetpointController_WSE + "Validates chiller stage status setpoint signal generation for plants with WSE" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController staSetCon( + final have_WSE=true, + final have_locSen=true, + final chiDesCap={500000,700000}, + final chiMinCap={100000,200000}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement}) + "Chiller stage setpoint controller" + annotation (Placement(transformation(extent={{60,140},{80,180}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController staSetCon1( + final have_WSE=true, + final have_locSen=true, + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{0,1,0},{1,1,0},{1,1,1}}, + final chiDesCap={300000,400000,500000}, + final chiMinCap={50000,100000,150000}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}) + "Chiller stage setpoint controller" + annotation (Placement(transformation(extent={{60,-100},{80,-60}}))); + +protected + parameter Real TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=285.15 + "Chilled water supply set temperature"; + + parameter Real aveTChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Average measured chilled water return temperature"; + + parameter Real minStaRuntime( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Minimum stage runtime"; + + parameter Real aveVChiWat_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.05 + "Average measured chilled water flow rate"; + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet( + final amplitude=7, + final offset=273.15 + 15, + final freqHz=1/21600) + "Chilled water return temeprature" + annotation (Placement(transformation(extent={{-200,140},{-180,160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow( + final offset=0, + final freqHz=1/21600, + final amplitude=0.037) + "Chilled water flow" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva[2]( + final k={true,true}) + "Chiller availability vector" + annotation (Placement(transformation(extent={{-120,200},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max "Maximum" + annotation (Placement(transformation(extent={{-160,100},{-140,120}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=10) "Zero order hold" + annotation (Placement(transformation(extent={{140,140},{160,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Integer to real conversion" + annotation (Placement(transformation(extent={{100,140},{120,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to integer conversion" + annotation (Placement(transformation(extent={{180,140},{200,160}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=100, + final falseHoldDuration=0) + "True hold to visualize the stage change initiation" + annotation (Placement(transformation(extent={{100,60},{120,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre "Pre block" + annotation (Placement(transformation(extent={{140,60},{160,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta( + final k=true) + "Plant status" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=10, + final delayOnInit=true) "True delay" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + + Buildings.Controls.OBC.CDL.Reals.AddParameter wseTPre( + final p=-3) "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{0,200},{20,220}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TCWSup( + final height=-2.1, + final duration=300, + final offset=273.15 + 16, + final startTime=1500) "Chilled water supply temperature ramp" + annotation (Placement(transformation(extent={{-120,100},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable wseSta( + final table=[0,1; 1500,1; 1500,0; 12500,0; + 12500,1; 14000,1], smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.LinearSegments) + "WSE is on during low loads, off during high loads" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr( + final t=0.5) "Greater threshold" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet1( + final amplitude=7, + final offset=273.15 + 15, + final freqHz=1/21600) + "Chilled water return temeprature" + annotation (Placement(transformation(extent={{-200,-100},{-180,-80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow1( + final offset=0, + final freqHz=1/21600, + final amplitude=0.037) + "Chilled water flow" + annotation (Placement(transformation(extent={{-200,-140},{-180,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva1[3]( + final k={true,true,true}) + "Chiller availability vector" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max1 "Maximum" + annotation (Placement(transformation(extent={{-160,-140},{-140,-120}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=10) "Zero order hold" + annotation (Placement(transformation(extent={{140,-100},{160,-80}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Type converter" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Type converter" + annotation (Placement(transformation(extent={{180,-100},{200,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1(final + trueHoldDuration=100, final falseHoldDuration=0) + "True hold to visualize the stage change initiation" + annotation (Placement(transformation(extent={{100,-180},{120,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 "Logical pre" + annotation (Placement(transformation(extent={{140,-180},{160,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta1( + final k=true) "Plant status" + annotation (Placement(transformation(extent={{-60,-180},{-40,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=10, + final delayOnInit=true) "True delay" + annotation (Placement(transformation(extent={{-20,-180},{0,-160}}))); + + Buildings.Controls.OBC.CDL.Reals.AddParameter wseTPre1( + final p=-3) + "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TCWSup1( + final height=-2.1, + final duration=300, + final offset=273.15 + 16, + final startTime=1500) "Chilled water supply temperature ramp" + annotation (Placement(transformation(extent={{-120,-140},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable wseSta1( + final table=[0,1; 1500,1; 1500,0; 12500,0; + 12500,1; 14000,1], smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.LinearSegments) + "WSE is on during low loads, off during high loads" + annotation (Placement(transformation(extent={{-60,-220},{-40,-200}}))); + + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1( + final t=0.5) "Greater than threshold" + annotation (Placement(transformation(extent={{-20,-220},{0,-200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-120,160},{-100,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zero( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp maxTowFanSpe( + final height=-0.05, + final duration=60, + final offset=1, + final startTime=13000) "Constant" + annotation (Placement(transformation(extent={{-160,180},{-140,200}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat1( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet1( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,-180},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zero1( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,-180},{-180,-160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp maxTowFanSpe1( + final height=-0.05, + final duration=60, + final offset=1, + final startTime=13000) "Constant" + annotation (Placement(transformation(extent={{-160,-60},{-140,-40}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant tunPar( + final k=0.06) + "Assume a constant tuning parameter" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Reals.AddParameter TOutWet( + final p=-10) + "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{-60,120},{-40,140}}))); + + Buildings.Controls.OBC.CDL.Reals.AddParameter TOutWet1( + final p=-10) + "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); + +equation + connect(dpChiWatSet.y, staSetCon.dpChiWatPumSet_local) annotation (Line( + points={{-98,70},{-92,70},{-92,159.048},{58,159.048}}, color={0,0,127})); + connect(dpChiWat.y, staSetCon.dpChiWatPum_local) annotation (Line(points={{-98,20}, + {-90,20},{-90,157.143},{58,157.143}}, color={0,0,127})); + connect(chiAva.y,staSetCon. uChiAva) annotation (Line(points={{-98,210},{-28, + 210},{-28,175.238},{58,175.238}}, + color={255,0,255})); + connect(zero.y,max. u2) annotation (Line(points={{-178,70},{-170,70},{-170, + 104},{-162,104}}, + color={0,0,127})); + connect(chiWatFlow.y,max. u1) annotation (Line(points={{-178,110},{-170,110}, + {-170,116},{-162,116}},color={0,0,127})); + connect(staSetCon.VChiWat_flow,max. y) annotation (Line(points={{58,140.952}, + {-130,140.952},{-130,110},{-138,110}}, + color={0,0,127})); + connect(TChiWatRet.y,staSetCon. TChiWatRet) annotation (Line(points={{-178, + 150},{-130,150},{-130,144.762},{58,144.762}}, + color={0,0,127})); + connect(staSetCon.ySta,intToRea. u) + annotation (Line(points={{82,150.476},{92,150.476},{92,150},{98,150}}, + color={255,127,0})); + connect(intToRea.y,zerOrdHol. u) + annotation (Line(points={{122,150},{138,150}}, + color={0,0,127})); + connect(zerOrdHol.y,reaToInt. u) + annotation (Line(points={{162,150},{178,150}}, + color={0,0,127})); + connect(reaToInt.y, staSetCon.uSta) annotation (Line(points={{202,150},{210, + 150},{210,100},{50,100},{50,170.476},{58,170.476}}, + color={255,127,0})); + connect(staSetCon.yChaEdg, truFalHol.u) annotation (Line(points={{82,166.667}, + {90,166.667},{90,70},{98,70}}, + color={255,0,255})); + connect(truFalHol.y,pre. u) + annotation (Line(points={{122,70},{138,70}}, color={255,0,255})); + connect(pre.y,staSetCon. chaPro) annotation (Line(points={{162,70},{170,70},{ + 170,50},{36,50},{36,177.143},{58,177.143}}, + color={255,0,255})); + connect(truDel.y,staSetCon. uPla) annotation (Line(points={{2,60},{30,60},{30, + 173.333},{58,173.333}}, + color={255,0,255})); + connect(maxTowFanSpe.y, staSetCon.uTowFanSpeMax) annotation (Line(points={{-138, + 190},{34,190},{34,147.619},{58,147.619}}, + color={0,0,127})); + connect(TCWSupSet.y, wseTPre.u) annotation (Line(points={{-98,170},{-80,170}, + {-80,216},{-16,216},{-16,210},{-2,210}}, color={0,0,127})); + connect(TCWSupSet.y, staSetCon.TChiWatSupSet) annotation (Line(points={{-98,170}, + {-20,170},{-20,167.619},{58,167.619}}, + color={0,0,127})); + connect(TCWSup.y, staSetCon.TChiWatSup) annotation (Line(points={{-98,110},{ + -70,110},{-70,165.714},{58,165.714}}, color={0,0,127})); + connect(greThr.y, staSetCon.uWseSta) annotation (Line(points={{2,20},{32,20}, + {32,179.048},{58,179.048}}, + color={255,0,255})); + connect(dpChiWatSet1.y, staSetCon1.dpChiWatPumSet_local) annotation (Line( + points={{-98,-170},{-92,-170},{-92,-80.9524},{58,-80.9524}}, color={0, + 0,127})); + connect(dpChiWat1.y, staSetCon1.dpChiWatPum_local) annotation (Line(points={{-98, + -220},{-88,-220},{-88,-82.8571},{58,-82.8571}}, color={0,0,127})); + connect(chiAva1.y, staSetCon1.uChiAva) annotation (Line(points={{-98,-30},{ + -28,-30},{-28,-64.7619},{58,-64.7619}}, + color={255,0,255})); + connect(zero1.y, max1.u2) annotation (Line(points={{-178,-170},{-170,-170},{ + -170,-136},{-162,-136}}, color={0,0,127})); + connect(chiWatFlow1.y, max1.u1) annotation (Line(points={{-178,-130},{-170, + -130},{-170,-124},{-162,-124}}, color={0,0,127})); + connect(staSetCon1.VChiWat_flow, max1.y) annotation (Line(points={{58, + -99.0476},{-130,-99.0476},{-130,-130},{-138,-130}}, + color={0,0,127})); + connect(TChiWatRet1.y, staSetCon1.TChiWatRet) annotation (Line(points={{-178, + -90},{-130,-90},{-130,-95.2381},{58,-95.2381}}, + color={0,0,127})); + connect(staSetCon1.ySta, intToRea1.u) + annotation (Line(points={{82,-89.5238},{92,-89.5238},{92,-90},{98,-90}}, + color={255,127,0})); + connect(intToRea1.y, zerOrdHol1.u) + annotation (Line(points={{122,-90},{138,-90}}, color={0,0,127})); + connect(zerOrdHol1.y, reaToInt1.u) + annotation (Line(points={{162,-90},{178,-90}}, color={0,0,127})); + connect(reaToInt1.y, staSetCon1.uSta) annotation (Line(points={{202,-90},{210, + -90},{210,-140},{50,-140},{50,-69.5238},{58,-69.5238}}, + color={255,127,0})); + connect(staSetCon1.yChaEdg, truFalHol1.u) annotation (Line(points={{82, + -73.3333},{90,-73.3333},{90,-170},{98,-170}}, + color={255,0,255})); + connect(truFalHol1.y, pre1.u) + annotation (Line(points={{122,-170},{138,-170}}, color={255,0,255})); + connect(pre1.y, staSetCon1.chaPro) annotation (Line(points={{162,-170},{170, + -170},{170,-190},{36,-190},{36,-62.8571},{58,-62.8571}}, + color={255,0,255})); + connect(plaSta1.y, truDel1.u) + annotation (Line(points={{-38,-170},{-22,-170}}, color={255,0,255})); + connect(truDel1.y, staSetCon1.uPla) annotation (Line(points={{2,-170},{26, + -170},{26,-66.6667},{58,-66.6667}}, + color={255,0,255})); + connect(maxTowFanSpe1.y, staSetCon1.uTowFanSpeMax) annotation (Line(points={{-138, + -50},{34,-50},{34,-92.381},{58,-92.381}}, + color={0,0,127})); + connect(TCWSupSet1.y, wseTPre1.u) annotation (Line(points={{-98,-70},{-80,-70}, + {-80,-24},{-16,-24},{-16,-30},{-2,-30}}, color={0,0,127})); + connect(staSetCon1.TWsePre, wseTPre1.y) annotation (Line(points={{58,-97.1429}, + {30,-97.1429},{30,-30},{22,-30}}, color={0,0,127})); + connect(TCWSupSet1.y, staSetCon1.TChiWatSupSet) annotation (Line(points={{-98,-70}, + {-20,-70},{-20,-72.381},{58,-72.381}}, + color={0,0,127})); + connect(TCWSup1.y, staSetCon1.TChiWatSup) annotation (Line(points={{-98,-130}, + {-70,-130},{-70,-74.2857},{58,-74.2857}}, + color={0,0,127})); + connect(wseSta1.y[1], greThr1.u) + annotation (Line(points={{-38,-210},{-22,-210}}, color={0,0,127})); + connect(greThr1.y, staSetCon1.uWseSta) annotation (Line(points={{2,-210},{32, + -210},{32,-60.9524},{58,-60.9524}}, + color={255,0,255})); + connect(plaSta.y, truDel.u) annotation (Line(points={{-38,60},{-22,60}}, + color={255,0,255})); + connect(wseSta.y[1], greThr.u) + annotation (Line(points={{-38,20},{-22,20}}, color={0,0,127})); + connect(tunPar.y, staSetCon.uTunPar) annotation (Line(points={{-38,100},{20, + 100},{20,149.524},{58,149.524}}, + color={0,0,127})); + connect(tunPar.y, staSetCon1.uTunPar) annotation (Line(points={{-38,100},{40, + 100},{40,-90.4762},{58,-90.4762}}, + color={0,0,127})); + connect(TCWSupSet.y, TOutWet.u) annotation (Line(points={{-98,170},{-80,170},{ + -80,130},{-62,130}}, color={0,0,127})); + connect(TOutWet.y, staSetCon.TOutWet) annotation (Line(points={{-38,130},{0, + 130},{0,151.429},{58,151.429}}, + color={0,0,127})); + connect(wseTPre.y, staSetCon.TWsePre) annotation (Line(points={{22,210},{40, + 210},{40,142.857},{58,142.857}}, + color={0,0,127})); + connect(TCWSupSet1.y, TOutWet1.u) annotation (Line(points={{-98,-70},{-80,-70}, + {-80,-120},{-62,-120}}, color={0,0,127})); + connect(TOutWet1.y, staSetCon1.TOutWet) annotation (Line(points={{-38,-120},{ + 28,-120},{28,-88.5714},{58,-88.5714}}, + color={0,0,127})); +annotation ( + experiment(StopTime=14000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_WSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-240},{220,240}}))); +end SetpointController_WSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_noWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_noWSE.mo new file mode 100644 index 00000000000..e47c43e5be2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_noWSE.mo @@ -0,0 +1,326 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Validation; +model SetpointController_noWSE + "Validates chiller stage status setpoint signal generation for plants without WSE" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController staSetCon( + have_locSen=true, + final chiDesCap={500000,700000}, + final chiMinCap={100000,200000}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement}) + "Chiller stage setpoint controller" + annotation (Placement(transformation(extent={{60,140},{84,178}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController staSetCon1( + final have_WSE=false, + have_locSen=true, + final nSta=4, + final nChi=3, + final staMat={{1,0,0},{0,1,0},{1,1,0},{1,1,1}}, + final chiDesCap={300000,400000,500000}, + final chiMinCap={50000,100000,150000}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.constantSpeedCentrifugal}) + "Chiller stage setpoint controller" + annotation (Placement(transformation(extent={{60,-100},{84,-62}}))); + +protected + Real TChiWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=285.15 + "Chilled water supply set temperature"; + + parameter Real aveTChiWatRet( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC")=288.15 + "Average measured chilled water return temperature"; + + parameter Real minStaRuntime( + final unit="s", + final quantity="Time", + displayUnit="h")=900 + "Minimum stage runtime"; + + parameter Real aveVChiWat_flow( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s")=0.05 + "Average measured chilled water flow rate"; + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol(final + trueHoldDuration=100, final falseHoldDuration=0) + "False hold to visualize the stage change initiation" + annotation (Placement(transformation(extent={{100,60},{120,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1(final + trueHoldDuration=100, final falseHoldDuration=0) + "False hold to visualize the stage change initiation" + annotation (Placement(transformation(extent={{100,-180},{120,-160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet( + final amplitude=7, + final offset=273.15 + 15, + final freqHz=1/21600) + "Chilled water return temeprature" + annotation (Placement(transformation(extent={{-200,140},{-180,160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow( + final offset=0, + final freqHz=1/21600, + final amplitude=0.037) + "Chilled water flow" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva[2]( + final k={true,true}) + "Chiller availability vector" + annotation (Placement(transformation(extent={{-120,200},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max "Maximum" + annotation (Placement(transformation(extent={{-160,80},{-140,100}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=10) "Short plant start delay" + annotation (Placement(transformation(extent={{140,140},{160,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea "Type converter" + annotation (Placement(transformation(extent={{100,140},{120,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt "Type converter" + annotation (Placement(transformation(extent={{180,140},{200,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre "Pre block" + annotation (Placement(transformation(extent={{140,60},{160,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta( + final k=true) "Plant status" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=10, + final delayOnInit=true) "True delay" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet1( + final amplitude=7, + final offset=273.15 + 15, + final freqHz=1/21600) + "Chilled water return temeprature" + annotation (Placement(transformation(extent={{-200,-100},{-180,-80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiWatFlow1( + final offset=0, + final freqHz=1/21600, + final amplitude=0.037) + "Chilled water flow" + annotation (Placement(transformation(extent={{-200,-140},{-180,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiAva1[3]( + final k={true,true,true}) + "Chiller availability vector" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Reals.Max max1 "Maximum" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=10) "Zero order hold" + annotation (Placement(transformation(extent={{140,-100},{160,-80}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 "Type converter" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 "Type converter" + annotation (Placement(transformation(extent={{180,-100},{200,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 "Pre block" + annotation (Placement(transformation(extent={{140,-180},{160,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta1( + final k=true) "Plant status" + annotation (Placement(transformation(extent={{-60,-180},{-40,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=10, + final delayOnInit=true) "True delay" + annotation (Placement(transformation(extent={{-20,-180},{0,-160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-120,160},{-100,180}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSup( + final k=273.15 + 14) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-120,100},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zero( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWat1( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSupSet1( + final k=273.15 + 14) + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,-180},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TCWSup1( + final k=273.15 + 14) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-120,-140},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zero1( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,-180},{-180,-160}}))); + +equation + connect(dpChiWatSet.y, staSetCon.dpChiWatPumSet_local) annotation (Line( + points={{-98,70},{-92,70},{-92,158.095},{57.6,158.095}}, color={0,0,127})); + connect(dpChiWat.y, staSetCon.dpChiWatPum_local) annotation (Line(points={{-98,20}, + {-90,20},{-90,156.286},{57.6,156.286}}, color={0,0,127})); + connect(TCWSupSet.y, staSetCon.TChiWatSupSet) annotation (Line(points={{-98,170}, + {-32,170},{-32,166.238},{57.6,166.238}}, + color={0,0,127})); + connect(chiAva.y, staSetCon.uChiAva) annotation (Line(points={{-98,210},{-28, + 210},{-28,173.476},{57.6,173.476}}, + color={255,0,255})); + connect(TCWSup.y, staSetCon.TChiWatSup) annotation (Line(points={{-98,110},{ + -94,110},{-94,164.429},{57.6,164.429}}, + color={0,0,127})); + connect(zero.y, max.u2) annotation (Line(points={{-178,70},{-170,70},{-170,84}, + {-162,84}}, color={0,0,127})); + connect(chiWatFlow.y, max.u1) annotation (Line(points={{-178,110},{-170,110},{ + -170,96},{-162,96}}, color={0,0,127})); + connect(staSetCon.VChiWat_flow, max.y) annotation (Line(points={{57.6,140.905}, + {-130,140.905},{-130,90},{-138,90}}, + color={0,0,127})); + connect(TChiWatRet.y, staSetCon.TChiWatRet) annotation (Line(points={{-178, + 150},{-130,150},{-130,144.524},{57.6,144.524}}, + color={0,0,127})); + connect(staSetCon.ySta, intToRea.u) + annotation (Line(points={{86.4,149.952},{92,149.952},{92,150},{98,150}}, + color={255,127,0})); + connect(intToRea.y, zerOrdHol.u) + annotation (Line(points={{122,150},{138,150}}, + color={0,0,127})); + connect(zerOrdHol.y, reaToInt.u) + annotation (Line(points={{162,150},{178,150}}, + color={0,0,127})); + connect(reaToInt.y, staSetCon.uSta) annotation (Line(points={{202,150},{210, + 150},{210,100},{50,100},{50,168.952},{57.6,168.952}}, + color={255,127,0})); + connect(staSetCon.yChaEdg, truFalHol.u) annotation (Line(points={{86.4, + 165.333},{90,165.333},{90,70},{98,70}}, + color={255,0,255})); + connect(truFalHol.y, pre.u) + annotation (Line(points={{122,70},{138,70}}, color={255,0,255})); + connect(pre.y, staSetCon.chaPro) annotation (Line(points={{162,70},{170,70},{ + 170,50},{40,50},{40,175.286},{57.6,175.286}}, + color={255,0,255})); + connect(plaSta.y, truDel.u) + annotation (Line(points={{-38,70},{-22,70}}, color={255,0,255})); + connect(truDel.y, staSetCon.uPla) annotation (Line(points={{2,70},{34,70},{34, + 171.667},{57.6,171.667}}, + color={255,0,255})); + connect(dpChiWatSet1.y, staSetCon1.dpChiWatPumSet_local) annotation (Line( + points={{-98,-170},{-92,-170},{-92,-81.9048},{57.6,-81.9048}}, color={0, + 0,127})); + connect(dpChiWat1.y, staSetCon1.dpChiWatPum_local) annotation (Line(points={{-98, + -220},{-90,-220},{-90,-83.7143},{57.6,-83.7143}}, color={0,0,127})); + connect(TCWSupSet1.y, staSetCon1.TChiWatSupSet) annotation (Line(points={{-98,-70}, + {-32,-70},{-32,-73.7619},{57.6,-73.7619}}, + color={0,0,127})); + connect(chiAva1.y, staSetCon1.uChiAva) annotation (Line(points={{-98,-30},{ + -28,-30},{-28,-66.5238},{57.6,-66.5238}}, + color={255,0,255})); + connect(TCWSup1.y, staSetCon1.TChiWatSup) annotation (Line(points={{-98,-130}, + {-94,-130},{-94,-75.5714},{57.6,-75.5714}}, + color={0,0,127})); + connect(zero1.y, max1.u2) annotation (Line(points={{-178,-170},{-170,-170},{ + -170,-156},{-162,-156}}, color={0,0,127})); + connect(chiWatFlow1.y, max1.u1) annotation (Line(points={{-178,-130},{-170, + -130},{-170,-144},{-162,-144}}, color={0,0,127})); + connect(staSetCon1.VChiWat_flow, max1.y) annotation (Line(points={{57.6, + -99.0952},{-130,-99.0952},{-130,-150},{-138,-150}}, + color={0,0,127})); + connect(TChiWatRet1.y, staSetCon1.TChiWatRet) annotation (Line(points={{-178, + -90},{-130,-90},{-130,-95.4762},{57.6,-95.4762}}, + color={0,0,127})); + connect(staSetCon1.ySta, intToRea1.u) + annotation (Line(points={{86.4,-90.0476},{92,-90.0476},{92,-90},{98,-90}}, + color={255,127,0})); + connect(intToRea1.y, zerOrdHol1.u) + annotation (Line(points={{122,-90},{138,-90}}, color={0,0,127})); + connect(zerOrdHol1.y, reaToInt1.u) + annotation (Line(points={{162,-90},{178,-90}}, color={0,0,127})); + connect(reaToInt1.y, staSetCon1.uSta) annotation (Line(points={{202,-90},{210, + -90},{210,-140},{50,-140},{50,-71.0476},{57.6,-71.0476}}, + color={255,127,0})); + connect(staSetCon1.yChaEdg, truFalHol1.u) annotation (Line(points={{86.4, + -74.6667},{90,-74.6667},{90,-170},{98,-170}}, + color={255,0,255})); + connect(truFalHol1.y, pre1.u) + annotation (Line(points={{122,-170},{138,-170}}, color={255,0,255})); + connect(pre1.y, staSetCon1.chaPro) annotation (Line(points={{162,-170},{170, + -170},{170,-190},{40,-190},{40,-64.7143},{57.6,-64.7143}}, + color={255,0,255})); + connect(plaSta1.y, truDel1.u) + annotation (Line(points={{-38,-170},{-22,-170}}, color={255,0,255})); + connect(truDel1.y, staSetCon1.uPla) annotation (Line(points={{2,-170},{34, + -170},{34,-68.3333},{57.6,-68.3333}}, + color={255,0,255})); +annotation ( + experiment( + StopTime=14000, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/SetpointController_noWSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.SetpointController. +

+", revisions=" + +"), +Icon(graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}),Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-220,-240},{220,240}}))); +end SetpointController_noWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/package.mo new file mode 100644 index 00000000000..48e9af3a874 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints; +package Validation "Collection of validation models" + + +annotation (preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.SetPoints.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/package.order new file mode 100644 index 00000000000..bcc339f4b82 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Validation/package.order @@ -0,0 +1,2 @@ +SetpointController_WSE +SetpointController_noWSE diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.mo new file mode 100644 index 00000000000..877214ea6cf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.mo @@ -0,0 +1,11 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging; +package SetPoints "Package for chiller stage setpoint control sequences" + extends Modelica.Icons.Package; + +annotation (preferredView="info", Documentation(info=" +

+This package contains chiller stage setpoint control sequences. The implementation +is based on section 5.20.4. in ASHRAE Guideline36-2021. +

+")); +end SetPoints; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.order new file mode 100644 index 00000000000..45752c2fcd2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.order @@ -0,0 +1,3 @@ +SetpointController +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.mo new file mode 100644 index 00000000000..fa6c0f926ff --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.mo @@ -0,0 +1,41 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Staging "Chiller staging sequences" +annotation (preferredView="info", Documentation(info=" +

This package contains chiller staging control sequences based on +ASHRAE Guideline36-2021.

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end Staging; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.order new file mode 100644 index 00000000000..0aa2322c4dc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.order @@ -0,0 +1,2 @@ +Processes +SetPoints diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Controller.mo new file mode 100644 index 00000000000..39dda2ebd53 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Controller.mo @@ -0,0 +1,588 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers; +block Controller "Cooling tower controller" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Integer totSta=5 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable"; + parameter Integer nTowCel=2 "Total number of cooling tower cells"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Boolean closeCoupledPlant=false + "True: the plant is close coupled, i.e. the pipe length from the chillers to cooling towers does not exceed approximately 100 feet"; + parameter Boolean have_WSE=true + "Flag to indicate if the plant has waterside economizer"; + parameter Real desCap(unit="W")=1e6 "Plant design capacity" + annotation (Dialog(group="Nominal")); + parameter Real fanSpeMin=0.1 "Minimum tower fan speed" + annotation (Dialog(group="Nominal")); + parameter Real fanSpeMax=1 "Maximum tower fan speed" + annotation (Dialog(group="Nominal")); + + // Fan speed control: when WSE is enabled + parameter Real chiMinCap[nChi]( + final unit=fill("W",nChi))={1e4,1e4} + "Minimum cyclining load below which chiller will begin cycling" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController intOpeCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Controller in the mode when WSE and chillers are enabled" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE)); + parameter Real kIntOpe=1 "Gain of controller" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE)); + parameter Real TiIntOpe(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE and (intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdIntOpe(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE and (intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController chiWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Controller in the mode when only WSE is enabled" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE)); + parameter Real kWSE=1 "Gain of controller" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE)); + parameter Real TiWSE(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE and (chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdWSE(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Fan speed", group="WSE enabled", + enable=have_WSE and (chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + // Fan speed control: controlling condenser return water temperature when WSE is not enabled + parameter Real LIFT_min[nChi]( + final unit=fill("K",nChi))={12,12} + "Minimum LIFT of each chiller" + annotation (Dialog(tab="Fan speed", group="Return temperature control")); + parameter Real TConWatSup_nominal[nChi]( + final unit=fill("K",nChi), + displayUnit=fill("degC",nChi))={293.15,293.15} + "Condenser water supply temperature (condenser entering) of each chiller" + annotation (Dialog(tab="Fan speed", group="Return temperature control")); + parameter Real TConWatRet_nominal[nChi]( + final unit=fill("K",nChi), + displayUnit=fill("degC",nChi))={303.15,303.15} + "Condenser water return temperature (condenser leaving) of each chiller" + annotation (Dialog(tab="Fan speed", group="Return temperature control")); + parameter Real TChiWatSupMin[nChi]( + final unit=fill("K",nChi), + displayUnit=fill("degC",nChi))={278.15,278.15} + "Lowest chilled water supply temperature oc each chiller" + annotation (Dialog(tab="Fan speed", group="Return temperature control")); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController couPlaCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of coupled plant controller" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=closeCoupledPlant)); + parameter Real kCouPla=1 "Gain of controller" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=closeCoupledPlant)); + parameter Real TiCouPla(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=closeCoupledPlant and (couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdCouPla(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=closeCoupledPlant and (couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + couPlaCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real yCouPlaMax=1 "Upper limit of output" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=closeCoupledPlant)); + parameter Real yCouPlaMin=0 "Lower limit of output" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=closeCoupledPlant)); + + parameter Real samplePeriod(unit="s")=30 + "Period of sampling condenser water supply and return temperature difference" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController supWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Condenser supply water temperature controller for less coupled plant" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant)); + parameter Real kSupCon=1 "Gain of controller" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant)); + parameter Real TiSupCon(unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant and (supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdSupCon(unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant and (supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + supWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real ySupConMax=1 "Upper limit of output" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant)); + parameter Real ySupConMin=0 "Lower limit of output" + annotation (Dialog(tab="Fan speed", group="Return temperature control", + enable=not closeCoupledPlant)); + parameter Real speChe=0.005 + "Lower threshold value to check fan or pump speed" + annotation (Dialog(tab="Fan speed", group="Advanced")); + parameter Real iniPlaTim(unit="s")=600 + "Time to hold return temperature at initial setpoint after plant being enabled" + annotation (Dialog(tab="Fan speed", group="Advanced")); + parameter Real ramTim(unit="s")=180 + "Time to ramp return water temperature from initial value to setpoint" + annotation (Dialog(tab="Fan speed", group="Advanced")); + parameter Real cheMinFanSpe(unit="s")=300 + "Threshold time for checking duration when tower fan equals to the minimum tower fan speed" + annotation (Dialog(tab="Fan speed", group="Advanced")); + parameter Real cheMaxTowSpe(unit="s")=300 + "Threshold time for checking duration when any enabled chiller maximum cooling speed equals to the minimum tower fan speed" + annotation (Dialog(tab="Fan speed", group="Advanced")); + parameter Real cheTowOff(unit="s")=60 + "Threshold time for checking duration when there is no enabled tower fan" + annotation (Dialog(tab="Fan speed", group="Advanced")); + + // Tower staging + parameter Real staVec[totSta]={0,0.5,1,1.5,2} + "Plant stage vector, element value like x.5 means chiller stage x plus WSE" + annotation (Dialog(tab="Tower staging", group="Nominal")); + parameter Real towCelOnSet[totSta]={0,1,1,2,2} + "Design number of tower fan cells that should be ON, according to current chiller stage and WSE status" + annotation (Dialog(tab="Tower staging")); + parameter Real chaTowCelIsoTim(unit="s")=300 + "Time to slowly change isolation valve" + annotation (Dialog(tab="Tower staging", group="Enable isolation valve")); + + // Water level control + parameter Real watLevMin( + final min=0)=0.7 + "Minimum cooling tower water level recommended by manufacturer" + annotation (Dialog(tab="Makeup water")); + parameter Real watLevMax=1 + "Maximum cooling tower water level recommended by manufacturer" + annotation (Dialog(tab="Makeup water")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput chiLoa[nChi]( + final unit=fill("W", nChi), + final quantity=fill("HeatFlowRate", nChi)) if have_WSE + "Current cooling load of each chiller" + annotation (Placement(transformation(extent={{-140,220},{-100,260}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Vector of chiller proven on status: true=ON" + annotation (Placement(transformation(extent={{-140,190},{-100,230}}), + iconTransformation(extent={{-140,150},{-100,190}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_WSE + "Waterside economizer proven on status: true=ON" + annotation (Placement(transformation(extent={{-140,160},{-100,200}}), + iconTransformation(extent={{-140,130},{-100,170}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final min=0, + final max=1, + final unit="1") "Measured fan speed of each tower cell" + annotation (Placement(transformation(extent={{-140,140},{-100,180}}), + iconTransformation(extent={{-140,110},{-100,150}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if have_WSE + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,120},{-100,160}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-140,100},{-100,140}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput reqPlaCap( + final unit="W", + final quantity="HeatFlowRate") "Current required plant capacity" + annotation (Placement(transformation(extent={{-140,80},{-100,120}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxTowSpeSet[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Maximum cooling tower speed setpoint from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-140,50},{-100,90}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowSta[nTowCel] + "Vector of tower cell proven on status: true=running tower cell" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-140,0},{-100,40}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum), + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-140,-40},{-100,0}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not closeCoupledPlant + "Condenser water supply temperature (condenser entering)" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-140,-90},{-100,-50}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage" + annotation (Placement(transformation(extent={{-140,-120},{-100,-80}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiStaSet + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-140,-140},{-100,-100}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowStaCha + "Cooling tower stage change command from plant staging process" + annotation (Placement(transformation(extent={{-140,-170},{-100,-130}}), + iconTransformation(extent={{-140,-150},{-100,-110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uIsoVal[nTowCel]( + final min=fill(0, nTowCel), + final max=fill(1, nTowCel), + final unit=fill("1", nTowCel)) + "Vector of tower cells isolation valve position" + annotation (Placement(transformation(extent={{-140,-240},{-100,-200}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput watLev + "Measured water level" + annotation (Placement(transformation(extent={{-140,-260},{-100,-220}}), + iconTransformation(extent={{-140,-210},{-100,-170}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaCel + "Lead tower cell status setpoint" + annotation (Placement(transformation(extent={{100,-50},{140,-10}}), + iconTransformation(extent={{100,90},{140,130}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yIsoVal[nTowCel]( + final min=fill(0, nTowCel), + final max=fill(1, nTowCel), + final unit=fill("1", nTowCel)) + "Cooling tower cells isolation valve position" + annotation (Placement(transformation(extent={{100,-90},{140,-50}}), + iconTransformation(extent={{100,30},{140,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowSta[nTowCel] + "Vector of tower cells status setpoint" + annotation (Placement(transformation(extent={{100,-130},{140,-90}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet[nTowCel]( + final min=fill(0, nTowCel), + final max=fill(1, nTowCel), + final unit=fill("1", nTowCel)) + "Fan speed setpoint of each cooling tower cell" + annotation (Placement(transformation(extent={{100,-170},{140,-130}}), + iconTransformation(extent={{100,-130},{140,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yMakUp + "Makeup water valve On-Off status" + annotation (Placement(transformation(extent={{100,-260},{140,-220}}), + iconTransformation(extent={{100,-190},{140,-150}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.Controller towFanSpe( + final nChi=nChi, + final nTowCel=nTowCel, + final nConWatPum=nConWatPum, + final closeCoupledPlant=closeCoupledPlant, + final have_WSE=have_WSE, + final desCap=desCap, + final fanSpeMin=fanSpeMin, + final fanSpeMax=fanSpeMax, + final chiMinCap=chiMinCap, + final intOpeCon=intOpeCon, + final kIntOpe=kIntOpe, + final TiIntOpe=TiIntOpe, + final TdIntOpe=TdIntOpe, + final chiWatCon=chiWatCon, + final kWSE=kWSE, + final TiWSE=TiWSE, + final TdWSE=TdWSE, + final LIFT_min=LIFT_min, + final TConWatSup_nominal=TConWatSup_nominal, + final samplePeriod=samplePeriod, + final cheMinFanSpe=cheMinFanSpe, + final cheMaxTowSpe=cheMaxTowSpe, + final cheTowOff=cheTowOff, + final iniPlaTim=iniPlaTim, + final ramTim=ramTim, + final TConWatRet_nominal=TConWatRet_nominal, + final TChiWatSupMin=TChiWatSupMin, + final couPlaCon=couPlaCon, + final kCouPla=kCouPla, + final TiCouPla=TiCouPla, + final TdCouPla=TdCouPla, + final yCouPlaMax=yCouPlaMax, + final yCouPlaMin=yCouPlaMin, + final supWatCon=supWatCon, + final kSupCon=kSupCon, + final TiSupCon=TiSupCon, + final TdSupCon=TdSupCon, + final ySupConMax=ySupConMax, + final ySupConMin=ySupConMin, + final speChe=speChe) "Tower fan speed" + annotation (Placement(transformation(extent={{-20,20},{0,60}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Controller towSta( + final have_WSE=have_WSE, + final nTowCel=nTowCel, + final nConWatPum=nConWatPum, + final totSta=totSta, + final staVec=staVec, + final towCelOnSet=towCelOnSet, + final chaTowCelIsoTim=chaTowCelIsoTim, + final speChe=speChe) "Cooling tower staging" + annotation (Placement(transformation(extent={{-20,-60},{0,-40}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.WaterLevel makUpWat( + final watLevMin=watLevMin, + final watLevMax=watLevMax) + "Make up water control" + annotation (Placement(transformation(extent={{-20,-250},{0,-230}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nTowCel] "Logical switch" + annotation (Placement(transformation(extent={{60,-160},{80,-140}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[nTowCel]( + final k=fill(0, nTowCel)) "Zero constant" + annotation (Placement(transformation(extent={{0,-190},{20,-170}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nTowCel) "Replicate real input" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + +equation + connect(towSta.yTowSta, yTowSta) + annotation (Line(points={{2,-54},{20,-54},{20,-110},{120,-110}}, color={255,0,255})); + connect(towSta.yIsoVal, yIsoVal) + annotation (Line(points={{2,-50},{40,-50},{40,-70},{120,-70}}, color={0,0,127})); + connect(towSta.yTowSta, swi.u2) + annotation (Line(points={{2,-54},{20,-54},{20,-150},{58,-150}}, color={255,0,255})); + connect(towFanSpe.ySpeSet, reaRep.u) + annotation (Line(points={{2,40},{18,40}}, color={0,0,127})); + connect(reaRep.y, swi.u1) + annotation (Line(points={{42,40},{50,40},{50,-142},{58,-142}}, color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{22,-180},{40,-180},{40,-158},{58,-158}}, + color={0,0,127})); + connect(towFanSpe.chiLoa, chiLoa) + annotation (Line(points={{-22,59},{-40,59},{-40,240},{-120,240}}, color={0,0,127})); + connect(towFanSpe.uChi, uChi) + annotation (Line(points={{-22,56},{-44,56},{-44,210},{-120,210}}, color={255,0,255})); + connect(towFanSpe.uWse, uWse) annotation (Line(points={{-22,53},{-48,53},{-48, + 180},{-120,180}}, color={255,0,255})); + connect(towFanSpe.uFanSpe,uFanSpe) + annotation (Line(points={{-22,50},{-52,50},{-52,160},{-120,160}}, color={0,0,127})); + connect(towFanSpe.TChiWatSup, TChiWatSup) + annotation (Line(points={{-22,47},{-56,47},{-56,140},{-120,140}}, color={0,0,127})); + connect(towFanSpe.TChiWatSupSet, TChiWatSupSet) + annotation (Line(points={{-22,44},{-60,44},{-60,120},{-120,120}}, color={0,0,127})); + connect(towFanSpe.reqPlaCap, reqPlaCap) + annotation (Line(points={{-22,41},{-64,41},{-64,100},{-120,100}}, color={0,0,127})); + connect(towFanSpe.uMaxTowSpeSet, uMaxTowSpeSet) + annotation (Line(points={{-22,38},{-68,38},{-68,70},{-120,70}}, color={0,0,127})); + connect(towFanSpe.uTow, uTowSta) annotation (Line(points={{-22,35},{-76,35},{-76, + 40},{-120,40}}, color={255,0,255})); + connect(towFanSpe.uPla, uPla) + annotation (Line(points={{-22,29},{-84,29},{-84,20},{-120,20}}, color={255,0,255})); + connect(towFanSpe.TConWatRet, TConWatRet) + annotation (Line(points={{-22,26},{-80,26},{-80,0},{-120,0}}, color={0,0,127})); + connect(towFanSpe.uConWatPumSpe, uConWatPumSpe) + annotation (Line(points={{-22,23},{-72,23},{-72,-20},{-120,-20}}, color={0,0,127})); + connect(towFanSpe.TConWatSup, TConWatSup) + annotation (Line(points={{-22,21},{-68,21},{-68,-40},{-120,-40}}, color={0,0,127})); + connect(towSta.uChiSta, uChiSta) + annotation (Line(points={{-22,-41},{-64,-41},{-64,-100},{-120,-100}}, color={255,127,0})); + connect(towSta.uIsoVal, uIsoVal) + annotation (Line(points={{-22,-57},{-40,-57},{-40,-220},{-120,-220}}, color={0,0,127})); + connect(makUpWat.watLev, watLev) + annotation (Line(points={{-22,-240},{-120,-240}}, color={0,0,127})); + connect(makUpWat.yMakUp, yMakUp) + annotation (Line(points={{2,-240},{120,-240}}, color={255,0,255})); + connect(uTowSta, towSta.uTowSta) + annotation (Line(points={{-120,40},{-76,40},{-76,-59},{-22,-59}}, color={255,0,255})); + connect(towSta.uChiStaSet, uChiStaSet) annotation (Line(points={{-22,-43},{-60, + -43},{-60,-120},{-120,-120}}, color={255,127,0})); + connect(towSta.uTowStaCha, uTowStaCha) annotation (Line(points={{-22,-45},{-56, + -45},{-56,-150},{-120,-150}}, color={255,0,255})); + connect(uWse, towSta.uWse) annotation (Line(points={{-120,180},{-48,180},{-48, + -47},{-22,-47}}, color={255,0,255})); + connect(uConWatPumSpe, towSta.uConWatPumSpe) annotation (Line(points={{-120,-20}, + {-72,-20},{-72,-53},{-22,-53}}, color={0,0,127})); + connect(towSta.yLeaCel, yLeaCel) annotation (Line(points={{2,-46},{40,-46},{40, + -30},{120,-30}}, color={255,0,255})); + connect(uEnaPla, towSta.uEnaPla) annotation (Line(points={{-120,-70},{-48,-70}, + {-48,-49},{-22,-49}}, color={255,0,255})); + connect(swi.y, ySpeSet) + annotation (Line(points={{82,-150},{120,-150}}, color={0,0,127})); + connect(uPla, towSta.uPla) annotation (Line(points={{-120,20},{-84,20},{-84,-51}, + {-22,-51}}, color={255,0,255})); +annotation ( + defaultComponentName="towCon", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-200},{100,200}}), graphics={ + Rectangle( + extent={{-100,-200},{100,200}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,248},{100,210}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,-120},{-26,-136}}, + textColor={255,0,255}, + textString="uTowStaCha"), + Text( + extent={{-100,196},{-62,184}}, + textColor={0,0,127}, + textString="chiLoa", + visible=have_WSE), + Text( + extent={{-98,-82},{-50,-98}}, + textColor={255,127,0}, + textString="uChiSta"), + Text( + extent={{-98,-100},{-32,-118}}, + textColor={255,127,0}, + textString="uChiStaSet"), + Text( + extent={{48,-160},{100,-176}}, + textColor={255,0,255}, + textString="yMakUp"), + Text( + extent={{-98,38},{-54,24}}, + textColor={255,0,255}, + textString="uTowSta"), + Text( + extent={{-98,18},{-68,4}}, + textColor={255,0,255}, + textString="uPla"), + Text( + extent={{-100,178},{-70,164}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-96,158},{-66,144}}, + textColor={255,0,255}, + textString="uWse", + visible=have_WSE), + Text( + extent={{-100,138},{-50,124}}, + textColor={0,0,127}, + textString="uFanSpe"), + Text( + extent={{-98,118},{-34,102}}, + textColor={0,0,127}, + textString="TChiWatSup", + visible=have_WSE), + Text( + extent={{-98,80},{-34,64}}, + textColor={0,0,127}, + textString="reqPlaCap"), + Text( + extent={{-96,98},{-16,82}}, + textColor={0,0,127}, + textString="TChiWatSupSet"), + Text( + extent={{-98,60},{-14,42}}, + textColor={0,0,127}, + textString="uMaxTowSpeSet"), + Text( + extent={{-96,-22},{-12,-40}}, + textColor={0,0,127}, + textString="uConWatPumSpe"), + Text( + extent={{-100,-2},{-36,-18}}, + textColor={0,0,127}, + textString="TConWatRet"), + Text( + extent={{-98,-42},{-34,-58}}, + textColor={0,0,127}, + textString="TConWatSup", + visible=not closeCoupledPlant), + Text( + extent={{-100,-178},{-56,-192}}, + textColor={0,0,127}, + textString="watLev"), + Text( + extent={{-98,-160},{-54,-176}}, + textColor={0,0,127}, + textString="uIsoVal"), + Text( + extent={{54,-100},{98,-116}}, + textColor={0,0,127}, + textString="ySpeSet"), + Text( + extent={{46,-40},{98,-56}}, + textColor={255,0,255}, + textString="yTowSta"), + Text( + extent={{54,58},{98,42}}, + textColor={0,0,127}, + textString="yIsoVal"), + Text( + extent={{48,120},{100,104}}, + textColor={255,0,255}, + textString="yLeaCel"), + Text( + extent={{-96,-64},{-58,-78}}, + textColor={255,0,255}, + textString="uEnaPla")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-260},{100,260}})), +Documentation(info=" +

+Block that controls cooling tower cells enabling status yTowSta, +the supply isolation valve positions yIsoVal of each cell and the +cell fan operating speed ySpeSet. +This is implemented according to ASHRAE Guideline36-2021, section 5.20.12. +The section specifies sequences to control cooling tower. +It includes three subsequences: +

+ +", revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Controller.mo new file mode 100644 index 00000000000..74c17aaccf0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Controller.mo @@ -0,0 +1,439 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed; +block Controller "Tower fan speed control" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Integer nTowCel=4 "Total number of cooling tower cells"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Boolean closeCoupledPlant=true + "Flag to indicate if the plant is close coupled"; + parameter Boolean have_WSE=true + "Flag to indicate if the plant has waterside economizer"; + parameter Real desCap( + final unit="W", + final quantity="HeatFlowRate")=1e6 "Plant design capacity"; + parameter Real fanSpeMin=0.1 "Minimum tower fan speed"; + parameter Real fanSpeMax=1 "Maximum tower fan speed" + annotation (Dialog(enable=have_WSE)); + parameter Real chiMinCap[nChi]( + each final unit="W", + final quantity=fill("HeatFlowRate", nChi))={1e4,1e4} + "Minimum cyclining load below which chiller will begin cycling" + annotation (Dialog(tab="WSE Enabled", group="Integrated", enable=have_WSE)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController intOpeCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="WSE Enabled", group="Integrated", enable=have_WSE)); + parameter Real kIntOpe=1 "Gain of controller" + annotation (Dialog(tab="WSE Enabled", group="Integrated",enable=have_WSE)); + parameter Real TiIntOpe(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="WSE Enabled", group="Integrated", + enable=have_WSE and (intOpeCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + intOpeCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdIntOpe(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="WSE Enabled", group="Integrated", + enable=have_WSE and (intOpeCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + intOpeCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController chiWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="WSE Enabled", group="WSE-only",enable=have_WSE)); + parameter Real kWSE=1 "Gain of controller" + annotation (Dialog(tab="WSE Enabled", group="WSE-only",enable=have_WSE)); + parameter Real TiWSE(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="WSE Enabled", group="WSE-only", + enable=have_WSE and (chiWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + chiWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdWSE(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="WSE Enabled", group="WSE-only", + enable=have_WSE and (chiWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + chiWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real LIFT_min[nChi]( + final unit=fill("K",nChi), + final quantity=fill("TemperatureDifference",nChi))={12,12} "Minimum LIFT of each chiller" + annotation (Dialog(tab="Return temperature control", group="Setpoint")); + parameter Real TConWatSup_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi))={293.15,293.15} + "Design condenser water supply temperature (condenser entering) of each chiller" + annotation (Dialog(tab="Return temperature control", group="Setpoint")); + parameter Real TConWatRet_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi))={303.15,303.15} + "Design condenser water return temperature (condenser leaving) of each chiller" + annotation (Dialog(tab="Return temperature control", group="Setpoint")); + parameter Real TChiWatSupMin[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi))={278.15,278.15} + "Lowest chilled water supply temperature of each chiller" + annotation (Dialog(tab="Return temperature control", group="Setpoint")); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController couPlaCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI "Type of controller" + annotation (Dialog(tab="Return temperature control", group="Coupled plant", + enable=closeCoupledPlant)); + parameter Real kCouPla=1 "Gain of controller" + annotation (Dialog(tab="Return temperature control", group="Coupled plant", + enable=closeCoupledPlant)); + parameter Real TiCouPla(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Return temperature control", group="Coupled plant", + enable=closeCoupledPlant and (couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdCouPla(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Return temperature control", group="Coupled plant", + enable=closeCoupledPlant and (couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real yCouPlaMax=1 "Upper limit of output" + annotation (Dialog(tab="Return temperature control", group="Coupled plant", + enable=closeCoupledPlant)); + parameter Real yCouPlaMin=0 "Lower limit of output" + annotation (Dialog(tab="Return temperature control", group="Coupled plant", + enable=closeCoupledPlant)); + parameter Real samplePeriod=30 + "Period of sampling condenser water supply and return temperature difference" + annotation (Dialog(tab="Return temperature control", group="Less coupled plant", + enable=not closeCoupledPlant)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController supWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI "Type of controller" + annotation (Dialog(tab="Return temperature control", group="Less coupled plant", + enable=not closeCoupledPlant)); + parameter Real kSupCon=1 "Gain of controller" + annotation (Dialog(tab="Return temperature control", group="Less coupled plant", + enable=not closeCoupledPlant)); + parameter Real TiSupCon(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Return temperature control", group="Less coupled plant", + enable=not closeCoupledPlant and (supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdSupCon(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Return temperature control", group="Less coupled plant", + enable=not closeCoupledPlant and (supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real ySupConMax=1 "Upper limit of output" + annotation (Dialog(tab="Return temperature control", + group="Less coupled plant", enable=not closeCoupledPlant)); + parameter Real ySupConMin=0 "Lower limit of output" + annotation (Dialog(tab="Return temperature control", + group="Less coupled plant", enable=not closeCoupledPlant)); + parameter Real speChe=0.005 "Lower threshold value to check fan or pump speed" + annotation (Dialog(tab="Advanced")); + parameter Real cheMinFanSpe(final quantity="Time", final unit="s")=300 + "Threshold time for checking duration when tower fan equals to the minimum tower fan speed" + annotation (Dialog(tab="Advanced", group="Return temperature control: Enable tower")); + parameter Real cheMaxTowSpe(final quantity="Time", final unit="s")=300 + "Threshold time for checking duration when any enabled chiller maximum cooling speed equals to the minimum tower fan speed" + annotation (Dialog(tab="Advanced", group="Return temperature control: Enable tower")); + parameter Real cheTowOff(final quantity="Time", final unit="s")=60 + "Threshold time for checking duration when there is no enabled tower fan" + annotation (Dialog(tab="Advanced", group="Return temperature control: Enable tower")); + parameter Real iniPlaTim(final quantity="Time", final unit="s")=600 + "Time to hold return temperature to initial setpoint after plant being enabled" + annotation (Dialog(tab="Advanced", group="Return temperature control: Setpoint")); + parameter Real ramTim(final quantity="Time", final unit="s")=180 + "Time to ramp return water temperature from initial value to setpoint" + annotation (Dialog(tab="Advanced", group="Return temperature control: Setpoint")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput chiLoa[nChi](final unit=fill( + "W", nChi), final quantity=fill("HeatFlowRate", nChi)) + if have_WSE "Current load of each chiller" + annotation (Placement(transformation(extent={{-140,120},{-100,160}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller enabling status: true=ON" + annotation (Placement(transformation(extent={{-140,100},{-100,140}}), + iconTransformation(extent={{-140,140},{-100,180}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_WSE + "Waterside economizer enabling status: true=ON" + annotation (Placement(transformation(extent={{-140,80},{-100,120}}), + iconTransformation(extent={{-140,110},{-100,150}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final min=0, + final max=1, + final unit="1") "Measured tower fan speed" + annotation (Placement(transformation(extent={{-140,60},{-100,100}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if have_WSE + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,40},{-100,80}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-140,10},{-100,50}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput reqPlaCap( + final unit="W", + final quantity="HeatFlowRate") "Current required plant capacity" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxTowSpeSet[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Maximum cooling tower speed setpoint from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-140,-50},{-100,-10}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTow[nTowCel] + "Cooling tower cell operating status: true=running tower cell" + annotation (Placement(transformation(extent={{-140,-80},{-100,-40}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-140,-120},{-100,-80}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-140,-140},{-100,-100}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum), + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-140,-160},{-100,-120}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not closeCoupledPlant + "Condenser water supply temperature (condenser entering)" + annotation (Placement(transformation(extent={{-140,-180},{-100,-140}}), + iconTransformation(extent={{-140,-210},{-100,-170}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") "Fan speed setpoint of each cooling tower cell" + annotation (Placement(transformation(extent={{100,-60},{140,-20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Controller + fanSpeRetTem( + final nChi=nChi, + final nTowCel=nTowCel, + final nConWatPum=nConWatPum, + final have_WSE=have_WSE, + final closeCoupledPlant=closeCoupledPlant, + final desCap=desCap, + final fanSpeMin=fanSpeMin, + final LIFT_min=LIFT_min, + final TConWatRet_nominal=TConWatRet_nominal, + final TConWatSup_nominal=TConWatSup_nominal, + final TChiWatSupMin=TChiWatSupMin, + final cheMinFanSpe=cheMinFanSpe, + final cheMaxTowSpe=cheMaxTowSpe, + final cheTowOff=cheTowOff, + final iniPlaTim=iniPlaTim, + final ramTim=ramTim, + final couPlaCon=couPlaCon, + final kCouPla=kCouPla, + final TiCouPla=TiCouPla, + final yCouPlaMax=yCouPlaMax, + final yCouPlaMin=yCouPlaMin, + final TdCouPla=TdCouPla, + final supWatCon=supWatCon, + final kSupCon=kSupCon, + final TiSupCon=TiSupCon, + final TdSupCon=TdSupCon, + final ySupConMax=ySupConMax, + final ySupConMin=ySupConMin, + final speChe=speChe) + "Fan speed control based on condenser water return temperature control" + annotation (Placement(transformation(extent={{20,-60},{60,-20}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Controller + fanSpeWse( + final nChi=nChi, + final chiMinCap=chiMinCap, + final fanSpeMin=fanSpeMin, + final intOpeCon=intOpeCon, + final kIntOpe=kIntOpe, + final TiIntOpe=TiIntOpe, + final TdIntOpe=TdIntOpe, + final fanSpeMax=fanSpeMax, + final fanSpeChe=speChe, + final chiWatCon=chiWatCon, + final kWSE=kWSE, + final TiWSE=TiWSE, + final TdWSE=TdWSE) if have_WSE + "Tower fan speed when waterside economizer is enabled" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + +equation + connect(fanSpeWse.ySpeSet, fanSpeRetTem.uTowSpeWSE) + annotation (Line(points={{-18,50},{0,50},{0,-22},{18,-22}}, color={0,0,127})); + connect(fanSpeWse.chiLoa, chiLoa) + annotation (Line(points={{-42,59},{-60,59},{-60,140},{-120,140}}, + color={0,0,127})); + connect(fanSpeWse.uChi, uChi) + annotation (Line(points={{-42,56},{-64,56},{-64,120},{-120,120}}, + color={255,0,255})); + connect(fanSpeWse.uWse, uWse) annotation (Line(points={{-42,52},{-68,52},{-68, + 100},{-120,100}}, color={255,0,255})); + connect(fanSpeWse.uFanSpe,uFanSpe) + annotation (Line(points={{-42,48},{-72,48},{-72,80},{-120,80}}, + color={0,0,127})); + connect(fanSpeWse.TChiWatSup, TChiWatSup) + annotation (Line(points={{-42,44},{-76,44},{-76,60},{-120,60}}, + color={0,0,127})); + connect(fanSpeWse.TChiWatSupSet, TChiWatSupSet) + annotation (Line(points={{-42,41},{-60,41},{-60,30},{-120,30}}, + color={0,0,127})); + connect(uChi, fanSpeRetTem.uChi) + annotation (Line(points={{-120,120},{-64,120},{-64,-25},{18,-25}}, + color={255,0,255})); + connect(uWse, fanSpeRetTem.uWse) annotation (Line(points={{-120,100},{-68,100}, + {-68,-28},{18,-28}}, color={255,0,255})); + connect(fanSpeRetTem.reqPlaCap, reqPlaCap) + annotation (Line(points={{18,-31},{-76,-31},{-76,0},{-120,0}}, + color={0,0,127})); + connect(fanSpeRetTem.uMaxTowSpeSet, uMaxTowSpeSet) + annotation (Line(points={{18,-34},{-80,-34},{-80,-30},{-120,-30}}, + color={0,0,127})); + connect(uFanSpe,fanSpeRetTem.uFanSpe) + annotation (Line(points={{-120,80},{-72,80},{-72,-37},{18,-37}}, + color={0,0,127})); + connect(fanSpeRetTem.uTow, uTow) annotation (Line(points={{18,-40},{-68,-40},{ + -68,-60},{-120,-60}}, color={255,0,255})); + connect(TChiWatSupSet, fanSpeRetTem.TChiWatSupSet) + annotation (Line(points={{-120,30},{-60,30},{-60,-46},{18,-46}}, + color={0,0,127})); + connect(fanSpeRetTem.uPla, uPla) + annotation (Line(points={{18,-49},{-60,-49},{-60,-100},{-120,-100}}, + color={255,0,255})); + connect(fanSpeRetTem.TConWatRet, TConWatRet) + annotation (Line(points={{18,-52},{-56,-52},{-56,-120},{-120,-120}}, + color={0,0,127})); + connect(fanSpeRetTem.uConWatPumSpe, uConWatPumSpe) + annotation (Line(points={{18,-55},{-52,-55},{-52,-140},{-120,-140}}, + color={0,0,127})); + connect(fanSpeRetTem.TConWatSup, TConWatSup) + annotation (Line(points={{18,-58},{-48,-58},{-48,-160},{-120,-160}}, + color={0,0,127})); + connect(fanSpeRetTem.ySpeSet,ySpeSet) + annotation (Line(points={{62,-40},{120,-40}}, + color={0,0,127})); + +annotation ( + defaultComponentName="towFanSpe", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-200},{100,200}}), + graphics={ + Rectangle( + extent={{-100,-200},{100,200}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,248},{100,210}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-100,170},{-64,154}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-100,200},{-50,182}}, + textColor={0,0,127}, + textString="chiLoa", + visible=have_WSE), + Text( + extent={{-98,110},{-48,92}}, + textColor={0,0,127}, + textString="uFanSpe"), + Text( + extent={{-100,80},{-26,64}}, + textColor={0,0,127}, + textString="TChiWatSup", + visible=have_WSE), + Text( + extent={{-98,52},{-14,34}}, + textColor={0,0,127}, + textString="TChiWatSupSet"), + Text( + extent={{-96,20},{-40,2}}, + textColor={0,0,127}, + textString="reqPlaCap"), + Text( + extent={{-100,-10},{-8,-24}}, + textColor={0,0,127}, + textString="uMaxTowSpeSet"), + Text( + extent={{-96,-130},{-28,-148}}, + textColor={0,0,127}, + textString="TConWatRet"), + Text( + extent={{-94,-158},{10,-176}}, + textColor={0,0,127}, + textString="uConWatPumSpe"), + Text( + extent={{-98,-180},{-16,-200}}, + textColor={0,0,127}, + textString="TConWatSup", + visible=not closeCoupledPlant), + Text( + extent={{48,10},{98,-8}}, + textColor={0,0,127}, + textString="ySpeSet"), + Text( + extent={{-96,140},{-60,124}}, + textColor={255,0,255}, + textString="uWse", + visible=have_WSE), + Text( + extent={{-100,-40},{-64,-56}}, + textColor={255,0,255}, + textString="uTow"), + Text( + extent={{-100,-100},{-64,-116}}, + textColor={255,0,255}, + textString="uPla")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-180},{100,160}})), +Documentation(info=" +

+Block that outputs cooling tower fan speed ySpeSet. This is implemented +according to ASHRAE Guideline36-2021, section 5.20.12.2, itema and c. +These sections specifies sequences to control tower fan speed in the mode +when waterside economizer (if the plant does have it) is enabled or disabled, for +maintaining condenser water return temperature at its setpoint. This control is +used for plants with dynamic load profiles, i.e. those for which PLR may change +by more than approximately 25% in any hour. +It includes two subsequences: +

+ +", revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Controller.mo new file mode 100644 index 00000000000..aa496eb38d4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Controller.mo @@ -0,0 +1,249 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE; +block Controller "Tower fan speed control when waterside economizer is enabled" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Real fanSpeMin=0.1 "Minimum tower fan speed"; + parameter Real fanSpeMax=1 "Maximum tower fan speed"; + parameter Real chiMinCap[nChi]( + each final unit="W", + final quantity=fill("HeatFlowRate", nChi))={1e4,1e4} + "Minimum cyclining load below which chiller will begin cycling" + annotation (Dialog(tab="Integrated operation")); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController intOpeCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Integrated operation", group="Controller")); + parameter Real kIntOpe=1 "Gain of controller" + annotation (Dialog(tab="Integrated operation", group="Controller")); + parameter Real TiIntOpe(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Integrated operation", group="Controller", + enable=intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real TdIntOpe(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Integrated operation", group="Controller", + enable=intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + intOpeCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real fanSpeChe=0.005 "Lower threshold value to check fan speed" + annotation (Dialog(tab="WSE-only")); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController chiWatCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="WSE-only", group="Controller")); + parameter Real kWSE=1 "Gain of controller" + annotation (Dialog(tab="WSE-only", group="Controller")); + parameter Real TiWSE(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="WSE-only", group="Controller", + enable=chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real TdWSE(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="WSE-only", group="Controller", + enable=chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput chiLoa[nChi]( + final unit=fill("W", nChi), + final quantity=fill("HeatFlowRate", nChi)) + "Current load of each chiller" + annotation (Placement(transformation(extent={{-140,60},{-100,100}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller enabling status: true=ON" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse + "Waterside economizer enabling status: true=ON" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final min=0, + final max=1, + final unit="1") "Measured tower fan speed" + annotation (Placement(transformation(extent={{-140,-50},{-100,-10}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,-80},{-100,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-140,-110},{-100,-70}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") + "Tower fan speed setpoint when WSE is enabled and there is any chiller running" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.IntegratedOperation + intOpe( + final nChi=nChi, + final chiMinCap=chiMinCap, + final fanSpeMin=fanSpeMin, + final fanSpeMax=fanSpeMax, + final conTyp=intOpeCon, + final k=kIntOpe, + final Ti=TiIntOpe, + final Td=TdIntOpe) + "Tower fan speed when the waterside economizer is enabled and the chillers are running" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.WSEOperation + wseOpe( + final fanSpeMin=fanSpeMin, + final fanSpeMax=fanSpeMax, + final fanSpeChe=fanSpeChe, + final chiWatCon=chiWatCon, + final k=kWSE, + final Ti=TiWSE, + final Td=TdWSE) + "Tower fan speed when the waterside economizer is running alone" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(final nin=nChi) "Logical or" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) "Zero constant" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + +equation + connect(intOpe.uChi, uChi) + annotation (Line(points={{-42,88},{-80,88},{-80,40},{-120,40}}, color={255,0,255})); + connect(intOpe.chiLoa, chiLoa) + annotation (Line(points={{-42,80},{-120,80}}, color={0,0,127})); + connect(wseOpe.uFanSpe,uFanSpe) + annotation (Line(points={{-42,-52},{-60,-52},{-60,-30},{-120,-30}}, color={0,0,127})); + connect(wseOpe.TChiWatSup, TChiWatSup) + annotation (Line(points={{-42,-60},{-120,-60}}, color={0,0,127})); + connect(wseOpe.TChiWatSupSet, TChiWatSupSet) + annotation (Line(points={{-42,-68},{-60,-68},{-60,-90},{-120,-90}}, color={0,0,127})); + connect(mulOr.y, swi.u2) + annotation (Line(points={{-18,40},{-2,40}}, color={255,0,255})); + connect(intOpe.ySpeSet, swi.u1) + annotation (Line(points={{-18,80},{-10,80},{-10,48},{-2,48}}, color={0,0,127})); + connect(wseOpe.ySpeSet, swi.u3) + annotation (Line(points={{-18,-60},{-10,-60},{-10,32},{-2,32}}, color={0,0,127})); + connect(uWse, swi1.u2) + annotation (Line(points={{-120,0},{58,0}}, color={255,0,255})); + connect(swi.y, swi1.u1) + annotation (Line(points={{22,40},{40,40},{40,8},{58,8}}, color={0,0,127})); + connect(zer.y, swi1.u3) + annotation (Line(points={{22,-30},{40,-30},{40,-8},{58,-8}}, color={0,0,127})); + connect(swi1.y,ySpeSet) + annotation (Line(points={{82,0},{120,0}}, color={0,0,127})); + connect(uChi, mulOr.u) + annotation (Line(points={{-120,40},{-42,40}}, color={255,0,255})); + connect(uWse, intOpe.uWse) + annotation (Line(points={{-120,0},{-60,0},{-60,72},{-42,72}}, color={255,0,255})); + +annotation ( + defaultComponentName="towFanSpeWse", + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Polygon( + points={{-20,80},{20,80},{0,10},{-20,80}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-40,10},{40,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-10},{-20,-80},{20,-80},{0,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,-80},{76,-94}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{76,-78},{78,-96}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{78,-78},{80,-96}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,100},{-50,82}}, + textColor={0,0,127}, + textString="chiLoa"), + Text( + extent={{-100,70},{-64,54}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-96,30},{-66,12}}, + textColor={255,0,255}, + textString="uWse"), + Text( + extent={{-96,-10},{-52,-26}}, + textColor={0,0,127}, + textString="uFanSpe"), + Text( + extent={{-96,-52},{-40,-66}}, + textColor={0,0,127}, + textString="TChiWatSup"), + Text( + extent={{-96,-82},{-24,-98}}, + textColor={0,0,127}, + textString="TChiWatSupSet"), + Text( + extent={{54,12},{98,-6}}, + textColor={0,0,127}, + textString="ySpeSet")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that outputs cooling tower fan speed ySpeSet when waterside +economizer is enabled. This is implemented according to ASHRAE Guideline36-2021, +section 5.20.12.2, item c. It includes two subsequences: +

+ +", revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/IntegratedOperation.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/IntegratedOperation.mo new file mode 100644 index 00000000000..9edd005814e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/IntegratedOperation.mo @@ -0,0 +1,317 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences; +block IntegratedOperation + "Tower fan speed control when the waterside economizer is enabled and the chillers are running" + + parameter Integer nChi = 2 "Total number of chillers"; + parameter Real chiMinCap[nChi]( + each final unit="W", + final quantity=fill("HeatFlowRate", nChi))={1e4, 1e4} + "Minimum cyclining load below which chiller will begin cycling"; + parameter Real fanSpeMin = 0.1 "Minimum cooling tower fan speed"; + parameter Real fanSpeMax = 1 "Maximum cooling tower fan speed"; + parameter Buildings.Controls.OBC.CDL.Types.SimpleController conTyp= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="Load controller")); + parameter Real k=1 "Gain of controller" + annotation (Dialog(group="Load controller")); + parameter Real Ti(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(group="Load controller", + enable=conTyp==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + conTyp==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real Td(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(group="Load controller", + enable=conTyp==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + conTyp==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real yMax=1 "Upper limit of load controller output" + annotation (Dialog(group="Load controller")); + parameter Real yMin=0 "Lower limit of load controller output" + annotation (Dialog(group="Load controller")); + parameter Real intModTim(final quantity="Time", final unit="s")=600 + "Threshold time after switching from WSE-only mode to integrated mode" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Vector of chillers proven on status: true=ON" + annotation (Placement(transformation(extent={{-200,80},{-160,120}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput chiLoa[nChi]( + final unit=fill("W", nChi), + final quantity=fill("HeatFlowRate", nChi)) "Current load of each chiller" + annotation (Placement(transformation(extent={{-200,40},{-160,80}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse + "Waterside economizer enabling status: true=ON" + annotation (Placement(transformation(extent={{-200,-20},{-160,20}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") + "Tower fan speed setpoint when WSE is enabled and there is any chiller running" + annotation (Placement(transformation(extent={{160,-100},{200,-60}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Switch fanSpe + "Switch from the holding maximum speed to regulated speed" + annotation (Placement(transformation(extent={{120,-90},{140,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiMinCycLoa[nChi]( + final k=chiMinCap) + "Minimum cycling load of each chiller" + annotation (Placement(transformation(extent={{-120,130},{-100,150}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[nChi]( + final k=fill(0, nChi)) "Zero constant" + annotation (Placement(transformation(extent={{-120,70},{-100,90}}))); + Buildings.Controls.OBC.CDL.Reals.PIDWithReset loaCon( + final controllerType=conTyp, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=yMax, + final yMin=yMin, + final reverseActing=false, + final y_reset=yMax) + "Controller to maintain chiller load at the sum of minimum cycling load of operating chillers" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum totMinCycLoa( + final k=fill(1.1, nChi), + final nin=nChi) + "Sum of minimum cycling load for the operating chillers" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum totLoa( + final nin=nChi) "Total load of operating chillers" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum minCycLoa(final nin=nChi) + "Sum of minimum cycling load for all chillers" + annotation (Placement(transformation(extent={{-20,130},{0,150}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div "Output first input divided by second input" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Reals.Divide div1 "Output first input divided by second input" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr chiOn(final nin=nChi) + "Check if there is any chiller running" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Reals.Line regFanSpe "Regulated fan speed" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1( + final k=yMin) "Load control minimum limit" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one( + final k=yMax) + "Load control maximum limit" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTowSpe( + final k=fanSpeMin) + "Minimum speed" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowSpe( + final k=fanSpeMax) + "Maximum tower fan speed" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg "Output true at the moment when input becomes true" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Check if it switches from WSE only mode to integrated operation mode" + annotation (Placement(transformation(extent={{0,-120},{20,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{40,-120},{60,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Timer intOpeTim( + final t=intModTim) + "Count the time after plant switching from WSE-only mode to integrated operation mode" + annotation (Placement(transformation(extent={{80,-120},{100,-100}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg "Output true when input becomes false" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre + "Breaks algebraic loops by an infinitesimal small time delay" + annotation (Placement(transformation(extent={{0,-150},{20,-130}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical and" + annotation (Placement(transformation(extent={{0,10},{20,30}}))); + +equation + connect(uChi, swi.u2) + annotation (Line(points={{-180,100},{-62,100}}, color={255,0,255})); + connect(chiMinCycLoa.y, swi.u1) + annotation (Line(points={{-98,140},{-80,140},{-80,108},{-62,108}}, color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{-98,80},{-80,80},{-80,92},{-62,92}}, color={0,0,127})); + connect(minCycLoa.y, div.u2) + annotation (Line(points={{2,140},{20,140},{20,94},{38,94}}, color={0,0,127})); + connect(minCycLoa.y, div1.u2) + annotation (Line(points={{2,140},{20,140},{20,54},{38,54}}, color={0,0,127})); + connect(totLoa.y, div1.u1) + annotation (Line(points={{2,60},{10,60},{10,66},{38,66}}, color={0,0,127})); + connect(totMinCycLoa.y, div.u1) + annotation (Line(points={{2,100},{10,100},{10,106},{38,106}}, color={0,0,127})); + connect(div.y, loaCon.u_s) + annotation (Line(points={{62,100},{78,100}}, color={0,0,127})); + connect(div1.y, loaCon.u_m) + annotation (Line(points={{62,60},{90,60},{90,88}}, color={0,0,127})); + connect(loaCon.y, regFanSpe.u) annotation (Line(points={{102,100},{120,100},{120, + 0},{40,0},{40,-40},{58,-40}}, color={0,0,127})); + connect(zer1.y, regFanSpe.x1) annotation (Line(points={{22,-20},{30,-20},{30,-32}, + {58,-32}}, color={0,0,127})); + connect(minTowSpe.y, regFanSpe.f1) annotation (Line(points={{-18,-20},{-10,-20}, + {-10,-36},{58,-36}}, color={0,0,127})); + connect(maxTowSpe.y, regFanSpe.f2) annotation (Line(points={{22,-60},{30,-60}, + {30,-48},{58,-48}}, color={0,0,127})); + connect(one.y, regFanSpe.x2) annotation (Line(points={{-18,-60},{-10,-60},{-10, + -44},{58,-44}}, color={0,0,127})); + connect(chiOn.y, edg.u) + annotation (Line(points={{-98,20},{-90,20},{-90,-140},{-62,-140}}, color={255,0,255})); + connect(uWse, and1.u1) + annotation (Line(points={{-180,0},{-70,0},{-70,-110},{-2,-110}}, color={255,0,255})); + connect(edg.y, and1.u2) + annotation (Line(points={{-38,-140},{-20,-140},{-20,-118},{-2,-118}}, color={255,0,255})); + connect(and1.y, lat.u) + annotation (Line(points={{22,-110},{38,-110}}, color={255,0,255})); + connect(lat.y, intOpeTim.u) + annotation (Line(points={{62,-110},{78,-110}}, color={255,0,255})); + connect(lat.y, fanSpe.u2) + annotation (Line(points={{62,-110},{70,-110},{70,-80},{118,-80}}, color={255,0,255})); + connect(regFanSpe.y, fanSpe.u3) + annotation (Line(points={{82,-40},{100,-40},{100,-88},{118,-88}}, color={0,0,127})); + connect(maxTowSpe.y, fanSpe.u1) + annotation (Line(points={{22,-60},{30,-60},{30,-72},{118,-72}}, color={0,0,127})); + connect(fanSpe.y,ySpeSet) + annotation (Line(points={{142,-80},{180,-80}}, color={0,0,127})); + connect(chiMinCycLoa.y, minCycLoa.u) + annotation (Line(points={{-98,140},{-22,140}}, color={0,0,127})); + connect(swi.y, totMinCycLoa.u) + annotation (Line(points={{-38,100},{-22,100}}, color={0,0,127})); + connect(chiLoa, totLoa.u) + annotation (Line(points={{-180,60},{-22,60}}, color={0,0,127})); + connect(uChi,chiOn. u) + annotation (Line(points={{-180,100},{-140,100},{-140,20},{-122,20}}, + color={255,0,255})); + connect(lat.y, falEdg.u) + annotation (Line(points={{62,-110},{70,-110},{70,-80},{-140,-80},{-140,-60}, + {-122,-60}}, color={255,0,255})); + connect(chiOn.y, and3.u1) + annotation (Line(points={{-98,20},{-62,20}}, color={255,0,255})); + connect(falEdg.y, and3.u2) + annotation (Line(points={{-98,-60},{-80,-60},{-80,12},{-62,12}}, + color={255,0,255})); + connect(pre.y, lat.clr) + annotation (Line(points={{22,-140},{30,-140},{30,-116},{38,-116}}, + color={255,0,255})); + connect(intOpeTim.passed, pre.u) + annotation (Line(points={{102,-118},{120,-118},{120,-154},{-10,-154}, + {-10,-140},{-2,-140}}, color={255,0,255})); + connect(and3.y, and2.u1) + annotation (Line(points={{-38,20},{-2,20}}, color={255,0,255})); + connect(uWse, and2.u2) + annotation (Line(points={{-180,0},{-20,0},{-20,12},{-2,12}}, color={255,0,255})); + connect(and2.y, loaCon.trigger) + annotation (Line(points={{22,20},{84,20},{84,88}}, color={255,0,255})); +annotation ( + defaultComponentName="wseTowSpeIntOpe", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100}, + {100,100}}), graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-40,10},{40,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{-20,80},{20,80},{0,10},{-20,80}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-10},{-20,-80},{20,-80},{0,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,-40},{80,-46}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,-56},{80,-68}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{44,-46},{48,-56}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{72,-46},{76,-56}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,-80},{76,-94}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{76,-78},{78,-96}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{78,-78},{80,-96}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-160},{160,160}})), +Documentation(info=" +

+Block that outputs cooling tower fan speed ySpeSet when both waterside +economizer and chillers are enabled, i.e. integrated operation. This is implemented +according to ASHRAE Guideline36-2021, section 5.20.12.2, item c.1. +

+

+When the waterside economizer is enabled (uWse=true) and chillers +are running (uChi=true): +

+
    +
  1. +Fan speed shall be equal to waterside economizer tower maximum speed. +
  2. +
  3. +The waterside economizer tower maximum speed shall be reset by a direct acting PID +loop maintaining the chiller load at 110% of the sum of minimum cycling load for +the operating chillers. Map the tower maximum speed from minimum speed +fanSpeMin at 0% loop output to 100% speed at 100% loop output. +Bias the loop to launch from 100% output. +
  4. +
  5. +When starting integrated operation after previously operating with only the waterside +economizer, hold the tower maximum speed at 100% for 10 minutes (intModTim) +to give the chiller time to get up to speed and produce at least minimum cycling +load, then enable the loop. +
  6. +
+", revisions=" + +")); +end IntegratedOperation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/IntegratedOperation.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/IntegratedOperation.mo new file mode 100644 index 00000000000..fcdaab6a005 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/IntegratedOperation.mo @@ -0,0 +1,116 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.Validation; +model IntegratedOperation + "Validates cooling tower fan speed control sequence for integrated operation of chillers and WSE" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.IntegratedOperation + intOpe(final nChi=2, final chiMinCap={1e4,1e4}, + k=0.5, + Ti=5) + "Tower fan speed control when chiller and waterside economizer are running" + annotation (Placement(transformation(extent={{70,-40},{90,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant wseSta(final k=true) "WSE status" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.05, final period=4000) + "Boolean pulse" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiSta "First chiller status" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta1(final k=false) + "Second chiller status" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + final amplitude=0.15*1e4, + final freqHz=1/1200, + final offset=1.1*1e4, + final startTime=100) "Chiller load" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + +equation + connect(booPul.y, chiSta.u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + connect(chiSta.y, intOpe.uChi[1]) + annotation (Line(points={{-18,80},{60,80},{60,-22.5},{68,-22.5}}, + color={255,0,255})); + connect(chiSta1.y, intOpe.uChi[2]) + annotation (Line(points={{-18,50},{60,50},{60,-21.5},{68,-21.5}}, + color={255,0,255})); + connect(con.y, intOpe.chiLoa[2]) + annotation (Line(points={{-58,-60},{40,-60},{40,-29.5},{68,-29.5}}, + color={0,0,127})); + connect(chiSta.y, swi.u2) + annotation (Line(points={{-18,80},{60,80},{60,0},{-20,0},{-20,-30}, + {-2,-30}}, color={255,0,255})); + connect(con.y, swi.u3) + annotation (Line(points={{-58,-60},{-20,-60},{-20,-38},{-2,-38}}, color={0,0,127})); + connect(sin.y, swi.u1) + annotation (Line(points={{-58,0},{-40,0},{-40,-22},{-2,-22}}, color={0,0,127})); + connect(swi.y, intOpe.chiLoa[1]) + annotation (Line(points={{22,-30},{46,-30},{46,-30.5},{68,-30.5}}, + color={0,0,127})); + connect(wseSta.y, intOpe.uWse) annotation (Line(points={{42,-80},{60,-80},{60, + -38},{68,-38}}, color={255,0,255})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/IntegratedOperation.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.IntegratedOperation. +

+

+The waterside economizer keeps operating and the chiller 1 is proven on since 200 seconds. Thus the plant +switches from the economizer only operation +to the integrated operation. +

+ +

+Note that this sequence does not control the fan speed when the ecnomizer is running only. Thus the fan +speed setpoint ySpeSet before 200 seconds is not +validate. +For the control when the economizer runs only, please see the example +in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.Validation.WSEOperation. +

+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false))); +end IntegratedOperation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/WSEOperation.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/WSEOperation.mo new file mode 100644 index 00000000000..6be6d6086ce --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/WSEOperation.mo @@ -0,0 +1,104 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.Validation; +model WSEOperation + "Validates cooling tower fan speed control sequence for WSE running only" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.WSEOperation + wseOpe( + fanSpeMin=0.1, + fanSpeMax=1, + chiWatCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI, + k=0.1, + Ti=5) + "Tower fan speed control when there is only waterside economizer is running" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiSup( + amplitude=0.5, + freqHz=1/1800, + offset=273.15 + 7.1) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiSupSet( + k=273.15 + 7) + "Chilled water supply water setpoint" + annotation (Placement(transformation(extent={{20,-40},{40,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1( + height=3, + duration=3600, + startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Discrete.UnitDelay fanSpe( + samplePeriod=1) + "Current fan speed" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + +equation + connect(chiSupSet.y, wseOpe.TChiWatSupSet) + annotation (Line(points={{42,-30},{50,-30},{50,22},{58,22}}, color={0,0,127})); + connect(chiSup.y, add2.u1) + annotation (Line(points={{-58,20},{-40,20},{-40,6},{-22,6}}, color={0,0,127})); + connect(ram1.y, add2.u2) + annotation (Line(points={{-58,-20},{-40,-20},{-40,-6},{-22,-6}}, color={0,0,127})); + connect(add2.y, wseOpe.TChiWatSup) + annotation (Line(points={{2,0},{20,0},{20,30},{58,30}}, color={0,0,127})); + connect(wseOpe.ySpeSet, fanSpe.u) annotation (Line(points={{82,30},{90,30},{90, + 80},{-30,80},{-30,60},{-22,60}}, color={0,0,127})); + connect(fanSpe.y, wseOpe.uFanSpe) annotation (Line(points={{2,60},{20,60},{20, + 38},{58,38}}, color={0,0,127})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/WSEOperation.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences.WSEOperation. +It shows following control process: +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{120,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end WSEOperation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..a9f95982c91 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/package.order new file mode 100644 index 00000000000..15a6b4c37ee --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/package.order @@ -0,0 +1,2 @@ +IntegratedOperation +WSEOperation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/WSEOperation.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/WSEOperation.mo new file mode 100644 index 00000000000..a165aa71d48 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/WSEOperation.mo @@ -0,0 +1,296 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Subsequences; +block WSEOperation + "Tower fan speed control when the waterside economizer is running alone" + + parameter Real fanSpeMin=0.1 "Minimum tower fan speed"; + parameter Real fanSpeMax=1 "Maximum tower fan speed"; + parameter Real fanSpeChe = 0.05 "Lower threshold value to check fan speed"; + parameter Buildings.Controls.OBC.CDL.Types.SimpleController chiWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(group="Chilled water controller")); + parameter Real k=1 "Gain of controller" + annotation (Dialog(group="Chilled water controller")); + parameter Real Ti(final quantity="Time", final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(group="Chilled water controller", + enable=chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real Td(final quantity="Time", final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(group="Chilled water controller", + enable=chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + chiWatCon==Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real yMax=1 + "Upper limit of chilled water controller output" + annotation (Dialog(group="Chilled water controller")); + parameter Real yMin=0 + "Lower limit of chilled water controller output" + annotation (Dialog(group="Chilled water controller")); + parameter Real cheCycOffTim(final quantity="Time", final unit="s")=300 + "Threshold time for checking if fan should cycle off" + annotation (Dialog(tab="Advanced")); + parameter Real minCycOffTim(final quantity="Time", final unit="s")=180 + "Minimum time of fan cycling off" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final unit="1") "Measured tower fan speed" + annotation (Placement(transformation(extent={{-280,106},{-240,146}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-280,-54},{-240,-14}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-280,-160},{-240,-120}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") + "Tower fan speed setpoint when WSE is enabled and there is any chiller running" + annotation (Placement(transformation(extent={{240,140},{280,180}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch fanCycOff "Cycle off fan" + annotation (Placement(transformation(extent={{100,150},{120,170}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.And and2 + "Check if the fan is at minimum speed and the chiller water supply temperature is lower than the setpoint" + annotation (Placement(transformation(extent={{0,150},{20,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTowSpe( + final k=fanSpeMin) "Minimum tower speed" + annotation (Placement(transformation(extent={{-220,30},{-200,50}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract dFanSpe + "Different between measured fan speed and the minimum fan speed" + annotation (Placement(transformation(extent={{-140,110},{-120,130}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys2( + final uLow=fanSpeChe, + final uHigh=fanSpeChe + 0.005) + "Check if tower fan speed is greater than minimum speed" + annotation (Placement(transformation(extent={{-100,110},{-80,130}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-60,110},{-40,130}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract dTChiSup + "Difference between chilled water supply temperature and its setpoint" + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys1( + final uLow=-0.1, + final uHigh=0.1) + "Check if chilled water supply temperature is greater than setpoint" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{200,150},{220,170}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys3( + final uLow=0.5*5/9, + final uHigh=1.5*5/9) + "Check if chilled water supply temperature is greater than setpoint by a threshold delta" + annotation (Placement(transformation(extent={{-160,-50},{-140,-30}}))); + Buildings.Controls.OBC.CDL.Reals.PIDWithReset chiWatTemCon( + final controllerType=chiWatCon, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=yMax, + final yMin=yMin, + final reverseActing=false, + final y_reset=0) + "Controller to maintain chilled water supply temperature at setpoint" + annotation (Placement(transformation(extent={{-140,-150},{-120,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=yMin) + "Minimum output from chilled water supply temperature control loop, default to be zero" + annotation (Placement(transformation(extent={{80,-110},{100,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one( + final k=yMax) + "Maximum output from chilled water supply temperature control loop" + annotation (Placement(transformation(extent={{-20,-190},{0,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxTowSpe( + final k=fanSpeMax) + "Maximum tower fan speed" + annotation (Placement(transformation(extent={{80,-190},{100,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Line lin + "Output the value of the input x along a line specified by two points" + annotation (Placement(transformation(extent={{160,-150},{180,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys4( + final uLow=fanSpeChe, + final uHigh=fanSpeChe + 0.005) + "Check if tower fan speed is greater than zero" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + Buildings.Controls.OBC.CDL.Logical.Not fanOff + "Check if the fan cycles off" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + Buildings.Controls.OBC.CDL.Logical.And cycOn + "Check if the fan should be turned on" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=cheCycOffTim) + "Check if the fan should cycle off" + annotation (Placement(transformation(extent={{40,150},{60,170}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay cycOffTim( + final delayTime=minCycOffTim) + "Check if the fan has been cycled off for threshold time" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + +equation + connect(uFanSpe, dFanSpe.u1) + annotation (Line(points={{-260,126},{-142,126}},color={0,0,127})); + connect(dFanSpe.y, hys2.u) + annotation (Line(points={{-118,120},{-102,120}}, color={0,0,127})); + connect(hys2.y, not2.u) + annotation (Line(points={{-78,120},{-62,120}},color={255,0,255})); + connect(TChiWatSup, dTChiSup.u1) + annotation (Line(points={{-260,-34},{-202,-34}}, color={0,0,127})); + connect(hys1.y, not1.u) + annotation (Line(points={{-78,160},{-62,160}},color={255,0,255})); + connect(dTChiSup.y, hys1.u) + annotation (Line(points={{-178,-40},{-170,-40},{-170,160},{-102,160}}, + color={0,0,127})); + connect(not1.y, and2.u1) + annotation (Line(points={{-38,160},{-2,160}},color={255,0,255})); + connect(not2.y, and2.u2) + annotation (Line(points={{-38,120},{-20,120},{-20,152},{-2,152}}, + color={255,0,255})); + connect(fanCycOff.y, swi.u2) + annotation (Line(points={{122,160},{198,160}}, color={255,0,255})); + connect(dTChiSup.y, hys3.u) + annotation (Line(points={{-178,-40},{-162,-40}}, color={0,0,127})); + connect(zer.y, lin.x1) + annotation (Line(points={{102,-100},{140,-100},{140,-132},{158,-132}}, + color={0,0,127})); + connect(chiWatTemCon.y, lin.u) + annotation (Line(points={{-118,-140},{158,-140}}, color={0,0,127})); + connect(one.y, lin.x2) + annotation (Line(points={{2,-180},{20,-180},{20,-144},{158,-144}}, + color={0,0,127})); + connect(maxTowSpe.y, lin.f2) + annotation (Line(points={{102,-180},{140,-180},{140,-148},{158,-148}}, + color={0,0,127})); + connect(lin.y, swi.u3) + annotation (Line(points={{182,-140},{190,-140},{190,152},{198,152}}, + color={0,0,127})); + connect(swi.y,ySpeSet) + annotation (Line(points={{222,160},{260,160}}, color={0,0,127})); + connect(minTowSpe.y, dFanSpe.u2) + annotation (Line(points={{-198,40},{-160,40},{-160,114},{-142,114}}, + color={0,0,127})); + connect(minTowSpe.y, lin.f1) + annotation (Line(points={{-198,40},{-100,40},{-100,-136},{158,-136}}, + color={0,0,127})); + connect(zer.y, swi.u1) + annotation (Line(points={{102,-100},{140,-100},{140,168},{198,168}}, + color={0,0,127})); + connect(TChiWatSupSet, chiWatTemCon.u_s) + annotation (Line(points={{-260,-140},{-142,-140}},color={0,0,127})); + connect(TChiWatSup, chiWatTemCon.u_m) + annotation (Line(points={{-260,-34},{-230,-34},{-230,-172},{-130,-172}, + {-130,-152}}, color={0,0,127})); + connect(TChiWatSupSet, dTChiSup.u2) + annotation (Line(points={{-260,-140},{-220,-140},{-220,-46},{-202,-46}}, + color={0,0,127})); + connect(and2.y, truDel.u) + annotation (Line(points={{22,160},{38,160}}, color={255,0,255})); + connect(truDel.y, fanCycOff.u) + annotation (Line(points={{62,160},{98,160}}, color={255,0,255})); + connect(hys4.y, fanOff.u) + annotation (Line(points={{-78,70},{-62,70}}, color={255,0,255})); + connect(hys3.y, cycOn.u2) + annotation (Line(points={{-138,-40},{20,-40},{20,62},{38,62}}, color={255,0,255})); + connect(uFanSpe, hys4.u) + annotation (Line(points={{-260,126},{-190,126},{-190,70},{-102,70}}, + color={0,0,127})); + connect(cycOn.y, fanCycOff.clr) annotation (Line(points={{62,70},{80,70},{80, + 154},{98,154}}, color={255,0,255})); + connect(fanOff.y, cycOffTim.u) + annotation (Line(points={{-38,70},{-22,70}}, color={255,0,255})); + connect(cycOffTim.y, cycOn.u1) + annotation (Line(points={{2,70},{38,70}}, color={255,0,255})); + connect(cycOn.y, chiWatTemCon.trigger) + annotation (Line(points={{62,70},{80,70},{80,-80},{-160,-80},{-160,-160}, + {-136,-160},{-136,-152}}, color={255,0,255})); + +annotation ( + defaultComponentName="wseTowSpeWSEOpe", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-40,10},{40,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{-20,80},{20,80},{0,10},{-20,80}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-10},{-20,-80},{20,-80},{0,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{40,-80},{76,-94}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{76,-78},{78,-96}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{78,-78},{80,-96}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-240,-200},{240,200}})), +Documentation(info=" +

+Block that output cooling tower fan speed yTowSpe when only waterside +economizer is running. This is implemented +according to ASHRAE Guideline36-2021, section 5.20.12.2, item c.2. +

+
    +
  1. +Fan speed shall be modulated to maintain chilled water supply temperature +TChiWatSup at setpoint TChiWatSupSet by a direct acting +PID loop that resets fan speed from minimum fanSpeMin at 0% loop output to +maximum fanSpeMax at 100% loop output. +
  2. +
  3. +If chilled water supply temperature TChiWatSup drops below setpoint +and fans have been at minimum speed fanSpeMin for 5 minutes (cheCycOffTim), +fans shall cycle off for at lease 3 minutes (minCycOffTim) and until +TChiWatSup rises above setpoint by 1 °F. +
  4. +
+", revisions=" + +")); +end WSEOperation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/package.mo new file mode 100644 index 00000000000..fc118184632 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE; +package Subsequences "Package of subsequences for tower fan speed control with waterside economizer being enabled" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for cooling tower fan speed control when the waterside +economizer is enabled. +The implementation is based on section 5.20.12.2, item c in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/package.order new file mode 100644 index 00000000000..70436fa5c3f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/package.order @@ -0,0 +1,3 @@ +IntegratedOperation +WSEOperation +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/Controller.mo new file mode 100644 index 00000000000..cf547cc1a8b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/Controller.mo @@ -0,0 +1,144 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Validation; +model Controller + "Validation sequence of controlling tower fan speed when waterside economizer is enabled" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Controller + wseOpe( + kWSE=0.1, + TiWSE=5) + "Tower fan speed control when waterside economizer is enabled" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiSupSet( + k=273.15 + 7) + "Chilled water supply water setpoint" + annotation (Placement(transformation(extent={{-100,-140},{-80,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{20,100},{40,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(k=0) + "Zero constant" + annotation (Placement(transformation(extent={{-100,80},{-80,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + amplitude=0.1*1e4, + freqHz=1/1200, + offset=1.05*1e4, + startTime=180) "Chiller load" + annotation (Placement(transformation(extent={{-100,120},{-80,140}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + width=0.5, + period=4000) + "Boolean pulse" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiSta1 "First chiller status" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta2( + k=false) "Second chiller status" + annotation (Placement(transformation(extent={{20,60},{40,80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + width=0.95, + period=3700) + "Waterside economizer enabling status" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + Buildings.Controls.OBC.CDL.Discrete.UnitDelay fanSpe( + samplePeriod=1) + "Current fan speed" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab( + table=[0,280.4; 400,279.9; 1000,281.65; 1600,280.4], + smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.HoldLastPoint) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + +equation + connect(booPul1.y, chiSta1.u) + annotation (Line(points={{-78,40},{-42,40}}, color={255,0,255})); + connect(con1.y, swi1.u3) + annotation (Line(points={{-78,90},{-60,90},{-60,102},{18,102}}, color={0,0,127})); + connect(sin.y, swi1.u1) + annotation (Line(points={{-78,130},{-60,130},{-60,118},{18,118}}, color={0,0,127})); + connect(chiSta1.y, swi1.u2) + annotation (Line(points={{-18,40},{0,40},{0,110},{18,110}}, color={255,0,255})); + connect(chiSta2.y, wseOpe.uChi[2]) + annotation (Line(points={{42,70},{70,70},{70,6},{98,6}}, color={255,0,255})); + connect(chiSta1.y, wseOpe.uChi[1]) + annotation (Line(points={{-18,40},{70,40},{70,6},{98,6}}, color={255,0,255})); + connect(swi1.y, wseOpe.chiLoa[1]) + annotation (Line(points={{42,110},{80,110},{80,9},{98,9}}, color={0,0,127})); + connect(con1.y, wseOpe.chiLoa[2]) + annotation (Line(points={{-78,90},{-60,90},{-60,9},{98,9}}, color={0,0,127})); + connect(wseSta.y, wseOpe.uWse) + annotation (Line(points={{-18,-30},{40,-30},{40,2},{98,2}}, color={255,0,255})); + connect(chiSupSet.y, wseOpe.TChiWatSupSet) + annotation (Line(points={{-78,-130},{70,-130},{70,-9},{98,-9}}, color={0,0,127})); + connect(wseOpe.ySpeSet, fanSpe.u) annotation (Line(points={{122,0},{130,0},{130, + -80},{-110,-80},{-110,-60},{-102,-60}}, color={0,0,127})); + connect(fanSpe.y, wseOpe.uFanSpe) annotation (Line(points={{-78,-60},{50,-60}, + {50,-2},{98,-2}},color={0,0,127})); + connect(timTab.y[1], wseOpe.TChiWatSup) annotation (Line(points={{-38,-100},{60, + -100},{60,-6},{98,-6}},color={0,0,127})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE.Controller. +

+

+In this example, at 2000 seconds the plant changes from economizer-only mode to integration mode which +have both the chiller and economizer operating. It then changes to chiller-only mode at 3530 seconds. +It implements following processes: +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-140,-160},{140,160}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/package.mo new file mode 100644 index 00000000000..cae386b1b2d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.EnabledWSE. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/package.mo new file mode 100644 index 00000000000..5212406ac84 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed; +package EnabledWSE "Package of sequences for control tower fan speed when waterside economizer is enabled" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains sequences for cooling tower fan speed control when the waterside +economizer is enabled. +The implementation is based on section 5.20.12.2, item c in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end EnabledWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Controller.mo new file mode 100644 index 00000000000..701f54705ec --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Controller.mo @@ -0,0 +1,659 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature; +block Controller + "Cooling tower speed control to maintain condenser water return temperature at setpoint" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Integer nTowCel=4 "Total number of cooling tower cells"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Boolean have_WSE=true "Flag to indicate if the plant has waterside economizer"; + parameter Boolean closeCoupledPlant=true "Flag to indicate if the plant is close coupled"; + parameter Real desCap( + final unit="W", + final quantity="HeatFlowRate")= 1e6 "Plant design capacity"; + parameter Real fanSpeMin=0.1 "Minimum tower fan speed"; + parameter Real LIFT_min[nChi]( + final unit=fill("K",nChi), + final quantity=fill("TemperatureDifference",nChi))={12,12} "Minimum LIFT of each chiller" + annotation (Dialog(tab="Setpoint")); + parameter Real TConWatSup_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi))={293.15,293.15} + "Design condenser water supply temperature (condenser entering) of each chiller" + annotation (Dialog(tab="Setpoint")); + parameter Real TConWatRet_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi))={303.15, 303.15} + "Design condenser water return temperature (condenser leaving) of each chiller" + annotation (Dialog(tab="Setpoint")); + parameter Real TChiWatSupMin[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi)) = {278.15, 278.15} + "Lowest chilled water supply temperature of each chiller" + annotation (Dialog(tab="Setpoint")); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController couPlaCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Coupled plant", group="Controller", enable=closeCoupledPlant)); + parameter Real kCouPla=1 "Gain of controller" + annotation (Dialog(tab="Coupled plant", group="Controller", enable=closeCoupledPlant)); + parameter Real TiCouPla( + final quantity="Time", + final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Coupled plant", + group="Controller", + enable=closeCoupledPlant and (couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdCouPla( + final quantity="Time", + final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Coupled plant", group="Controller", + enable=closeCoupledPlant and (couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + couPlaCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real yCouPlaMax=1 "Upper limit of output" + annotation (Dialog(tab="Coupled plant", group="Controller", enable=closeCoupledPlant)); + parameter Real yCouPlaMin=0 "Lower limit of output" + annotation (Dialog(tab="Coupled plant", group="Controller", enable=closeCoupledPlant)); + + parameter Real samplePeriod=30 + "Period of sampling condenser water supply and return temperature difference" + annotation (Dialog(tab="Less coupled plant", + group="Return water temperature controller", + enable=not closeCoupledPlant)); + parameter Buildings.Controls.OBC.CDL.Types.SimpleController supWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI "Type of controller" + annotation (Dialog(tab="Less coupled plant", + group="Supply water temperature controller", + enable=not closeCoupledPlant)); + parameter Real kSupCon=1 "Gain of controller" + annotation (Dialog(tab="Less coupled plant", + group="Supply water temperature controller", + enable=not closeCoupledPlant)); + parameter Real TiSupCon( + final quantity="Time", + final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Less coupled plant", + group="Supply water temperature controller", + enable=not closeCoupledPlant and (supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or + supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real TdSupCon( + final quantity="Time", + final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Less coupled plant", + group="Supply water temperature controller", + enable=not closeCoupledPlant and (supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + parameter Real ySupConMax=1 "Upper limit of output" + annotation (Dialog(tab="Less coupled plant", + group="Supply water temperature controller", + enable=not closeCoupledPlant)); + parameter Real ySupConMin=0 "Lower limit of output" + annotation (Dialog(tab="Less coupled plant", + group="Supply water temperature controller", + enable=not closeCoupledPlant)); + + parameter Real speChe=0.01 "Lower threshold value to check fan or pump speed" + annotation (Dialog(tab="Advanced")); + parameter Real cheMinFanSpe( + final quantity="Time", + final unit="s")=300 + "Threshold time for checking duration when tower fan equals to the minimum tower fan speed" + annotation (Dialog(tab="Advanced", group="Enable tower")); + parameter Real cheMaxTowSpe( + final quantity="Time", + final unit="s")=300 + "Threshold time for checking duration when any enabled chiller maximum cooling speed equals to the minimum tower fan speed" + annotation (Dialog(tab="Advanced", group="Enable tower")); + parameter Real cheTowOff( + final quantity="Time", + final unit="s")=60 + "Threshold time for checking duration when there is no enabled tower fan" + annotation (Dialog(tab="Advanced", group="Enable tower")); + parameter Real iniPlaTim( + final quantity="Time", + final unit="s")=600 + "Time to hold return temperature to initial setpoint after plant being enabled" + annotation (Dialog(tab="Advanced", + group="Setpoint: Plant startup")); + parameter Real ramTim( + final quantity="Time", + final unit="s")=180 + "Time to ramp return water temperature from initial value to setpoint" + annotation (Dialog(tab="Advanced", + group="Setpoint: Plant startup")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uTowSpeWSE( + final min=0, + final max=1, + final unit="1") if have_WSE + "Cooling tower speed when the waterside economizer is enabled" + annotation (Placement(transformation(extent={{-200,220},{-160,260}}), + iconTransformation(extent={{-240,160},{-200,200}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller enabling status: true=ON" + annotation (Placement(transformation(extent={{-200,190},{-160,230}}), + iconTransformation(extent={{-240,130},{-200,170}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_WSE + "Waterside economizer status: true=ON" + annotation (Placement(transformation(extent={{-200,150},{-160,190}}), + iconTransformation(extent={{-240,100},{-200,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput reqPlaCap( + final unit="W", + final quantity="HeatFlowRate") "Current required plant capacity" + annotation (Placement(transformation(extent={{-200,80},{-160,120}}), + iconTransformation(extent={{-240,70},{-200,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxTowSpeSet[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Maximum cooling tower speed setpoint from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-200,20},{-160,60}}), + iconTransformation(extent={{-240,40},{-200,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final min=0, + final max=1, + final unit="1") "Measured speed of current enabled tower fans" + annotation (Placement(transformation(extent={{-200,-10},{-160,30}}), + iconTransformation(extent={{-240,10},{-200,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTow[nTowCel] + "Cooling tower operating status: true=running tower cell" + annotation (Placement(transformation(extent={{-200,-50},{-160,-10}}), + iconTransformation(extent={{-240,-20},{-200,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final quantity="ThermodynamicTemperature", + displayUnit="degC", + final unit="K") "Chilled water supply setpoint temperature" + annotation (Placement(transformation(extent={{-200,-100},{-160,-60}}), + iconTransformation(extent={{-240,-80},{-200,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-200,-140},{-160,-100}}), + iconTransformation(extent={{-240,-110},{-200,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final quantity="ThermodynamicTemperature", + displayUnit="degC", + final unit="K") "Condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-200,-180},{-160,-140}}), + iconTransformation(extent={{-240,-140},{-200,-100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum), + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-200,-220},{-160,-180}}), + iconTransformation(extent={{-240,-170},{-200,-130}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatSup( + final quantity="ThermodynamicTemperature", + displayUnit="degC", + final unit="K") if not closeCoupledPlant + "Condenser water supply temperature (condenser entering)" + annotation (Placement(transformation(extent={{-200,-300},{-160,-260}}), + iconTransformation(extent={{-240,-200},{-200,-160}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") "Fan speed setpoint of each cooling tower cell" + annotation (Placement(transformation(extent={{160,190},{200,230}}), + iconTransformation(extent={{200,-20},{240,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TConWatSupSet( + final quantity="ThermodynamicTemperature", + displayUnit="degC", + final unit="K") if not closeCoupledPlant + "Condenser water supply temperature setpoint" + annotation (Placement(transformation(extent={{160,-232},{200,-192}}), + iconTransformation(extent={{200,-210},{240,-170}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Setpoint conWatRetSet( + final nChi=nChi, + final LIFT_min=LIFT_min, + final iniPlaTim=iniPlaTim, + final ramTim=ramTim, + final TConWatRet_nominal=TConWatRet_nominal, + final TChiWatSupMin=TChiWatSupMin) "Return temperature setpoint" + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Enable enaTow( + final nChi=nChi, + final nTowCel=nTowCel, + final fanSpeChe=speChe, + final fanSpeMin=fanSpeMin, + final cheMinFanSpe=cheMinFanSpe, + final cheMaxTowSpe=cheMaxTowSpe, + final cheTowOff=cheTowOff) "Enable and disable cooling tower fans" + annotation (Placement(transformation(extent={{40,10},{60,30}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Coupled + couTowSpe( + final nChi=nChi, + final nConWatPum=nConWatPum, + final fanSpeMin=fanSpeMin, + final pumSpeChe=speChe, + final controllerType=couPlaCon, + final k=kCouPla, + final Ti=TiCouPla, + final Td=TdCouPla, + final yMax=yCouPlaMax, + final yMin=yCouPlaMin) if closeCoupledPlant + "Tower fan speed control when the plant is close coupled" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.LessCoupled + lesCouTowSpe( + final nChi=nChi, + final nConWatPum=nConWatPum, + final pumSpeChe=speChe, + final fanSpeMin=fanSpeMin, + final samplePeriod=samplePeriod, + final iniPlaTim=iniPlaTim, + final TConWatSup_nominal=TConWatSup_nominal, + final TConWatRet_nominal=TConWatRet_nominal, + final supWatCon=supWatCon, + final kSupCon=kSupCon, + final TiSupCon=TiSupCon, + final TdSupCon=TdSupCon, + final ySupConMax=ySupConMax, + final ySupConMin=ySupConMin) if not closeCoupledPlant + "Tower fan speed control when the plant is not close coupled" + annotation (Placement(transformation(extent={{40,-230},{60,-210}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChi) "Check if any chiller is enabled" + annotation (Placement(transformation(extent={{-120,200},{-100,220}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 if have_WSE + "Waterside economizer is not enabled" + annotation (Placement(transformation(extent={{-120,160},{-100,180}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "Any chiller is enabled and waterside economizer is not enabled" + annotation (Placement(transformation(extent={{-20,200},{0,220}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter parLoaRat( + final k=1/desCap) "Plant partial load ratio" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Reals.Line plrTowMaxSpe + "Tower maximum speed resetted by partial load ratio" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Switch the speed when the fan is enabled or disabled " + annotation (Placement(transformation(extent={{120,10},{140,30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Switch between when waterside economizer is enabled and disabled" + annotation (Placement(transformation(extent={{100,200},{120,220}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant lowPlrTowMaxSpe( + final k=0.7) + "Lower bound of tower maximum speed" + annotation (Placement(transformation(extent={{-120,130},{-100,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) "Zero constant" + annotation (Placement(transformation(extent={{-60,130},{-40,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal( + final k=0.5) "Constant 0.5" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant uppPlrTowMaxSpe( + final k=1) + "Upper bound of tower maximum speed" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant tru( + final k=true) if not have_WSE "True constant" + annotation (Placement(transformation(extent={{-80,160},{-60,180}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2( + final k=0) if not have_WSE + "Zero constant" + annotation (Placement(transformation(extent={{40,160},{60,180}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis proOn[nConWatPum]( + final uLow=fill(speChe, nConWatPum), + final uHigh=fill(2*speChe, nConWatPum)) + "Check if the condenser water pump is proven on" + annotation (Placement(transformation(extent={{-140,-270},{-120,-250}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nConWatPum] + "Convert boolean input to integer output" + annotation (Placement(transformation(extent={{-100,-270},{-80,-250}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nConWatPum) "Sum up integer inputs" + annotation (Placement(transformation(extent={{-40,-270},{-20,-250}}))); + +equation + connect(uWse, not1.u) + annotation (Line(points={{-180,170},{-122,170}}, color={255,0,255})); + connect(mulOr.y, and2.u1) + annotation (Line(points={{-98,210},{-22,210}}, color={255,0,255})); + connect(not1.y, and2.u2) + annotation (Line(points={{-98,170},{-90,170},{-90,202},{-22,202}}, + color={255,0,255})); + connect(reqPlaCap, parLoaRat.u) + annotation (Line(points={{-180,100},{-122,100}}, color={0,0,127})); + connect(zer.y, plrTowMaxSpe.x1) + annotation (Line(points={{-38,140},{-30,140},{-30,108},{-22,108}}, + color={0,0,127})); + connect(lowPlrTowMaxSpe.y, plrTowMaxSpe.f1) + annotation (Line(points={{-98,140},{-70,140},{-70,104},{-22,104}}, + color={0,0,127})); + connect(parLoaRat.y, plrTowMaxSpe.u) + annotation (Line(points={{-98,100},{-22,100}}, color={0,0,127})); + connect(hal.y, plrTowMaxSpe.x2) + annotation (Line(points={{-98,60},{-70,60},{-70,96},{-22,96}}, + color={0,0,127})); + connect(uppPlrTowMaxSpe.y, plrTowMaxSpe.f2) + annotation (Line(points={{-38,60},{-30,60},{-30,92},{-22,92}}, + color={0,0,127})); + connect(uChi, conWatRetSet.uChi) + annotation (Line(points={{-180,210},{-140,210},{-140,-62},{-42,-62}}, + color={255,0,255})); + connect(parLoaRat.y, conWatRetSet.uOpeParLoaRat) + annotation (Line(points={{-98,100},{-80,100},{-80,-67},{-42,-67}}, + color={0,0,127})); + connect(conWatRetSet.TChiWatSupSet, TChiWatSupSet) + annotation (Line(points={{-42,-73},{-80,-73},{-80,-80},{-180,-80}}, + color={0,0,127})); + connect(conWatRetSet.uPla, uPla) + annotation (Line(points={{-42,-78},{-60,-78},{-60,-120},{-180,-120}}, + color={255,0,255})); + connect(enaTow.uMaxTowSpeSet, uMaxTowSpeSet) + annotation (Line(points={{38,29},{-120,29},{-120,40},{-180,40}}, + color={0,0,127})); + connect(enaTow.uFanSpe,uFanSpe) + annotation (Line(points={{38,26},{-130,26},{-130,10},{-180,10}}, + color={0,0,127})); + connect(enaTow.uTow, uTow) + annotation (Line(points={{38,14},{-110,14},{-110,-30},{-180,-30}}, + color={255,0,255})); + connect(conWatRetSet.TConWatRetSet, couTowSpe.TConWatRetSet) + annotation (Line(points={{-18,-70},{0,-70},{0,-120},{38,-120}}, + color={0,0,127})); + connect(couTowSpe.TConWatRet, TConWatRet) + annotation (Line(points={{38,-124},{-100,-124},{-100,-160},{-180,-160}}, + color={0,0,127})); + connect(couTowSpe.uConWatPumSpe, uConWatPumSpe) + annotation (Line(points={{38,-128},{-80,-128},{-80,-200},{-180,-200}}, + color={0,0,127})); + connect(uMaxTowSpeSet, couTowSpe.uMaxTowSpeSet) + annotation (Line(points={{-180,40},{-120,40},{-120,-132},{38,-132}}, + color={0,0,127})); + connect(plrTowMaxSpe.y, couTowSpe.plrTowMaxSpe) + annotation (Line(points={{2,100},{20,100},{20,-140},{38,-140}}, + color={0,0,127})); + connect(conWatRetSet.TConWatRetSet, lesCouTowSpe.TConWatRetSet) + annotation (Line(points={{-18,-70},{0,-70},{0,-210},{38,-210}}, + color={0,0,127})); + connect(TConWatRet, lesCouTowSpe.TConWatRet) + annotation (Line(points={{-180,-160},{-100,-160},{-100,-212},{38,-212}}, + color={0,0,127})); + connect(uConWatPumSpe, lesCouTowSpe.uConWatPumSpe) + annotation (Line(points={{-180,-200},{-80,-200},{-80,-218},{38,-218}}, + color={0,0,127})); + connect(lesCouTowSpe.TConWatSup, TConWatSup) + annotation (Line(points={{38,-222},{0,-222},{0,-280},{-180,-280}}, + color={0,0,127})); + connect(uMaxTowSpeSet, lesCouTowSpe.uMaxTowSpeSet) + annotation (Line(points={{-180,40},{-120,40},{-120,-225},{38,-225}}, + color={0,0,127})); + connect(plrTowMaxSpe.y, lesCouTowSpe.plrTowMaxSpe) + annotation (Line(points={{2,100},{20,100},{20,-230},{38,-230}}, + color={0,0,127})); + connect(enaTow.yTow, swi.u2) + annotation (Line(points={{62,20},{118,20}}, color={255,0,255})); + connect(couTowSpe.ySpeSet, swi.u1) + annotation (Line(points={{62,-130},{100,-130},{100,28},{118,28}}, + color={0,0,127})); + connect(lesCouTowSpe.ySpeSet, swi.u1) + annotation (Line(points={{62,-220},{100,-220},{100,28},{118,28}}, + color={0,0,127})); + connect(zer1.y, swi.u3) + annotation (Line(points={{62,-20},{80,-20},{80,12},{118,12}}, + color={0,0,127})); + connect(tru.y, and2.u2) + annotation (Line(points={{-58,170},{-40,170},{-40,202},{-22,202}}, + color={255,0,255})); + connect(and2.y, swi1.u2) + annotation (Line(points={{2,210},{98,210}}, color={255,0,255})); + connect(swi.y, swi1.u1) + annotation (Line(points={{142,20},{150,20},{150,190},{60,190},{60,218}, + {98,218}}, color={0,0,127})); + connect(uTowSpeWSE, swi1.u3) + annotation (Line(points={{-180,240},{80,240},{80,202},{98,202}}, + color={0,0,127})); + connect(zer2.y, swi1.u3) + annotation (Line(points={{62,170},{80,170},{80,202},{98,202}}, + color={0,0,127})); + connect(swi1.y,ySpeSet) + annotation (Line(points={{122,210},{180,210}}, color={0,0,127})); + connect(uChi, mulOr.u) + annotation (Line(points={{-180,210},{-122,210}}, color={255,0,255})); + connect(uConWatPumSpe, proOn.u) + annotation (Line(points={{-180,-200},{-150,-200},{-150,-260},{-142,-260}}, + color={0,0,127})); + connect(proOn.y, booToInt.u) + annotation (Line(points={{-118,-260},{-102,-260}}, color={255,0,255})); + connect(mulSumInt.y, enaTow.uConWatPumNum) + annotation (Line(points={{-18,-260},{10,-260},{10,11},{38,11}}, + color={255,127,0})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-78,-260},{-42,-260}}, + color={255,127,0})); + connect(conWatRetSet.TConWatRetSet, enaTow.TTowSet) + annotation (Line(points={{-18,-70},{0,-70},{0,22},{38,22}}, color={0,0,127})); + connect(TConWatRet, enaTow.TTow) annotation (Line(points={{-180,-160},{-100, + -160},{-100,18},{38,18}}, color={0,0,127})); + connect(uChi, couTowSpe.uChi) + annotation (Line(points={{-180,210},{-140,210},{-140,-136},{38,-136}}, + color={255,0,255})); + connect(uChi, lesCouTowSpe.uChi) + annotation (Line(points={{-180,210},{-140,210},{-140,-227},{38,-227}}, + color={255,0,255})); + connect(uPla, lesCouTowSpe.uPla) + annotation (Line(points={{-180,-120},{-60,-120},{-60,-215},{38,-215}}, + color={255,0,255})); + connect(lesCouTowSpe.TConWatSupSet, TConWatSupSet) + annotation (Line(points={{62,-212},{180,-212}}, color={0,0,127})); + +annotation ( + defaultComponentName="towFanSpe", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-200,-200}, + {200,200}}), graphics={ + Rectangle( + extent={{-200,-200},{200,200}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-200,280},{200,200}}, + textColor={0,0,255}, + textString="%name"), + Polygon( + points={{-40,160},{40,160},{0,20},{-40,160}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-80,20},{80,-20}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-20},{-40,-160},{60,-160},{0,-20}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{120,-104},{140,-104},{150,-120},{140,-136},{120,-136},{110,-120}, + {120,-104}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{128,-136},{132,-160}}, + lineColor={200,200,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Line(points={{100,-160}}, color={28,108,200}), + Rectangle( + extent={{92,-160},{170,-170}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{114,-110},{144,-128}}, + textColor={28,108,200}, + textString="CWRT"), + Text( + extent={{-200,160},{-158,142}}, + textColor={255,0,255}, + textString="uChi"), + Text( + extent={{-196,188},{-118,172}}, + textColor={0,0,127}, + textString="uTowSpeWSE", + visible=have_WSE), + Text( + extent={{-200,130},{-154,114}}, + textColor={255,0,255}, + textString="uWse", + visible=have_WSE), + Text( + extent={{-198,12},{-160,-6}}, + textColor={255,0,255}, + textString="uTow"), + Text( + extent={{-200,-80},{-160,-98}}, + textColor={255,0,255}, + textString="uPla"), + Text( + extent={{-200,100},{-126,82}}, + textColor={0,0,127}, + textString="reqPlaCap"), + Text( + extent={{-196,72},{-104,54}}, + textColor={0,0,127}, + textString="uMaxTowSpeSet"), + Text( + extent={{-200,40},{-134,22}}, + textColor={0,0,127}, + textString="uFanSpe"), + Text( + extent={{-198,-50},{-118,-68}}, + textColor={0,0,127}, + textString="TChiWatSupSet"), + Text( + extent={{-200,-112},{-114,-128}}, + textColor={0,0,127}, + textString="TConWatRet"), + Text( + extent={{-196,-142},{-94,-158}}, + textColor={0,0,127}, + textString="uConWatPumSpe"), + Text( + extent={{-198,-170},{-118,-188}}, + textColor={0,0,127}, + textString="TConWatSup", + visible=not closeCoupledPlant), + Text( + extent={{122,12},{200,-6}}, + textColor={0,0,127}, + textString="ySpeSet"), + Text( + extent={{114,-178},{194,-196}}, + textColor={0,0,127}, + textString="TConWatSupSet", + visible=not closeCoupledPlant)}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-300},{160,280}}), graphics={ + Text( + extent={{-148,280},{-78,262}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="When there is no WSE:"), + Text( + extent={{-148,264},{-24,258}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="- if no chiller is enabled, then tower fan speed should be zero;"), + Text( + extent={{-148,258},{-14,248}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="- if any chiller is enabled, then control fan speed with sequence here;"), + Text( + extent={{6,278},{70,266}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="When there is WSE:"), + Text( + extent={{6,264},{150,256}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="- if WSE is not enabled, then control fan speed with sequence here;"), + Text( + extent={{6,256},{150,248}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="- if WSE is enabled, then fan speed will be controlled by uTowSpeWSE;")}), +Documentation(info=" +

+Block that outputs cooling tower fan speed ySpeSet for maintaining +condenser water return temperature at setpoint. This is implemented +according to ASHRAE Guideline36-2021, section 5.20.12.2, +item a. It includes four subsequences: +

+ +", revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Coupled.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Coupled.mo new file mode 100644 index 00000000000..68a624b8bbe --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Coupled.mo @@ -0,0 +1,236 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences; +block Coupled + "Sequence of defining cooling tower fan speed when the plant is close coupled" + + parameter Integer nChi = 2 "Total number of chillers"; + parameter Integer nConWatPum = 2 "Total number of condenser water pumps"; + parameter Real fanSpeMin = 0.1 "Minimum cooling tower fan speed"; + parameter Real pumSpeChe = 0.01 + "Lower threshold value to check if condenser water pump is proven on"; + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI "Type of controller" + annotation (Dialog(group="Controller")); + parameter Real k=1 "Gain of controller" + annotation (Dialog(group="Controller")); + parameter Real Ti( + final quantity="Time", + final unit="s")=0.5 + "Time constant of integrator block" + annotation (Dialog(group="Controller")); + parameter Real Td( + final quantity="Time", + final unit="s")=0.1 + "Time constant of derivative block" + annotation (Dialog(group="Controller", enable= + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real yMax=1 "Upper limit of output" + annotation (Dialog(group="Controller")); + parameter Real yMin=0 "Lower limit of output" + annotation (Dialog(group="Controller")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRetSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-160,60},{-120,100}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-160,20},{-120,60}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum), + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxTowSpeSet[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Maximum cooling tower speed setpoint from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-160,-60},{-120,-20}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller enabling status: true=ON" + annotation (Placement(transformation(extent={{-160,-100},{-120,-60}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput plrTowMaxSpe( + final min=0, + final max=1, + final unit="1") + "Tower maximum speed that reset based on plant partial load ratio" + annotation (Placement(transformation(extent={{-160,-150},{-120,-110}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") "Fan speed setpoint of each cooling tower cell" + annotation (Placement(transformation(extent={{120,-20},{160,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPID( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=yMax, + final yMin=yMin, + final reverseActing=false, + final y_reset=yMin) + "Condenser water return temperature controller" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Reals.Line CWRTSpd + "Fan speed calculated based on return water temperature control loop" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTowSpe( + final k=fanSpeMin) "Minimum tower speed" + annotation (Placement(transformation(extent={{-80,110},{-60,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=yMin) "Zero constant" + annotation (Placement(transformation(extent={{0,110},{20,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one( + final k=yMax) "Constant one" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis proOn[nConWatPum]( + final uLow=fill(pumSpeChe, nConWatPum), + final uHigh=fill(2*pumSpeChe, nConWatPum)) + "Check if the condenser water pump is proven on" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyProOn( + final nin=nConWatPum) + "Check if there is any condenser water pump is proven on" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMin fanSpe(final nin=3) + "Cooling tower fan speed" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMin maxSpe( + final nin=nChi) + "Lowest value of the maximum cooling tower speed from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one1[nChi]( + final k=fill(1, nChi)) "Constant one" + annotation (Placement(transformation(extent={{-100,-120},{-80,-100}}))); + +equation + connect(TConWatRet, conPID.u_m) + annotation (Line(points={{-140,40},{-70,40},{-70,68}}, color={0,0,127})); + connect(TConWatRetSet, conPID.u_s) + annotation (Line(points={{-140,80},{-82,80}}, color={0,0,127})); + connect(conPID.y, CWRTSpd.u) + annotation (Line(points={{-58,80},{78,80}}, color={0,0,127})); + connect(zer.y, CWRTSpd.x1) + annotation (Line(points={{22,120},{60,120},{60,88},{78,88}}, color={0,0,127})); + connect(minTowSpe.y, CWRTSpd.f1) + annotation (Line(points={{-58,120},{-20,120},{-20,84},{78,84}}, color={0,0,127})); + connect(one.y, CWRTSpd.x2) + annotation (Line(points={{22,60},{40,60},{40,76},{78,76}}, color={0,0,127})); + connect(one.y, CWRTSpd.f2) + annotation (Line(points={{22,60},{40,60},{40,72},{78,72}}, color={0,0,127})); + connect(uConWatPumSpe, proOn.u) + annotation (Line(points={{-140,0},{-102,0}}, color={0,0,127})); + connect(proOn.y, anyProOn.u) + annotation (Line(points={{-78,0},{-62,0}}, color={255,0,255})); + connect(anyProOn.y, conPID.trigger) + annotation (Line(points={{-38,0},{0,0},{0,30},{-76,30},{-76,68}}, + color={255,0,255})); + connect(uChi, swi1.u2) + annotation (Line(points={{-140,-80},{-62,-80}}, color={255,0,255})); + connect(one1.y, swi1.u3) + annotation (Line(points={{-78,-110},{-70,-110},{-70,-88},{-62,-88}}, + color={0,0,127})); + connect(uMaxTowSpeSet, swi1.u1) + annotation (Line(points={{-140,-40},{-80,-40},{-80,-72},{-62,-72}}, + color={0,0,127})); + connect(swi1.y, maxSpe.u) + annotation (Line(points={{-38,-80},{-22,-80}}, color={0,0,127})); + connect(CWRTSpd.y, fanSpe.u[1]) + annotation (Line(points={{102,80},{110,80},{110,30},{10,30},{10,-80.6667},{ + 18,-80.6667}}, + color={0,0,127})); + connect(maxSpe.y, fanSpe.u[2]) + annotation (Line(points={{2,-80},{18,-80}}, color={0,0,127})); + connect(plrTowMaxSpe, fanSpe.u[3]) + annotation (Line(points={{-140,-130},{10,-130},{10,-79.3333},{18,-79.3333}}, + color={0,0,127})); + connect(anyProOn.y, swi.u2) + annotation (Line(points={{-38,0},{78,0}}, color={255,0,255})); + connect(zer.y, swi.u3) + annotation (Line(points={{22,120},{60,120},{60,-8},{78,-8}}, + color={0,0,127})); + connect(fanSpe.y, swi.u1) + annotation (Line(points={{42,-80},{50,-80},{50,8},{78,8}}, color={0,0,127})); + connect(swi.y,ySpeSet) + annotation (Line(points={{102,0},{140,0}}, color={0,0,127})); + +annotation ( + defaultComponentName="couTowSpe", + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-140},{120,140}})), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Polygon( + points={{-20,80},{20,80},{0,10},{-20,80}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-40,10},{40,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-10},{-20,-80},{20,-80},{0,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid)}), +Documentation(info=" +

+Block that outputs cooling tower fan speed ySpeSet based on the control +of condenser water return temperature for the plant that is close coupled. +This is implemented according to ASHRAE Guideline36-2021, section 5.20.12.2, item a.6-7. +

+ +", revisions=" + +")); +end Coupled; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Enable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Enable.mo new file mode 100644 index 00000000000..808841ba48e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Enable.mo @@ -0,0 +1,421 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences; +block Enable "Sequence for enabling and disabling tower fan" + + parameter Integer nChi=2 "Total number of chillers"; + parameter Integer nTowCel=4 "Total number of cooling tower cells"; + parameter Real fanSpeChe( + final unit="1")= 0.01 + "Lower threshold value to check fan speed"; + parameter Real fanSpeMin( + final unit="1", + final min=0, + final max=1) = 0.1 "Minimum tower fan speed"; + parameter Real cheMinFanSpe( + final quantity="Time", + final unit="s")=300 + "Threshold time for checking duration when tower fan equals to the minimum tower fan speed" + annotation (Dialog(tab="Advanced")); + parameter Real cheMaxTowSpe( + final quantity="Time", + final unit="s")=300 + "Threshold time for checking duration when any enabled chiller maximum cooling speed equals to the minimum tower fan speed" + annotation (Dialog(tab="Advanced")); + parameter Real cheTowOff( + final quantity="Time", + final unit="s")=60 + "Threshold time for checking duration when there is no enabled tower fan" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxTowSpeSet[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Maximum cooling tower speed setpoint from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-320,190},{-280,230}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final min=0, + final max=1, + final unit="1") "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,100},{-280,140}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TTowSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Setpoint of tower temperature, could be condenser water return or supply temperature" + annotation (Placement(transformation(extent={{-320,20},{-280,60}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TTow( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured tower temperature, could be condenser water return or supply temperature" + annotation (Placement(transformation(extent={{-320,-30},{-280,10}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTow[nTowCel] + "Cooling tower operating status: true=running tower cell" + annotation (Placement(transformation(extent={{-320,-140},{-280,-100}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uConWatPumNum + "Number of enabled condenser water pumps" + annotation (Placement(transformation(extent={{-320,-180},{-280,-140}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTow + "Tower fan status: true=enable any number of fans; false=disable all fans" + annotation (Placement(transformation(extent={{280,-230},{320,-190}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Subtract sub0[nChi] + "Difference between enabled chiller head pressure control maximum tower speed and the minimum tower speed" + annotation (Placement(transformation(extent={{-160,150},{-140,170}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys[nChi]( + final uLow=fill(fanSpeChe, nChi), + final uHigh=fill(2*fanSpeChe, nChi)) + "Check if chiller head pressure control maximum tower speed is greater than the minimum tower speed " + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChi) + "Check if any enabled chiller head pressure control maximum tower speed equals to the minimum tower speed" + annotation (Placement(transformation(extent={{-20,150},{0,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nChi] "Logical not" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2( + final delayTime=cheMaxTowSpe, + final delayOnInit=true) + "Count the time when the chiller head pressure control maximum tower speed equals tower minimum speed" + annotation (Placement(transformation(extent={{20,150},{40,170}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys1[nChi]( + final uLow=fill(fanSpeChe, nChi), + final uHigh=fill(2*fanSpeChe, nChi)) + "Check if chiller has been enabled, an enabled chiller will have the head pressure control maximum cooling tower speed that is greater than zero" + annotation (Placement(transformation(extent={{-240,200},{-220,220}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-200,170},{-180,190}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub1 + "Difference between tower fan speed and the minimum fan speed" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys2( + final uLow=fanSpeChe, + final uHigh=2*fanSpeChe) + "Check if tower fan speed is greater than minimum speed" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Check if tower fan speed equals to the minimum speed" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub2 + "Difference between the return water temperature and the adjusted setpoint" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys3( + final uLow=0.1, + final uHigh=0.15) + "Check if tower temperature is a delta below setpoint" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 + "Tower fans have been at minimum speed for a threshold time and tower return water temperature drops below a adjusted setpoint" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + Buildings.Controls.OBC.CDL.Logical.Or disTow + "Check if the tower fans should be disabled" + annotation (Placement(transformation(extent={{60,150},{80,170}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1( + final nin=nTowCel) + "True when any tower fan is enaled" + annotation (Placement(transformation(extent={{-240,-130},{-220,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 "No enabled tower fan" + annotation (Placement(transformation(extent={{-160,-130},{-140,-110}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=cheTowOff, + final delayOnInit=true) + "Count the time when all tower cells are off" + annotation (Placement(transformation(extent={{-120,-130},{-100,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub3 + "Difference between the return water temperature and the adjusted setpoint" + annotation (Placement(transformation(extent={{-160,-50},{-140,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys4( + final uLow=0.1, + final uHigh=0.15) + "Check if tower temperature is above the adjusted setpoint" + annotation (Placement(transformation(extent={{-120,-50},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=nChi) + "Check if all enabled chillers head pressure control maximum tower speed are greater than tower minimum speed" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + Buildings.Controls.OBC.CDL.Logical.And enaTow + "Check if tower fans should be enabled" + annotation (Placement(transformation(extent={{60,-20},{80,0}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu + "Check integer number equality" + annotation (Placement(transformation(extent={{-100,-170},{-80,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) "Zero constant" + annotation (Placement(transformation(extent={{-160,-210},{-140,-190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTowSpe[nChi]( + final k=fill(fanSpeMin, nChi)) + "Minimum tower speed" + annotation (Placement(transformation(extent={{-240,70},{-220,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one[nChi]( + final k=fill(1, nChi)) "Constant one" + annotation (Placement(transformation(extent={{-240,140},{-220,160}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter addPar( + final p=5/9) "Tower temperature setpoint plus 1 degF" + annotation (Placement(transformation(extent={{-240,-80},{-220,-60}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter addPar1( + final p=-5/9) + "Temperature of a delta value below the tower temperature setpoint" + annotation (Placement(transformation(extent={{-240,30},{-220,50}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=cheMinFanSpe, + final delayOnInit=true) + "Count the time when the tower fan is at minimum speed" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2 "Logical switch" + annotation (Placement(transformation(extent={{240,-170},{260,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant disFan1( + final k=false) + "Disable tower fan when no condenser water pump is ON" + annotation (Placement(transformation(extent={{120,-210},{140,-190}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 "Logical switch" + annotation (Placement(transformation(extent={{200,-100},{220,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Or chaTow + "Tower fan should be enabled or disabled" + annotation (Placement(transformation(extent={{140,-20},{160,0}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 + "Logical and" + annotation (Placement(transformation(extent={{0,-20},{20,0}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3 + "Logical switch" + annotation (Placement(transformation(extent={{140,150},{160,170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{80,200},{100,220}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Break algebraic loop" + annotation (Placement(transformation(extent={{240,-220},{260,-200}}))); + +equation + connect(sub0.y, hys.u) + annotation (Line(points={{-138,160},{-122,160}}, color={0,0,127})); + connect(hys.y, not1.u) + annotation (Line(points={{-98,160},{-62,160}},color={255,0,255})); + connect(mulOr.y, truDel2.u) + annotation (Line(points={{2,160},{18,160}}, color={255,0,255})); + connect(uMaxTowSpeSet, hys1.u) + annotation (Line(points={{-300,210},{-242,210}}, color={0,0,127})); + connect(hys1.y, swi.u2) + annotation (Line(points={{-218,210},{-210,210},{-210,180},{-202,180}}, + color={255,0,255})); + connect(uMaxTowSpeSet, swi.u1) + annotation (Line(points={{-300,210},{-260,210},{-260,188},{-202,188}}, + color={0,0,127})); + connect(one.y, swi.u3) + annotation (Line(points={{-218,150},{-210,150},{-210,172},{-202,172}}, + color={0,0,127})); + connect(swi.y, sub0.u1) + annotation (Line(points={{-178,180},{-170,180},{-170,166},{-162,166}}, + color={0,0,127})); + connect(uFanSpe, sub1.u1) + annotation (Line(points={{-300,120},{-200,120},{-200,106},{-162,106}}, + color={0,0,127})); + connect(sub1.y, hys2.u) + annotation (Line(points={{-138,100},{-122,100}}, color={0,0,127})); + connect(hys2.y, not2.u) + annotation (Line(points={{-98,100},{-62,100}},color={255,0,255})); + connect(sub2.y, hys3.u) + annotation (Line(points={{-138,20},{-122,20}}, color={0,0,127})); + connect(hys3.y, and2.u2) + annotation (Line(points={{-98,20},{10,20},{10,92},{18,92}}, color={255,0,255})); + connect(and2.y, disTow.u2) + annotation (Line(points={{42,100},{50,100},{50,152},{58,152}}, + color={255,0,255})); + connect(mulOr1.y, not3.u) + annotation (Line(points={{-218,-120},{-162,-120}}, color={255,0,255})); + connect(not3.y, truDel.u) + annotation (Line(points={{-138,-120},{-122,-120}}, color={255,0,255})); + connect(TTow, sub3.u1) + annotation (Line(points={{-300,-10},{-180,-10},{-180,-34},{-162,-34}}, + color={0,0,127})); + connect(sub3.y, hys4.u) + annotation (Line(points={{-138,-40},{-122,-40}}, color={0,0,127})); + connect(not1.y, mulOr.u) + annotation (Line(points={{-38,160},{-22,160}}, color={255,0,255})); + connect(hys.y, mulAnd.u) + annotation (Line(points={{-98,160},{-80,160},{-80,-10},{-62,-10}}, + color={255,0,255})); + connect(uTow, mulOr1.u) + annotation (Line(points={{-300,-120},{-242,-120}}, color={255,0,255})); + connect(uConWatPumNum, intEqu.u1) + annotation (Line(points={{-300,-160},{-102,-160}}, color={255,127,0})); + connect(conInt.y, intEqu.u2) + annotation (Line(points={{-138,-200},{-120,-200},{-120,-168},{-102,-168}}, + color={255,127,0})); + connect(TTowSet, addPar1.u) + annotation (Line(points={{-300,40},{-242,40}}, color={0,0,127})); + connect(addPar1.y, sub2.u1) + annotation (Line(points={{-218,40},{-180,40},{-180,26},{-162,26}},color={0,0,127})); + connect(TTowSet, addPar.u) + annotation (Line(points={{-300,40},{-260,40},{-260,-70},{-242,-70}}, color={0,0,127})); + connect(not2.y, truDel1.u) + annotation (Line(points={{-38,100},{-22,100}}, color={255,0,255})); + connect(disFan1.y, logSwi2.u1) + annotation (Line(points={{142,-200},{160,-200},{160,-152},{238,-152}}, + color={255,0,255})); + connect(intEqu.y, logSwi2.u2) + annotation (Line(points={{-78,-160},{238,-160}}, + color={255,0,255})); + connect(mulOr1.y, logSwi1.u3) + annotation (Line(points={{-218,-120},{-200,-120},{-200,-98},{198,-98}}, + color={255,0,255})); + connect(chaTow.y, logSwi1.u2) + annotation (Line(points={{162,-10},{170,-10},{170,-90},{198,-90}}, + color={255,0,255})); + connect(logSwi1.y, logSwi2.u3) + annotation (Line(points={{222,-90},{230,-90},{230,-168},{238,-168}}, + color={255,0,255})); + connect(addPar.y, sub3.u2) annotation (Line(points={{-218,-70},{-200,-70},{-200, + -46},{-162,-46}},color={0,0,127})); + connect(TTow, sub2.u2) annotation (Line(points={{-300,-10},{-180,-10},{-180,14}, + {-162,14}}, color={0,0,127})); + connect(minTowSpe.y, sub0.u2) annotation (Line(points={{-218,80},{-180,80},{-180, + 154},{-162,154}}, color={0,0,127})); + connect(minTowSpe[1].y, sub1.u2) annotation (Line(points={{-218,80},{-180,80}, + {-180,94},{-162,94}}, color={0,0,127})); + connect(enaTow.u1, and1.y) + annotation (Line(points={{58,-10},{22,-10}}, color={255,0,255})); + connect(disTow.y, logSwi3.u2) + annotation (Line(points={{82,160},{138,160}}, color={255,0,255})); + connect(con.y, logSwi3.u1) annotation (Line(points={{102,210},{120,210},{120,168}, + {138,168}}, color={255,0,255})); + connect(enaTow.y, logSwi3.u3) annotation (Line(points={{82,-10},{120,-10},{120, + 152},{138,152}}, color={255,0,255})); + connect(logSwi3.y, logSwi1.u1) annotation (Line(points={{162,160},{180,160},{180, + -82},{198,-82}}, color={255,0,255})); + connect(enaTow.y, chaTow.u1) + annotation (Line(points={{82,-10},{138,-10}}, color={255,0,255})); + connect(disTow.y, chaTow.u2) annotation (Line(points={{82,160},{100,160},{100, + -18},{138,-18}}, color={255,0,255})); + connect(mulAnd.y, and1.u1) + annotation (Line(points={{-38,-10},{-2,-10}}, color={255,0,255})); + connect(hys4.y, and1.u2) annotation (Line(points={{-98,-40},{-20,-40},{-20,-18}, + {-2,-18}}, color={255,0,255})); + connect(truDel.y, enaTow.u2) annotation (Line(points={{-98,-120},{40,-120},{40, + -18},{58,-18}}, color={255,0,255})); + connect(truDel1.y, and2.u1) + annotation (Line(points={{2,100},{18,100}}, color={255,0,255})); + connect(truDel2.y, disTow.u1) + annotation (Line(points={{42,160},{58,160}}, color={255,0,255})); + connect(logSwi2.y, pre2.u) annotation (Line(points={{262,-160},{270,-160},{270, + -180},{230,-180},{230,-210},{238,-210}}, color={255,0,255})); + connect(pre2.y, yTow) + annotation (Line(points={{262,-210},{300,-210}}, color={255,0,255})); +annotation ( + defaultComponentName="enaTow", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-280,-240},{280,240}}), graphics={ + Rectangle( + extent={{-278,58},{278,-138}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-278,238},{278,62}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-278,-142},{278,-238}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{146,226},{250,212}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Disable tower fans"), + Text( + extent={{144,46},{238,30}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Enable tower fans"), + Text( + extent={{-114,-214},{94,-230}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Disable tower fans when no running condenser water pump")}), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), +Documentation(info=" +

+Block that outputs signal yTowSta for enabling and disabling cooling tower +fan. This is implemented according to ASHRAE Guideline36-2021, +section 5.20.12.2, item a.11-l2. +

+
    +
  1. +Disable the tower fans if either: + +
  2. +
  3. +Enable the tower fans if: + +
  4. +
  5. +When all condenser water pumps are commanded OFF, disable the PID loop and +stop all tower fans. +
  6. +
+

+Note that the tower temperature TTow could be condenser water return +temperature or condenser water supply temperature, depending on whether the fan +speed control is to maintain return temperature or supply temperature. +

+", revisions=" + +")); +end Enable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/LessCoupled.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/LessCoupled.mo new file mode 100644 index 00000000000..f344fb5fe43 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/LessCoupled.mo @@ -0,0 +1,379 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences; +block LessCoupled + "Sequence of defining cooling tower fan speed when the plant is not close coupled" + + parameter Integer nChi = 2 "Total number of chillers"; + parameter Integer nConWatPum = 2 "Total number of condenser water pumps"; + parameter Real pumSpeChe = 0.01 + "Lower threshold value to check if condenser water pump is proven on"; + parameter Real fanSpeMin( + final unit="1", + final min=0, + final max=1)= 0.1 + "Minimum cooling tower fan speed"; + + parameter Real samplePeriod( + final quantity="Time", + final unit="s", + final max=30) = 30 + "Period of sampling condenser water supply and return temperature difference" + annotation (Dialog(group="Return water temperature controller")); + parameter Real iniPlaTim( + final quantity="Time", + final unit="s") = 300 + "Threshold time to hold the initial temperature difference at the plant initial stage" + annotation (Dialog(group="Return water temperature controller")); + parameter Real TConWatSup_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi)) = {293.15, 293.15} + "Design condenser water supply temperature (condenser entering) of each chiller" + annotation (Dialog(group="Return water temperature controller")); + parameter Real TConWatRet_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi)) = {303.15, 303.15} + "Design condenser water return temperature (condenser leaving) of each chiller" + annotation (Dialog(group="Return water temperature controller")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController supWatCon= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Supply water temperature controller" + annotation (Dialog(group="Supply water temperature controller")); + parameter Real kSupCon=1 "Gain of controller" + annotation (Dialog(group="Supply water temperature controller")); + parameter Real TiSupCon( + final quantity="Time", + final unit="s")=0.5 "Time constant of integrator block" + annotation (Dialog(group="Supply water temperature controller")); + parameter Real TdSupCon( + final quantity="Time", + final unit="s")=0.1 "Time constant of derivative block" + annotation (Dialog(group="Supply water temperature controller", enable= + supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or + supWatCon == Buildings.Controls.OBC.CDL.Types.SimpleController.PID)); + parameter Real ySupConMax=1 "Upper limit of output" + annotation (Dialog(group="Supply water temperature controller")); + parameter Real ySupConMin=0 "Lower limit of output" + annotation (Dialog(group="Supply water temperature controller")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRetSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-220,160},{-180,200}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatRet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature (condenser leaving)" + annotation (Placement(transformation(extent={{-220,130},{-180,170}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-220,80},{-180,120}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final min=fill(0, nConWatPum), + final max=fill(1, nConWatPum), + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-220,-40},{-180,0}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatSup( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water supply temperature (condenser entering)" + annotation (Placement(transformation(extent={{-220,-80},{-180,-40}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxTowSpeSet[nChi]( + final min=fill(0, nChi), + final max=fill(1, nChi), + final unit=fill("1", nChi)) + "Maximum cooling tower speed setpoint from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{-220,-110},{-180,-70}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller enabling status: true=ON" + annotation (Placement(transformation(extent={{-220,-140},{-180,-100}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput plrTowMaxSpe( + final min=0, + final max=1, + final unit="1") + "Tower maximum speed that reset based on plant partial load ratio" + annotation (Placement(transformation(extent={{-220,-200},{-180,-160}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TConWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water supply temperature setpoint" + annotation (Placement(transformation(extent={{160,130},{200,170}}), + iconTransformation(extent={{100,60},{140,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySpeSet( + final min=0, + final max=1, + final unit="1") "Fan speed setpoint of each cooling tower cell" + annotation (Placement(transformation(extent={{160,-160},{200,-120}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.PIDWithReset supCon( + final controllerType=supWatCon, + final k=kSupCon, + final Ti=TiSupCon, + final Td=TdSupCon, + final yMax=ySupConMax, + final yMin=ySupConMin, + final reverseActing=false, + final y_reset=ySupConMin) "Condenser water supply temperature controller" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Hysteresis proOn[nConWatPum]( + final uLow=fill(pumSpeChe, nConWatPum), + final uHigh=fill(2*pumSpeChe, nConWatPum)) + "Check if the condenser water pump is proven on" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyProOn( + final nin=nConWatPum) + "Check if any condenser water pump is proven on" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTowSpe( + final k=fanSpeMin) "Minimum tower speed" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1( + final k=ySupConMin) + "Zero constant" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one1( + final k=ySupConMax) "Maximum speed" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Line CWSTSpd + "Fan speed calculated based on supply water temperature control" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMin maxSpe(final nin=nChi) + "Lowest value of the maximum cooling tower speed from each chiller head pressure control loop" + annotation (Placement(transformation(extent={{0,-130},{20,-110}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMin fanSpe(final nin=3) + "Cooling tower fan speed" + annotation (Placement(transformation(extent={{60,-130},{80,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one2[nChi]( + final k=fill(1,nChi)) "Constant one" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-40,-130},{-20,-110}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] + "Convert chiller status to real number, true becomes 1 and false becomes 0" + annotation (Placement(transformation(extent={{-140,40},{-120,60}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter enaDesConWatRet[nChi]( + final k=TConWatRet_nominal) + "Design condenser water return temperature of the enabled chiller" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter enaDesConWatSup[nChi]( + final k=TConWatSup_nominal) + "Design condenser water supply temperature of the enabled chiller" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub2[nChi] + "Difference of the design supply and return condenser water temperature" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax multiMax(nin=nChi) + "Difference of the design supply and return condenser water temperature of the enabled chiller" + annotation (Placement(transformation(extent={{20,40},{40,60}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=iniPlaTim, + final delayOnInit=true) + "Count the time after plant being enabled" + annotation (Placement(transformation(extent={{-140,90},{-120,110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch delTem "Temperature difference value" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract meaTemDif + "Difference of the condenser return and supply water temperature" + annotation (Placement(transformation(extent={{-140,130},{-120,150}}))); + Buildings.Controls.OBC.CDL.Reals.MovingAverage movMea( + final delta=300) + "Moving average of the sampled temperature difference" + annotation (Placement(transformation(extent={{-60,130},{-40,150}}))); + Buildings.Controls.OBC.CDL.Discrete.Sampler sam( + final samplePeriod=samplePeriod) + "Sample the temperature difference" + annotation (Placement(transformation(extent={{-100,130},{-80,150}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract conWatSupSet + "Condenser water supply temperature setpoint" + annotation (Placement(transformation(extent={{100,140},{120,160}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai[nChi]( + final k=fill(0.5, nChi)) + "Gain factor" + annotation (Placement(transformation(extent={{-10,40},{10,60}}))); + +equation + connect(proOn.y,anyProOn. u) + annotation (Line(points={{-118,-20},{-102,-20}}, color={255,0,255})); + connect(uConWatPumSpe, proOn.u) + annotation (Line(points={{-200,-20},{-142,-20}}, color={0,0,127})); + connect(zer1.y, CWSTSpd.x1) + annotation (Line(points={{62,0},{80,0},{80,-22},{98,-22}}, color={0,0,127})); + connect(minTowSpe.y, CWSTSpd.f1) + annotation (Line(points={{2,0},{20,0},{20,-26},{98,-26}}, + color={0,0,127})); + connect(supCon.y, CWSTSpd.u) + annotation (Line(points={{2,-30},{98,-30}}, color={0,0,127})); + connect(TConWatSup, supCon.u_m) + annotation (Line(points={{-200,-60},{-10,-60},{-10,-42}}, color={0,0,127})); + connect(one1.y, CWSTSpd.x2) + annotation (Line(points={{2,-80},{20,-80},{20,-34},{98,-34}}, color={0,0,127})); + connect(one1.y, CWSTSpd.f2) + annotation (Line(points={{2,-80},{20,-80},{20,-38},{98,-38}}, color={0,0,127})); + connect(CWSTSpd.y, fanSpe.u[1]) + annotation (Line(points={{122,-30},{140,-30},{140,-80},{40,-80},{40, + -120.667},{58,-120.667}}, + color={0,0,127})); + connect(maxSpe.y, fanSpe.u[2]) + annotation (Line(points={{22,-120},{58,-120}},color={0,0,127})); + connect(plrTowMaxSpe, fanSpe.u[3]) + annotation (Line(points={{-200,-180},{40,-180},{40,-119.333},{58,-119.333}}, + color={0,0,127})); + connect(anyProOn.y, supCon.trigger) + annotation (Line(points={{-78,-20},{-60,-20},{-60,-50},{-16,-50},{-16,-42}}, + color={255,0,255})); + connect(fanSpe.y, swi.u1) + annotation (Line(points={{82,-120},{100,-120},{100,-132},{118,-132}}, + color={0,0,127})); + connect(anyProOn.y, swi.u2) + annotation (Line(points={{-78,-20},{-60,-20},{-60,-140},{118,-140}}, + color={255,0,255})); + connect(zer2.y, swi.u3) + annotation (Line(points={{82,-170},{100,-170},{100,-148},{118,-148}}, + color={0,0,127})); + connect(swi1.y, maxSpe.u) + annotation (Line(points={{-18,-120},{-2,-120}}, + color={0,0,127})); + connect(uChi, swi1.u2) + annotation (Line(points={{-200,-120},{-42,-120}}, color={255,0,255})); + connect(uMaxTowSpeSet, swi1.u1) + annotation (Line(points={{-200,-90},{-120,-90},{-120,-112},{-42,-112}}, + color={0,0,127})); + connect(one2.y, swi1.u3) + annotation (Line(points={{-138,-150},{-120,-150},{-120,-128},{-42,-128}}, + color={0,0,127})); + connect(swi.y,ySpeSet) + annotation (Line(points={{142,-140},{180,-140}},color={0,0,127})); + connect(uChi, booToRea.u) annotation (Line(points={{-200,-120},{-170,-120},{-170, + 50},{-142,50}}, color={255,0,255})); + connect(booToRea.y, enaDesConWatRet.u) annotation (Line(points={{-118,50},{-100, + 50},{-100,70},{-82,70}}, color={0,0,127})); + connect(booToRea.y, enaDesConWatSup.u) annotation (Line(points={{-118,50},{-100, + 50},{-100,30},{-82,30}}, color={0,0,127})); + connect(enaDesConWatRet.y, sub2.u1) annotation (Line(points={{-58,70},{-50,70}, + {-50,56},{-42,56}}, color={0,0,127})); + connect(enaDesConWatSup.y, sub2.u2) annotation (Line(points={{-58,30},{-50,30}, + {-50,44},{-42,44}}, color={0,0,127})); + connect(uPla, truDel.u) + annotation (Line(points={{-200,100},{-142,100}}, color={255,0,255})); + connect(multiMax.y, delTem.u3) annotation (Line(points={{42,50},{50,50},{50,92}, + {58,92}}, color={0,0,127})); + connect(TConWatSup, meaTemDif.u2) annotation (Line(points={{-200,-60},{-160,-60}, + {-160,134},{-142,134}}, color={0,0,127})); + connect(TConWatRet, meaTemDif.u1) annotation (Line(points={{-200,150},{-160,150}, + {-160,146},{-142,146}}, color={0,0,127})); + connect(meaTemDif.y, sam.u) + annotation (Line(points={{-118,140},{-102,140}}, color={0,0,127})); + connect(sam.y, movMea.u) + annotation (Line(points={{-78,140},{-62,140}}, color={0,0,127})); + connect(movMea.y, delTem.u1) annotation (Line(points={{-38,140},{50,140},{50,108}, + {58,108}}, color={0,0,127})); + connect(conWatSupSet.y, TConWatSupSet) + annotation (Line(points={{122,150},{180,150}}, color={0,0,127})); + connect(TConWatRetSet, conWatSupSet.u1) annotation (Line(points={{-200,180},{80, + 180},{80,156},{98,156}}, color={0,0,127})); + connect(delTem.y, conWatSupSet.u2) annotation (Line(points={{82,100},{90,100}, + {90,144},{98,144}}, color={0,0,127})); + connect(conWatSupSet.y, supCon.u_s) annotation (Line(points={{122,150},{140,150}, + {140,20},{-40,20},{-40,-30},{-22,-30}}, color={0,0,127})); + connect(sub2.y, gai.u) + annotation (Line(points={{-18,50},{-12,50}}, color={0,0,127})); + connect(gai.y, multiMax.u) + annotation (Line(points={{12,50},{18,50}}, color={0,0,127})); + + connect(truDel.y, delTem.u2) + annotation (Line(points={{-118,100},{58,100}}, color={255,0,255})); +annotation ( + defaultComponentName="lesCouTowSpe", + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-180,-200},{160,200}})), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Polygon( + points={{-20,80},{20,80},{0,10},{-20,80}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-40,10},{40,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-10},{-20,-80},{20,-80},{0,-10}}, + lineColor={28,108,200}, + fillColor={240,240,240}, + fillPattern=FillPattern.Solid)}), +Documentation(info=" +

+Block that outputs cooling tower fan speed ySpeSet based on the control +of condenser water return temperature for the plant that is not closed coupled. +This is implemented according to ASHRAE Guideline36-2021, section 5.20.12.2, +item a.8-10. +

+ +", revisions=" + +")); +end LessCoupled; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Setpoint.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Setpoint.mo new file mode 100644 index 00000000000..9fcc22cfd4e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Setpoint.mo @@ -0,0 +1,290 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences; +block Setpoint "Calculate condener return water temperature setpoint" + + parameter Integer nChi = 2 "Total number of chillers"; + parameter Real LIFT_min[nChi]( + final unit=fill("K",nChi), + final quantity=fill("TemperatureDifference",nChi))={12, 12} + "Minimum LIFT of each chiller" + annotation (Evaluate=true); + parameter Real TConWatRet_nominal[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi))= {303.15, 303.15} + "Design condenser water return temperature (condenser leaving) of each chiller" + annotation (Evaluate=true); + parameter Real TChiWatSupMin[nChi]( + final unit=fill("K",nChi), + final quantity=fill("ThermodynamicTemperature",nChi), + displayUnit=fill("degC",nChi)) = {278.15, 278.15} + "Minimum chilled water supply temperature of each chiller" + annotation (Evaluate=true); + parameter Real iniPlaTim( + final quantity="Time", + final unit="s")= 600 + "Time to hold return temperature to initial setpoint after plant being enabled" + annotation (Dialog(tab="Advanced")); + parameter Real ramTim( + final quantity="Time", + final unit="s") = 600 + "Time to ramp return water temperature setpoint from initial value to calculated one" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Vector of chillers proven on status: true=ON" + annotation (Placement(transformation(extent={{-340,20},{-300,60}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uOpeParLoaRat( + final unit="1", + final min=0, + final max=1) "Current plant partial load ratio" + annotation (Placement(transformation(extent={{-340,-60},{-300,-20}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Chilled water supply setpoint temperature" + annotation (Placement(transformation(extent={{-340,-110},{-300,-70}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-340,-170},{-300,-130}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TConWatRetSet( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{300,-170},{340,-130}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Reals.Add conWatRet + "Condenser water return temperature" + annotation (Placement(transformation(extent={{220,18},{240,38}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.MultiMin lifMax( + final nin=nChi) "Maximum chiller LIFT" + annotation (Placement(transformation(extent={{-120,130},{-100,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiLifMin[nChi]( + final k=LIFT_min) + "Minimum LIFT of chillers" + annotation (Placement(transformation(extent={{-280,60},{-260,80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zeoCon[nChi]( + final k=fill(0, nChi)) "Zero constant" + annotation (Placement(transformation(extent={{-280,0},{-260,20}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-160,30},{-140,50}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax lifMin( + final nin=nChi) "Minimum enabled chiller LIFT" + annotation (Placement(transformation(extent={{-120,30},{-100,50}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract coeA + "Coefficient A" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract coeB "Coefficient B" + annotation (Placement(transformation(extent={{40,124},{60,144}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro "Product of inputs" + annotation (Placement(transformation(extent={{40,-44},{60,-24}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 "Add inputs" + annotation (Placement(transformation(extent={{80,-38},{100,-18}}))); + Buildings.Controls.OBC.CDL.Reals.Min min "Minimum value of two inputs" + annotation (Placement(transformation(extent={{120,-70},{140,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Max tarLif "Target chiller LIFT" + annotation (Placement(transformation(extent={{180,24},{200,44}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zeoTim( + final k=0) "Zero constant" + annotation (Placement(transformation(extent={{-40,-130},{-20,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxRamTim( + final k=ramTim) + "Time to change the return water temperature from initial value to setpoint" + annotation (Placement(transformation(extent={{-100,-190},{-80,-170}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay delPlaEna( + final delayTime=iniPlaTim) + "Delay plant enabling status" + annotation (Placement(transformation(extent={{-220,-160},{-200,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Timer chaTim + "Count the time after starting to ramp condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + Buildings.Controls.OBC.CDL.Reals.Line lin + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{260,-160},{280,-140}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant desConWatRet[nChi]( + final k=TConWatRet_nominal) + "Design condenser water return (condenser leaving) temperature of each chiller" + annotation (Placement(transformation(extent={{-240,160},{-220,180}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minChiWatSup[nChi]( + final k=TChiWatSupMin) + "Lowest chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-240,100},{-220,120}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract maxLif[nChi] + "Maximum LIFT of each chiller" + annotation (Placement(transformation(extent={{-160,130},{-140,150}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter addPar( + final p=-10*5/9) + "Output sum of input and a parameter" + annotation (Placement(transformation(extent={{-100,-130},{-80,-110}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMin lowDesConWatRet( + final nin=nChi) + "Lowest design condenser water return temperature" + annotation (Placement(transformation(extent={{-160,-130},{-140,-110}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai( + final k=1.1) "Gain factor" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + +equation + connect(uChi, swi.u2) + annotation (Line(points={{-320,40},{-162,40}}, color={255,0,255})); + connect(zeoCon.y, swi.u3) + annotation (Line(points={{-258,10},{-220,10},{-220,32},{-162,32}}, + color={0,0,127})); + connect(chiLifMin.y, swi.u1) + annotation (Line(points={{-258,70},{-220,70},{-220,48},{-162,48}}, + color={0,0,127})); + connect(lifMax.y, coeA.u1) + annotation (Line(points={{-98,140},{-80,140},{-80,106},{-62,106}}, + color={0,0,127})); + connect(lifMin.y, coeA.u2) + annotation (Line(points={{-98,40},{-70,40},{-70,94},{-62,94}},color={0,0,127})); + connect(lifMax.y, coeB.u1) + annotation (Line(points={{-98,140},{38,140}}, color={0,0,127})); + connect(coeB.y, add2.u1) + annotation (Line(points={{62,134},{70,134},{70,-22},{78,-22}}, color={0,0,127})); + connect(pro.y, add2.u2) + annotation (Line(points={{62,-34},{78,-34}}, color={0,0,127})); + connect(lifMax.y, min.u2) + annotation (Line(points={{-98,140},{-80,140},{-80,-66},{118,-66}}, + color={0,0,127})); + connect(add2.y, min.u1) + annotation (Line(points={{102,-28},{110,-28},{110,-54},{118,-54}}, + color={0,0,127})); + connect(min.y, tarLif.u2) + annotation (Line(points={{142,-60},{160,-60},{160,28},{178,28}}, + color={0,0,127})); + connect(lifMin.y, tarLif.u1) + annotation (Line(points={{-98,40},{178,40}}, color={0,0,127})); + connect(tarLif.y, conWatRet.u1) + annotation (Line(points={{202,34},{218,34}}, + color={0,0,127})); + connect(TChiWatSupSet, conWatRet.u2) + annotation (Line(points={{-320,-90},{210,-90},{210,22},{218,22}}, + color={0,0,127})); + connect(swi.y, lifMin.u) + annotation (Line(points={{-138,40},{-122,40}}, color={0,0,127})); + connect(uPla, delPlaEna.u) + annotation (Line(points={{-320,-150},{-222,-150}}, + color={255,0,255})); + connect(delPlaEna.y, chaTim.u) + annotation (Line(points={{-198,-150},{-162,-150}},color={255,0,255})); + connect(zeoTim.y, lin.x1) + annotation (Line(points={{-18,-120},{0,-120},{0,-142},{258,-142}}, + color={0,0,127})); + connect(chaTim.y, lin.u) + annotation (Line(points={{-138,-150},{258,-150}},color={0,0,127})); + connect(maxRamTim.y, lin.x2) + annotation (Line(points={{-78,-180},{-60,-180},{-60,-154},{258,-154}}, + color={0,0,127})); + connect(conWatRet.y, lin.f2) + annotation (Line(points={{242,28},{250,28},{250,-158},{258,-158}}, + color={0,0,127})); + connect(lin.y, TConWatRetSet) + annotation (Line(points={{282,-150},{320,-150}}, color={0,0,127})); + connect(uOpeParLoaRat, pro.u2) + annotation (Line(points={{-320,-40},{38,-40}}, color={0,0,127})); + connect(desConWatRet.y, maxLif.u1) + annotation (Line(points={{-218,170},{-200,170},{-200,146},{-162,146}}, + color={0,0,127})); + connect(maxLif.y,lifMax.u) + annotation (Line(points={{-138,140},{-122,140}}, color={0,0,127})); + connect(lowDesConWatRet.y, addPar.u) + annotation (Line(points={{-138,-120},{-102,-120}}, color={0,0,127})); + connect(addPar.y, lin.f1) + annotation (Line(points={{-78,-120},{-60,-120},{-60,-146},{258,-146}}, + color={0,0,127})); + connect(desConWatRet.y, lowDesConWatRet.u) + annotation (Line(points={{-218,170},{-200,170},{-200,-120},{-162,-120}}, + color={0,0,127})); + connect(minChiWatSup.y, maxLif.u2) annotation (Line(points={{-218,110},{-180, + 110},{-180,134},{-162,134}}, + color={0,0,127})); + connect(coeA.y, gai.u) + annotation (Line(points={{-38,100},{-22,100}}, color={0,0,127})); + connect(gai.y, coeB.u2) annotation (Line(points={{2,100},{20,100},{20,128},{38, + 128}}, color={0,0,127})); + connect(gai.y, pro.u1) annotation (Line(points={{2,100},{20,100},{20,-28},{38, + -28}},color={0,0,127})); +annotation ( + defaultComponentName="conWatRetSet", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-300,-200},{300,200}})), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S")}), +Documentation(info=" +

+Block that ouputs condenser water return temperature setpoint TConWatRetSet +for the tower fan speed control to maintain the return temperature at setpoint. This +implementation is for plants with parallel chiller plants only. It is based on +ASHRAE Guideline36-2021, section 5.20.12.2, item a.5 and a.14. +

+

+The return water temperature setpoint TConWatRetSet shall be the output +of the following equations. +

+
+   TConWatRetSet = TChiWatSupSet + LIFT_target
+
+
+   LIFT_target = Max(LIFT_min, Min(LIFT_max, A*plaParLoaRat + B))
+
+
+   LIFT_max = TConWatRet_nominal - TChiWatSupMin
+
+
+   A = 1.1*(LIFT_max - LIFT_min)
+
+
+   B = LIFT_max - A
+
+
+ +

+Upon plant startup (uPla becomes true), hold TConWatRetSet +at 10 °F less than the minimum TConWatRet_nominal for 10 minutes +(iniPlaTim) before ramping the setpoint to the calculated value above +over 10 minutes (ramTim). +

+ +", revisions=" + +")); +end Setpoint; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Coupled.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Coupled.mo new file mode 100644 index 00000000000..5bd289a3438 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Coupled.mo @@ -0,0 +1,153 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Validation; +model Coupled + "Validation sequence of controlling tower fan speed based on condenser water return temperature control for close coupled plant" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Coupled + couTowSpe(k=0.1, Ti=5) + "Tower fan speed control based on the condenser water return temperature control for close coupled plants" + annotation (Placement(transformation(extent={{60,80},{80,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conRet( + final amplitude=1, + final freqHz=1/1800, + final offset=273.15 + 32) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-80,110},{-60,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1( + final height=2, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-20,80},{0,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conRetSet( + final k=273.15 + 32) + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-20,110},{0,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conWatPumSpe[2]( + final height=fill(0.5, 2), + final duration=fill(3600, 2), + final startTime=fill(300, 2)) "Measured condenser water pump speed" + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp towMaxSpe( + final height=0.25, + final duration=3600, + final offset=0.5) "Maximum tower speed specified by head pressure control loop" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp towMaxSpe1( + final height=-0.25, + final duration=3600, + final offset=0.8) "Maximum tower speed specified by head pressure control loop" + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plrTowMaxSpe( + final height=-0.3, + final duration=3600, + final offset=0.9) "Maximum tower speed reset based on the partial load" + annotation (Placement(transformation(extent={{0,-120},{20,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta1( + final width=0.2, final period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[2] "Logical not" + annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[2] "Logical switch" + annotation (Placement(transformation(extent={{0,-20},{20,0}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta2( + final width=0.1, + final period=3600) + "Chiller one enabling status" + annotation (Placement(transformation(extent={{-80,-120},{-60,-100}}))); + +equation + connect(conRetSet.y, couTowSpe.TConWatRetSet) + annotation (Line(points={{2,120},{20,120},{20,100},{58,100}}, color={0,0,127})); + connect(conRet.y, add2.u1) + annotation (Line(points={{-58,120},{-40,120},{-40,96},{-22,96}}, color={0,0,127})); + connect(ram1.y, add2.u2) + annotation (Line(points={{-58,60},{-40,60},{-40,84},{-22,84}}, color={0,0,127})); + connect(add2.y, couTowSpe.TConWatRet) + annotation (Line(points={{2,90},{20,90},{20,96},{58,96}}, color={0,0,127})); + connect(conWatPumSpe.y, couTowSpe.uConWatPumSpe) + annotation (Line(points={{2,50},{26,50},{26,92},{58,92}}, color={0,0,127})); + connect(chiSta1.y, not1[1].u) + annotation (Line(points={{-58,-70},{-50,-70},{-50,-90},{-42,-90}}, + color={255,0,255})); + connect(chiSta2.y, not1[2].u) + annotation (Line(points={{-58,-110},{-50,-110},{-50,-90},{-42,-90}}, + color={255,0,255})); + connect(not1.y, swi.u2) + annotation (Line(points={{-18,-90},{-14,-90},{-14,-10},{-2,-10}}, + color={255,0,255})); + connect(towMaxSpe1.y, swi[2].u1) + annotation (Line(points={{-58,-30},{-20,-30},{-20,-2},{-2,-2}}, + color={0,0,127})); + connect(towMaxSpe.y, swi[1].u1) + annotation (Line(points={{-58,10},{-20,10},{-20,-2},{-2,-2}}, color={0,0,127})); + connect(swi.y, couTowSpe.uMaxTowSpeSet) + annotation (Line(points={{22,-10},{32,-10},{32,88},{58,88}}, color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{-18,-50},{-8,-50},{-8,-18},{-2,-18}}, color={0,0,127})); + connect(not1.y, couTowSpe.uChi) + annotation (Line(points={{-18,-90},{38,-90},{38,84},{58,84}}, color={255,0,255})); + connect(plrTowMaxSpe.y, couTowSpe.plrTowMaxSpe) + annotation (Line(points={{22,-110},{44,-110},{44,80},{58,80}}, color={0,0,127})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Coupled.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Coupled. +

+

+It shows tower fan speed control for a plant with 2 chillers. The chiller 2 becomes proven on +since 360 seconds and the chiller 1 becomes proven on since 720 seconds. It shows following +processes: +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-140},{100,140}}))); +end Coupled; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Enable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Enable.mo new file mode 100644 index 00000000000..9ec1cad5a44 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Enable.mo @@ -0,0 +1,209 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Validation; +model Enable + "Validation sequence of enabling and disabling tower fans" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Enable + enaTow "Enabling tower fans" + annotation (Placement(transformation(extent={{-140,40},{-120,60}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Enable + disTow "Disable tower fans due to the low head pressure control maximum tower fan speed" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Enable + disTow1 "Disable tower fans due to low fan speed and low tower temperature" + annotation (Placement(transformation(extent={{220,40},{240,60}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conRetSet( + final k=273.15 + 32) "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-220,-10},{-200,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant offTowSta[4]( + final k=fill(false,4)) "Tower is OFF" + annotation (Placement(transformation(extent={{-220,-60},{-200,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conRet1( + final height=2, + final duration=3600, + final offset=273.15 + 32.5) "Condenser return water temperature" + annotation (Placement(transformation(extent={{-260,-40},{-240,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe1( + final k=0.2) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-220,80},{-200,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe2( + final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-260,60},{-240,80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe( + final k=0) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-220,30},{-200,50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeConPum( + final k=1) + "Operating condenser water pumps" + annotation (Placement(transformation(extent={{-260,-90},{-240,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe3( + final k=0.1) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-40,80},{-20,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe4( + final k=0.2) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe1( + final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conRetSet1( + final k=273.15 + 32) + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conRet2( + final height=2, + final duration=3600, + final offset=273.15 + 32.5) "Condenser return water temperature" + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onTowSta1[4]( + final k=fill(true,4)) "Tower is ON" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeConPum1( + final k=2) "Operating condenser water pumps" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe5(final k=0.2) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{140,80},{160,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe6(final k=0.2) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{100,60},{120,80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe2(final k=0.1) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{140,30},{160,50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conRetSet2( + final k=273.15 + 32) "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conRet3( + final height=-2, + final duration=3600, + final offset=273.15 + 32.5) "Condenser return water temperature" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onTowSta2[4]( + final k=fill(true,4)) "Tower is ON" + annotation (Placement(transformation(extent={{140,-70},{160,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeConPum2( + final k=2) + "Operating condenser water pumps" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + +equation + connect(hpTowSpe1.y, enaTow.uMaxTowSpeSet[1]) + annotation (Line(points={{-198,90},{-180,90},{-180,59},{-142,59}}, + color={0,0,127})); + connect(hpTowSpe2.y, enaTow.uMaxTowSpeSet[2]) + annotation (Line(points={{-238,70},{-180,70},{-180,59},{-142,59}}, + color={0,0,127})); + connect(towFanSpe.y,enaTow.uFanSpe) + annotation (Line(points={{-198,40},{-180,40},{-180,56},{-142,56}}, + color={0,0,127})); + connect(conRetSet.y, enaTow.TTowSet) annotation (Line(points={{-198,0},{ + -174,0},{-174,52},{-142,52}}, color={0,0,127})); + connect(conRet1.y, enaTow.TTow) annotation (Line(points={{-238,-30},{-168, + -30},{-168,48},{-142,48}}, color={0,0,127})); + connect(offTowSta.y, enaTow.uTow) annotation (Line(points={{-198,-50},{-162,-50}, + {-162,44},{-142,44}}, color={255,0,255})); + connect(opeConPum.y, enaTow.uConWatPumNum) + annotation (Line(points={{-238,-80},{-156,-80},{-156,41},{-142,41}}, + color={255,127,0})); + connect(hpTowSpe3.y, disTow.uMaxTowSpeSet[1]) + annotation (Line(points={{-18,90},{0,90},{0,59},{38,59}}, color={0,0,127})); + connect(hpTowSpe4.y, disTow.uMaxTowSpeSet[2]) + annotation (Line(points={{-58,70},{0,70},{0,59},{38,59}}, color={0,0,127})); + connect(towFanSpe1.y,disTow.uFanSpe) + annotation (Line(points={{-18,40},{0,40},{0,56},{38,56}}, color={0,0,127})); + connect(conRetSet1.y, disTow.TTowSet) + annotation (Line(points={{-18,0},{6,0},{6,52},{38,52}}, color={0,0,127})); + connect(conRet2.y, disTow.TTow) annotation (Line(points={{-58,-30},{12,-30}, + {12,48},{38,48}}, color={0,0,127})); + connect(onTowSta1.y, disTow.uTow) annotation (Line(points={{-18,-60},{18,-60}, + {18,44},{38,44}}, color={255,0,255})); + connect(opeConPum1.y, disTow.uConWatPumNum) + annotation (Line(points={{-58,-80},{24,-80},{24,41},{38,41}}, + color={255,127,0})); + connect(hpTowSpe5.y, disTow1.uMaxTowSpeSet[1]) + annotation (Line(points={{162,90},{180,90},{180,59},{218,59}}, + color={0,0,127})); + connect(hpTowSpe6.y, disTow1.uMaxTowSpeSet[2]) + annotation (Line(points={{122,70},{180,70},{180,59},{218,59}}, + color={0,0,127})); + connect(towFanSpe2.y,disTow1.uFanSpe) + annotation (Line(points={{162,40},{180,40},{180,56},{218,56}}, + color={0,0,127})); + connect(conRetSet2.y, disTow1.TTowSet) annotation (Line(points={{162,0}, + {186,0},{186,52},{218,52}}, color={0,0,127})); + connect(conRet3.y, disTow1.TTow) annotation (Line(points={{122,-30},{192, + -30},{192,48},{218,48}}, color={0,0,127})); + connect(onTowSta2.y, disTow1.uTow) annotation (Line(points={{162,-60},{198,-60}, + {198,44},{218,44}}, color={255,0,255})); + connect(opeConPum2.y, disTow1.uConWatPumNum) + annotation (Line(points={{122,-80},{204,-80},{204,41},{218,41}}, + color={255,127,0})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Enable.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Enable. +It shows the sequences for enabling and disabling the tower fans under +different conditions. +

+
    +
  1. +The instance enaTow shows that the tower fans will be enabled when: + +
  2. +
  3. +The instance disTow shows that all the tower fans should be disabled +when the enabled chiller's head pressure control maximum tower fan speed +uMaxTowSpeSet has equaled tower minimum speed fanSpeMin +for 5 minutes. +
  4. +
  5. +The instance disTow1 shows that all the tower fans should be disabled +when the tower fans speed uFanSpe have been at minimum speed for +5 minutes and the tower temperature TTow drops below the setpoint +minus 1 °F. +
  6. +
+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-280,-120},{280,120}}))); +end Enable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/LessCoupled.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/LessCoupled.mo new file mode 100644 index 00000000000..5dda04be665 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/LessCoupled.mo @@ -0,0 +1,193 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Validation; +model LessCoupled + "Validation sequence of controlling tower fan speed based on condenser water return temperature control for less coupled plant" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.LessCoupled + lesCouTowSpe + "Tower fan speed control based on the condenser water return temperature control for close coupled plants" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conRet( + amplitude=2, + freqHz=1/1800, + offset=273.15 + 32) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-80,130},{-60,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1( + height=3, + duration=3600, + startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,100},{-60,120}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-20,100},{0,120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conRetSet( + k=273.15 + 32) "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-20,130},{0,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conWatPumSpe[2]( + height=fill(0.5, 2), + duration=fill(3600, 2), + startTime=fill(300, 2)) "Measured condenser water pump speed" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp towMaxSpe( + height=0.25, + duration=3600, + offset=0.5) "Maximum tower speed specified by head pressure control loop" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp towMaxSpe1( + height=-0.25, + duration=3600, + offset=0.8) "Maximum tower speed specified by head pressure control loop" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plrTowMaxSpe( + height=-0.3, + duration=3600, + offset=0.9) "Maximum tower speed reset based on the partial load" + annotation (Placement(transformation(extent={{50,-140},{70,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conSup( + amplitude=2, + freqHz=1/1800, + offset=273.15 + 29) "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram2( + height=3, + duration=3600, + startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Add add1 "Add real inputs" + annotation (Placement(transformation(extent={{-20,20},{0,40}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[2] "Logical switch" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[2]( + k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[2] "Logical not" + annotation (Placement(transformation(extent={{-40,-140},{-20,-120}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta1( + width=0.2, + period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta2( + width=0.1, + period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaEna( + k=true) "Plant enable status" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + +equation + connect(conRetSet.y, lesCouTowSpe.TConWatRetSet) + annotation (Line(points={{2,140},{40,140},{40,90},{58,90}}, color={0,0,127})); + connect(conRet.y, add2.u1) + annotation (Line(points={{-58,140},{-40,140},{-40,116},{-22,116}}, + color={0,0,127})); + connect(ram1.y, add2.u2) + annotation (Line(points={{-58,110},{-40,110},{-40,104},{-22,104}}, + color={0,0,127})); + connect(add2.y, lesCouTowSpe.TConWatRet) + annotation (Line(points={{2,110},{32,110},{32,88},{58,88}}, + color={0,0,127})); + connect(conWatPumSpe.y, lesCouTowSpe.uConWatPumSpe) + annotation (Line(points={{-58,60},{20,60},{20,82},{58,82}}, color={0,0,127})); + connect(conSup.y, add1.u1) + annotation (Line(points={{-58,30},{-40,30},{-40,36},{-22,36}}, + color={0,0,127})); + connect(ram2.y, add1.u2) + annotation (Line(points={{-58,0},{-40,0},{-40,24},{-22,24}}, color={0,0,127})); + connect(add1.y, lesCouTowSpe.TConWatSup) + annotation (Line(points={{2,30},{26,30},{26,78},{58,78}}, + color={0,0,127})); + connect(chiSta1.y, not1[1].u) + annotation (Line(points={{-58,-100},{-50,-100},{-50,-130},{-42,-130}}, + color={255,0,255})); + connect(chiSta2.y, not1[2].u) + annotation (Line(points={{-58,-140},{-50,-140},{-50,-130},{-42,-130}}, + color={255,0,255})); + connect(towMaxSpe.y, swi[1].u1) + annotation (Line(points={{-58,-40},{-40,-40},{-40,-42},{-2,-42}}, + color={0,0,127})); + connect(towMaxSpe1.y, swi[2].u1) + annotation (Line(points={{-58,-70},{-40,-70},{-40,-42},{-2,-42}}, + color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{-18,-90},{-6,-90},{-6,-58},{-2,-58}}, color={0,0,127})); + connect(not1.y, swi.u2) + annotation (Line(points={{-18,-130},{-12,-130},{-12,-50},{-2,-50}}, + color={255,0,255})); + connect(swi.y, lesCouTowSpe.uMaxTowSpeSet) + annotation (Line(points={{22,-50},{32,-50},{32,75},{58,75}}, color={0,0,127})); + connect(not1.y, lesCouTowSpe.uChi) + annotation (Line(points={{-18,-130},{38,-130},{38,73},{58,73}}, color={255,0,255})); + connect(plrTowMaxSpe.y, lesCouTowSpe.plrTowMaxSpe) + annotation (Line(points={{72,-130},{80,-130},{80,60},{44,60},{44,70}, + {58,70}}, color={0,0,127})); + connect(plaEna.y, lesCouTowSpe.uPla) annotation (Line(points={{2,80},{14,80},{ + 14,85},{58,85}}, color={255,0,255})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/LessCoupled.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.LessCoupled. +

+

+It shows the calculation of the condenser water supply temperature setpoint and +the tower fan speed setpoint. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-160},{100,160}}))); +end LessCoupled; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Setpoint.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Setpoint.mo new file mode 100644 index 00000000000..56861348958 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Setpoint.mo @@ -0,0 +1,116 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Validation; +model Setpoint + "Validation sequence of specifying condener return water temperature setpoint" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Setpoint + conWatRetSet( + nChi=2, + LIFT_min={12,14}, + TConWatRet_nominal={303.15,305.15}) + "Specify condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + width=0.15, + period=3600) + "Generate boolean pulse" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + k=false) "Constant false" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp parLoaRat( + height=0.6, + duration=3600) + "Partial load ratio" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + k=0) "Constant zero" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatSupSet( + k=273.15 + 6.5) + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + +equation + connect(booPul.y, not1.u) + annotation (Line(points={{-58,60},{-42,60}}, color={255,0,255})); + connect(not1.y, conWatRetSet.uChi[1]) + annotation (Line(points={{-18,60},{50,60},{50,27.5},{58,27.5}}, + color={255,0,255})); + connect(con.y, conWatRetSet.uChi[2]) + annotation (Line(points={{-18,30},{40,30},{40,28.5},{58,28.5}}, + color={255,0,255})); + connect(not1.y, swi.u2) + annotation (Line(points={{-18,60},{-10,60},{-10,-20},{-2,-20}}, + color={255,0,255})); + connect(zer.y, swi.u3) + annotation (Line(points={{-58,-40},{-20,-40},{-20,-28},{-2,-28}}, + color={0,0,127})); + connect(parLoaRat.y, swi.u1) + annotation (Line(points={{-58,0},{-20,0},{-20,-12},{-2,-12}}, color={0,0,127})); + connect(swi.y, conWatRetSet.uOpeParLoaRat) + annotation (Line(points={{22,-20},{30,-20},{30,23},{58,23}}, color={0,0,127})); + connect(chiWatSupSet.y, conWatRetSet.TChiWatSupSet) + annotation (Line(points={{22,-60},{40,-60},{40,17},{58,17}}, color={0,0,127})); + connect(not1.y, conWatRetSet.uPla) + annotation (Line(points={{-18,60},{50,60},{50,12},{58,12}}, color={255,0,255})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Setpoint.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences.Setpoint. +

+

+It shows the calculation of the condenser water return temperature setpoint for the +case that the plant is enabled at 540 seconds. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-80},{100,80}}))); +end Setpoint; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..dfced9fabbd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/package.order new file mode 100644 index 00000000000..5efb88623d5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/package.order @@ -0,0 +1,4 @@ +Coupled +Enable +LessCoupled +Setpoint diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/package.mo new file mode 100644 index 00000000000..477800edf6f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature; +package Subsequences "Control subsequences of tower fan for controlling condenser water return temperature" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for cooling tower fan speed control, for controlling +condenser water return temperature. +The implementation is based on section 5.20.12.2, item a in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/package.order new file mode 100644 index 00000000000..8e76a4ce365 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/package.order @@ -0,0 +1,5 @@ +Coupled +Enable +LessCoupled +Setpoint +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/Controller.mo new file mode 100644 index 00000000000..0b69b71fb50 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/Controller.mo @@ -0,0 +1,318 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Validation; +model Controller + "Validation sequence of controlling tower fan speed based on condenser water return temperature control" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Controller + towFanSpe + "Tow fan speed for close coupled plants that have waterside economizer" + annotation (Placement(transformation(extent={{-120,180},{-80,220}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Controller + towFanSpe1( + closeCoupledPlant=false) + "Tow fan speed for less coupled plants that have waterside economizer" + annotation (Placement(transformation(extent={{100,180},{140,220}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Controller + towFanSpe2( + have_WSE=false) + "Tow fan speed for close coupled plants that have no waterside economizer" + annotation (Placement(transformation(extent={{320,180},{360,220}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp speWSE( + height=0.9, + duration=3600) + "Tower fan speed when waterside economizer is enabled" + annotation (Placement(transformation(extent={{-360,150},{-340,170}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + width=0.2, + period=3600, + shift=-3000) + "Waterside economizer enabling status" + annotation (Placement(transformation(extent={{-360,50},{-340,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plaCap( + height=8e5, + duration=3600, + offset=1e5) "Real operating chiller plant capacity" + annotation (Placement(transformation(extent={{-360,20},{-340,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conSup( + amplitude=2, + freqHz=1/1800, + offset=273.15 + 29) "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-360,-250},{-340,-230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram2( + height=3, + duration=3600, + startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-290},{-340,-270}}))); + Buildings.Controls.OBC.CDL.Reals.Add add1 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-270},{-280,-250}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram3( + height=3, + duration=3600, + startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-200},{-340,-180}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conRet2( + amplitude=2, + freqHz=1/1800, + offset=273.15 + 28) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-360,-170},{-340,-150}}))); + Buildings.Controls.OBC.CDL.Reals.Add add3 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-190},{-280,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conWatPumSpe1[2]( + height=fill(0.5, 2), + duration=fill(3600, 2), + startTime=fill(300, 2)) "Measured condenser water pump speed" + annotation (Placement(transformation(extent={{-300,-230},{-280,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe1(k=0.5) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-320,0},{-300,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe2(k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-360,-40},{-340,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe3(k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,-60},{-300,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatSupSet( + k=273.15 + 6.5) + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{-360,-120},{-340,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta1( + width=0.2, period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-360,110},{-340,130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta2(k=false) + "Chiller two enabling status" + annotation (Placement(transformation(extent={{-360,80},{-340,100}}))); + Buildings.Controls.OBC.CDL.Logical.Or or3 "Logical or" + annotation (Placement(transformation(extent={{-260,-150},{-240,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Or or4 "Logical or" + annotation (Placement(transformation(extent={{-260,-90},{-240,-70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + nout=4) "Replicate boolean input" + annotation (Placement(transformation(extent={{-200,-90},{-180,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-320,110},{-300,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,180},{-300,200}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-240,150},{-220,170}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-240,-20},{-220,0}}))); + +equation + connect(ram2.y,add1. u2) + annotation (Line(points={{-338,-280},{-320,-280},{-320,-266},{-302,-266}}, + color={0,0,127})); + connect(conSup.y,add1. u1) + annotation (Line(points={{-338,-240},{-320,-240},{-320,-254},{-302,-254}}, + color={0,0,127})); + connect(wseSta.y, towFanSpe.uWse) + annotation (Line(points={{-338,60},{-188,60},{-188,212},{-122,212}}, + color={255,0,255})); + connect(plaCap.y, towFanSpe.reqPlaCap) + annotation (Line(points={{-338,30},{-182,30},{-182,209},{-122,209}}, + color={0,0,127})); + connect(towFanSpe3.y,towFanSpe.uFanSpe) + annotation (Line(points={{-298,-50},{-170,-50},{-170,203},{-122,203}}, + color={0,0,127})); + connect(chiWatSupSet.y, towFanSpe.TChiWatSupSet) + annotation (Line(points={{-338,-110},{-158,-110},{-158,194},{-122,194}}, + color={0,0,127})); + connect(conRet2.y, add3.u1) + annotation (Line(points={{-338,-160},{-320,-160},{-320,-174},{-302,-174}}, + color={0,0,127})); + connect(ram3.y, add3.u2) + annotation (Line(points={{-338,-190},{-320,-190},{-320,-186},{-302,-186}}, + color={0,0,127})); + connect(add3.y, towFanSpe.TConWatRet) + annotation (Line(points={{-278,-180},{-146,-180},{-146,188},{-122,188}}, + color={0,0,127})); + connect(conWatPumSpe1.y, towFanSpe.uConWatPumSpe) + annotation (Line(points={{-278,-220},{-140,-220},{-140,185},{-122,185}}, + color={0,0,127})); + connect(wseSta.y, towFanSpe1.uWse) + annotation (Line(points={{-338,60},{32,60},{32,212},{98,212}}, + color={255,0,255})); + connect(plaCap.y, towFanSpe1.reqPlaCap) + annotation (Line(points={{-338,30},{38,30},{38,209},{98,209}}, + color={0,0,127})); + connect(towFanSpe3.y,towFanSpe1.uFanSpe) + annotation (Line(points={{-298,-50},{50,-50},{50,203},{98,203}}, + color={0,0,127})); + connect(chiWatSupSet.y, towFanSpe1.TChiWatSupSet) + annotation (Line(points={{-338,-110},{62,-110},{62,194},{98,194}}, + color={0,0,127})); + connect(add3.y, towFanSpe1.TConWatRet) + annotation (Line(points={{-278,-180},{74,-180},{74,188},{98,188}}, + color={0,0,127})); + connect(conWatPumSpe1.y, towFanSpe1.uConWatPumSpe) + annotation (Line(points={{-278,-220},{80,-220},{80,185},{98,185}}, + color={0,0,127})); + connect(add1.y, towFanSpe1.TConWatSup) + annotation (Line(points={{-278,-260},{86,-260},{86,182},{98,182}}, + color={0,0,127})); + connect(plaCap.y, towFanSpe2.reqPlaCap) + annotation (Line(points={{-338,30},{246,30},{246,209},{318,209}}, + color={0,0,127})); + connect(towFanSpe3.y,towFanSpe2.uFanSpe) + annotation (Line(points={{-298,-50},{258,-50},{258,203},{318,203}}, + color={0,0,127})); + connect(chiWatSupSet.y, towFanSpe2.TChiWatSupSet) + annotation (Line(points={{-338,-110},{270,-110},{270,194},{318,194}}, + color={0,0,127})); + connect(add3.y, towFanSpe2.TConWatRet) + annotation (Line(points={{-278,-180},{282,-180},{282,188},{318,188}}, + color={0,0,127})); + connect(conWatPumSpe1.y, towFanSpe2.uConWatPumSpe) + annotation (Line(points={{-278,-220},{288,-220},{288,185},{318,185}}, + color={0,0,127})); + connect(chiSta2.y, towFanSpe.uChi[2]) + annotation (Line(points={{-338,90},{-194,90},{-194,215},{-122,215}}, + color={255,0,255})); + connect(chiSta2.y, towFanSpe1.uChi[2]) + annotation (Line(points={{-338,90},{26,90},{26,215},{98,215}}, + color={255,0,255})); + connect(chiSta2.y, towFanSpe2.uChi[2]) + annotation (Line(points={{-338,90},{240,90},{240,215},{318,215}}, + color={255,0,255})); + connect(or3.y, towFanSpe.uPla) + annotation (Line(points={{-238,-140},{-152,-140},{-152,191},{-122,191}}, + color={255,0,255})); + connect(or3.y, towFanSpe1.uPla) + annotation (Line(points={{-238,-140},{68,-140},{68,191},{98,191}}, + color={255,0,255})); + connect(or3.y, towFanSpe2.uPla) + annotation (Line(points={{-238,-140},{276,-140},{276,191},{318,191}}, + color={255,0,255})); + connect(or3.y, booRep.u) + annotation (Line(points={{-238,-140},{-220,-140},{-220,-80},{-202,-80}}, + color={255,0,255})); + connect(booRep.y, towFanSpe.uTow) annotation (Line(points={{-178,-80},{-164,-80}, + {-164,200},{-122,200}}, color={255,0,255})); + connect(booRep.y, towFanSpe1.uTow) annotation (Line(points={{-178,-80},{56,-80}, + {56,200},{98,200}}, color={255,0,255})); + connect(booRep.y, towFanSpe2.uTow) annotation (Line(points={{-178,-80},{264,-80}, + {264,200},{318,200}}, color={255,0,255})); + connect(chiSta1.y, not1.u) + annotation (Line(points={{-338,120},{-322,120}}, color={255,0,255})); + connect(not1.y, towFanSpe.uChi[1]) + annotation (Line(points={{-298,120},{-194,120},{-194,215},{-122,215}}, + color={255,0,255})); + connect(not1.y, towFanSpe1.uChi[1]) + annotation (Line(points={{-298,120},{26,120},{26,215},{98,215}}, + color={255,0,255})); + connect(not1.y, towFanSpe2.uChi[1]) + annotation (Line(points={{-298,120},{240,120},{240,215},{318,215}}, + color={255,0,255})); + connect(wseSta.y, swi.u2) + annotation (Line(points={{-338,60},{-292,60},{-292,160},{-242,160}}, + color={255,0,255})); + connect(speWSE.y, swi.u1) + annotation (Line(points={{-338,160},{-300,160},{-300,168},{-242,168}}, + color={0,0,127})); + connect(zer.y, swi.u3) + annotation (Line(points={{-298,190},{-260,190},{-260,152},{-242,152}}, + color={0,0,127})); + connect(swi.y, towFanSpe.uTowSpeWSE) + annotation (Line(points={{-218,160},{-200,160},{-200,218},{-122,218}}, + color={0,0,127})); + connect(swi.y, towFanSpe1.uTowSpeWSE) + annotation (Line(points={{-218,160},{20,160},{20,218},{98,218}}, color={0,0,127})); + connect(not1.y, swi1.u2) + annotation (Line(points={{-298,120},{-280,120},{-280,-10},{-242,-10}}, + color={255,0,255})); + connect(hpTowSpe1.y, swi1.u1) + annotation (Line(points={{-298,10},{-276,10},{-276,-2},{-242,-2}}, + color={0,0,127})); + connect(zer.y, swi1.u3) + annotation (Line(points={{-298,190},{-260,190},{-260,-18},{-242,-18}}, + color={0,0,127})); + connect(swi1.y, towFanSpe.uMaxTowSpeSet[1]) + annotation (Line(points={{-218,-10},{-176,-10},{-176,206},{-122,206}}, + color={0,0,127})); + connect(hpTowSpe2.y, towFanSpe.uMaxTowSpeSet[2]) + annotation (Line(points={{-338,-30},{-176,-30},{-176,206},{-122,206}}, + color={0,0,127})); + connect(swi1.y, towFanSpe1.uMaxTowSpeSet[1]) + annotation (Line(points={{-218,-10},{44,-10},{44,206},{98,206}}, + color={0,0,127})); + connect(hpTowSpe2.y, towFanSpe1.uMaxTowSpeSet[2]) + annotation (Line(points={{-338,-30},{44,-30},{44,206},{98,206}}, + color={0,0,127})); + connect(swi1.y, towFanSpe2.uMaxTowSpeSet[1]) + annotation (Line(points={{-218,-10},{252,-10},{252,206},{318,206}}, + color={0,0,127})); + connect(hpTowSpe2.y, towFanSpe2.uMaxTowSpeSet[2]) + annotation (Line(points={{-338,-30},{252,-30},{252,206},{318,206}}, + color={0,0,127})); + connect(not1.y, or4.u1) annotation (Line(points={{-298,120},{-280,120},{-280,-80}, + {-262,-80}}, color={255,0,255})); + connect(chiSta2.y, or4.u2) annotation (Line(points={{-338,90},{-286,90},{-286, + -88},{-262,-88}}, color={255,0,255})); + connect(wseSta.y, or3.u2) annotation (Line(points={{-338,60},{-292,60},{-292,-148}, + {-262,-148}}, color={255,0,255})); + connect(or4.y, or3.u1) annotation (Line(points={{-238,-80},{-230,-80},{-230,-100}, + {-270,-100},{-270,-140},{-262,-140}}, color={255,0,255})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature.Controller. +

+

+It shows the calculations of the fan speed setpoint for the three different plants, +including the close coupled plants that have waterside economizer (towFanSpe), +the less coupled plants that have waterside economizer (towFanSpe1), +and the close coupled plants that have no waterside economizer (towFanSpe2). +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-400,-300},{400,300}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/package.mo new file mode 100644 index 00000000000..e288478dfc3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.ReturnWaterTemperature. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/package.mo new file mode 100644 index 00000000000..8f8f3b5a679 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed; +package ReturnWaterTemperature "Sequences of control tower fan speed for controlling condenser water return temperature" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains sequences of cooling tower fan speed control, for control condenser +water return temperature. +The implementation is based on section 5.20.12.2, item a in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end ReturnWaterTemperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/Controller.mo new file mode 100644 index 00000000000..bf8a580556e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/Controller.mo @@ -0,0 +1,353 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.Validation; +model Controller "Validation sequence of controlling tower fan speed" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.Controller + cloCouWitWse + "Tower fan speed controller of plant that is close coupled and has waterside economizer" + annotation (Placement(transformation(extent={{-80,280},{-60,320}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.Controller + lesCouWitWse(final closeCoupledPlant=false) + "Tower fan speed controller of plant that is less coupled and has waterside economizer" + annotation (Placement(transformation(extent={{100,280},{120,320}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.Controller + cloCouNoWse(final have_WSE=false) + "Tower fan speed controller of plant that is close coupled and has no waterside economizer" + annotation (Placement(transformation(extent={{280,280},{300,320}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + final width=0.2, final period=3600, + shift=-3000) + "Waterside economizer enabling status" + annotation (Placement(transformation(extent={{-360,140},{-340,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plaCap( + final height=8e5, + final duration=3600, + final offset=1e5) "Real operating chiller plant capacity" + annotation (Placement(transformation(extent={{-360,10},{-340,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conSup( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 29) "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-360,-250},{-340,-230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram2( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-290},{-340,-270}}))); + Buildings.Controls.OBC.CDL.Reals.Add add1 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-270},{-280,-250}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram3( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-200},{-340,-180}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conRet2( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 28) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-360,-170},{-340,-150}}))); + Buildings.Controls.OBC.CDL.Reals.Add add3 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-190},{-280,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conWatPumSpe1[2]( + final height=fill(0.5, 2), + final duration=fill(3600, 2), + final startTime=fill(300, 2)) "Measured condenser water pump speed" + annotation (Placement(transformation(extent={{-300,-230},{-280,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe1(final k=0.5) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-320,-10},{-300,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe2(final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-360,-70},{-340,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe3(final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,110},{-300,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatSupSet( + final k=273.15 + 6.5) + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{-360,-120},{-340,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta1( + final width=0.2, final period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-360,200},{-340,220}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta2(final k=false) + "Chiller two enabling status" + annotation (Placement(transformation(extent={{-360,170},{-340,190}}))); + Buildings.Controls.OBC.CDL.Logical.Or or3 "Logical or" + annotation (Placement(transformation(extent={{-260,-150},{-240,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Or or4 "Logical or" + annotation (Placement(transformation(extent={{-260,-90},{-240,-70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=4) "Replicate boolean input" + annotation (Placement(transformation(extent={{-200,-90},{-180,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-320,200},{-300,220}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,-50},{-300,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-240,-30},{-220,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-260,260},{-240,280}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{-360,240},{-340,260}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + final amplitude=0.2*1e4, + final freqHz=1/1200, + final offset=1.1*1e4, + final startTime=180) "Chiller load" + annotation (Placement(transformation(extent={{-360,280},{-340,300}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiSup( + final amplitude=0.5, + final freqHz=1/1800, + final offset=273.15 + 7.1) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-360,80},{-340,100}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,40},{-340,60}}))); + Buildings.Controls.OBC.CDL.Reals.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-260,60},{-240,80}}))); + +equation + connect(ram2.y,add1. u2) + annotation (Line(points={{-338,-280},{-320,-280},{-320,-266},{-302,-266}}, + color={0,0,127})); + connect(conSup.y,add1. u1) + annotation (Line(points={{-338,-240},{-320,-240},{-320,-254},{-302,-254}}, + color={0,0,127})); + connect(conRet2.y, add3.u1) + annotation (Line(points={{-338,-160},{-320,-160},{-320,-174},{-302,-174}}, + color={0,0,127})); + connect(ram3.y, add3.u2) + annotation (Line(points={{-338,-190},{-320,-190},{-320,-186},{-302,-186}}, + color={0,0,127})); + connect(or3.y, booRep.u) + annotation (Line(points={{-238,-140},{-220,-140},{-220,-80},{-202,-80}}, + color={255,0,255})); + connect(chiSta1.y, not1.u) + annotation (Line(points={{-338,210},{-322,210}}, color={255,0,255})); + connect(not1.y, swi1.u2) + annotation (Line(points={{-298,210},{-280,210},{-280,-20},{-242,-20}}, + color={255,0,255})); + connect(hpTowSpe1.y, swi1.u1) + annotation (Line(points={{-298,0},{-260,0},{-260,-12},{-242,-12}}, + color={0,0,127})); + connect(zer.y, swi1.u3) + annotation (Line(points={{-298,-40},{-260,-40},{-260,-28},{-242,-28}}, + color={0,0,127})); + connect(con1.y,swi2. u3) + annotation (Line(points={{-338,250},{-320,250},{-320,262},{-262,262}}, + color={0,0,127})); + connect(sin.y,swi2. u1) + annotation (Line(points={{-338,290},{-320,290},{-320,278},{-262,278}}, + color={0,0,127})); + connect(not1.y, swi2.u2) + annotation (Line(points={{-298,210},{-280,210},{-280,270},{-262,270}}, + color={255,0,255})); + connect(con1.y, cloCouWitWse.chiLoa[2]) + annotation (Line(points={{-338,250},{-210,250},{-210,319},{-82,319}}, + color={0,0,127})); + connect(not1.y, cloCouWitWse.uChi[1]) + annotation (Line(points={{-298,210},{-200,210},{-200,316},{-82,316}}, + color={255,0,255})); + connect(chiSta2.y, cloCouWitWse.uChi[2]) + annotation (Line(points={{-338,180},{-200,180},{-200,316},{-82,316}}, + color={255,0,255})); + connect(wseSta.y, cloCouWitWse.uWse) + annotation (Line(points={{-338,150},{-190,150},{-190,313},{-82,313}}, + color={255,0,255})); + connect(towFanSpe3.y, cloCouWitWse.uFanSpe) + annotation (Line(points={{-298,120},{-180,120},{-180,310},{-82,310}}, + color={0,0,127})); + connect(chiSup.y,add2. u1) + annotation (Line(points={{-338,90},{-320,90},{-320,76},{-262,76}}, + color={0,0,127})); + connect(ram1.y,add2. u2) + annotation (Line(points={{-338,50},{-320,50},{-320,64},{-262,64}}, + color={0,0,127})); + connect(add2.y, cloCouWitWse.TChiWatSup) + annotation (Line(points={{-238,70},{-170,70},{-170,307},{-82,307}}, + color={0,0,127})); + connect(chiWatSupSet.y, cloCouWitWse.TChiWatSupSet) + annotation (Line(points={{-338,-110},{-160,-110},{-160,304},{-82,304}}, + color={0,0,127})); + connect(plaCap.y, cloCouWitWse.reqPlaCap) + annotation (Line(points={{-338,20},{-150,20},{-150,301},{-82,301}}, + color={0,0,127})); + connect(swi1.y, cloCouWitWse.uMaxTowSpeSet[1]) + annotation (Line(points={{-218,-20},{-140,-20},{-140,298},{-82,298}}, + color={0,0,127})); + connect(hpTowSpe2.y, cloCouWitWse.uMaxTowSpeSet[2]) + annotation (Line(points={{-338,-60},{-140,-60},{-140,298},{-82,298}}, + color={0,0,127})); + connect(booRep.y, cloCouWitWse.uTow) + annotation (Line(points={{-178,-80},{-130,-80},{-130,295},{-82,295}}, + color={255,0,255})); + connect(or3.y, cloCouWitWse.uPla) + annotation (Line(points={{-238,-140},{-120,-140},{-120,289},{-82,289}}, + color={255,0,255})); + connect(add3.y, cloCouWitWse.TConWatRet) + annotation (Line(points={{-278,-180},{-110,-180},{-110,286},{-82,286}}, + color={0,0,127})); + connect(conWatPumSpe1.y, cloCouWitWse.uConWatPumSpe) + annotation (Line(points={{-278,-220},{-100,-220},{-100,283},{-82,283}}, + color={0,0,127})); + connect(swi2.y, cloCouWitWse.chiLoa[1]) + annotation (Line(points={{-238,270},{-210,270},{-210,319},{-82,319}}, + color={0,0,127})); + connect(swi2.y, lesCouWitWse.chiLoa[1]) + annotation (Line(points={{-238,270},{-40,270},{-40,319},{98,319}}, + color={0,0,127})); + connect(con1.y, lesCouWitWse.chiLoa[2]) + annotation (Line(points={{-338,250},{-40,250},{-40,319},{98,319}}, + color={0,0,127})); + connect(not1.y, lesCouWitWse.uChi[1]) + annotation (Line(points={{-298,210},{-30,210},{-30,316},{98,316}}, + color={255,0,255})); + connect(chiSta2.y, lesCouWitWse.uChi[2]) + annotation (Line(points={{-338,180},{-20,180},{-20,316},{98,316}}, + color={255,0,255})); + connect(wseSta.y, lesCouWitWse.uWse) + annotation (Line(points={{-338,150},{-10,150},{-10,313},{98,313}}, + color={255,0,255})); + connect(towFanSpe3.y, lesCouWitWse.uFanSpe) + annotation (Line(points={{-298,120},{0,120},{0,310},{98,310}}, + color={0,0,127})); + connect(add2.y, lesCouWitWse.TChiWatSup) + annotation (Line(points={{-238,70},{10,70},{10,307},{98,307}}, + color={0,0,127})); + connect(chiWatSupSet.y, lesCouWitWse.TChiWatSupSet) + annotation (Line(points={{-338,-110},{20,-110},{20,304},{98,304}}, + color={0,0,127})); + connect(plaCap.y, lesCouWitWse.reqPlaCap) + annotation (Line(points={{-338,20},{30,20},{30,301},{98,301}}, + color={0,0,127})); + connect(swi1.y, lesCouWitWse.uMaxTowSpeSet[1]) + annotation (Line(points={{-218,-20},{40,-20},{40,298},{98,298}}, + color={0,0,127})); + connect(hpTowSpe2.y, lesCouWitWse.uMaxTowSpeSet[2]) + annotation (Line(points={{-338,-60},{40,-60},{40,298},{98,298}}, + color={0,0,127})); + connect(booRep.y, lesCouWitWse.uTow) + annotation (Line(points={{-178,-80},{50,-80},{50,295},{98,295}}, + color={255,0,255})); + connect(or3.y, lesCouWitWse.uPla) + annotation (Line(points={{-238,-140},{60,-140},{60,289},{98,289}}, + color={255,0,255})); + connect(add3.y, lesCouWitWse.TConWatRet) + annotation (Line(points={{-278,-180},{70,-180},{70,286},{98,286}}, + color={0,0,127})); + connect(conWatPumSpe1.y, lesCouWitWse.uConWatPumSpe) + annotation (Line(points={{-278,-220},{80,-220},{80,283},{98,283}}, + color={0,0,127})); + connect(add1.y, lesCouWitWse.TConWatSup) + annotation (Line(points={{-278,-260},{90,-260},{90,281},{98,281}}, + color={0,0,127})); + connect(not1.y, cloCouNoWse.uChi[1]) + annotation (Line(points={{-298,210},{140,210},{140,316},{278,316}}, + color={255,0,255})); + connect(chiSta2.y, cloCouNoWse.uChi[2]) + annotation (Line(points={{-338,180},{140,180},{140,316},{278,316}}, + color={255,0,255})); + connect(towFanSpe3.y, cloCouNoWse.uFanSpe) + annotation (Line(points={{-298,120},{150,120},{150,310},{278,310}}, + color={0,0,127})); + connect(chiWatSupSet.y, cloCouNoWse.TChiWatSupSet) + annotation (Line(points={{-338,-110},{160,-110},{160,304},{278,304}}, + color={0,0,127})); + connect(plaCap.y, cloCouNoWse.reqPlaCap) + annotation (Line(points={{-338,20},{170,20},{170,301},{278,301}}, + color={0,0,127})); + connect(swi1.y, cloCouNoWse.uMaxTowSpeSet[1]) + annotation (Line(points={{-218,-20},{180,-20},{180,298},{278,298}}, + color={0,0,127})); + connect(hpTowSpe2.y, cloCouNoWse.uMaxTowSpeSet[2]) + annotation (Line(points={{-338,-60},{180,-60},{180,298},{278,298}}, + color={0,0,127})); + connect(booRep.y, cloCouNoWse.uTow) + annotation (Line(points={{-178,-80},{190,-80},{190,295},{278,295}}, + color={255,0,255})); + connect(or3.y, cloCouNoWse.uPla) + annotation (Line(points={{-238,-140},{200,-140},{200,289},{278,289}}, + color={255,0,255})); + connect(add3.y, cloCouNoWse.TConWatRet) + annotation (Line(points={{-278,-180},{210,-180},{210,286},{278,286}}, + color={0,0,127})); + connect(conWatPumSpe1.y, cloCouNoWse.uConWatPumSpe) + annotation (Line(points={{-278,-220},{220,-220},{220,283},{278,283}}, + color={0,0,127})); + connect(not1.y, or4.u1) annotation (Line(points={{-298,210},{-280,210},{-280,-80}, + {-262,-80}}, color={255,0,255})); + connect(chiSta2.y, or4.u2) annotation (Line(points={{-338,180},{-286,180},{-286, + -88},{-262,-88}}, color={255,0,255})); + connect(wseSta.y, or3.u2) annotation (Line(points={{-338,150},{-292,150},{-292, + -148},{-262,-148}}, color={255,0,255})); + connect(or4.y, or3.u1) annotation (Line(points={{-238,-80},{-230,-80},{-230,-100}, + {-270,-100},{-270,-140},{-262,-140}}, color={255,0,255})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed.Controller. +

+

+It shows the calculations of the fan speed setpoint for the three different plants, +including the close coupled plants that have waterside economizer (cloCouWitWse), +the less coupled plants that have waterside economizer (lesCouWitWse), +and the close coupled plants that have no waterside economizer (cloCouNoWse). +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-400,-340},{400,340}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/package.mo new file mode 100644 index 00000000000..4305240aa80 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.FanSpeed. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.mo new file mode 100644 index 00000000000..e441d19f344 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers; +package FanSpeed "Package of sequences for cooling tower fan speed control" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains sequences for cooling tower fan speed control. +The implementation is based on section 5.20.12.2 in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end FanSpeed; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.order new file mode 100644 index 00000000000..62759a805aa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.order @@ -0,0 +1,4 @@ +Controller +EnabledWSE +ReturnWaterTemperature +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Controller.mo new file mode 100644 index 00000000000..8366663f076 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Controller.mo @@ -0,0 +1,243 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging; +block Controller "Sequence of staging cooling tower cells" + + parameter Boolean have_WSE=true + "Flag to indicate if the plant has waterside economizer"; + parameter Integer nTowCel=4 "Total number of cooling tower cells"; + parameter Integer nConWatPum=2 "Total number of condenser water pumps"; + parameter Integer totSta=6 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable"; + parameter Real staVec[totSta]={0,0.5,1,1.5,2,2.5} + "Plant stage vector with size of total number of stages, element value like x.5 means chiller stage x plus WSE"; + parameter Real towCelOnSet[totSta]={0,2,2,4,4,4} + "Design number of tower fan cells that should be ON, according to current chiller stage and WSE status"; + parameter Real chaTowCelIsoTim=90 + "Nominal time needed for open isolation valve of the tower cells"; + parameter Real speChe=0.01 + "Lower threshold value to check if condenser water pump is proven on" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage" + annotation (Placement(transformation(extent={{-140,110},{-100,150}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiStaSet + "Current chiller stage setpoint" + annotation (Placement(transformation(extent={{-140,80},{-100,120}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowStaCha + "Cooling tower stage change command from plant staging process" + annotation (Placement(transformation(extent={{-140,50},{-100,90}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-140,-10},{-100,30}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-140,-40},{-100,0}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-140,-70},{-100,-30}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uIsoVal[nTowCel]( + final max=fill(1, nTowCel)) + "Vector of tower cells isolation valve position" + annotation (Placement(transformation(extent={{-140,-120},{-100,-80}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowSta[nTowCel] + "Vector of tower cells proven on status: true=proven on" + annotation (Placement(transformation(extent={{-140,-150},{-100,-110}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaCel + "Lead tower cell status" + annotation (Placement(transformation(extent={{100,64},{140,104}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yIsoVal[nTowCel]( + final unit=fill("1", nTowCel), + final min=fill(0, nTowCel), + final max=fill(1, nTowCel)) + "Vector of tower cells isolation valve position" + annotation (Placement(transformation(extent={{100,-14},{140,26}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowSta[nTowCel] + "Vector of tower cells status setpoint" + annotation (Placement(transformation(extent={{100,-80},{140,-40}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEndSta + "Rising edge to indicate the staging process is done" + annotation (Placement(transformation(extent={{100,-120},{140,-80}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.CellsNumber + enaCel( + final have_WSE=have_WSE, + final nConWatPum=nConWatPum, + final nTowCel=nTowCel, + final totSta=totSta, + final staVec=staVec, + final towCelOnSet=towCelOnSet, + final speChe=speChe) "Total number of enabled cells" + annotation (Placement(transformation(extent={{-40,80},{-20,100}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.StageProcesses + staPro( + final nTowCel=nTowCel, + final chaTowCelIsoTim=chaTowCelIsoTim) + "Tower staging process" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.ChangeCells ideChaCel( + final nTowCel=nTowCel) + "Identify which cell should change status" + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + +equation + connect(uChiSta, enaCel.uChiSta) annotation (Line(points={{-120,130},{-74,130}, + {-74,99},{-42,99}}, color={255,127,0})); + connect(uChiStaSet, enaCel.uChiStaSet) annotation (Line(points={{-120,100},{-80, + 100},{-80,96},{-42,96}}, color={255,127,0})); + connect(enaCel.uTowStaCha, uTowStaCha) annotation (Line(points={{-42,92},{-80, + 92},{-80,70},{-120,70}}, color={255,0,255})); + connect(uWse, enaCel.uWse) annotation (Line(points={{-120,40},{-74,40},{-74,89}, + {-42,89}}, color={255,0,255})); + connect(enaCel.uConWatPumSpe, uConWatPumSpe) annotation (Line(points={{-42,81}, + {-56,81},{-56,-50},{-120,-50}}, color={0,0,127})); + connect(enaCel.yLeaCel, yLeaCel) annotation (Line(points={{-18,84},{120,84}}, + color={255,0,255})); + connect(staPro.yIsoVal, yIsoVal) + annotation (Line(points={{22,6},{120,6}}, color={0,0,127})); + connect(staPro.yTowSta, yTowSta) annotation (Line(points={{22,0},{60,0},{60,-60}, + {120,-60}}, color={255,0,255})); + connect(uTowSta, staPro.uTowSta) annotation (Line(points={{-120,-130},{-20,-130}, + {-20,-8},{-2,-8}}, color={255,0,255})); + connect(uIsoVal, staPro.uIsoVal) annotation (Line(points={{-120,-100},{-26,-100}, + {-26,0},{-2,0}}, color={0,0,127})); + connect(staPro.yEndSta, yEndSta) annotation (Line(points={{22,-6},{50,-6},{50, + -100},{120,-100}}, color={255,0,255})); + connect(uEnaPla, enaCel.uEnaPla) annotation (Line(points={{-120,10},{-68,10}, + {-68,87},{-42,87}},color={255,0,255})); + connect(enaCel.yNumCel, ideChaCel.uCelNum) annotation (Line(points={{-18,90},{ + 0,90},{0,64},{18,64}}, color={255,127,0})); + connect(uTowSta, ideChaCel.uTowSta) annotation (Line(points={{-120,-130},{-50, + -130},{-50,56},{18,56}}, color={255,0,255})); + connect(ideChaCel.yChaCel, staPro.uChaCel) annotation (Line(points={{42,56},{ + 60,56},{60,20},{-20,20},{-20,8},{-2,8}}, color={255,0,255})); + connect(uPla, enaCel.uPla) annotation (Line(points={{-120,-20},{-62,-20},{-62, + 83},{-42,83}}, color={255,0,255})); +annotation ( + defaultComponentName="towSta", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-100,-140},{100,140}})), + Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,-64},{-62,-76}}, + textColor={0,0,127}, + textString="uIsoVal"), + Text( + extent={{-100,76},{-46,64}}, + textColor={255,127,0}, + textString="uChiStaSet"), + Text( + extent={{-98,96},{-60,84}}, + textColor={255,127,0}, + textString="uChiSta"), + Text( + extent={{-100,56},{-40,44}}, + textColor={255,0,255}, + textString="uTowStaCha"), + Text( + extent={{-100,36},{-70,24}}, + textColor={255,0,255}, + textString="uWse", + visible=have_WSE), + Text( + extent={{-100,-24},{-22,-36}}, + textColor={0,0,127}, + textString="uConWatPumSpe"), + Text( + extent={{-98,-82},{-58,-96}}, + textColor={255,0,255}, + textString="uTowSta"), + Text( + extent={{56,-32},{98,-44}}, + textColor={255,0,255}, + textString="yTowSta"), + Text( + extent={{62,6},{100,-6}}, + textColor={0,0,127}, + textString="yIsoVal"), + Text( + extent={{60,48},{98,36}}, + textColor={255,0,255}, + textString="yLeaCel"), + Text( + extent={{58,-82},{100,-94}}, + textColor={255,0,255}, + textString="yEndSta"), + Text( + extent={{-96,16},{-58,2}}, + textColor={255,0,255}, + textString="uEnaPla"), + Text( + extent={{-100,-4},{-70,-16}}, + textColor={255,0,255}, + visible=have_WSE, + textString="uPla")}), +Documentation(info=" +

+Block controls cooling tower fan staging. This is implemented accoding to +ASHRAE Guideline36-2021, section 5.20.12.1, +which specifies tower fan staging process. It includes two subsequences: +

+ +

+Note that in this implementation, input uTowStaCha +is from chiller staging process sequence. The input is also used for the +condenser water pump staging. Thus, the tower stage changes are initiated concurrentlyl +with condenser water pump stage. +

+

+The sequence also assumes the cells are enabled in order as it is labelled, meaning +that it enabled the cells as cell 1, 2, 3, etc. +

+", revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/CellsNumber.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/CellsNumber.mo new file mode 100644 index 00000000000..9751ff601b2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/CellsNumber.mo @@ -0,0 +1,367 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences; +block CellsNumber + "Sequence for identifying total number of enabling cells" + + parameter Boolean have_WSE = true + "Flag to indicate if the plant has waterside economizer"; + parameter Integer nConWatPum = 2 "Total number of condenser water pumps"; + parameter Integer nTowCel = 4 + "Total number of cooling tower cells"; + parameter Integer totSta = 6 + "Total number of plant stages, including stage zero and the stages with a WSE, if applicable"; + parameter Real staVec[totSta]={0,0.5,1,1.5,2,2.5} + "Plant stage vector with size of total number of stages, element value like x.5 means chiller stage x plus WSE"; + parameter Real towCelOnSet[totSta] = {0,2,2,4,4,4} + "Design number of tower fan cells that should be ON, according to current chiller stage and WSE status"; + parameter Real speChe = 0.01 + "Lower threshold value to check if condenser water pump is proven on" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiSta + "Current chiller stage" + annotation (Placement(transformation(extent={{-300,80},{-260,120}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uChiStaSet + "Current chiller stage setpoint integer" + annotation (Placement(transformation(extent={{-300,40},{-260,80}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowStaCha + "Cooling tower stage change command from plant staging process" + annotation (Placement(transformation(extent={{-300,0},{-260,40}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uWse if have_WSE + "Water side economizer status: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-300,-60},{-260,-20}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-300,-110},{-260,-70}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-300,-150},{-260,-110}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum]( + final unit=fill("1", nConWatPum)) "Current condenser water pump speed" + annotation (Placement(transformation(extent={{-300,-180},{-260,-140}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yNumCel + "Total number of enabled cells" + annotation (Placement(transformation(extent={{260,90},{300,130}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLeaCel + "Lead tower cell status" + annotation (Placement(transformation(extent={{260,-110},{300,-70}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real input to integer output" + annotation (Placement(transformation(extent={{220,100},{240,120}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1 + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-160,-50},{-140,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=false) if not have_WSE + "Constant false" + annotation (Placement(transformation(extent={{-220,-80},{-200,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Add add3 "Add real inputs" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=totSta) "Replicate real input" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con4[totSta]( + final k=staVec) "Stage indicator array" + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract sub4[totSta] "Sum of real inputs" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr[totSta]( + final t=fill(-0.1,totSta)) "Check stage indicator" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[totSta] + "Convert boolean input to integer" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=totSta) "Sun of input vector " + annotation (Placement(transformation(extent={{160,-50},{180,-30}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor celOnNum( + final nin=totSta) + "Number of cells should be enabled at current plant stage" + annotation (Placement(transformation(extent={{120,140},{140,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con5[totSta]( + final k=towCelOnSet) + "Number of enabling cells at each stage" + annotation (Placement(transformation(extent={{80,140},{100,160}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis proOn[nConWatPum]( + final uLow=fill(speChe, nConWatPum), + final uHigh=fill(2*speChe, nConWatPum)) + "Check if the condenser water pump is proven on" + annotation (Placement(transformation(extent={{-220,-170},{-200,-150}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Convert integer input to real" + annotation (Placement(transformation(extent={{-220,130},{-200,150}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea2 + "Convert integer input to real" + annotation (Placement(transformation(extent={{-220,50},{-200,70}}))); + Buildings.Controls.OBC.CDL.Integers.Equal norOpe + "Normal operation, not in the chiller stage change process" + annotation (Placement(transformation(extent={{-220,90},{-200,110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 + "Chiller stage index in the staging process" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nConWatPum) + "Check if any condenser water pump is running" + annotation (Placement(transformation(extent={{-140,-170},{-120,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{200,-100},{220,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi + "Chiller stage index to identify total number of enabling cells" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[totSta] + "Break algebric loop" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Ensure extraction index is within the range" + annotation (Placement(transformation(extent={{80,20},{100,40}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr + "Check if it is greater than 0" + annotation (Placement(transformation(extent={{200,-50},{220,-30}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea + "Convert boolean to real" + annotation (Placement(transformation(extent={{80,60},{100,80}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply mul "Product of the inputs" + annotation (Placement(transformation(extent={{180,100},{200,120}}))); + Buildings.Controls.OBC.CDL.Logical.And anyPumOn + "Check if there is any condenser water pump is proven on" + annotation (Placement(transformation(extent={{-60,-140},{-40,-120}}))); +equation + connect(uWse, booToRea1.u) + annotation (Line(points={{-280,-40},{-162,-40}}, color={255,0,255})); + connect(con2.y, booToRea1.u) + annotation (Line(points={{-198,-70},{-180,-70},{-180,-40},{-162,-40}}, + color={255,0,255})); + connect(booToRea1.y, add3.u2) + annotation (Line(points={{-138,-40},{-120,-40},{-120,-26},{-82,-26}}, + color={0,0,127})); + connect(add3.y, reaRep.u) + annotation (Line(points={{-58,-20},{-42,-20}}, color={0,0,127})); + connect(reaRep.y, sub4.u1) + annotation (Line(points={{-18,-20},{-10,-20},{-10,-34},{-2,-34}}, + color={0,0,127})); + connect(con4.y, sub4.u2) + annotation (Line(points={{-18,-70},{-10,-70},{-10,-46},{-2,-46}}, + color={0,0,127})); + connect(sub4.y, greEquThr.u) + annotation (Line(points={{22,-40},{38,-40}}, color={0,0,127})); + connect(con5.y, celOnNum.u) + annotation (Line(points={{102,150},{118,150}}, color={0,0,127})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{142,-40},{158,-40}}, color={255,127,0})); + connect(uConWatPumSpe, proOn.u) + annotation (Line(points={{-280,-160},{-222,-160}}, color={0,0,127})); + connect(uChiSta, norOpe.u1) + annotation (Line(points={{-280,100},{-222,100}}, color={255,127,0})); + connect(intToRea1.y, swi.u1) + annotation (Line(points={{-198,140},{-170,140},{-170,108},{-122,108}}, + color={0,0,127})); + connect(uTowStaCha, swi1.u2) + annotation (Line(points={{-280,20},{-162,20}}, color={255,0,255})); + connect(uChiSta, intToRea1.u) annotation (Line(points={{-280,100},{-240,100}, + {-240,140},{-222,140}}, color={255,127,0})); + connect(uChiStaSet, norOpe.u2) annotation (Line(points={{-280,60},{-240,60},{ + -240,92},{-222,92}}, color={255,127,0})); + connect(uChiStaSet, intToRea2.u) + annotation (Line(points={{-280,60},{-222,60}}, color={255,127,0})); + connect(intToRea2.y, swi1.u1) annotation (Line(points={{-198,60},{-180,60},{ + -180,28},{-162,28}}, color={0,0,127})); + connect(intToRea1.y, swi1.u3) annotation (Line(points={{-198,140},{-170,140}, + {-170,12},{-162,12}}, color={0,0,127})); + connect(swi1.y, swi.u3) annotation (Line(points={{-138,20},{-130,20},{-130,92}, + {-122,92}}, color={0,0,127})); + connect(swi.y, add3.u1) annotation (Line(points={{-98,100},{-90,100},{-90,-14}, + {-82,-14}}, color={0,0,127})); + connect(reaToInt.y, yNumCel) + annotation (Line(points={{242,110},{280,110}}, color={255,127,0})); + connect(proOn.y, mulOr.u) annotation (Line(points={{-198,-160},{-170,-160},{-170, + -160},{-142,-160}}, color={255,0,255})); + connect(uEnaPla, or2.u1) + annotation (Line(points={{-280,-90},{198,-90}}, color={255,0,255})); + connect(or2.y, yLeaCel) + annotation (Line(points={{222,-90},{280,-90}}, color={255,0,255})); + connect(greEquThr.y, pre1.u) + annotation (Line(points={{62,-40},{78,-40}}, color={255,0,255})); + connect(pre1.y, booToInt.u) + annotation (Line(points={{102,-40},{118,-40}}, color={255,0,255})); + connect(norOpe.y, swi.u2) + annotation (Line(points={{-198,100},{-122,100}}, color={255,0,255})); + connect(mulSumInt.y, intGreThr.u) + annotation (Line(points={{182,-40},{198,-40}}, color={255,127,0})); + connect(intGreThr.y, intSwi.u2) annotation (Line(points={{222,-40},{230,-40}, + {230,-10},{60,-10},{60,30},{78,30}}, color={255,0,255})); + connect(mulSumInt.y, intSwi.u1) annotation (Line(points={{182,-40},{190,-40}, + {190,-20},{50,-20},{50,38},{78,38}}, color={255,127,0})); + connect(conInt.y, intSwi.u3) annotation (Line(points={{22,10},{40,10},{40,22}, + {78,22}}, color={255,127,0})); + connect(intSwi.y, celOnNum.index) + annotation (Line(points={{102,30},{130,30},{130,138}}, color={255,127,0})); + connect(intGreThr.y, booToRea.u) annotation (Line(points={{222,-40},{230,-40}, + {230,-10},{60,-10},{60,70},{78,70}}, color={255,0,255})); + connect(celOnNum.y, mul.u1) annotation (Line(points={{142,150},{160,150},{160, + 116},{178,116}}, color={0,0,127})); + connect(booToRea.y, mul.u2) annotation (Line(points={{102,70},{160,70},{160, + 104},{178,104}}, color={0,0,127})); + connect(mul.y, reaToInt.u) + annotation (Line(points={{202,110},{218,110}}, color={0,0,127})); + connect(mulOr.y, anyPumOn.u2) annotation (Line(points={{-118,-160},{-80,-160}, + {-80,-138},{-62,-138}}, color={255,0,255})); + connect(uPla, anyPumOn.u1) + annotation (Line(points={{-280,-130},{-62,-130}}, color={255,0,255})); + connect(anyPumOn.y, or2.u2) annotation (Line(points={{-38,-130},{180,-130},{ + 180,-98},{198,-98}}, color={255,0,255})); +annotation ( + defaultComponentName="enaCelNum", + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-96,-84},{-18,-96}}, + textColor={0,0,127}, + textString="uConWatPumSpe"), + Text( + extent={{-98,-2},{-72,-16}}, + textColor={255,0,255}, + textString="uWse", + visible=have_WSE), + Text( + extent={{-98,26},{-40,14}}, + textColor={255,0,255}, + textString="uTowStaCha"), + Text( + extent={{-98,66},{-44,54}}, + textColor={255,127,0}, + textString="uChiStaSet"), + Text( + extent={{-100,96},{-56,84}}, + textColor={255,127,0}, + textString="uChiSta"), + Text( + extent={{54,6},{98,-6}}, + textColor={255,127,0}, + textString="yNumCel"), + Text( + extent={{56,-52},{98,-64}}, + textColor={255,0,255}, + textString="yLeaCel"), + Text( + extent={{-98,-22},{-60,-36}}, + textColor={255,0,255}, + textString="uEnaPla"), + Text( + extent={{-98,-62},{-72,-76}}, + textColor={255,0,255}, + visible=have_WSE, + textString="uPla")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-260,-180},{260,180}}), + graphics={ + Text( + extent={{-228,178},{-106,158}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Identify total number of operation cells")}), + Documentation(info=" +

+This block outputs total number of enabling tower cells according to current plant +stage and generates boolean output to enable or disable lead tower cell(s). +It is implemented according to ASHRAE Guideline36-2021, section 5.20.12.1, +

+ +

+The number of enabled tower cells shall be set by plant stage (chiller and economizer) +per the table below. +Note that the table would need to be edited by the system design team for each plant +based on the condenser water flow per stage, number of towers in the plant, and +tower minimum flow requirements. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Chiller stage Number of enabled cells
00
0+WSE2
12
1+WSE4
24
2+WSE4
+
+ +

+If there is change of plant stage uChiSta or waterside economizer +status uWseSta, the cells should be enabled or disabled as below: +

+ +

+The input uTowStaCha is the output from the chiller staging process. +They indicate in the chiller staging process (uChiStauChiStaSet) +when to change the condenser water pump status so also stage the tower cells. +

+", revisions=" + +")); +end CellsNumber; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/ChangeCells.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/ChangeCells.mo new file mode 100644 index 00000000000..27e9e933662 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/ChangeCells.mo @@ -0,0 +1,99 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences; +block ChangeCells "Identify changing cells" + + parameter Integer nTowCel = 4 + "Total number of cooling tower cells"; + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uCelNum + "Total number of cells that should be enabled" + annotation (Placement(transformation(extent={{-180,-40},{-140,0}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowSta[nTowCel] + "Vector of tower cells proven on status: true=enabled tower cell" + annotation (Placement(transformation(extent={{-180,-80},{-140,-40}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowSta[nTowCel] + "True: tower cell should be enabled" + annotation (Placement(transformation(extent={{120,40},{160,80}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaCel[nTowCel] + "True: the cell should change status, either become enabled or disabled" + annotation (Placement(transformation(extent={{120,0},{160,40}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + +protected + final parameter Integer celInd[nTowCel]={i for i in 1:nTowCel} + "Tower cell index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nTowCel]( + final k=celInd) + "Tower cell index array" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nTowCel) + "Replicate integer input" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not chaCel[nTowCel] "True: the cell should change the status" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqual intLesEqu[nTowCel] + "True: the cell should be enabled" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nTowCel] + "Convert boolean to equal" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nTowCel] + "True: cooling tower cell status is the same as commanded on" + annotation (Placement(transformation(extent={{40,10},{60,30}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nTowCel] + "Convert boolean to equal" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + +equation + connect(uCelNum, intRep.u) + annotation (Line(points={{-160,-20},{-122,-20}}, color={255,127,0})); + connect(conInt.y, intLesEqu.u1) + annotation (Line(points={{-98,20},{-62,20}}, color={255,127,0})); + connect(intRep.y, intLesEqu.u2) annotation (Line(points={{-98,-20},{-80,-20},{ + -80,12},{-62,12}}, color={255,127,0})); + connect(uTowSta, booToInt1.u) + annotation (Line(points={{-160,-60},{-22,-60}}, color={255,0,255})); + connect(intLesEqu.y, booToInt.u) + annotation (Line(points={{-38,20},{-22,20}}, color={255,0,255})); + connect(booToInt.y, intEqu.u1) + annotation (Line(points={{2,20},{38,20}}, color={255,127,0})); + connect(booToInt1.y, intEqu.u2) annotation (Line(points={{2,-60},{20,-60},{20, + 12},{38,12}}, color={255,127,0})); + connect(intEqu.y, chaCel.u) + annotation (Line(points={{62,20},{78,20}}, color={255,0,255})); + connect(chaCel.y, yChaCel) + annotation (Line(points={{102,20},{140,20}}, color={255,0,255})); + connect(intLesEqu.y, yTowSta) annotation (Line(points={{-38,20},{-30,20},{-30, + 60},{140,60}}, color={255,0,255})); +annotation (defaultComponentName="ideChaCel", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false,extent={{-140,-80},{120,80}})), + Documentation(info=" +

+This block identifies the cooling tower cells that should change the enabling +status, either should be enabled or disabled. +

+

+It assumes that the cells are enabled in order as cell 1, 2, 3, etc. +

+", revisions=" + +")); +end ChangeCells; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/StageProcesses.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/StageProcesses.mo new file mode 100644 index 00000000000..67742888614 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/StageProcesses.mo @@ -0,0 +1,464 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences; +block StageProcesses "Sequence for process of staging cells" + + parameter Integer nTowCel = 4 + "Total number of cooling tower cells"; + parameter Real chaTowCelIsoTim( + final quantity="Time", + final unit="s") = 90 + "Nominal time needed for open isolation valve"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChaCel[nTowCel] + "Vector of boolean flags to show if a cell should change its status: true = the cell should change status (be enabled or disabled)" + annotation (Placement(transformation(extent={{-240,350},{-200,390}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uIsoVal[nTowCel]( + final unit=fill("1", nTowCel), + final min=fill(0, nTowCel), + final max=fill(1, nTowCel)) "Cooling tower cells isolation valve position" + annotation (Placement(transformation(extent={{-240,60},{-200,100}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uTowSta[nTowCel] + "Vector of tower cells proven on status: true=enabled tower cell" + annotation (Placement(transformation(extent={{-240,-260},{-200,-220}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yIsoVal[nTowCel]( + final unit=fill("1", nTowCel), + final min=fill(0, nTowCel), + final max=fill(1, nTowCel)) "Cooling tower cells isolation valve setpoint" + annotation (Placement(transformation(extent={{200,80},{240,120}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTowSta[nTowCel] + "Vector of tower cells status setpoint" + annotation (Placement(transformation(extent={{200,-280},{240,-240}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEndSta + "Rising edge to indicate the staging process is done" + annotation (Placement(transformation(extent={{200,-380},{240,-340}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Switch swi2[nTowCel] "Logical switch" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim + "Count the time after changing up-stream device status" + annotation (Placement(transformation(extent={{-120,290},{-100,310}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con9(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-40,310},{-20,330}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con7( + final k=chaTowCelIsoTim) "Time to change cooling tower isolation valve" + annotation (Placement(transformation(extent={{-120,260},{-100,280}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con8(final k=1) + "Fully open valve" + annotation (Placement(transformation(extent={{-40,260},{-20,280}}))); + Buildings.Controls.OBC.CDL.Reals.Line lin1 + "Chilled water isolation valve setpoint" + annotation (Placement(transformation(extent={{40,290},{60,310}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nTowCel) + "Replicate real input" + annotation (Placement(transformation(extent={{140,220},{160,240}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[nTowCel] "Logical switch" + annotation (Placement(transformation(extent={{120,-30},{140,-10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nTowCel) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-40,-20},{-20,0}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys3[nTowCel]( + final uLow=fill(0.025, nTowCel), + final uHigh=fill(0.05, nTowCel)) "Check if isolation valve is enabled" + annotation (Placement(transformation(extent={{-140,-120},{-120,-100}}))); + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys4[nTowCel]( + final uLow=fill(0.925, nTowCel), + final uHigh=fill(0.975, nTowCel)) "Check if isolation valve is open more than 95%" + annotation (Placement(transformation(extent={{-140,-150},{-120,-130}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd fulOpe( + final nin=nTowCel) + "Enabled valves are fully open" + annotation (Placement(transformation(extent={{80,-120},{100,-100}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 + "Check if it has fully open the valve and the opening process time has past the threshold" + annotation (Placement(transformation(extent={{100,-160},{120,-140}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greEquThr( + final t=chaTowCelIsoTim) + "Check if it has past the target time of open isolation valve " + annotation (Placement(transformation(extent={{0,-180},{20,-160}}))); + Buildings.Controls.OBC.CDL.Logical.And and1[nTowCel] + "True: cells should be enabled" + annotation (Placement(transformation(extent={{20,-230},{40,-210}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nTowCel) + "Replicate boolean input" + annotation (Placement(transformation(extent={{140,-160},{160,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nTowCel]( + final k=fill(true, nTowCel)) "Enable cells" + annotation (Placement(transformation(extent={{-60,-210},{-40,-190}}))); + Buildings.Controls.OBC.CDL.Logical.Switch enaNexCel[nTowCel] + "Enable next cells" + annotation (Placement(transformation(extent={{80,-230},{100,-210}}))); + Buildings.Controls.OBC.CDL.Logical.And and2[nTowCel] "Logical and" + annotation (Placement(transformation(extent={{-120,220},{-100,240}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nTowCel] "Logical and" + annotation (Placement(transformation(extent={{-60,220},{-40,240}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd enaCel( + final nin=nTowCel) "New cells should be enabled" + annotation (Placement(transformation(extent={{-20,220},{0,240}}))); + Buildings.Controls.OBC.CDL.Reals.Switch celPosSet + "Slowly change the opening setpoint to 1 of the enabling cells isolation valve, or change the setpoint to 0 of the disabling cells" + annotation (Placement(transformation(extent={{100,220},{120,240}}))); + Buildings.Controls.OBC.CDL.Logical.And enaPro "Enabling cells process" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Not disCel "Disable cell" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.And disPro "Disabling cells process" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Logical.Switch newTowCell[nTowCel] + "New tower cell status" + annotation (Placement(transformation(extent={{160,-270},{180,-250}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nTowCel) "In the enabling process" + annotation (Placement(transformation(extent={{80,-270},{100,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Switch disExiCel[nTowCel] + "Disable existing cells" + annotation (Placement(transformation(extent={{80,-310},{100,-290}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nTowCel) "In the disabling process" + annotation (Placement(transformation(extent={{0,-310},{20,-290}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr staPro(nin=nTowCel) + "In tower staging process" + annotation (Placement(transformation(extent={{60,360},{80,380}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr opeVal( + final nin=nTowCel) "Check if there is any opened valve" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 + "Check if the opened valves are fully open" + annotation (Placement(transformation(extent={{140,-90},{160,-70}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nTowCel] + "Convert boolean input to integer" + annotation (Placement(transformation(extent={{0,-120},{20,-100}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nTowCel] + "Convert boolean input to integer" + annotation (Placement(transformation(extent={{0,-150},{20,-130}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nTowCel] + "Check if the opened valves are fully open" + annotation (Placement(transformation(extent={{40,-120},{60,-100}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nTowCel) "In the disabling process" + annotation (Placement(transformation(extent={{120,-350},{140,-330}}))); + Buildings.Controls.OBC.CDL.Logical.Or celChaSta[nTowCel] + "True: there are cells changed status" + annotation (Placement(transformation(extent={{-80,-370},{-60,-350}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg[nTowCel] + "Check if there is any cell being disabled" + annotation (Placement(transformation(extent={{-140,-350},{-120,-330}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg[nTowCel] + "Check if there is any cell being enabled" + annotation (Placement(transformation(extent={{-140,-390},{-120,-370}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr endStaPro( + final nin=nTowCel) + "Check if there is any cell changed status so it means that the staging process is done" + annotation (Placement(transformation(extent={{40,-370},{60,-350}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat[nTowCel] "Change cells status" + annotation (Placement(transformation(extent={{-120,360},{-100,380}}))); + Buildings.Controls.OBC.CDL.Logical.Edge havCha[nTowCel] "Edge" + annotation (Placement(transformation(extent={{-180,360},{-160,380}}))); + Buildings.Controls.OBC.CDL.Logical.And and4[nTowCel] + "True: cells should be disabled" + annotation (Placement(transformation(extent={{-140,-270},{-120,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Switch disExiCel1[nTowCel] + "Disable existing cells" + annotation (Placement(transformation(extent={{-60,-290},{-40,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nTowCel]( + final k=fill(false, nTowCel)) + "Disable cells" + annotation (Placement(transformation(extent={{-140,-220},{-120,-200}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep5( + final nout=nTowCel) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-40,140},{-20,160}}))); + Buildings.Controls.OBC.CDL.Logical.And ideDisCel[nTowCel] + "Identifying the cells to be disabled" + annotation (Placement(transformation(extent={{60,140},{80,160}}))); + Buildings.Controls.OBC.CDL.Reals.Switch offVal[nTowCel] + "Shut off valve if it is disabling cell" + annotation (Placement(transformation(extent={{120,140},{140,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con3[nTowCel]( + final k=fill(0, nTowCel)) + "Constant zero" + annotation (Placement(transformation(extent={{60,180},{80,200}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi3[nTowCel] + "Logical switch" + annotation (Placement(transformation(extent={{160,90},{180,110}}))); + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold holDisPro( + final trueHoldDuration=chaTowCelIsoTim, + final falseHoldDuration=0) + "Holding the disable process" + annotation (Placement(transformation(extent={{-100,140},{-80,160}}))); + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truHol2[nTowCel]( + final trueHoldDuration=fill(chaTowCelIsoTim, nTowCel), + final falseHoldDuration=fill(0, nTowCel)) + "Holding the cell changing signal" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + +equation + connect(con9.y, lin1.x1) + annotation (Line(points={{-18,320},{30,320},{30,308},{38,308}}, + color={0,0,127})); + connect(con7.y, lin1.x2) + annotation (Line(points={{-98,270},{-60,270},{-60,296},{38,296}}, + color={0,0,127})); + connect(con8.y, lin1.f2) + annotation (Line(points={{-18,270},{0,270},{0,292},{38,292}}, + color={0,0,127})); + connect(tim.y, lin1.u) + annotation (Line(points={{-98,300},{38,300}}, color={0,0,127})); + connect(reaRep.y, swi2.u1) + annotation (Line(points={{162,230},{180,230},{180,210},{30,210},{30,38},{58, + 38}}, color={0,0,127})); + connect(swi2.y, swi.u1) + annotation (Line(points={{82,30},{100,30},{100,-12},{118,-12}}, + color={0,0,127})); + connect(uIsoVal, swi2.u3) + annotation (Line(points={{-220,80},{-160,80},{-160,22},{58,22}}, + color={0,0,127})); + connect(booRep.y, swi.u2) + annotation (Line(points={{-18,-10},{80,-10},{80,-20},{118,-20}}, + color={255,0,255})); + connect(greEquThr.y, and5.u2) + annotation (Line(points={{22,-170},{70,-170},{70,-158},{98,-158}}, + color={255,0,255})); + connect(uIsoVal, hys4.u) + annotation (Line(points={{-220,80},{-160,80},{-160,-140},{-142,-140}}, + color={0,0,127})); + connect(uIsoVal, hys3.u) + annotation (Line(points={{-220,80},{-160,80},{-160,-110},{-142,-110}}, + color={0,0,127})); + connect(tim.y, greEquThr.u) + annotation (Line(points={{-98,300},{-70,300},{-70,-170},{-2,-170}}, + color={0,0,127})); + connect(and5.y, booRep1.u) + annotation (Line(points={{122,-150},{138,-150}}, color={255,0,255})); + connect(booRep1.y, and1.u1) + annotation (Line(points={{162,-150},{180,-150},{180,-192},{0,-192},{0,-220}, + {18,-220}}, color={255,0,255})); + connect(and1.y, enaNexCel.u2) + annotation (Line(points={{42,-220},{78,-220}}, color={255,0,255})); + connect(con1.y, enaNexCel.u1) annotation (Line(points={{-38,-200},{60,-200},{60, + -212},{78,-212}}, color={255,0,255})); + connect(uTowSta, enaNexCel.u3) annotation (Line(points={{-220,-240},{60,-240}, + {60,-228},{78,-228}}, color={255,0,255})); + connect(celPosSet.y, reaRep.u) + annotation (Line(points={{122,230},{138,230}}, color={0,0,127})); + connect(uTowSta, and2.u2) annotation (Line(points={{-220,-240},{-180,-240},{-180, + 222},{-122,222}}, color={255,0,255})); + connect(and2.y, not1.u) + annotation (Line(points={{-98,230},{-62,230}}, color={255,0,255})); + connect(not1.y, enaCel.u) annotation (Line(points={{-38,230},{-22,230}}, + color={255,0,255})); + connect(lin1.y, celPosSet.u1) annotation (Line(points={{62,300},{80,300},{80,238}, + {98,238}}, color={0,0,127})); + connect(enaCel.y, enaPro.u1) annotation (Line(points={{2,230},{20,230},{20,200}, + {-120,200},{-120,-60},{-62,-60}}, color={255,0,255})); + connect(enaCel.y, disCel.u) annotation (Line(points={{2,230},{20,230},{20,200}, + {-120,200},{-120,60},{-102,60}}, color={255,0,255})); + connect(disCel.y, disPro.u1) + annotation (Line(points={{-78,60},{-60,60},{-60,50},{-42,50}}, color={255,0,255})); + connect(booRep2.y, newTowCell.u2) + annotation (Line(points={{102,-260},{158,-260}}, color={255,0,255})); + connect(enaNexCel.y, newTowCell.u1) annotation (Line(points={{102,-220},{120,-220}, + {120,-252},{158,-252}}, color={255,0,255})); + connect(booRep3.y, disExiCel.u2) + annotation (Line(points={{22,-300},{78,-300}}, color={255,0,255})); + connect(uTowSta, disExiCel.u3) annotation (Line(points={{-220,-240},{60,-240}, + {60,-308},{78,-308}}, color={255,0,255})); + connect(disPro.y, booRep3.u) annotation (Line(points={{-18,50},{0,50},{0,12},{ + -110,12},{-110,-300},{-2,-300}}, color={255,0,255})); + connect(enaPro.y, booRep2.u) annotation (Line(points={{-38,-60},{-30,-60},{-30, + -260},{78,-260}}, color={255,0,255})); + connect(disExiCel.y, newTowCell.u3) annotation (Line(points={{102,-300},{140,-300}, + {140,-268},{158,-268}}, color={255,0,255})); + connect(newTowCell.y, yTowSta) + annotation (Line(points={{182,-260},{220,-260}}, color={255,0,255})); + connect(con9.y, lin1.f1) annotation (Line(points={{-18,320},{30,320},{30,304}, + {38,304}}, color={0,0,127})); + connect(staPro.y, tim.u) annotation (Line(points={{82,370},{100,370},{100,340}, + {-140,340},{-140,300},{-122,300}}, color={255,0,255})); + connect(staPro.y, disPro.u2) annotation (Line(points={{82,370},{100,370},{100, + 340},{-140,340},{-140,42},{-42,42}}, color={255,0,255})); + connect(staPro.y, enaPro.u2) annotation (Line(points={{82,370},{100,370},{100, + 340},{-140,340},{-140,-68},{-62,-68}}, color={255,0,255})); + connect(hys3.y, booToInt.u) + annotation (Line(points={{-118,-110},{-2,-110}}, color={255,0,255})); + connect(hys4.y, booToInt1.u) + annotation (Line(points={{-118,-140},{-2,-140}},color={255,0,255})); + connect(booToInt.y, intEqu.u1) + annotation (Line(points={{22,-110},{38,-110}}, color={255,127,0})); + connect(booToInt1.y, intEqu.u2) annotation (Line(points={{22,-140},{30,-140},{ + 30,-118},{38,-118}}, color={255,127,0})); + connect(intEqu.y, fulOpe.u) + annotation (Line(points={{62,-110},{78,-110}}, color={255,0,255})); + connect(hys3.y, opeVal.u) annotation (Line(points={{-118,-110},{-20,-110},{-20, + -80},{-2,-80}}, color={255,0,255})); + connect(opeVal.y, and3.u1) + annotation (Line(points={{22,-80},{138,-80}}, color={255,0,255})); + connect(fulOpe.y, and3.u2) annotation (Line(points={{102,-110},{120,-110},{120, + -88},{138,-88}}, color={255,0,255})); + connect(and3.y, and5.u1) annotation (Line(points={{162,-80},{180,-80},{180,-130}, + {70,-130},{70,-150},{98,-150}},color={255,0,255})); + connect(staPro.y, booRep.u) annotation (Line(points={{82,370},{100,370},{100,340}, + {-140,340},{-140,-10},{-42,-10}}, color={255,0,255})); + connect(uTowSta, falEdg.u) annotation (Line(points={{-220,-240},{-180,-240},{-180, + -340},{-142,-340}}, color={255,0,255})); + connect(uTowSta, edg.u) annotation (Line(points={{-220,-240},{-180,-240},{-180, + -380},{-142,-380}}, color={255,0,255})); + connect(booRep4.y, lat.clr) annotation (Line(points={{142,-340},{180,-340},{180, + -318},{-150,-318},{-150,364},{-122,364}}, color={255,0,255})); + connect(falEdg.y, celChaSta.u1) annotation (Line(points={{-118,-340},{-100,-340}, + {-100,-360},{-82,-360}},color={255,0,255})); + connect(edg.y, celChaSta.u2) annotation (Line(points={{-118,-380},{-100,-380}, + {-100,-368},{-82,-368}}, color={255,0,255})); + connect(celChaSta.y, endStaPro.u) annotation (Line(points={{-58,-360},{38,-360}}, + color={255,0,255})); + connect(uChaCel, havCha.u) annotation (Line(points={{-220,370},{-182,370}}, + color={255,0,255})); + connect(havCha.y, lat.u) annotation (Line(points={{-158,370},{-122,370}}, + color={255,0,255})); + connect(endStaPro.y, yEndSta) + annotation (Line(points={{62,-360},{220,-360}},color={255,0,255})); + connect(endStaPro.y, booRep4.u) annotation (Line(points={{62,-360},{80,-360},{ + 80,-340},{118,-340}}, color={255,0,255})); + connect(uTowSta, and4.u2) annotation (Line(points={{-220,-240},{-180,-240},{-180, + -268},{-142,-268}}, color={255,0,255})); + connect(uChaCel, and4.u1) annotation (Line(points={{-220,370},{-190,370},{-190, + -260},{-142,-260}}, color={255,0,255})); + connect(and4.y, disExiCel1.u2) annotation (Line(points={{-118,-260},{-80,-260}, + {-80,-280},{-62,-280}}, color={255,0,255})); + connect(uTowSta, disExiCel1.u3) annotation (Line(points={{-220,-240},{-180,-240}, + {-180,-288},{-62,-288}}, color={255,0,255})); + connect(con2.y, disExiCel1.u1) annotation (Line(points={{-118,-210},{-70,-210}, + {-70,-272},{-62,-272}}, color={255,0,255})); + connect(disExiCel1.y, disExiCel.u1) annotation (Line(points={{-38,-280},{50,-280}, + {50,-292},{78,-292}}, color={255,0,255})); + connect(con9.y, celPosSet.u3) annotation (Line(points={{-18,320},{30,320},{30, + 222},{98,222}}, color={0,0,127})); + connect(enaCel.y, celPosSet.u2) + annotation (Line(points={{2,230},{98,230}}, color={255,0,255})); + connect(uIsoVal, swi.u3) annotation (Line(points={{-220,80},{-160,80},{-160,-28}, + {118,-28}}, color={0,0,127})); + connect(lat.y, staPro.u) + annotation (Line(points={{-98,370},{58,370}}, color={255,0,255})); + connect(lat.y, and1.u2) annotation (Line(points={{-98,370},{-80,370},{-80,350}, + {-170,350},{-170,-228},{18,-228}}, color={255,0,255})); + connect(lat.y, swi2.u2) annotation (Line(points={{-98,370},{-80,370},{-80,350}, + {-170,350},{-170,30},{58,30}}, color={255,0,255})); + connect(lat.y, and2.u1) annotation (Line(points={{-98,370},{-80,370},{-80,350}, + {-170,350},{-170,230},{-122,230}}, color={255,0,255})); + connect(disPro.y, holDisPro.u) annotation (Line(points={{-18,50},{0,50},{0,130}, + {-110,130},{-110,150},{-102,150}}, color={255,0,255})); + connect(havCha.y, truHol2.u) annotation (Line(points={{-158,370},{-130,370},{-130, + 100},{-102,100}}, color={255,0,255})); + connect(holDisPro.y, booRep5.u) + annotation (Line(points={{-78,150},{-42,150}}, color={255,0,255})); + connect(booRep5.y, ideDisCel.u1) + annotation (Line(points={{-18,150},{58,150}}, color={255,0,255})); + connect(truHol2.y, ideDisCel.u2) annotation (Line(points={{-78,100},{20,100},{ + 20,142},{58,142}}, color={255,0,255})); + connect(ideDisCel.y, offVal.u2) + annotation (Line(points={{82,150},{118,150}}, color={255,0,255})); + connect(con3.y, offVal.u1) annotation (Line(points={{82,190},{100,190},{100,158}, + {118,158}}, color={0,0,127})); + connect(uIsoVal, offVal.u3) annotation (Line(points={{-220,80},{100,80},{100,142}, + {118,142}}, color={0,0,127})); + connect(booRep5.y, swi3.u2) annotation (Line(points={{-18,150},{40,150},{40,100}, + {158,100}}, color={255,0,255})); + connect(offVal.y, swi3.u1) annotation (Line(points={{142,150},{150,150},{150,108}, + {158,108}}, color={0,0,127})); + connect(swi.y, swi3.u3) annotation (Line(points={{142,-20},{150,-20},{150,92}, + {158,92}}, color={0,0,127})); + connect(swi3.y, yIsoVal) + annotation (Line(points={{182,100},{220,100}}, color={0,0,127})); +annotation ( + defaultComponentName="towCelStaPro", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-200,-400},{200,400}}), graphics={ + Rectangle( + extent={{-138,-62},{178,-198}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{12,-180},{144,-204}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Check if all enabled isolation valves + have been fully open")}), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-98,88},{-54,76}}, + textColor={255,0,255}, + textString="uChaCel"), + Text( + extent={{-100,6},{-62,-6}}, + textColor={0,0,127}, + textString="uIsoVal"), + Text( + extent={{-100,-74},{-56,-86}}, + textColor={255,0,255}, + textString="uTowSta"), + Text( + extent={{62,66},{100,54}}, + textColor={0,0,127}, + textString="yIsoVal"), + Text( + extent={{56,8},{100,-4}}, + textColor={255,0,255}, + textString="yTowSta"), + Text( + extent={{56,-52},{100,-64}}, + textColor={255,0,255}, + textString="yEndSta")}), +Documentation(info=" +

+This block outputs new status vector of cells. When staging up cells, the cells +should be enabled only when their supply isolation valves have been proven fully +open. It is implemented according to ASHRAE Guideline36-2021, +section 5.20.12.1, item e and f which specifies the process of enabling and disabling +tower fan cells. +

+ +", revisions=" + +")); +end StageProcesses; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/CellsNumber.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/CellsNumber.mo new file mode 100644 index 00000000000..5015d9d7bd6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/CellsNumber.mo @@ -0,0 +1,193 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.Validation; +model CellsNumber + "Validation sequence of identifying total number of enabling cells" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.CellsNumber + enaTowCel( + nConWatPum=2, + nTowCel=4) "Find number of enabling cells" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + width=0.15, + period=3600, + shift=300) "Water side economizer status" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiStaGen( + height=1.2, + duration=3600, + offset=1) "Generate chiller stage" + annotation (Placement(transformation(extent={{-100,40},{-80,60}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger chiStaSet "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant curChiSta( + k=1) "Current chiller stage" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + width=0.75, + period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + Buildings.Controls.OBC.CDL.Logical.Not StaTow "Stage tower cells" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conWatPumSpe[2]( + k=fill(0.5, 2)) "Condenser water pump speed" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + k=false) + "Constant false" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(k=true) + "Constant false" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); +equation + connect(chiStaGen.y, chiStaSet.u) + annotation (Line(points={{-78,50},{-62,50}}, color={0,0,127})); + connect(curChiSta.y, enaTowCel.uChiSta) + annotation (Line(points={{-38,90},{40,90},{40,9},{58,9}}, color={255,127,0})); + connect(chiStaSet.y, enaTowCel.uChiStaSet) + annotation (Line(points={{-38,50},{34,50},{34,6},{58,6}}, color={255,127,0})); + connect(booPul2.y, StaTow.u) + annotation (Line(points={{-78,10},{-62,10}}, color={255,0,255})); + connect(StaTow.y, enaTowCel.uTowStaCha) + annotation (Line(points={{-38,10},{28,10},{28,2},{58,2}}, color={255,0,255})); + connect(wseSta.y, enaTowCel.uWse) + annotation (Line(points={{-38,-30},{-8,-30},{-8,-1},{58,-1}}, color={255,0,255})); + connect(conWatPumSpe.y, enaTowCel.uConWatPumSpe) + annotation (Line(points={{-38,-100},{8,-100},{8,-9},{58,-9}}, color={0,0,127})); + connect(con.y, enaTowCel.uEnaPla) annotation (Line(points={{42,-100},{50,-100}, + {50,-3},{58,-3}}, color={255,0,255})); + connect(con1.y, enaTowCel.uPla) annotation (Line(points={{-58,-70},{40,-70},{40, + -7},{58,-7}}, color={255,0,255})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/CellsNumber.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.CellsNumber. +

+

+It shows the calculation of total number of tower cells when the plant is +operating in scenarios including: +

+ +

+Note in this example, the total number of tower cells is specified +according to following table. It is defined by the +parameter towCelOnSet[totSta]. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Plant stage IndexNumber of enabled cells
010
WSE22
1 chiller32
1 chiller + WSE44
2 chillers54
2 chillers + WSE64
+
+

+The example shows following process: +

+ + +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}}))); +end CellsNumber; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/ChangeCells.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/ChangeCells.mo new file mode 100644 index 00000000000..6f9d2e98ba5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/ChangeCells.mo @@ -0,0 +1,90 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.Validation; +model ChangeCells + "Validation sequence of identifying cells that should change status" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.ChangeCells + enaTowCel( + nTowCel=4) "Find enabling cells" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable celNum( + table=[0, 2; + 1200,2; + 2000,3; + 2800,2; + 3200,1], + period=3600) "Number of cell that should be enabled" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre[4] "Current tower cell status" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + +equation + connect(celNum.y[1], enaTowCel.uCelNum) annotation (Line(points={{-38,40},{0,40}, + {0,4},{18,4}}, color={255,127,0})); + connect(pre.y, enaTowCel.uTowSta) annotation (Line(points={{-38,-40},{0,-40},{ + 0,-4},{18,-4}}, color={255,0,255})); + connect(enaTowCel.yTowSta, pre.u) annotation (Line(points={{42,4},{60,4},{60,-60}, + {-70,-60},{-70,-40},{-62,-40}}, color={255,0,255})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/ChangeCells.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.ChangeCells. +It shows the process of enabling and disabling tower cells +according to the input uCelNum that specifies +total number of cells that should be enabled. +

+

+Note that this sequence assumes that the cells are enabled +sequentially as 1, 2, 3, etc. Thus, for example if it +requires two enabled cells, cell 1 and 2 will be enabled. +While if it requires three enabled cell, cell 1, 2 and 3 will +be enabled. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}}))); +end ChangeCells; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/StageProcesses.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/StageProcesses.mo new file mode 100644 index 00000000000..528b7d84f6b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/StageProcesses.mo @@ -0,0 +1,137 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.Validation; +model StageProcesses + "Validation sequence of tower cells staging process" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.StageProcesses + enaPro(nTowCel=4) "Enable tower cells process" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.StageProcesses + disPro(nTowCel=4) "Disable tower cells process" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[4]( + final k=fill(false,4)) "Constant zero" + annotation (Placement(transformation(extent={{-100,10},{-80,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[4]( + final k={false,true,true,false}) + "Enabling cells index" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp1 "Chiller stage up status" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.1, + final period=3800) "Boolean pulse" + annotation (Placement(transformation(extent={{-140,50},{-120,70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[4] "Logical switch" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=4) "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[4]( + final samplePeriod=fill(10, 4)) "Isolation valve actual position" + annotation (Placement(transformation(extent={{100,30},{120,50}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre[4] "Tower cell actual status" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1[4](final + samplePeriod=fill(10, 4)) "Isolation valve actual position" + annotation (Placement(transformation(extent={{100,-50},{120,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[4]( + pre_u_start={false,true,true,false}) "Tower cell actual status" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi[4] "Logical switch" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1[4]( + final k={0,1,1,0}) + "Initial isolation valve positions" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + +equation + connect(booPul2.y, staUp1.u) + annotation (Line(points={{-118,60},{-102,60}}, color={255,0,255})); + connect(enaPro.yIsoVal, zerOrdHol.u) annotation (Line(points={{82,46},{92,46}, + {92,40},{98,40}}, color={0,0,127})); + connect(zerOrdHol.y, enaPro.uIsoVal) annotation (Line(points={{122,40},{140,40}, + {140,20},{50,20},{50,40},{58,40}}, color={0,0,127})); + connect(con2.y, logSwi.u1) + annotation (Line(points={{-38,100},{-20,100},{-20,68},{-2,68}}, color={255,0,255})); + connect(con.y, logSwi.u3) + annotation (Line(points={{-78,20},{-20,20},{-20,52},{-2,52}}, color={255,0,255})); + connect(logSwi.y, enaPro.uChaCel) annotation (Line(points={{22,60},{30,60},{30, + 48},{58,48}}, color={255,0,255})); + connect(booRep.y, logSwi.u2) + annotation (Line(points={{-38,60},{-2,60}},color={255,0,255})); + connect(staUp1.y, booRep.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(enaPro.yTowSta, pre.u) annotation (Line(points={{82,40},{88,40},{88,0}, + {98,0}}, color={255,0,255})); + connect(pre.y, enaPro.uTowSta) annotation (Line(points={{122,0},{140,0},{140,-20}, + {40,-20},{40,32},{58,32}}, color={255,0,255})); + connect(disPro.yIsoVal, zerOrdHol1.u) annotation (Line(points={{82,-34},{92,-34}, + {92,-40},{98,-40}}, color={0,0,127})); + connect(disPro.yTowSta, pre1.u) annotation (Line(points={{82,-40},{88,-40},{88, + -80},{98,-80}}, color={255,0,255})); + connect(pre1.y, disPro.uTowSta) annotation (Line(points={{122,-80},{140,-80},{ + 140,-100},{40,-100},{40,-48},{58,-48}}, color={255,0,255})); + connect(logSwi.y, disPro.uChaCel) annotation (Line(points={{22,60},{30,60},{30, + -32},{58,-32}}, color={255,0,255})); + connect(swi.y, disPro.uIsoVal) + annotation (Line(points={{22,-40},{58,-40}}, color={0,0,127})); + connect(booRep.y, swi.u2) annotation (Line(points={{-38,60},{-30,60},{-30,-40}, + {-2,-40}}, color={255,0,255})); + connect(con1.y, swi.u3) annotation (Line(points={{-78,-70},{-40,-70},{-40,-48}, + {-2,-48}}, color={0,0,127})); + connect(zerOrdHol1.y, swi.u1) annotation (Line(points={{122,-40},{140,-40},{140, + -60},{-20,-60},{-20,-32},{-2,-32}}, color={0,0,127})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/StageProcesses.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences.StageProcesses. +It demonstrates the process of enabling (enaPro) and +disabling (disPro) tower cells. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-160,-120},{160,120}}))); +end StageProcesses; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..2d2ed7afcdd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Subsequences. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/package.order new file mode 100644 index 00000000000..94c95466a73 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/package.order @@ -0,0 +1,3 @@ +CellsNumber +ChangeCells +StageProcesses diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/package.mo new file mode 100644 index 00000000000..64e7c0be431 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging; +package Subsequences "Control subsequences of cooling tower staging" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for cooling tower staging. +The implementation is based on section 5.20.12.1 in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/package.order new file mode 100644 index 00000000000..94d113f9fd8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/package.order @@ -0,0 +1,4 @@ +CellsNumber +ChangeCells +StageProcesses +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/Controller.mo new file mode 100644 index 00000000000..f8280bfb124 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/Controller.mo @@ -0,0 +1,154 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Validation; +model Controller "Validation sequence of tower cell controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Controller + towSta( + final nTowCel=2, + final nConWatPum=2, + final totSta=5, + final staVec={0,0.5,1,1.5,2}, + final towCelOnSet={0,1,1,2,2}) + "Cooling tower staging control, specifies total number of cells and the staging process" + annotation (Placement(transformation(extent={{40,-20},{60,0}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] "Actual cells status" + annotation (Placement(transformation(extent={{80,-24},{100,-4}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2]( + final samplePeriod=fill(2, 2)) "Actual isolation valve positions" + annotation (Placement(transformation(extent={{80,-80},{100,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + final width=0.15, + final period=3600, + final shift=300) "Water side economizer status" + annotation (Placement(transformation(extent={{-120,-50},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiStaGen( + final height=1.2, + final duration=3600, + final offset=1) "Generate chiller stage" + annotation (Placement(transformation(extent={{-120,30},{-100,50}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger chiStaSet + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.75, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not StaTow "Stage tower cells" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant conWatPumSpe[2]( + final k=fill(0.5, 2)) "Condenser water pump speed" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-120,110},{-100,130}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiStaSet2( + final k=1) + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2(k=true) + "Constant false" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); +equation + connect(pre1.y, towSta.uTowSta) + annotation (Line(points={{102,-14},{120,-14},{120,10},{-14,10},{-14,-19},{38, + -19}}, color={255,0,255})); + connect(towSta.yIsoVal, zerOrdHol.u) + annotation (Line(points={{62,-10},{70,-10},{70,-70},{78,-70}}, color={0,0,127})); + connect(zerOrdHol.y, towSta.uIsoVal) + annotation (Line(points={{102,-70},{120,-70},{120,-90},{-20,-90},{-20,-17},{ + 38,-17}}, color={0,0,127})); + connect(chiStaGen.y,chiStaSet. u) + annotation (Line(points={{-98,40},{-82,40}}, color={0,0,127})); + connect(booPul2.y,StaTow. u) + annotation (Line(points={{-98,0},{-82,0}}, color={255,0,255})); + connect(chiStaSet.y, towSta.uChiStaSet) annotation (Line(points={{-58,40},{20, + 40},{20,-3},{38,-3}}, color={255,127,0})); + connect(StaTow.y, towSta.uTowStaCha) annotation (Line(points={{-58,0},{-40,0}, + {-40,-5},{38,-5}}, color={255,0,255})); + connect(wseSta.y, towSta.uWse) annotation (Line(points={{-98,-40},{-34,-40},{-34, + -7},{38,-7}}, color={255,0,255})); + connect(conWatPumSpe.y, towSta.uConWatPumSpe) annotation (Line(points={{-58,-100}, + {-26,-100},{-26,-13},{38,-13}}, color={0,0,127})); + connect(towSta.yTowSta, pre1.u) annotation (Line(points={{62,-14},{78,-14}}, + color={255,0,255})); + connect(con1.y, towSta.uEnaPla) annotation (Line(points={{-98,120},{0,120},{0, + -9},{38,-9}}, color={255,0,255})); + connect(chiStaSet2.y, towSta.uChiSta) annotation (Line(points={{-58,80},{30,80}, + {30,-1},{38,-1}}, color={255,127,0})); + connect(con2.y, towSta.uPla) annotation (Line(points={{-58,-60},{-30,-60},{-30, + -11},{38,-11}}, color={255,0,255})); +annotation (experiment( + StopTime=3600, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging.Controller. +It shows the process of staging tower cells when there is chiller stage +setpoint change and the enabling-disabling waterside economizer. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-160},{140,160}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/package.mo new file mode 100644 index 00000000000..bf670594143 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Staging. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.mo new file mode 100644 index 00000000000..9f3e5043bc0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers; +package Staging "Package of sequences for cooling tower staging" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains sequences for cooling tower staging. +The implementation is based on section 5.20.12.1 in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Staging; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WaterLevel.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WaterLevel.mo new file mode 100644 index 00000000000..7a8a72cc5e3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WaterLevel.mo @@ -0,0 +1,51 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Validation; +model WaterLevel + "Validation sequence of cooling tower make-up water control" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.WaterLevel + makUpWat( + final watLevMin=0.7, + final watLevMax=1.2) "Makeup water level control" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Sin watLev( + final amplitude=1, + final freqHz=1/7200, + final offset=0.3) "Measured water level" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + +equation + connect(watLev.y, makUpWat.watLev) + annotation (Line(points={{-18,0},{18,0}}, color={0,0,127})); + +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WaterLevel.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.WaterLevel. +

+", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}))); +end WaterLevel; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithWSE.mo new file mode 100644 index 00000000000..d18b795868e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithWSE.mo @@ -0,0 +1,291 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Validation; +model WithWSE + "Validation sequence of controlling tower of a plant with waterside economizer" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller + towCon( + nChi=2, + nTowCel=2, + nConWatPum=2, + have_WSE=true, + kWSE=0.5, + TiWSE=10) + "Cooling tower controller" + annotation (Placement(transformation(extent={{200,340},{220,380}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + final width=0.15, + final period=3600) + "Waterside economizer enabling status" + annotation (Placement(transformation(extent={{-360,200},{-340,220}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plaCap( + final height=8e5, + final duration=3600, + final offset=1e5) "Real operating chiller plant capacity" + annotation (Placement(transformation(extent={{-360,70},{-340,90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conSup( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 29) "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-360,-190},{-340,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram2( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-230},{-340,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Add conWatSupTem + "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-300,-210},{-280,-190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram3( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-150},{-340,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conRet2( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 28) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-360,-110},{-340,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Add conWatRetTem + "Condenser water return temperature" + annotation (Placement(transformation(extent={{-300,-130},{-280,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conWatPumSpe1[2]( + final height=fill(0.5, 2), + final duration=fill(3600, 2), + final startTime=fill(300, 2)) "Measured condenser water pump speed" + annotation (Placement(transformation(extent={{-300,-170},{-280,-150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe1(final k=0.5) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-320,50},{-300,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe2(final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-360,-10},{-340,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe3(final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,170},{-300,190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatSupSet( + final k=273.15 + 6.5) + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{-360,-50},{-340,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta1( + final width=0.4, + final period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-360,260},{-340,280}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiTwoSta(final k=false) + "Chiller two enabling status" + annotation (Placement(transformation(extent={{-360,230},{-340,250}}))); + Buildings.Controls.OBC.CDL.Logical.Or or3 "Logical or" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Or or4 "Logical or" + annotation (Placement(transformation(extent={{-160,-30},{-140,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiOneSta "Chiller one status" + annotation (Placement(transformation(extent={{-320,260},{-300,280}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,10},{-300,30}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-240,30},{-220,50}}))); + Buildings.Controls.OBC.CDL.Reals.Switch chiOneLoa "Chiller one load" + annotation (Placement(transformation(extent={{-260,320},{-240,340}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiTwoLoa(final k=0) + "Chiller two load" + annotation (Placement(transformation(extent={{-360,300},{-340,320}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin( + final amplitude=0.2*1e4, + final freqHz=1/1200, + final offset=1.1*1e4, + final startTime=180) "Chiller load" + annotation (Placement(transformation(extent={{-360,340},{-340,360}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin chiSup( + final amplitude=0.5, + final freqHz=1/1800, + final offset=273.15 + 6.7) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-360,140},{-340,160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1( + final height=0, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,100},{-340,120}}))); + Buildings.Controls.OBC.CDL.Reals.Add chiWatSupTem + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-260,120},{-240,140}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger chiSta "Chiller stage " + annotation (Placement(transformation(extent={{-140,-240},{-120,-220}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay towStaUp( + final delayTime=30) "Cooling tower stage up" + annotation (Placement(transformation(extent={{-140,-330},{-120,-310}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2](final + samplePeriod=fill(5, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{280,320},{300,340}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] "Break algebraic" + annotation (Placement(transformation(extent={{280,370},{300,390}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp watLev( + final height=1.2, + final duration=3600, + final offset=0.5) "Water level in cooling tower" + annotation (Placement(transformation(extent={{140,50},{160,70}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiStaSet( + final k=1) "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-140,-270},{-120,-250}}))); + Buildings.Controls.OBC.CDL.Logical.Not wseSta1 "Water side economizer status" + annotation (Placement(transformation(extent={{-320,200},{-300,220}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3(final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); +equation + connect(ram2.y, conWatSupTem.u2) annotation (Line(points={{-338,-220},{-320,-220}, + {-320,-206},{-302,-206}}, color={0,0,127})); + connect(conSup.y, conWatSupTem.u1) annotation (Line(points={{-338,-180},{-320, + -180},{-320,-194},{-302,-194}}, color={0,0,127})); + connect(conRet2.y, conWatRetTem.u1) annotation (Line(points={{-338,-100},{-320, + -100},{-320,-114},{-302,-114}}, color={0,0,127})); + connect(ram3.y, conWatRetTem.u2) annotation (Line(points={{-338,-140},{-320,-140}, + {-320,-126},{-302,-126}}, color={0,0,127})); + connect(chiSta1.y, chiOneSta.u) + annotation (Line(points={{-338,270},{-322,270}}, color={255,0,255})); + connect(chiOneSta.y, swi1.u2) annotation (Line(points={{-298,270},{-280,270},{ + -280,40},{-242,40}}, color={255,0,255})); + connect(hpTowSpe1.y, swi1.u1) + annotation (Line(points={{-298,60},{-260,60},{-260,48},{-242,48}}, + color={0,0,127})); + connect(zer.y, swi1.u3) + annotation (Line(points={{-298,20},{-260,20},{-260,32},{-242,32}}, + color={0,0,127})); + connect(chiTwoLoa.y, chiOneLoa.u3) annotation (Line(points={{-338,310},{-320,310}, + {-320,322},{-262,322}}, color={0,0,127})); + connect(sin.y, chiOneLoa.u1) annotation (Line(points={{-338,350},{-320,350},{-320, + 338},{-262,338}}, color={0,0,127})); + connect(chiOneSta.y, chiOneLoa.u2) annotation (Line(points={{-298,270},{-280,270}, + {-280,330},{-262,330}}, color={255,0,255})); + connect(chiSup.y, chiWatSupTem.u1) annotation (Line(points={{-338,150},{-320,150}, + {-320,136},{-262,136}}, color={0,0,127})); + connect(ram1.y, chiWatSupTem.u2) annotation (Line(points={{-338,110},{-320,110}, + {-320,124},{-262,124}}, color={0,0,127})); + connect(chiOneLoa.y, towCon.chiLoa[1]) annotation (Line(points={{-238,330},{ + -40,330},{-40,378.5},{198,378.5}}, color={0,0,127})); + connect(chiTwoLoa.y, towCon.chiLoa[2]) annotation (Line(points={{-338,310},{ + -40,310},{-40,379.5},{198,379.5}}, color={0,0,127})); + connect(chiOneSta.y, towCon.uChi[1]) annotation (Line(points={{-298,270},{-30, + 270},{-30,376.5},{198,376.5}}, color={255,0,255})); + connect(chiTwoSta.y, towCon.uChi[2]) annotation (Line(points={{-338,240},{-30, + 240},{-30,377.5},{198,377.5}}, color={255,0,255})); + connect(towFanSpe3.y,towCon.uFanSpe) annotation (Line(points={{-298,180},{ + -10,180},{-10,373},{198,373}}, color={0,0,127})); + connect(chiWatSupTem.y, towCon.TChiWatSup) annotation (Line(points={{-238,130}, + {0,130},{0,371},{198,371}}, color={0,0,127})); + connect(chiWatSupSet.y, towCon.TChiWatSupSet) annotation (Line(points={{-338, + -40},{10,-40},{10,369},{198,369}}, color={0,0,127})); + connect(plaCap.y, towCon.reqPlaCap) annotation (Line(points={{-338,80},{20,80}, + {20,367},{198,367}}, color={0,0,127})); + connect(swi1.y, towCon.uMaxTowSpeSet[1]) annotation (Line(points={{-218,40},{ + 30,40},{30,364.5},{198,364.5}}, color={0,0,127})); + connect(hpTowSpe2.y, towCon.uMaxTowSpeSet[2]) annotation (Line(points={{-338,0}, + {40,0},{40,365.5},{198,365.5}}, color={0,0,127})); + connect(or3.y, towCon.uPla) annotation (Line(points={{-58,-70},{60,-70},{60,361}, + {198,361}}, color={255,0,255})); + connect(conWatRetTem.y, towCon.TConWatRet) annotation (Line(points={{-278, + -120},{70,-120},{70,359},{198,359}}, color={0,0,127})); + connect(conWatPumSpe1.y, towCon.uConWatPumSpe) annotation (Line(points={{-278, + -160},{80,-160},{80,357},{198,357}}, color={0,0,127})); + connect(conWatSupTem.y, towCon.TConWatSup) annotation (Line(points={{-278, + -200},{90,-200},{90,355},{198,355}}, color={0,0,127})); + connect(chiOneSta.y, chiSta.u) annotation (Line(points={{-298,270},{-188,270}, + {-188,-230},{-142,-230}}, color={255,0,255})); + connect(chiSta.y, towCon.uChiSta) annotation (Line(points={{-118,-230},{100, + -230},{100,351},{198,351}}, color={255,127,0})); + connect(chiOneSta.y, towStaUp.u) annotation (Line(points={{-298,270},{-188,270}, + {-188,-320},{-142,-320}}, color={255,0,255})); + connect(towCon.yIsoVal, zerOrdHol.u) annotation (Line(points={{222,365},{260,365}, + {260,330},{278,330}}, color={0,0,127})); + connect(zerOrdHol.y, towCon.uIsoVal) annotation (Line(points={{302,330},{320, + 330},{320,300},{150,300},{150,343},{198,343}}, color={0,0,127})); + connect(watLev.y, towCon.watLev) annotation (Line(points={{162,60},{170,60},{ + 170,341},{198,341}}, color={0,0,127})); + connect(towCon.yTowSta, pre1.u) annotation (Line(points={{222,355},{250,355},{ + 250,380},{278,380}}, color={255,0,255})); + connect(pre1.y, towCon.uTowSta) annotation (Line(points={{302,380},{340,380}, + {340,280},{50,280},{50,363},{198,363}},color={255,0,255})); + connect(towStaUp.y, towCon.uTowStaCha) annotation (Line(points={{-118,-320},{ + 120,-320},{120,347},{198,347}}, color={255,0,255})); + connect(chiStaSet.y, towCon.uChiStaSet) annotation (Line(points={{-118,-260}, + {108,-260},{108,349},{198,349}},color={255,127,0})); + connect(wseSta.y, wseSta1.u) + annotation (Line(points={{-338,210},{-322,210}}, color={255,0,255})); + connect(wseSta1.y, towCon.uWse) annotation (Line(points={{-298,210},{-200,210}, + {-200,375},{198,375}}, color={255,0,255})); + connect(con3.y, towCon.uEnaPla) annotation (Line(points={{-58,-140},{94,-140}, + {94,353},{198,353}}, color={255,0,255})); + connect(chiOneSta.y, or4.u1) annotation (Line(points={{-298,270},{-188,270},{-188, + -20},{-162,-20}}, color={255,0,255})); + connect(chiTwoSta.y, or4.u2) annotation (Line(points={{-338,240},{-194,240},{-194, + -28},{-162,-28}}, color={255,0,255})); + connect(wseSta1.y, or3.u2) annotation (Line(points={{-298,210},{-200,210},{-200, + -78},{-82,-78}}, color={255,0,255})); + connect(or4.y, or3.u1) annotation (Line(points={{-138,-20},{-120,-20},{-120,-70}, + {-82,-70}}, color={255,0,255})); +annotation (experiment(StopTime=3500.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithWSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller. +It demonstates the cooling tower control of a less coupled chiller plant that has +two chillers with waterside economizer. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-400,-420},{400,420}}))); +end WithWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithoutWSE.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithoutWSE.mo new file mode 100644 index 00000000000..e3d406e851a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithoutWSE.mo @@ -0,0 +1,268 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Validation; +model WithoutWSE + "Validation sequence of controlling tower of a plant without waterside economizer" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller + towCon( + nChi=2, + totSta=3, + nTowCel=2, + nConWatPum=2, + have_WSE=false, + kWSE=0.5, + TiWSE=10, + staVec={0,1,2}, + towCelOnSet={0,1,2}) + "Cooling tower controller" + annotation (Placement(transformation(extent={{200,340},{220,380}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp plaCap( + final height=8e5, + final duration=3600, + final offset=1e5) "Real operating chiller plant capacity" + annotation (Placement(transformation(extent={{-360,130},{-340,150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conSup( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 29) "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-360,-190},{-340,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram2( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-230},{-340,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Add conWatSupTem + "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-300,-210},{-280,-190}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram3( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,-130},{-340,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Sin conRet2( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 28) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-360,-90},{-340,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Add conWatRetTem + "Condenser water return temperature" + annotation (Placement(transformation(extent={{-300,-110},{-280,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp conWatPumSpe1( + final height=0.5, + final duration=3600, + final startTime=300) "Measured condenser water pump speed" + annotation (Placement(transformation(extent={{-240,-140},{-220,-120}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant hpTowSpe1(final k=0.5) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-320,110},{-300,130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant towFanSpe3(final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,150},{-300,170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant chiWatSupSet( + final k=273.15 + 6.5) + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{-360,-50},{-340,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta1(final width=0.1, + final period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-360,260},{-340,280}}))); + Buildings.Controls.OBC.CDL.Logical.Or or3 "Logical or" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiOneSta "Chiller one status" + annotation (Placement(transformation(extent={{-320,260},{-300,280}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,70},{-300,90}}))); + Buildings.Controls.OBC.CDL.Reals.Switch maxTowSpe1 + "Max tower speed from chiller 1 head pressure control" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger chiSta "Chiller stage " + annotation (Placement(transformation(extent={{-140,-230},{-120,-210}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay towStaUp( + final delayTime=30) "Cooling tower stage up" + annotation (Placement(transformation(extent={{-140,-330},{-120,-310}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2](final + samplePeriod=fill(5, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{280,320},{300,340}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] "Break algebraic" + annotation (Placement(transformation(extent={{280,370},{300,390}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp watLev( + final height=1.2, + final duration=3600, + final offset=0.5) "Water level in cooling tower" + annotation (Placement(transformation(extent={{140,50},{160,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3(final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-80,-190},{-60,-170}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator conWatPumSpe( + final nout=2) + "Condenser water pump speed" + annotation (Placement(transformation(extent={{20,-160},{40,-140}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-20,-160},{0,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta2( + final width=0.7, + final period=3600) + "Chiller one enabling status" + annotation (Placement(transformation(extent={{-360,198},{-340,218}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiTwoSta1 + "Chiller two status" + annotation (Placement(transformation(extent={{-320,198},{-300,218}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger chiSta3 + "Chiller stage " + annotation (Placement(transformation(extent={{-100,-260},{-80,-240}}))); + Buildings.Controls.OBC.CDL.Reals.Switch maxTowSpe2 + "Max tower speed from chiller 2 head pressure control" + annotation (Placement(transformation(extent={{-160,30},{-140,50}}))); + Buildings.Controls.OBC.CDL.Integers.Add addInt "Chiller stage" + annotation (Placement(transformation(extent={{-40,-250},{-20,-230}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable intTimTab( + table=[0,0; 360,1; 1560,2; 3600,2], + period=3600) "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-40,-290},{-20,-270}}))); +equation + connect(ram2.y, conWatSupTem.u2) annotation (Line(points={{-338,-220},{-320,-220}, + {-320,-206},{-302,-206}}, color={0,0,127})); + connect(conSup.y, conWatSupTem.u1) annotation (Line(points={{-338,-180},{-320, + -180},{-320,-194},{-302,-194}}, color={0,0,127})); + connect(conRet2.y, conWatRetTem.u1) annotation (Line(points={{-338,-80},{-320, + -80},{-320,-94},{-302,-94}}, color={0,0,127})); + connect(ram3.y, conWatRetTem.u2) annotation (Line(points={{-338,-120},{-320, + -120},{-320,-106},{-302,-106}}, color={0,0,127})); + connect(chiSta1.y, chiOneSta.u) + annotation (Line(points={{-338,270},{-322,270}}, color={255,0,255})); + connect(chiOneSta.y, maxTowSpe1.u2) annotation (Line(points={{-298,270},{-280, + 270},{-280,100},{-162,100}}, color={255,0,255})); + connect(hpTowSpe1.y, maxTowSpe1.u1) annotation (Line(points={{-298,120},{-240, + 120},{-240,108},{-162,108}}, color={0,0,127})); + connect(zer.y, maxTowSpe1.u3) annotation (Line(points={{-298,80},{-260,80},{-260, + 92},{-162,92}}, color={0,0,127})); + connect(chiOneSta.y, towCon.uChi[1]) annotation (Line(points={{-298,270},{-30, + 270},{-30,376.5},{198,376.5}}, color={255,0,255})); + connect(towFanSpe3.y,towCon.uFanSpe) annotation (Line(points={{-298,160},{-10, + 160},{-10,373},{198,373}}, color={0,0,127})); + connect(chiWatSupSet.y, towCon.TChiWatSupSet) annotation (Line(points={{-338, + -40},{10,-40},{10,369},{198,369}}, color={0,0,127})); + connect(plaCap.y, towCon.reqPlaCap) annotation (Line(points={{-338,140},{20,140}, + {20,367},{198,367}}, color={0,0,127})); + connect(maxTowSpe1.y, towCon.uMaxTowSpeSet[1]) annotation (Line(points={{-138, + 100},{30,100},{30,364.5},{198,364.5}}, color={0,0,127})); + connect(or3.y, towCon.uPla) annotation (Line(points={{-78,-70},{60,-70},{60, + 361},{198,361}}, color={255,0,255})); + connect(conWatRetTem.y, towCon.TConWatRet) annotation (Line(points={{-278, + -100},{70,-100},{70,359},{198,359}}, color={0,0,127})); + connect(conWatSupTem.y, towCon.TConWatSup) annotation (Line(points={{-278, + -200},{90,-200},{90,355},{198,355}}, color={0,0,127})); + connect(chiOneSta.y, chiSta.u) annotation (Line(points={{-298,270},{-188,270}, + {-188,-220},{-142,-220}}, color={255,0,255})); + connect(chiOneSta.y, towStaUp.u) annotation (Line(points={{-298,270},{-188,270}, + {-188,-320},{-142,-320}}, color={255,0,255})); + connect(towCon.yIsoVal, zerOrdHol.u) annotation (Line(points={{222,365},{260,365}, + {260,330},{278,330}}, color={0,0,127})); + connect(zerOrdHol.y, towCon.uIsoVal) annotation (Line(points={{302,330},{320, + 330},{320,300},{150,300},{150,343},{198,343}}, color={0,0,127})); + connect(watLev.y, towCon.watLev) annotation (Line(points={{162,60},{170,60},{ + 170,341},{198,341}}, color={0,0,127})); + connect(towCon.yTowSta, pre1.u) annotation (Line(points={{222,355},{250,355},{ + 250,380},{278,380}}, color={255,0,255})); + connect(pre1.y, towCon.uTowSta) annotation (Line(points={{302,380},{340,380}, + {340,280},{50,280},{50,363},{198,363}},color={255,0,255})); + connect(towStaUp.y, towCon.uTowStaCha) annotation (Line(points={{-118,-320},{ + 120,-320},{120,347},{198,347}}, color={255,0,255})); + connect(con3.y, towCon.uEnaPla) annotation (Line(points={{-58,-180},{94,-180}, + {94,353},{198,353}}, color={255,0,255})); + connect(or3.y, swi2.u2) annotation (Line(points={{-78,-70},{-40,-70},{-40, + -150},{-22,-150}}, color={255,0,255})); + connect(zer.y, swi2.u3) annotation (Line(points={{-298,80},{-260,80},{-260,-158}, + {-22,-158}}, color={0,0,127})); + connect(conWatPumSpe1.y, swi2.u1) annotation (Line(points={{-218,-130},{-60, + -130},{-60,-142},{-22,-142}}, color={0,0,127})); + connect(swi2.y, conWatPumSpe.u) + annotation (Line(points={{2,-150},{18,-150}}, color={0,0,127})); + connect(conWatPumSpe.y, towCon.uConWatPumSpe) annotation (Line(points={{42,-150}, + {80,-150},{80,357},{198,357}}, color={0,0,127})); + connect(chiOneSta.y, or3.u1) annotation (Line(points={{-298,270},{-188,270},{-188, + -70},{-102,-70}}, color={255,0,255})); + connect(chiSta2.y, chiTwoSta1.u) + annotation (Line(points={{-338,208},{-322,208}}, color={255,0,255})); + connect(chiTwoSta1.y, towCon.uChi[2]) annotation (Line(points={{-298,208},{-30, + 208},{-30,377.5},{198,377.5}}, color={255,0,255})); + connect(chiTwoSta1.y, or3.u2) annotation (Line(points={{-298,208},{-200,208},{ + -200,-78},{-102,-78}}, color={255,0,255})); + connect(chiTwoSta1.y, chiSta3.u) annotation (Line(points={{-298,208},{-200,208}, + {-200,-250},{-102,-250}}, color={255,0,255})); + connect(chiSta.y, addInt.u1) annotation (Line(points={{-118,-220},{-60,-220},{ + -60,-234},{-42,-234}}, color={255,127,0})); + connect(chiSta3.y, addInt.u2) annotation (Line(points={{-78,-250},{-62,-250},{ + -62,-246},{-42,-246}}, color={255,127,0})); + connect(addInt.y, towCon.uChiSta) annotation (Line(points={{-18,-240},{100,-240}, + {100,351},{198,351}}, color={255,127,0})); + connect(intTimTab.y[1], towCon.uChiStaSet) annotation (Line(points={{-18,-280}, + {108,-280},{108,349},{198,349}}, color={255,127,0})); + connect(chiTwoSta1.y, maxTowSpe2.u2) annotation (Line(points={{-298,208},{-270, + 208},{-270,40},{-162,40}}, color={255,0,255})); + connect(hpTowSpe1.y, maxTowSpe2.u1) annotation (Line(points={{-298,120},{-240, + 120},{-240,48},{-162,48},{-162,48}}, color={0,0,127})); + connect(zer.y, maxTowSpe2.u3) annotation (Line(points={{-298,80},{-260,80},{-260, + 32},{-162,32}}, color={0,0,127})); + connect(maxTowSpe2.y, towCon.uMaxTowSpeSet[2]) annotation (Line(points={{-138, + 40},{40,40},{40,365.5},{198,365.5}}, color={0,0,127})); +annotation (experiment(StopTime=3500.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/WithoutWSE.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller. +It demonstates the cooling tower control of a less coupled chiller plant that has +two chillers without waterside economizer. +

+ +", revisions=" + +"), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-400,-420},{400,420}}))); +end WithoutWSE; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.mo new file mode 100644 index 00000000000..79f10a8d6e2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.order new file mode 100644 index 00000000000..6aa0be3aa90 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.order @@ -0,0 +1,3 @@ +WaterLevel +WithWSE +WithoutWSE diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/WaterLevel.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/WaterLevel.mo new file mode 100644 index 00000000000..41f00727292 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/WaterLevel.mo @@ -0,0 +1,102 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers; +block WaterLevel + "Sequences to control water level in cooling tower" + + parameter Real watLevMin( + final min=0) + "Minimum cooling tower water level recommended by manufacturer"; + parameter Real watLevMax( + final min=0) + "Maximum cooling tower water level recommended by manufacturer"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput watLev + "Measured water level" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yMakUp + "Makeup water valve On-Off status" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Reals.Hysteresis hys( + final uLow=watLevMin, + final uHigh=watLevMax) + "Check if water level is lower than minimum level" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Check if it should add water" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant minWatLev( + final k=watLevMin) "Minimum water level" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxWatLev( + final k=watLevMax) "Maximum water level" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Utilities.Assert assMes( + final message="The maximum level has to be greater than the minimum level.") + "Print warning when the maximum level is not set to be greater than the minimum level" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Greater greEqu + "Check if maximum level is set to be greater than minimum level" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + +equation + connect(watLev, hys.u) + annotation (Line(points={{-120,0},{-12,0}}, color={0,0,127})); + connect(hys.y, not1.u) + annotation (Line(points={{12,0},{38,0}}, color={255,0,255})); + connect(not1.y, yMakUp) + annotation (Line(points={{62,0},{120,0}}, color={255,0,255})); + connect(maxWatLev.y, greEqu.u1) + annotation (Line(points={{-18,-40},{18,-40}}, color={0,0,127})); + connect(minWatLev.y, greEqu.u2) + annotation (Line(points={{-18,-80},{0,-80},{0,-48},{18,-48}}, color={0,0,127})); + connect(greEqu.y, assMes.u) + annotation (Line(points={{42,-40},{58,-40}}, color={255,0,255})); + +annotation ( + defaultComponentName = "makUpWat", + Diagram( + coordinateSystem(preserveAspectRatio=false)), Icon(graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-96,6},{-56,-6}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="watLev"), + Text( + extent={{58,8},{98,-4}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yMakUp"), + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), +Documentation(info=" +

+Block that outputs yMakUp to control cooling tower make-up water +valve. It is implemented according to ASHRAE Guideline36-2021, +section 5.20.13, tower make-up water. +

+

+Make-up water valve shall cycle based on tower water fill level sensor. The +valve shall open when water level watLev falls below the minimum +fill level watLevMin recommended by the tower manufacturer. It +shall close when the water level goes above the maximum level watLevMax. +

+", +revisions=" + +")); +end WaterLevel; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.mo new file mode 100644 index 00000000000..8b47a36e0c5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Towers "Package of sequences for cooling tower control" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains sequences for cooling tower control. +The implementation is based on section 5.20.12 in ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end Towers; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.order new file mode 100644 index 00000000000..94909647c67 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.order @@ -0,0 +1,5 @@ +Controller +WaterLevel +FanSpeed +Staging +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/ChillerAndStageTypes.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/ChillerAndStageTypes.mo new file mode 100644 index 00000000000..ce55ea5c5fa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/ChillerAndStageTypes.mo @@ -0,0 +1,34 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types; +package ChillerAndStageTypes "Chiller and stage type enumeration" + + constant Integer positiveDisplacement = 1 "Positive displacement chiller or a stage with all positive displacement chillers"; + constant Integer variableSpeedCentrifugal = 2 "Variable speed centrifugal chiller or a stage with any variable speed and no constant speed centrifugal chillers"; + constant Integer constantSpeedCentrifugal = 3 "Constant speed centrifugal chiller or a stage with any constant speed centrifugal chiller"; + +annotation ( +Documentation(info=" +

+This package provides constants that indicate the chiller type based on the compressor type +and a chiller stage type based on the type of chillers being staged. +The chiller types are enumerated in the order of the recommended staging hierarchy, per +section 5.2.4.13., July Draft. +

+", revisions=" + +"), Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end ChillerAndStageTypes; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/ChillerTypes/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/ChillerTypes/package.order new file mode 100644 index 00000000000..303feed67da --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/ChillerTypes/package.order @@ -0,0 +1,3 @@ +positiveDisplacement +variableSpeedCentrifugal +constantSpeedCentrifugal diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/package.mo new file mode 100644 index 00000000000..7f7a66c18c8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Types "Package with type definitions for control sequences" + + annotation (Documentation(info=" +

+This package provides type definitions used in chiller plant control sequences. +

+", revisions=" + +"), Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), Polygon( + origin={-12.167,-23}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{12.167,65},{14.167,93},{36.167,89},{24.167,20},{4.167,-30}, + {14.167,-30},{24.167,-30},{24.167,-40},{-5.833,-50},{-15.833, + -30},{4.167,20},{12.167,65}}, + smooth=Smooth.Bezier, + lineColor={0,0,0}), Polygon( + origin={2.7403,1.6673}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{49.2597,22.3327},{31.2597,24.3327},{7.2597,18.3327},{-26.7403, + 10.3327},{-46.7403,14.3327},{-48.7403,6.3327},{-32.7403,0.3327},{-6.7403, + 4.3327},{33.2597,14.3327},{49.2597,14.3327},{49.2597,22.3327}}, + smooth=Smooth.Bezier)})); +end Types; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/package.order new file mode 100644 index 00000000000..bd092360edf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Types/package.order @@ -0,0 +1 @@ +ChillerAndStageTypes diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/Controller.mo new file mode 100644 index 00000000000..a949acd9abd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/Controller.mo @@ -0,0 +1,368 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Validation; +model Controller "Validation head pressure controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Controller chiPlaCon( + final closeCoupledPlant=false, + final nChi=2, + final have_parChi=true, + final have_ponyChiller=false, + final desCap=400, + final TChiWatSupMin={278.15,278.15}, + final minChiLif=10, + final have_heaPreConSig=false, + final anyVsdCen=false, + final heaExcAppDes=2, + final nChiWatPum=2, + final have_heaChiWatPum=true, + final have_locSenChiWatPum=false, + final nSenChiWatPum=1, + final nConWatPum=2, + final have_heaConWatPum=true, + final nSta=2, + final totSta=6, + final staMat=[1,0; 1,1], + final staVec={0,0.5,1,1.5,2,2.5}, + final desConWatPumSpe={0,0.5,0.75,0.6,0.75,0.9}, + final desConWatPumNum={0,1,1,2,2,2}, + final towCelOnSet={0,1,1,2,2,2}, + final nTowCel=2, + final cooTowAppDes=2, + final dpChiWatPumMax={10*6894.76}, + final TChiWatSupMax=291.15, + final have_WSE=true, + final chiDesCap={200,200}, + final chiMinCap={20,20}, + final chiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Types.ChillerAndStageTypes.positiveDisplacement}) + "Chiller plant controller" + annotation (Placement(transformation(extent={{-20,-180},{80,220}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uChiWatPum[2]( + final k={true,false}) "Chilled water pump status" + annotation (Placement(transformation(extent={{-260,122},{-240,142}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTabLin1( + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + final table=[0,2; 600,4; 1200,6; 1800,6; 2400,8; 3000,8; 3600,8; 4200,6; 4800,6; + 5400,6; 6000,7; 6600,7; 7200,7]) + "Time table with smoothness method of constant segments" + annotation (Placement(transformation(extent={{-320,-80},{-300,-60}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real to integer" + annotation (Placement(transformation(extent={{-280,-80},{-260,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uChiAva[2]( + final k={true,true}) + "Chilled availability" + annotation (Placement(transformation(extent={{-240,-60},{-220,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TChiWatSup( + final height=4, + final duration=7200, + final offset=273.15 + 7) "Chilled water supply" + annotation (Placement(transformation(extent={{-300,0},{-280,20}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TOutWet( + final k=283.15) + "Outdoor wet bulb temperatur" + annotation (Placement(transformation(extent={{-300,50},{-280,70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TOut1( + final k=313.15) "Outdoor dry bulb temperature" + annotation (Placement(transformation(extent={{-260,-190},{-240,-170}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TChiWatRet( + final height=5, + final duration=3600, + final offset=273.15 + 15) "Chilled water return temperature" + annotation (Placement(transformation(extent={{-240,20},{-220,40}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TChiWatRetDow( + final height=3, + final duration=3600, + final offset=273.15 + 10) "Chilled water return downstream of WSE" + annotation (Placement(transformation(extent={{-300,-170},{-280,-150}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TConWatRet( + final k=307.15) + "Condenser water return temperature" + annotation (Placement(transformation(extent={{-220,-250},{-200,-230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TConWatSup( + final k=305.15) + "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-260,-230},{-240,-210}}))); + Buildings.Controls.OBC.CDL.Reals.Max max1 "Current fan speed" + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[2] + "Condenser water pump status" + annotation (Placement(transformation(extent={{220,-50},{240,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro[2] "Condenser water pump speed" + annotation (Placement(transformation(extent={{260,-10},{280,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpChiWat( + final height=2*6895, + final duration=3600, + final offset=3*6895, + final startTime=0) "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-260,80},{-240,100}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[2] + "Boolean to real" + annotation (Placement(transformation(extent={{-240,160},{-220,180}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply pro1[2] "Chiller cooling load" + annotation (Placement(transformation(extent={{-200,-138},{-180,-118}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta + "Chiller one status" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta + "Chiller two status" + annotation (Placement(transformation(extent={{140,80},{160,100}}))); + Buildings.Controls.OBC.CDL.Logical.Pre towSta1[2]( + final pre_u_start=fill(false, 2)) + "Tower cell status" + annotation (Placement(transformation(extent={{120,-180},{140,-160}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp watLev( + final height=1.2, + final duration=3600, + final offset=0.5) "Water level in cooling tower" + annotation (Placement(transformation(extent={{-260,-270},{-240,-250}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2]( + final samplePeriod=fill(5, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{120,-100},{140,-80}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1[2]( + final samplePeriod=fill(5, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{200,40},{220,60}}))); + Buildings.Controls.OBC.CDL.Logical.Pre conWatPum[2]( + final pre_u_start=fill(false, 2)) + "Condenser water pump status setpoint" + annotation (Placement(transformation(extent={{160,-50},{180,-30}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2[2]( + final samplePeriod=fill(5, 2)) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{120,-70},{140,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp chiCooLoa[2]( + final height={80,70}, + final duration=fill(3600, 2), + final offset={20,25}) + "Current chiller cooling load" + annotation (Placement(transformation(extent={{-300,-130},{-280,-110}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr + "Check if the WSE pump should be enabled" + annotation (Placement(transformation(extent={{-200,-100},{-180,-80}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TEntHex( + final height=3, + final duration=3600, + final offset=273.15 + 14) + "Chilled water temperature entering heat exchanger" + annotation (Placement(transformation(extent={{-280,-40},{-260,-20}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol3( + final samplePeriod=5) + "Output the input signal with a zero order hold" + annotation (Placement(transformation(extent={{148,-150},{168,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable chiWatFlo( + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.LinearSegments, + final table=[0,0; 6500,0; 7000,0.005; 7500,0.008; 9200,0.02; 10000,0.020; + 10800,0.024], + extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.HoldLastPoint) + "Time table with smoothness method of constant segments" + annotation (Placement(transformation(extent={{-300,-210},{-280,-190}}))); +equation + connect(chiPlaCon.uChiWatPum, uChiWatPum.y) annotation (Line(points={{-30,180}, + {-190,180},{-190,132},{-238,132}}, color={255,0,255})); + connect(timTabLin1.y[1], reaToInt1.u) + annotation (Line(points={{-298,-70},{-282,-70}}, color={0,0,127})); + connect(reaToInt1.y, chiPlaCon.TChiWatSupResReq) annotation (Line(points={{-258, + -70},{-100,-70},{-100,-50},{-30,-50}}, color={255,127,0})); + connect(chiPlaCon.yChi[1], chiOneSta.u) annotation (Line(points={{90,97.5},{120, + 97.5},{120,140},{138,140}}, color={255,0,255})); + connect(chiPlaCon.yChi[2], chiTwoSta.u) annotation (Line(points={{90,102.5},{114, + 102.5},{114,90},{138,90}}, color={255,0,255})); + connect(uChiAva.y, chiPlaCon.uChiAva) annotation (Line(points={{-218,-50},{-124, + -50},{-124,5},{-30,5}}, color={255,0,255})); + connect(TOutWet.y, chiPlaCon.TOutWet) + annotation (Line(points={{-278,60},{-150,60},{-150,100},{-30,100}}, color={0,0,127})); + connect(TOut1.y, chiPlaCon.TOut) annotation (Line(points={{-238,-180},{-150,-180}, + {-150,-100},{-30,-100}}, color={0,0,127})); + connect(TChiWatRet.y, chiPlaCon.TChiWatRet) + annotation (Line(points={{-218,30},{-128,30},{-128,80},{-30,80}}, color={0,0,127})); + connect(TChiWatSup.y, chiPlaCon.TChiWatSup) + annotation (Line(points={{-278,10},{-144,10},{-144,60},{-30,60}}, color={0,0,127})); + connect(TChiWatRetDow.y, chiPlaCon.TChiWatRetDow) annotation (Line(points={{-278, + -160},{-170,-160},{-170,90},{-30,90}}, color={0,0,127})); + connect(TConWatRet.y, chiPlaCon.TConWatRet) annotation (Line(points={{-198,-240}, + {-134,-240},{-134,70},{-30,70}}, color={0,0,127})); + connect(TConWatSup.y, chiPlaCon.TConWatSup) annotation (Line(points={{-238,-220}, + {-120,-220},{-120,-140},{-30,-140}}, color={0,0,127})); + connect(watLev.y, chiPlaCon.watLev) annotation (Line(points={{-238,-260},{-90, + -260},{-90,-160},{-30,-160}}, color={0,0,127})); + connect(chiPlaCon.yTowFanSpe[2], max1.u2) annotation (Line(points={{90,-97.5}, + {106,-97.5},{106,-146},{118,-146}},color={0,0,127})); + connect(chiPlaCon.yTowFanSpe[1], max1.u1) annotation (Line(points={{90,-102.5}, + {112,-102.5},{112,-134},{118,-134}}, color={0,0,127})); + connect(chiPlaCon.yTowCel, towSta1.u) annotation (Line(points={{90,-85},{96,-85}, + {96,-170},{118,-170}}, color={255,0,255})); + connect(towSta1.y, chiPlaCon.uTowSta) annotation (Line(points={{142,-170},{160, + -170},{160,-190},{-40,-190},{-40,-170},{-30,-170}}, color={255,0,255})); + connect(chiPlaCon.yTowCelIsoVal, zerOrdHol.u) annotation (Line(points={{90,-70}, + {100,-70},{100,-90},{118,-90}}, color={0,0,127})); + connect(zerOrdHol.y, chiPlaCon.uIsoVal) annotation (Line(points={{142,-90},{ + 190,-90},{190,-210},{-70,-210},{-70,-150},{-30,-150}}, color={0,0,127})); + connect(chiPlaCon.yConWatPum, conWatPum.u) annotation (Line(points={{90,20},{ + 108,20},{108,-40},{158,-40}}, color={255,0,255})); + connect(conWatPum.y, chiPlaCon.uConWatPum) annotation (Line(points={{182,-40}, + {210,-40},{210,-230},{-100,-230},{-100,-90},{-30,-90}}, color={255,0,255})); + connect(conWatPum.y, booToRea.u) + annotation (Line(points={{182,-40},{218,-40}}, color={255,0,255})); + connect(booToRea.y, pro.u2) annotation (Line(points={{242,-40},{250,-40},{250, + -6},{258,-6}}, color={0,0,127})); + connect(pro.y, chiPlaCon.uConWatPumSpe) annotation (Line(points={{282,0},{300, + 0},{300,-250},{-110,-250},{-110,-80},{-30,-80}}, color={0,0,127})); + connect(chiPlaCon.yChiWatIsoVal, zerOrdHol2.u) annotation (Line(points={{90,-15}, + {100,-15},{100,-60},{118,-60}}, color={0,0,127})); + connect(zerOrdHol2.y, chiPlaCon.uChiWatIsoVal) annotation (Line(points={{142,-60}, + {200,-60},{200,-220},{-80,-220},{-80,-40},{-30,-40}}, color={0,0,127})); + connect(dpChiWat.y, chiPlaCon.dpChiWat_remote[1]) annotation (Line(points={{-238,90}, + {-180,90},{-180,140},{-30,140}}, color={0,0,127})); + connect(booToRea1.y, pro1.u1) annotation (Line(points={{-218,170},{-210,170}, + {-210,-122},{-202,-122}}, color={0,0,127})); + connect(chiCooLoa.y, pro1.u2) annotation (Line(points={{-278,-120},{-220,-120}, + {-220,-134},{-202,-134}}, color={0,0,127})); + connect(pro1.y, chiPlaCon.uChiCooLoa) annotation (Line(points={{-178,-128},{-70, + -128},{-70,-110},{-30,-110}}, color={0,0,127})); + connect(chiPlaCon.yConWatPumSpe, zerOrdHol1.u) annotation (Line(points={{90,50}, + {198,50}}, color={0,0,127})); + connect(reaToInt1.y, chiPlaCon.chiPlaReq) annotation (Line(points={{-258,-70}, + {-100,-70},{-100,-60},{-30,-60}}, color={255,127,0})); + connect(reaToInt1.y, intGreThr.u) annotation (Line(points={{-258,-70},{-220,-70}, + {-220,-90},{-202,-90}}, color={255,127,0})); + connect(intGreThr.y, chiPlaCon.uEcoPum) annotation (Line(points={{-178,-90},{-140, + -90},{-140,-5},{-30,-5}}, color={255,0,255})); + connect(TEntHex.y, chiPlaCon.TEntHex) annotation (Line(points={{-258,-30},{-148, + -30},{-148,-15},{-30,-15}}, color={0,0,127})); + connect(max1.y, zerOrdHol3.u) + annotation (Line(points={{142,-140},{146,-140}}, color={0,0,127})); + connect(zerOrdHol3.y, chiPlaCon.uFanSpe) annotation (Line(points={{170,-140}, + {180,-140},{180,-200},{-60,-200},{-60,-130},{-30,-130}}, color={0,0, + 127})); + connect(chiOneSta.y, booToRea1[1].u) annotation (Line(points={{162,140},{200,140}, + {200,260},{-250,260},{-250,170},{-242,170}}, color={255,0,255})); + connect(chiOneSta.y, chiPlaCon.uChiConIsoVal[1]) annotation (Line(points={{162,140}, + {200,140},{200,260},{-90,260},{-90,207.5},{-30,207.5}}, color= + {255,0,255})); + connect(chiOneSta.y, chiPlaCon.uConWatReq[1]) annotation (Line(points={{162,140}, + {200,140},{200,260},{-90,260},{-90,187.5},{-30,187.5}}, color={255, + 0,255})); + connect(chiOneSta.y, chiPlaCon.uChiIsoVal[1]) annotation (Line(points={{162,140}, + {200,140},{200,260},{-90,260},{-90,167.5},{-30,167.5}}, color={255, + 0,255})); + connect(chiOneSta.y, chiPlaCon.uChi[1]) annotation (Line(points={{162,140},{200, + 140},{200,260},{-90,260},{-90,117.5},{-30,117.5}}, color={255,0, + 255})); + connect(chiOneSta.y, chiPlaCon.uChiHeaCon[1]) annotation (Line(points={{162,140}, + {200,140},{200,260},{-90,260},{-90,-32.5},{-30,-32.5}}, color={255, + 0,255})); + connect(chiTwoSta.y, booToRea1[2].u) annotation (Line(points={{162,90},{210,90}, + {210,270},{-260,270},{-260,170},{-242,170}}, color={255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiConIsoVal[2]) annotation (Line(points={{162,90}, + {210,90},{210,270},{-100,270},{-100,212.5},{-30,212.5}}, + color={255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uConWatReq[2]) annotation (Line(points={{162,90}, + {210,90},{210,270},{-100,270},{-100,192.5},{-30,192.5}}, color={ + 255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiIsoVal[2]) annotation (Line(points={{162,90}, + {210,90},{210,270},{-100,270},{-100,172.5},{-30,172.5}}, color={ + 255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChi[2]) annotation (Line(points={{162,90},{210, + 90},{210,270},{-100,270},{-100,122.5},{-30,122.5}}, color={255,0, + 255})); + connect(chiTwoSta.y, chiPlaCon.uChiHeaCon[2]) annotation (Line(points={{162,90}, + {210,90},{210,270},{-100,270},{-100,-27.5},{-30,-27.5}}, color={ + 255,0,255})); + connect(chiOneSta.y, chiPlaCon.uChiWatReq[1]) annotation (Line(points={{162, + 140},{200,140},{200,260},{-90,260},{-90,197.5},{-30,197.5}}, color={ + 255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiWatReq[2]) annotation (Line(points={{162, + 90},{210,90},{210,270},{-100,270},{-100,202.5},{-30,202.5}}, color={ + 255,0,255})); + connect(zerOrdHol1.y, pro.u1) annotation (Line(points={{222,50},{252,50},{252, + 6},{258,6}}, color={0,0,127})); + connect(chiWatFlo.y[1], chiPlaCon.VChiWat_flow) annotation (Line(points={{ + -278,-200},{-160,-200},{-160,130},{-30,130}}, color={0,0,127})); +annotation ( + experiment(StopTime=10800.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates composed chiller plant controller + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Controller. It shows the +process of enabling plant, enabling waterside economizer and staging up one chiller. The plant: +

+ + +

+The example shows following process: +

+ +", revisions=" + +"), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent = {{-100,-100},{100,100}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points = {{-36,60},{64,0},{-36,-60},{-36,60}})}), Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-340,-300},{340, + 300}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/package.mo new file mode 100644 index 00000000000..537c92018e6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Polygon( + origin={8.0,14.0}, + lineColor={78,138,73}, + fillColor={78,138,73}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-58.0,46.0},{42.0,-14.0},{-58.0,-74.0},{-58.0,46.0}})}), +preferredView="info", Documentation(info=" +

+This package contains validation models for the classes in + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure. +

+

+Note that most validation models contain simple input data +which may not be realistic, but for which the correct +output can be obtained through an analytic solution. +The examples plot various outputs, which have been verified against these +solutions. These model outputs are stored as reference data and +used for continuous validation whenever models in the library change. +

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.mo new file mode 100644 index 00000000000..71402bd6b90 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.mo @@ -0,0 +1,25 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem; +package ChillerPlant "Chiller plant control sequences" + +annotation (preferredView="info", Documentation(info=" +

+This package contains control sequences for a chiller plant comprising a single +chiller or multiple chillers, chilled and condenser water pumps, cooling towers +and an optional water side economizer. +

+

+The control sequences are implemented based on ASHRAE Guideline36-2021. +

+"), + Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0)})); +end ChillerPlant; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.order new file mode 100644 index 00000000000..849ffc10154 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.order @@ -0,0 +1,11 @@ +Controller +Economizers +Generic +HeadPressure +MinimumFlowBypass +Pumps +SetPoints +Staging +Towers +Types +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.mo new file mode 100644 index 00000000000..3174c2e5132 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.mo @@ -0,0 +1,47 @@ +within Buildings.Controls.OBC.ASHRAE; +package PrimarySystem "Package with primary system control sequences" + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for primary HVAC systems. +

+

+The sequences are developed according to ASHRAE Guideline36-2021. +

+"), +Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100.0,-100.0},{100.0,100.0}}, + radius=25.0), + Ellipse( + origin={10.0,10.0}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10.0,10.0}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10.0,10.0}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})})); +end PrimarySystem; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.order new file mode 100644 index 00000000000..14d2951a766 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.order @@ -0,0 +1 @@ +ChillerPlant diff --git a/Buildings/Controls/OBC/ASHRAE/package.order b/Buildings/Controls/OBC/ASHRAE/package.order index f718b0a1739..4d8c195216a 100644 --- a/Buildings/Controls/OBC/ASHRAE/package.order +++ b/Buildings/Controls/OBC/ASHRAE/package.order @@ -1 +1,2 @@ G36 +PrimarySystem diff --git a/Buildings/Examples/ChillerPlant/package.order b/Buildings/Examples/ChillerPlant/package.order deleted file mode 100644 index 8b8f6051ce5..00000000000 --- a/Buildings/Examples/ChillerPlant/package.order +++ /dev/null @@ -1,4 +0,0 @@ -DataCenterContinuousTimeControl -DataCenterDiscreteTimeControl -DataCenterRenewables -BaseClasses diff --git a/Buildings/Examples/ChillerPlant/BaseClasses/Controls/BatteryControl.mo b/Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/BatteryControl.mo similarity index 95% rename from Buildings/Examples/ChillerPlant/BaseClasses/Controls/BatteryControl.mo rename to Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/BatteryControl.mo index 6a575fbd540..6f417e5090e 100644 --- a/Buildings/Examples/ChillerPlant/BaseClasses/Controls/BatteryControl.mo +++ b/Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/BatteryControl.mo @@ -1,4 +1,4 @@ -within Buildings.Examples.ChillerPlant.BaseClasses.Controls; +within Buildings.Examples.ChillerPlants.DataCenter.BaseClasses.Controls; model BatteryControl "Controller for battery" Modelica.Blocks.Interfaces.RealInput SOC "State of charge" annotation ( @@ -121,23 +121,23 @@ equation annotation (Line(points={{-99,-120},{80,-120},{80,48}}, color={255,0,255})); connect(t1.inPort, alternative.split[1]) - annotation (Line(points={{16,120},{8,120},{8,115},{-0.56,115}}, + annotation (Line(points={{16,120},{8,120},{8,77.5},{-0.56,77.5}}, color={0,0,0})); connect(t2.inPort, alternative.split[2]) - annotation (Line(points={{16,60},{8,60},{8,65},{-0.56,65}}, + annotation (Line(points={{16,60},{8,60},{8,102.5},{-0.56,102.5}}, color={0,0,0})); connect(t3.outPort, alternative.join[1]) - annotation (Line(points={{81.5,120},{92,120},{92,115},{100.56,115}}, + annotation (Line(points={{81.5,120},{92,120},{92,77.5},{100.56,77.5}}, color={0,0,0})); connect(t4.outPort, alternative.join[2]) - annotation (Line(points={{81.5,60},{92,60},{92,65},{100.56,65}}, + annotation (Line(points={{81.5,60},{92,60},{92,102.5},{100.56,102.5}}, color={0,0,0})); connect(charge.active, multiSwitch1.u[1]) annotation (Line( - points={{50,109},{50,92},{64,92},{64,1.5},{104,1.5}}, + points={{50,109},{50,92},{64,92},{64,-0.75},{104,-0.75}}, color={255,0,255}, pattern=LinePattern.Dash)); connect(discharge.active, multiSwitch1.u[2]) annotation (Line( - points={{50,49},{50,49},{50,-4},{104,-4},{104,-1.5}}, + points={{50,49},{50,49},{50,-4},{104,-4},{104,0.75}}, color={255,0,255}, pattern=LinePattern.Dash)); annotation ( Documentation(info=" diff --git a/Buildings/Examples/ChillerPlant/BaseClasses/Controls/ChillerSwitch.mo b/Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/ChillerSwitch.mo similarity index 98% rename from Buildings/Examples/ChillerPlant/BaseClasses/Controls/ChillerSwitch.mo rename to Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/ChillerSwitch.mo index a96c0141dbe..8947bc19f1c 100644 --- a/Buildings/Examples/ChillerPlant/BaseClasses/Controls/ChillerSwitch.mo +++ b/Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/ChillerSwitch.mo @@ -1,4 +1,4 @@ -within Buildings.Examples.ChillerPlant.BaseClasses.Controls; +within Buildings.Examples.ChillerPlants.DataCenter.BaseClasses.Controls; block ChillerSwitch "Control unit for enabling/disabling chiller" extends Modelica.Blocks.Icons.Block; Modelica.Blocks.Interfaces.RealInput chiCHWST( diff --git a/Buildings/Examples/ChillerPlant/BaseClasses/Controls/Examples/BatteryControl.mo b/Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/Examples/BatteryControl.mo similarity index 79% rename from Buildings/Examples/ChillerPlant/BaseClasses/Controls/Examples/BatteryControl.mo rename to Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/Examples/BatteryControl.mo index 359be944fc2..b24b35d5957 100644 --- a/Buildings/Examples/ChillerPlant/BaseClasses/Controls/Examples/BatteryControl.mo +++ b/Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/Examples/BatteryControl.mo @@ -1,7 +1,7 @@ -within Buildings.Examples.ChillerPlant.BaseClasses.Controls.Examples; +within Buildings.Examples.ChillerPlants.DataCenter.BaseClasses.Controls.Examples; model BatteryControl "Test model for battery control" extends Modelica.Icons.Example; - Buildings.Examples.ChillerPlant.BaseClasses.Controls.BatteryControl + Buildings.Examples.ChillerPlants.DataCenter.BaseClasses.Controls.BatteryControl con "Battery control" annotation (Placement(transformation(extent={{0,0},{20,20}}))); Modelica.Blocks.Sources.Sine SOC( @@ -19,7 +19,7 @@ equation StopTime=604800, Tolerance=1e-6), __Dymola_Commands(file= - "modelica://Buildings/Resources/Scripts/Dymola/Examples/ChillerPlant/BaseClasses/Controls/Examples/BatteryControl.mos" + "modelica://Buildings/Resources/Scripts/Dymola/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/Examples/BatteryControl.mos" "Simulate and plot"), Documentation(revisions="