diff --git a/Buildings/Applications/DataCenters/ChillerCooled/Examples/BaseClasses/PartialDataCenter.mo b/Buildings/Applications/DataCenters/ChillerCooled/Examples/BaseClasses/PartialDataCenter.mo index 1e23ed09aac..1c741e37323 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 283dd51ef49..470b7da83fa 100644 --- a/Buildings/Applications/DataCenters/DXCooled/Examples/DXCooledAirsideEconomizer.mo +++ b/Buildings/Applications/DataCenters/DXCooled/Examples/DXCooledAirsideEconomizer.mo @@ -38,7 +38,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/PrimarySystem/BoilerPlant/BypassValve/BypassValvePosition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/BypassValvePosition.mo new file mode 100644 index 00000000000..39eae7fa0f0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/BypassValvePosition.mo @@ -0,0 +1,194 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.BypassValve; +block BypassValvePosition + "Sequence for controlling minimum flow bypass valve position" + + parameter Integer nPum = 2 + "Number of pumps"; + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller"; + + parameter Real k( + final min=0, + final unit="1", + displayUnit="1") = 1 + "Gain of controller"; + + parameter Real Ti( + final min=0, + final unit="s", + displayUnit="s", + final quantity="time") = 0.5 + "Time constant of integrator block"; + + parameter Real Td( + final min=0, + final unit="s", + displayUnit="s", + final quantity="time") = 0.1 + "Time constant of derivative block"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPumSta[nPum] + "Input signals indicating pump statuses" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured hot-water flow-rate through primary circuit" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatMinSet_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Calculated hot water minimum flow setpoint through boilers" + annotation (Placement(transformation(extent={{-140,60},{-100,100}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMinBypValPos( + final unit="1", + displayUnit="1", + final min=0) + "Minimum bypass valve position for condensation control in non-condensing boilers" + annotation (Placement(transformation(extent={{-140,-80},{-100,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yBypValPos( + final unit="1", + displayUnit="1", + final min=0) + "Bypass valve opening position" + annotation (Placement(transformation(extent={{100,-50},{140,-10}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Difference between measured flowrate and minimum flow setpoint" + annotation (Placement(transformation(extent={{-70,30},{-50,50}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Block to detect if any of the pumps are proved ON" + annotation (Placement(transformation(extent={{-70,-10},{-50,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div + "Normalize measured hot water flowrate" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=0) + "Constant Real source" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max + "Ensure bypass valve position is greater than lower limit for condensation control" + annotation (Placement(transformation(extent={{70,-40},{90,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) + "Prevent division by zero" + annotation (Placement(transformation(extent={{-70,70},{-50,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.PIDWithReset conPID( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=1, + final yMin=0, + xi_start=1, + reverseActing=false) + "PID loop to regulate flow through primary loop using bypass valve" + annotation (Placement(transformation(extent={{20,60},{40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Reset PID loop when it is activated" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + +equation + + connect(mulOr.u[1:nPum], uPumSta) annotation (Line(points={{-72,0},{-120,0}}, + color={255,0,255})); + + connect(uMinBypValPos, max.u2) annotation (Line(points={{-120,-60},{50,-60},{50, + -36},{68,-36}}, color={0,0,127})); + connect(max.y, yBypValPos) + annotation (Line(points={{92,-30},{120,-30}}, color={0,0,127})); + connect(VHotWatMinSet_flow, addPar.u) + annotation (Line(points={{-120,80},{-72,80}}, color={0,0,127})); + connect(addPar.y, div.u2) annotation (Line(points={{-48,80},{-40,80},{-40,34}, + {-22,34}}, color={0,0,127})); + connect(con.y, conPID.u_s) + annotation (Line(points={{2,70},{18,70}}, color={0,0,127})); + connect(div.y, conPID.u_m) + annotation (Line(points={{2,40},{30,40},{30,58}}, color={0,0,127})); + connect(mulOr.y, edg.u) annotation (Line(points={{-48,0},{-22,0}}, + color={255,0,255})); + connect(edg.y, conPID.trigger) + annotation (Line(points={{2,0},{24,0},{24,58}}, color={255,0,255})); + + connect(conPID.y, max.u1) annotation (Line(points={{42,70},{50,70},{50,-24},{68, + -24}}, color={0,0,127})); + connect(sub2.y, div.u1) annotation (Line(points={{-48,40},{-28,40},{-28,46},{-22, + 46}}, color={0,0,127})); + connect(VHotWatMinSet_flow,sub2. u1) annotation (Line(points={{-120,80},{-80,80}, + {-80,46},{-72,46}}, color={0,0,127})); + connect(VHotWat_flow,sub2. u2) annotation (Line(points={{-120,40},{-80,40},{-80, + 34},{-72,34}}, color={0,0,127})); +annotation (defaultComponentName="bypValPos", + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), + graphics={Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={28,108,200}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-70,20},{70,-20}}, + textColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.None, + textString="bypValPos"), + Text( + extent={{-100,146},{100,108}}, + textColor={0,0,255}, + textString="%name")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}})), + Documentation(info=" +

+ Control sequence for bypass circuit valve position yBypValPos + for boiler plant loop. +

+ + ", revisions=" + + ")); +end BypassValvePosition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/BypassValvePosition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/BypassValvePosition.mo new file mode 100644 index 00000000000..2cbf2ebfdc3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/BypassValvePosition.mo @@ -0,0 +1,105 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.BypassValve.Validation; +block BypassValvePosition + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.BypassValve.BypassValvePosition + bypValPos( + final nPum=2, + final k=1, + final Ti=10, + final Td=10e-6) + "Test instance for bypass valve controller" + annotation (Placement(transformation(extent={{10,-10},{30,10}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=1.2) + "Minimum flow setpoint" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=0.5, + final freqHz=1/75, + final phase=0, + final offset=1.2, + final startTime=1) + "Sine input" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.5, + final period=300) + "Boolean pulse generator" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=0.2) + "Minimum valve position for condensation control" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) + "Boolean replicator" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=0) + "Constant zero signal" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Pass zero flowrate when pumps are switched off" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + +equation + connect(con.y, bypValPos.VHotWatMinSet_flow) annotation (Line(points={{-18,60}, + {0,60},{0,6},{8,6}}, color={0,0,127})); + connect(con1.y, bypValPos.uMinBypValPos) annotation (Line(points={{-18,-60},{0, + -60},{0,-6},{8,-6}}, color={0,0,127})); + connect(booPul.y, booRep.u) + annotation (Line(points={{-58,-20},{-42,-20}}, color={255,0,255})); + connect(booRep.y, bypValPos.uPumSta) annotation (Line(points={{-18,-20},{-10,-20}, + {-10,-2},{8,-2}}, color={255,0,255})); + + connect(swi.y, bypValPos.VHotWat_flow) annotation (Line(points={{-18,20},{-10, + 20},{-10,2},{8,2}}, color={0,0,127})); + connect(sin.y, swi.u1) annotation (Line(points={{-58,20},{-50,20},{-50,28},{-42, + 28}}, color={0,0,127})); + connect(con2.y, swi.u3) annotation (Line(points={{-58,60},{-54,60},{-54,12},{-42, + 12}}, color={0,0,127})); + connect(booPul.y, swi.u2) annotation (Line(points={{-58,-20},{-46,-20},{-46,20}, + {-42,20}}, color={255,0,255})); +annotation ( +Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.BypassValve.BypassValvePosition. +

+", 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)), + __Dymola_Commands(file= + "./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/BypassValvePosition.mos" + "Simulate and plot"), + experiment( + StartTime=0, + StopTime=300, + Interval=1, + Tolerance=1e-06)); +end BypassValvePosition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/package.mo new file mode 100644 index 00000000000..e9aa405304f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/package.mo @@ -0,0 +1,32 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.BypassValve; +package Validation "Validation models for BypassValve sequences" + + + + + annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

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

+")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/package.order new file mode 100644 index 00000000000..6f71a7959fc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/Validation/package.order @@ -0,0 +1 @@ +BypassValvePosition diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/package.mo new file mode 100644 index 00000000000..73c036b4bd6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/package.mo @@ -0,0 +1,42 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package BypassValve "Control sequences for minimum flow bypass valve" + annotation(Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Ellipse( + origin={10,10}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10,10}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10,10}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10,10}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})}), + Documentation(info=" +

+ This package contains control sequences for the minimum flow bypass valve. +

+ ")); +end BypassValve; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/package.order new file mode 100644 index 00000000000..79ae6896090 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/BypassValve/package.order @@ -0,0 +1,2 @@ +BypassValvePosition +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Controller.mo new file mode 100644 index 00000000000..1385924af7b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Controller.mo @@ -0,0 +1,2260 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +model Controller + "Boiler plant controller" + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType_priPum= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Primary pump control parameters", group="PID parameters")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType_bypVal= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="Bypass valve control parameters")); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType_secPum= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="Secondary pump control parameters", group="PID parameters")); + + parameter Boolean have_priOnl = false + "Is the boiler plant a primary-only, condensing boiler plant?" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Boolean have_heaPriPum = true + "True: Headered primary hot water pumps; + False: Dedicated primary hot water pumps" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Boolean have_varPriPum = false + "True: Variable-speed primary pumps; + False: Fixed-speed primary pumps" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Boolean have_secFloSen=false + "True: Flowrate sensor in secondary loop; + False: Flowrate sensor in decoupler" + annotation(Dialog(tab="General", + group="Boiler plant configuration parameters", + enable = not have_priOnl)); + + parameter Boolean have_priSecTemSen=false + "True: Temperature sensors in primary and secondary loops; + False: Temperature sensors in boiler supply and secondary loop" + annotation (Dialog(tab="Primary pump control parameters", + group="General parameters", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Boolean have_varSecPum = false + "True: Variable-speed secondary pumps; + False: Fixed-speed secondary pumps" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Integer nIgnReq( + final min=0) = 0 + "Number of hot-water requests to be ignored before enabling boiler plant loop" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Integer nSchRow( + final min=1) = 4 + "Number of rows to be created for plant schedule table" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Integer nBoi + "Number of boilers" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer boiTyp[nBoi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler} + "Boiler type" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer nSta + "Number of boiler plant stages" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer staMat[nSta, nBoi] + "Staging matrix with stage as row index and boiler as column index" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer nPumPri + "Number of primary pumps in the boiler plant loop" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer nHotWatResReqIgn = 2 + "Number of hot-water supply temperature reset requests to be ignored" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Integer nSenPri + "Total number of remote differential pressure sensors in primary loop" + annotation(Dialog(tab="General", + group="Boiler plant configuration parameters", + enable = have_remDPRegPri or have_locDPRegPri)); + + parameter Integer numIgnReq = 0 + "Number of ignored requests" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable= speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Integer nPumPri_nominal( + final max=nPumPri, + final min=1) = nPumPri + "Total number of pumps that operate at design conditions" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Integer nPumSec + "Total number of secondary hot water pumps" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Integer nSenSec + "Total number of remote differential pressure sensors in secondary loop" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Integer nPumSec_nominal( + final max=nPumSec) = nPumSec + "Total number of pumps that operate at design conditions in secondary loop" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Real schTab[nSchRow,2] = [0,1;6,1;18,1;24,1] + "Table defining schedule for enabling plant" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Real TOutLoc( + final unit="K", + displayUnit="K") = 300 + "Boiler lock-out temperature for outdoor air" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Real locDt( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 1 + "Temperature deadband for boiler lockout" + annotation(dialog(tab="Plant enable/disable parameters", group="Advanced")); + + parameter Real plaOffThrTim( + final unit="s", + displayUnit="s") = 900 + "Minimum time for which the plant has to stay off once it has been disabled" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Real plaOnThrTim( + final unit="s", + displayUnit="s") = plaOffThrTim + "Minimum time for which the boiler plant has to stay on once it has been enabled" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Real staOnReqTim( + final unit="s", + displayUnit="s") = 180 + "Time-limit for receiving hot-water requests to maintain enabled plant on" + annotation(dialog(tab="Plant enable/disable parameters")); + + parameter Real boiDesCap[nBoi]( + final unit="W", + displayUnit="W", + final quantity="Power") + "Design boiler capacities vector" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real boiFirMin[nBoi]( + final unit="1", + displayUnit="1") + "Boiler minimum firing ratio" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real delStaCha( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Hold period for each stage change" + annotation(Dialog(tab="Staging setpoint parameters", group="General parameters")); + + parameter Real avePer( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Time period for the capacity requirement rolling average" + annotation(Dialog(tab="Staging setpoint parameters", group="Capacity requirement calculation parameters")); + + parameter Real fraNonConBoi( + final unit="1", + displayUnit="1") = 0.9 + "Fraction of current stage design capacity at which efficiency condition is + satisfied for non-condensing boilers" + annotation(Dialog(tab="Staging setpoint parameters", group="Efficiency condition parameters")); + + parameter Real fraConBoi( + final unit="1", + displayUnit="1") = 1.5 + "Fraction of higher stage design capacity at which efficiency condition is + satisfied for condensing boilers" + annotation(Dialog(tab="Staging setpoint parameters", group="Efficiency condition parameters")); + + parameter Real delEffCon( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Enable delay for heating capacity requirement condition" + annotation(Dialog(tab="Staging setpoint parameters", group="Efficiency condition parameters")); + + parameter Real TDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 10 + "Required temperature difference between setpoint and measured temperature" + annotation(Dialog(tab="Staging setpoint parameters", group="Failsafe condition parameters")); + + parameter Real delFaiCon( + final unit="s", + displayUnit="s", + final quantity="Time") = 900 + "Enable delay for temperature condition" + annotation(Dialog(tab="Staging setpoint parameters", group="Failsafe condition parameters")); + + parameter Real sigDif( + final unit="1", + displayUnit="1") = 0.1 + "Signal hysteresis deadband for flowrate measurements" + annotation (Dialog(tab="Staging setpoint parameters", group="Advanced")); + + parameter Real TDifHys( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1 + "Temperature deadband for hysteresis loop" + annotation (Dialog(tab="Staging setpoint parameters", group="Advanced")); + + parameter Real fraMinFir( + final unit="1", + displayUnit="1") = 1.1 + "Fraction of boiler minimum firing rate that required capacity needs to be + to initiate stage-down process" + annotation(Dialog(tab="Staging setpoint parameters", group="Staging down parameters")); + + parameter Real delMinFir( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Delay for staging based on minimum firing rate of current stage" + annotation(Dialog(tab="Staging setpoint parameters", group="Staging down parameters")); + + parameter Real fraDesCap( + final unit="1", + displayUnit="1") = 0.8 + "Fraction of design capacity of next lower stage that heating capacity needs + to be for staging down" + annotation(Dialog(tab="Staging setpoint parameters", group="Staging down parameters")); + + parameter Real delDesCapNonConBoi( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Enable delay for capacity requirement condition for non-condensing boilers" + annotation(Dialog(tab="Staging setpoint parameters", group="Staging down parameters")); + + parameter Real delDesCapConBoi( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for capacity requirement condition for condensing boilers" + annotation(Dialog(tab="Staging setpoint parameters", group="Staging down parameters")); + + parameter Real delBypVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for bypass valve condition for primary-only plants" + annotation ( + Evaluate=true, + Dialog( + enable=have_priOnl, + tab="Staging setpoint parameters", + group="Staging down parameters")); + + parameter Real TCirDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 3 + "Required return water temperature difference between primary and secondary + circuits for staging down" + annotation ( + Evaluate=true, + Dialog( + enable=not + (have_priOnl), + tab="Staging setpoint parameters", + group="Staging down parameters")); + + parameter Real delTRetDif( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for measured hot water return temperature difference condition" + annotation ( + Evaluate=true, + Dialog( + enable=not + (have_priOnl), + tab="Staging setpoint parameters", + group="Staging down parameters")); + + parameter Real bypValClo( + final unit="1", + displayUnit="1") = 0 + "Adjustment for signal received when bypass valve is closed" + annotation ( + Evaluate=true, + Dialog( + enable=have_priOnl, + tab="Staging setpoint parameters", + group="Advanced")); + + parameter Real dTemp( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 0.1 + "Hysteresis deadband for measured temperatures" + annotation (Dialog(tab="Staging setpoint parameters", group="Advanced")); + + parameter Real minFloSet[nBoi]( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate", + final min=1e-6, + final max=maxFloSet) + "Design minimum hot water flow through each boiler" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real maxFloSet[nBoi]( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate", + final min=minFloSet) + "Design maximum hot water flow through each boiler" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real bypSetRat( + final unit="m3/s2", + displayUnit="m3/s2", + final min=0) = 0.001 + "Rate at which to reset bypass valve setpoint during stage change" + annotation(Dialog(tab="Staging setpoint parameters", group="General parameters")); + + parameter Real TPlaHotWatSetMax( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 353.15 + "The maximum allowed hot-water setpoint temperature for the plant" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real TConBoiHotWatSetMax( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 353.15 + "The maximum allowed hot water setpoint temperature for condensing boilers" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real TConBoiHotWatSetOff( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = -10 + "The offset for hot water setpoint temperature for condensing boilers in + non-condensing stage type" + annotation(Dialog(tab="Supply temperature reset parameters", group="General parameters")); + + parameter Real THotWatSetMinNonConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 341.48 + "The minimum allowed hot-water setpoint temperature for non-condensing boilers" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real THotWatSetMinConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 305.37 + "The minimum allowed hot-water setpoint temperature for condensing boilers" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real delTimVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Delay time" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real samPerVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Sample period" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real triAmoVal( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = -2 + "Setpoint trim value" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real resAmoVal( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 3 + "Setpoint respond value" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real maxResVal( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 7 + "Setpoint maximum respond value" + annotation(Dialog(tab="Supply temperature reset parameters", group="Trim-and-Respond Logic parameters")); + + parameter Real holTimVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Minimum setpoint hold time for stage change process" + annotation(Dialog(tab="Supply temperature reset parameters", group="General parameters")); + + parameter Real TMinSupNonConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 333.2 + "Minimum supply temperature required for non-condensing boilers" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real delProSupTemSet( + final unit="s", + displayUnit="s", + final quantity="time")=300 + "Process time-out for hot water supply temperature setpoint reset" + annotation (Dialog(tab="Staging process parameters",group="Time and delay parameters")); + + parameter Real delEnaMinFloSet( + final unit="s", + displayUnit="s", + final quantity="time")=60 + "Enable delay after minimum flow setpoint is achieved in bypass valve" + annotation (Dialog(tab="Staging process parameters",group="Time and delay parameters")); + + parameter Real chaIsoValRat( + final unit="1/s", + displayUnit="1/s") = 1/60 + "Rate at which to slowly change isolation valve position, should be determined + in the field" + annotation (Dialog(tab="Staging process parameters",group="Time and delay parameters")); + + parameter Real chaIsoValTim( + final unit="s", + displayUnit="s", + final quantity="time") = 1/chaIsoValRat + "Time to slowly change isolation valve position from fully closed to fully open, + should be determined in the field" + annotation (Dialog(tab="Staging process parameters", group="Time and delay parameters")); + + parameter Real delPreBoiEna( + final unit="s", + displayUnit="s", + final quantity="time") = 30 + "Time delay after valve and pump change process has been completed before + starting boiler change process" + annotation (Dialog(tab="Staging process parameters",group="Time and delay parameters")); + + parameter Real boiChaProOnTim( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Enabled boiler operation time to indicate if it is proven on during a staging + process where one boiler is turned on and the other is turned off" + annotation (Dialog(tab="Staging process parameters",group="Time and delay parameters")); + + parameter Real delBoiEna( + final unit="s", + displayUnit="s", + final quantity="time") = 180 + "Time delay after boiler change process has been completed before turning off + excess valves and pumps" + annotation (Dialog(tab="Staging process parameters",group="Time and delay parameters")); + + parameter Real k_bypVal( + final min=0, + final unit="1", + displayUnit="1") = 1 + "Gain of controller" + annotation(Dialog(tab="Bypass valve control parameters")); + + parameter Real Ti_bypVal( + final min=0, + final unit="s", + displayUnit="s", + final quantity="time") = 0.5 + "Time constant of integrator block" + annotation(Dialog(tab="Bypass valve control parameters")); + + parameter Real Td_bypVal( + final min=0, + final unit="s", + displayUnit="s", + final quantity="time") = 0.1 + "Time constant of derivative block" + annotation(Dialog(tab="Bypass valve control parameters")); + + parameter Real minPumSpePri( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpePri) = 0.1 + "Minimum pump speed" + annotation (Dialog(tab="Primary pump control parameters", group="General parameters", enable=have_varPriPum)); + + parameter Real maxPumSpePri( + final unit="1", + displayUnit="1", + final min=minPumSpePri, + final max=1) = 1 + "Maximum pump speed" + annotation (Dialog(tab="Primary pump control parameters", group="General parameters", enable=have_varPriPum)); + + parameter Real VHotWatPri_flow_nominal( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Plant design hot water flow rate thorugh primary loop" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Real boiDesFlo[nBoi]( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Vector of design flowrates for all boilers in plant" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Real maxLocDpPri( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Maximum primary loop local differential pressure setpoint" + annotation (Dialog(tab="Primary pump control parameters", group="DP-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP + or speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP)); + + parameter Real minLocDpPri( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Minimum primary loop local differential pressure setpoint" + annotation (Dialog(tab="Primary pump control parameters", + group="DP-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP + or speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP)); + + parameter Real offTimThr_priPum( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 180 + "Threshold to check lead boiler off time" + annotation (Dialog(tab="Primary pump control parameters", group="Pump staging parameters")); + + parameter Real timPer_priPum( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 600 + "Delay time period for enabling and disabling lag pumps" + annotation (Dialog(tab="Primary pump control parameters", group="Pump staging parameters")); + + parameter Real staCon_priPum( + final unit="1", + displayUnit="1") = -0.03 + "Constant used in the staging equation" + annotation (Dialog(tab="Primary pump control parameters", group="Pump staging parameters")); + + parameter Real relFloHys_priPum( + final unit="1", + displayUnit="1") = 0.01 + "Constant value used in hysteresis for checking relative flow rate" + annotation (Dialog(tab="Primary pump control parameters", group="Pump staging parameters")); + + parameter Real delTim_priPum( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 900 + "Delay time" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real samPer_priPum( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 120 + "Sample period of component" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real triAmo_priPum( + final unit="1", + displayUnit="1") = -0.02 + "Trim amount" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real resAmo_priPum( + final unit="1", + displayUnit="1") = 0.03 + "Respond amount" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real maxRes_priPum( + final unit="1", + displayUnit="1") = 0.06 + "Maximum response per time interval" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real twoReqLimLow_priPum( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1.2 + "Lower limit of hysteresis loop sending two requests" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real twoReqLimHig_priPum( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 2 + "Higher limit of hysteresis loop sending two requests" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real oneReqLimLow_priPum( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 0.2 + "Lower limit of hysteresis loop sending one request" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real oneReqLimHig_priPum( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1 + "Higher limit of hysteresis loop sending one request" + annotation (Dialog(tab="Primary pump control parameters", + group="Temperature-based speed regulation", + enable = speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real k_priPum( + final unit="1", + displayUnit="1", + final min=0) = 1 + "Gain of controller" + annotation (Dialog(tab="Primary pump control parameters", group="PID parameters")); + + parameter Real Ti_priPum( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Primary pump control parameters", group="PID parameters")); + + parameter Real Td_priPum( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Primary pump control parameters", group="PID parameters")); + + parameter Real TRetSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 333.15 + "Minimum hot water return temperature for optimal non-condensing boiler performance" + annotation(Dialog(tab="Condensation control parameters")); + + parameter Real TRetMinAll( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 330.35 + "Minimum allowed hot water return temperature for non-condensing boiler" + annotation(Dialog(tab="Condensation control parameters")); + + parameter Real minSecPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=1) = 0 + "Minimum secondary pump speed" + annotation(Dialog(tab="Condensation control parameters")); + + parameter Real minPriPumSpeSta[nSta]( + final unit=fill("1",nSta), + displayUnit=fill("1",nSta), + final min=fill(0,nSta), + final max=fill(1,nSta)) + "Vector of minimum primary pump speed for each stage" + annotation(Dialog(group="Boiler plant configuration parameters")); + + parameter Real minPumSpeSec( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpeSec) = 0.1 + "Minimum pump speed" + annotation (Dialog(tab="Secondary pump control parameters", + group="General parameters", + enable=have_varSecPum)); + + parameter Real maxPumSpeSec( + final unit="1", + displayUnit="1", + final min=minPumSpeSec, + final max=1) = 1 + "Maximum pump speed" + annotation (Dialog(tab="Secondary pump control parameters", + group="General parameters", + enable=have_varSecPum)); + + parameter Real VHotWatSec_flow_nominal( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") = 0.5 + "Secondary loop design hot water flow rate" + annotation (Dialog(group="Boiler plant configuration parameters")); + + parameter Real maxLocDpSec( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Maximum hot water loop local differential pressure setpoint in secondary loop" + annotation (Dialog(tab="Secondary pump control parameters", group="DP-based speed regulation", + enable = speConTypSec == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP)); + + parameter Real minLocDpSec( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Minimum hot water loop local differential pressure setpoint in secondary loop" + annotation (Dialog(tab="Secondary pump control parameters", + group="DP-based speed regulation", + enable = speConTypSec == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP)); + + parameter Real offTimThr( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 180 + "Threshold to check lead boiler off time" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real timPerSec( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 600 + "Delay time period for enabling and disabling secondary lag pumps" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real staConSec( + final unit="1", + displayUnit="1") = -0.03 + "Constant used in the staging equation" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real speLim( + final unit="1", + displayUnit="1") = 0.9 + "Speed limit with longer enable delay for enabling next lag pump" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real speLim1( + final unit="1", + displayUnit="1") = 0.99 + "Speed limit with shorter enable delay for enabling next lag pump" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real speLim2( + final unit="1", + displayUnit="1") = 0.4 + "Speed limit for disabling last lag pump" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real timPer1( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Delay time period for enabling next lag pump at speed limit speLim" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real timPer2( + final unit="s", + displayUnit="s", + final quantity="time") = 60 + "Delay time period for enabling next lag pump at speed limit speLim1" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real timPer3( + final unit="s", + displayUnit="s", + final quantity="time") = 600 + "Delay time period for disabling last lag pump" + annotation (Dialog(tab="Secondary pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real k_sec( + final unit="1", + displayUnit="1", + final min=0) = 1 + "Gain of controller" + annotation (Dialog(tab="Secondary pump control parameters", + group="PID parameters", + enable=have_varSecPum)); + + parameter Real Ti_sec( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Secondary pump control parameters", + group="PID parameters", + enable=have_varSecPum)); + + parameter Real Td_sec( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Secondary pump control parameters", + group="PID parameters", + enable=have_varSecPum)); + + parameter Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes + speConTypPri = Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP + "Primary pump speed regulation method" + annotation (Dialog(group="Boiler plant configuration parameters", enable=have_varPriPum)); + + parameter Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes + speConTypSec = Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP + "Secondary pump speed regulation method" + annotation (Dialog(group="Boiler plant configuration parameters", enable=have_varSecPum)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiAva[nBoi] + "Boiler availability status signal" + annotation (Placement(transformation(extent={{-440,50},{-400,90}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoi[nBoi] + "Boiler status vector from plant" + annotation (Placement(transformation(extent={{-440,-380},{-400,-340}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPriPum[nPumPri] + "Primary pump proven on signal from plant" + annotation (Placement(transformation(extent={{-440,-420},{-400,-380}}), + iconTransformation(extent={{-140,-220},{-100,-180}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uSecPum[nPumSec] if not have_priOnl + "Secondary pump proven on signal" + annotation (Placement(transformation(extent={{-440,-460},{-400,-420}}), + iconTransformation(extent={{-140,-250},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput plaReq + "Plant requests" + annotation (Placement(transformation(extent={{-440,330},{-400,370}}), + iconTransformation(extent={{-140,270},{-100,310}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput TSupResReq + "Hot water supply temperature reset requests" + annotation (Placement(transformation(extent={{-440,360},{-400,400}}), + iconTransformation(extent={{-140,300},{-100,340}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured outdoor air temperature" + annotation (Placement(transformation(extent={{-440,290},{-400,330}}), + iconTransformation(extent={{-140,240},{-100,280}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupPri( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-440,250},{-400,290}}), + iconTransformation(extent={{-140,210},{-100,250}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TRetPri( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured hot water primary return temperature" + annotation (Placement(transformation(extent={{-440,210},{-400,250}}), + iconTransformation(extent={{-140,180},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatPri_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured hot water primary circuit flowrate" + annotation (Placement(transformation(extent={{-440,170},{-400,210}}), + iconTransformation(extent={{-140,150},{-100,190}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatPri_rem[nSenPri]( + final unit=fill("Pa", nSenPri), + displayUnit=fill("Pa", nSenPri), + final quantity=fill("PressureDifference", nSenPri)) if have_varPriPum and (have_remDPRegPri or have_locDPRegPri) + "Measured differential pressure between hot water supply and return in primary circuit" + annotation (Placement(transformation(extent={{-440,90},{-400,130}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TRetSec( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not have_priOnl + "Measured hot water secondary return temperature" + annotation (Placement(transformation(extent={{-440,130},{-400,170}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatSec_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if not have_priOnl and have_secFloSen + "Measured hot water secondary circuit flowrate" + annotation (Placement(transformation(extent={{-440,-90},{-400,-50}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatDec_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if not have_priOnl and have_varPriPum + and have_floRegPri and not have_secFloSen + "Measured hot water flowrate through decoupler leg" + annotation (Placement(transformation(extent={{-440,-130},{-400,-90}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupSec( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") if not have_priOnl and + have_varPriPum and have_temRegPri and have_priSecTemSen + "Measured hot water supply temperature in secondary circuit" + annotation (Placement(transformation(extent={{-440,-170},{-400,-130}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupBoi[nBoi]( + final unit=fill("K", nBoi), + displayUnit=fill("degC", nBoi), + final quantity=fill("ThermodynamicTemperature", nBoi)) if not have_priOnl + and have_varPriPum and have_temRegPri and not have_priSecTemSen + "Measured hot water supply temperatureat boiler outlets" + annotation (Placement(transformation(extent={{-440,-210},{-400,-170}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatSec_rem[nSenSec]( + final unit=fill("Pa", nSenSec), + displayUnit=fill("Pa", nSenSec), + final quantity=fill("PressureDifference", nSenSec)) if not + have_priOnl and have_varSecPum and (have_remDPRegSec or have_locDPRegSec) + "Measured differential pressure between hot water supply and return in secondary circuit" + annotation (Placement(transformation(extent={{-440,-250},{-400,-210}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatPri_loc( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference") if have_varPriPum and have_locDPRegPri + "Measured differential pressure between hot water supply and return in primary circuit" + annotation (Placement(transformation(extent={{-440,-290},{-400,-250}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatSec_loc( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference") if not have_priOnl and + have_varSecPum and have_locDPRegSec + "Measured differential pressure between hot water supply and return in secondary circuit" + annotation (Placement(transformation(extent={{-440,-330},{-400,-290}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal[nBoi]( + final unit=fill("1",nBoi), + displayUnit=fill("1",nBoi)) if have_heaPriPum + "Measured boiler isolation valve position signals from plant" + annotation (Placement(transformation(extent={{-440,-500},{-400,-460}}), + iconTransformation(extent={{-140,-280},{-100,-240}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uBypValPos( + final unit="1", + displayUnit="1") if have_priOnl + "Measured bypass valve position signal from plant" + annotation (Placement(transformation(extent={{-440,-540},{-400,-500}}), + iconTransformation(extent={{-140,-310},{-100,-270}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uPriPumSpe[nPumPri]( + final unit=fill("1",nBoi), + displayUnit=fill("1",nBoi)) if not have_priOnl + "Measured primary pump speed signal from plant" + annotation (Placement(transformation(extent={{-440,-580},{-400,-540}}), + iconTransformation(extent={{-140,-340},{-100,-300}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler status vector" + annotation (Placement(transformation(extent={{400,180},{440,220}}), + iconTransformation(extent={{100,80},{140,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPriPum[nPumPri] + "Primary pump enable status vector" + annotation (Placement(transformation(extent={{400,-150},{440,-110}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput ySecPum[nPumSec] if not have_priOnl + "Secondary pump enable status vector" + annotation (Placement(transformation(extent={{400,-360},{440,-320}}), + iconTransformation(extent={{100,-160},{140,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPla + "Plant enable signal" + annotation (Placement(transformation(extent={{400,280},{440,320}}), + iconTransformation(extent={{100,160},{140,200}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TPlaHotWatSupSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Plant hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{400,220},{440,260}}), + iconTransformation(extent={{100,120},{140,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal[nBoi]( + final unit=fill("1",nBoi), + displayUnit=fill("1",nBoi)) if have_heaPriPum + "Boiler hot water isolation valve position vector" + annotation (Placement(transformation(extent={{400,100},{440,140}}), + iconTransformation(extent={{100,0},{140,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPriPumSpe( + final unit="1", + displayUnit="1") if have_varPriPum + "Primary pump speed" + annotation (Placement(transformation(extent={{400,-190},{440,-150}}), + iconTransformation(extent={{100,-120},{140,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yBypValPos( + final unit="1", + displayUnit="1") if have_priOnl + "Bypass valve position" + annotation (Placement(transformation(extent={{400,-50},{440,-10}}), + iconTransformation(extent={{100,-40},{140,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySecPumSpe( + final unit="1", + displayUnit="1") if not have_priOnl and have_varSecPum + "Secondary pump speed vector" + annotation (Placement(transformation(extent={{400,-410},{440,-370}}), + iconTransformation(extent={{100,-200},{140,-160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TBoiHotWatSupSet[nBoi]( + final unit=fill("K", nBoi), + displayUnit=fill("K", nBoi), + final quantity=fill("ThermodynamicTemperature", nBoi)) + "Boiler hot water supply temperature setpoint vector" + annotation (Placement(transformation(extent={{400,150},{440,190}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable plaEna( + final nIgnReq=nIgnReq, + final nSchRow=nSchRow, + final schTab=schTab, + final TOutLoc=TOutLoc, + final plaOffThrTim=plaOffThrTim, + final plaOnThrTim=plaOnThrTim, + final staOnReqTim=staOnReqTim) + "Plant enable controller" + annotation (Placement(transformation(extent={{-340,320},{-320,340}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.SetpointController staSetCon( + final have_priOnl=have_priOnl, + final nBoi=nBoi, + final boiTyp=boiTyp, + final nSta=nSta, + final staMat=staMat, + final boiDesCap=boiDesCap, + final boiFirMin=boiFirMin, + final boiMinPriPumSpeSta=minPriPumSpeSta, + final delStaCha=delStaCha, + final avePer=avePer, + final fraNonConBoi=fraNonConBoi, + final fraConBoi=fraConBoi, + final delEffCon=delEffCon, + final TDif=TDif, + final delFaiCon=delFaiCon, + final sigDif=sigDif, + final TDifHys=TDifHys, + final fraMinFir=fraMinFir, + final delMinFir=delMinFir, + final fraDesCap=fraDesCap, + final delDesCapNonConBoi=delDesCapNonConBoi, + final delDesCapConBoi=delDesCapConBoi, + final TCirDif=TCirDif, + final delTRetDif=delTRetDif, + final dTemp=dTemp) + "Staging setpoint controller" + annotation (Placement(transformation(extent={{-210,-18},{-190,18}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.MinimumFlowSetPoint minBoiFloSet( + final nBoi=nBoi, + final nSta=nSta, + final staMat=staMat, + final minFloSet=minFloSet, + final maxFloSet=maxFloSet, + final bypSetRat=bypSetRat) if have_priOnl + "Minimum flow setpoint for the primary loop" + annotation (Placement(transformation(extent={{250,310},{270,330}}))); + +protected + parameter Boolean have_remDPRegPri = (speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP) + "Boolean flag for primary pump speed control with remote differential pressure"; + + parameter Boolean have_locDPRegPri = (speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP) + "Boolean flag for primary pump speed control with local differential pressure"; + + parameter Boolean have_temRegPri = (speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Boolean flag for primary pump speed control with temperature readings"; + + parameter Boolean have_floRegPri = (speConTypPri == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate) + "Boolean flag for primary pump speed control with flowrate readings"; + + parameter Boolean have_remDPRegSec = (speConTypSec == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP) + "Boolean flag for secondary pump speed control with remote differential pressure"; + + parameter Boolean have_locDPRegSec = (speConTypSec == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.localDP) + "Boolean flag for secondary pump speed control with local differential pressure"; + + parameter Integer staInd[nSta]={i for i in 1:nSta} + "Staging indices starting at 1"; + + parameter Integer priPumInd[nPumPri]={i for i in 1:nPumPri} + "Vector of primary pump indices up to total number of primary pumps"; + + parameter Integer secPumInd[nPumSec]={i for i in 1:nPumSec} + "Vector of secondary pump indices up to total number of secondary pumps"; + + Buildings.Controls.OBC.CDL.Continuous.IntegratorWithReset intWitRes + "Used to break algebraic loop and sample staging setpoint signal" + annotation (Placement(transformation(extent={{-210,360},{-190,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=0) + "Constant zero signal source for integrator input" + annotation (Placement(transformation(extent={{-130,360},{-110,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.IntegratorWithReset intWitRes1 + "Used to break algebraic loop and sample next boiler index to be enabled/disabled" + annotation (Placement(transformation(extent={{90,370},{110,390}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha1 + "Detect changes in staging setpoint signal" + annotation (Placement(transformation(extent={{-220,320},{-200,340}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha2 + "Detect changes to boiler index that is next enabled/disabled" + annotation (Placement(transformation(extent={{76,344},{96,364}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMax mulMax( + final nin=nPumPri) if not have_priOnl + "Identify maximum measured pump speed" + annotation (Placement(transformation(extent={{-380,-570},{-360,-550}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha[nPumPri] + "Detect changes in primary pump status" + annotation (Placement(transformation(extent={{160,-430},{180,-410}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPumPri) + "Pass true signal when any of the pump statuses change" + annotation (Placement(transformation(extent={{200,-430},{220,-410}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Up upProCon( + final have_priOnl=have_priOnl, + final have_heaPriPum=have_heaPriPum, + final nBoi=nBoi, + final nSta=nSta, + final TMinSupNonConBoi=TMinSupNonConBoi, + final delProSupTemSet=delProSupTemSet, + final delEnaMinFloSet=delEnaMinFloSet, + final chaIsoValTim=chaIsoValTim, + final delPreBoiEna=delPreBoiEna, + final boiChaProOnTim=boiChaProOnTim, + final delBoiEna=delBoiEna, + final sigDif=TDifHys, + final relFloDif=sigDif) + "Stage-up process controller" + annotation (Placement(transformation(extent={{120,76},{140,116}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Down dowProCon( + final have_priOnl=have_priOnl, + final have_heaPriPum=have_heaPriPum, + final nBoi=nBoi, + final nSta=nSta, + final delEnaMinFloSet=delEnaMinFloSet, + final chaIsoValTim=chaIsoValTim, + final delPreBoiEna=delPreBoiEna, + final boiChaProOnTim=boiChaProOnTim, + final delBoiEna=delBoiEna, + relFloDif=sigDif) + "Stage-down process controller" + annotation (Placement(transformation(extent={{120,20},{140,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller priPumCon( + final controllerType=controllerType_priPum, + final have_heaPriPum=have_heaPriPum, + final have_priOnl=have_priOnl, + final have_varPriPum=have_varPriPum, + final have_secFloSen=have_secFloSen, + final have_priSecTemSen=have_priSecTemSen, + final nPum=nPumPri, + final nBoi=nBoi, + final nSen=nSenPri, + final numIgnReq=numIgnReq, + final nPum_nominal=nPumPri, + final minPumSpe=minPumSpePri, + final maxPumSpe=maxPumSpePri, + final VHotWat_flow_nominal=VHotWatPri_flow_nominal, + final boiDesFlo=boiDesFlo, + final maxLocDp=maxLocDpPri, + final minLocDp=minLocDpPri, + final offTimThr=offTimThr_priPum, + final timPer=timPer_priPum, + final delBoiDis=delBoiEna, + final staCon=staCon_priPum, + final relFloHys=relFloHys_priPum, + final delTim=delTim_priPum, + final samPer=samPer_priPum, + final triAmo=triAmo_priPum, + final resAmo=resAmo_priPum, + final maxRes=maxRes_priPum, + final twoReqLimLow=twoReqLimLow_priPum, + final twoReqLimHig=twoReqLimHig_priPum, + final oneReqLimLow=oneReqLimLow_priPum, + final oneReqLimHig=oneReqLimHig_priPum, + final k=k_priPum, + final Ti=Ti_priPum, + final Td=Td_priPum, + final speConTyp=speConTypPri) + "Primary pump controller" + annotation (Placement(transformation(extent={{120,-208},{140,-152}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.BypassValve.BypassValvePosition bypValPos( + final nPum=nPumPri, + final controllerType=controllerType_bypVal, + final k=k_bypVal, + final Ti=Ti_bypVal, + final Td=Td_bypVal) if have_priOnl + "Bypass valve controller" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset hotWatSupTemRes( + final nPum=nPumPri, + final nSta=nSta, + final nBoi=nBoi, + final nHotWatResReqIgn=nHotWatResReqIgn, + final boiTyp=boiTyp, + final TPlaHotWatSetMax = TPlaHotWatSetMax, + final TConBoiHotWatSetMax = TConBoiHotWatSetMax, + final TConBoiHotWatSetOff=TConBoiHotWatSetOff, + final THotWatSetMinNonConBoi = THotWatSetMinNonConBoi, + final THotWatSetMinConBoi = THotWatSetMinConBoi, + final delTimVal=delTimVal, + final samPerVal=samPerVal, + final triAmoVal = triAmoVal, + final resAmoVal=resAmoVal, + final maxResVal=maxResVal, + final holTimVal=holTimVal) + "Hot water supply temperature setpoint reset controller" + annotation (Placement(transformation(extent={{-140,170},{-120,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Pass true signal at completion of stage up or stage down process" + annotation (Placement(transformation(extent={{180,60},{200,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.CondensationControl conSet( + final have_priOnl=have_priOnl, + final have_varPriPum=have_varPriPum, + final nSta=nSta, + final TRetSet=TRetSet, + final TRetMinAll=TRetMinAll, + final minSecPumSpe=minSecPumSpe, + final minPriPumSpeSta=minPriPumSpeSta) + "Condensation control setpoint controller" + annotation (Placement(transformation(extent={{-60,-112},{-40,-92}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Latch to identify if process is stage-up or stage-down" + annotation (Placement(transformation(extent={{-50,350},{-30,370}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Switch input signal between stage-up and stage-down processes" + annotation (Placement(transformation(extent={{22,320},{42,340}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Switch input signal between stage-up and stage-down processes" + annotation (Placement(transformation(extent={{20,370},{40,390}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Latch to identify if staging process is complete or not" + annotation (Placement(transformation(extent={{-188,170},{-168,190}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.MinimumFlowSetPoint minBoiFloSet1[nSta]( + final nBoi=fill(nBoi, nSta), + final nSta=fill(nSta, nSta), + final staMat=fill(staMat, nSta), + final minFloSet=fill(minFloSet, nSta), + final maxFloSet=fill(maxFloSet, nSta), + final bypSetRat=fill(bypSetRat, nSta)) + "Calculate vector of minimum flow setpoints for all stages" + annotation (Placement(transformation(extent={{-340,0},{-320,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nSta]( + final k=fill(0, nSta)) + "Constant zero Integer source" + annotation (Placement(transformation(extent={{-390,20},{-370,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nSta]( + final k=fill(false, nSta)) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{-390,-10},{-370,10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1[nSta]( + final k=staInd) + "Constant stage Integer source" + annotation (Placement(transformation(extent={{-390,-40},{-370,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2[nPumPri]( + final k=priPumInd) + "Constant stage Integer source" + annotation (Placement(transformation(extent={{60,-138},{80,-118}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Sample stage setpoint when stage change process is complete" + annotation (Placement(transformation(extent={{-160,-50},{-140,-30}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-128,-50},{-108,-30}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Integer to Real converter" + annotation (Placement(transformation(extent={{-190,-50},{-170,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpHotWatSet( + final k=maxLocDpPri) if have_priOnl + "Differential pressure setpoint for primary circuit" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nBoi] + "Switch input signal between stage-up and stage-down processes" + annotation (Placement(transformation(extent={{180,260},{200,280}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{120,260},{140,280}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nBoi] if have_heaPriPum + "Switch input signal between stage-up and stage-down processes" + annotation (Placement(transformation(extent={{180,220},{200,240}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-180,360},{-160,380}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Integer to Real conversion" + annotation (Placement(transformation(extent={{-240,360},{-220,380}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre4 + "Logical pre block" + annotation (Placement(transformation(extent={{-216,170},{-196,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre6 if have_priOnl + "Logical pre block to break algebraic loop" + annotation (Placement(transformation(extent={{60,320},{80,340}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea2 + "Integer to Real conversion" + annotation (Placement(transformation(extent={{60,370},{80,390}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{120,370},{140,390}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{300,-20},{320,0}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantDisable plaDis( + final have_priOnl=have_priOnl, + final have_heaPriPum=have_heaPriPum, + final nBoi=nBoi, + final chaHotWatIsoRat=chaIsoValRat, + final delBoiDis=delBoiEna) + "Plant disable process controller" + annotation (Placement(transformation(extent={{240,60},{260,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Controller secPumCon( + final controllerType=controllerType_secPum, + final have_varSecPum=true, + final have_secFloSen=have_secFloSen, + final nPum=nPumSec, + final nPumPri=nPumPri, + final nBoi=nBoi, + final nSen=nSenSec, + final nPum_nominal=nPumSec, + final minPumSpe=minPumSpeSec, + final maxPumSpe=maxPumSpeSec, + final VHotWat_flow_nominal=VHotWatSec_flow_nominal, + final maxLocDp=maxLocDpSec, + final minLocDp=minLocDpSec, + final offTimThr=offTimThr, + final delBoiDis=0, + final timPer=timPerSec, + final staCon=staConSec, + final speLim=speLim, + final speLim1=speLim1, + final speLim2=speLim2, + final timPer1=timPer1, + final timPer2=timPer2, + final timPer3=timPer3, + final k=k_sec, + final Ti=Ti_sec, + final Td=Td_sec, + final speConTyp=speConTypSec) if not have_priOnl + "Secondary pump controller" + annotation (Placement(transformation(extent={{120,-380},{140,-340}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 if not have_priOnl + "Switch input signal between stage-up and stage-down processes" + annotation (Placement(transformation(extent={{64,280},{84,300}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3[nPumSec]( + final k=secPumInd) if not have_priOnl + "Constant stage Integer source" + annotation (Placement(transformation(extent={{60,-290},{80,-270}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpHotWatSet1( + final k=maxLocDpSec) if not have_priOnl + "Differential pressure setpoint for secondary circuit" + annotation (Placement(transformation(extent={{60,-390},{80,-370}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 if not have_priOnl + "Or operator for pump stage change signal from up-staging, down-staging and plant disable process controllers" + annotation (Placement(transformation(extent={{58,-220},{78,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Ensure stage-down process is not initiated when plant is disabled" + annotation (Placement(transformation(extent={{-28,50},{-8,70}}))); + +equation + connect(staSetCon.yBoi, upProCon.uBoiSet) annotation (Line(points={{-188,-10}, + {64,-10},{64,95},{118,95}},color={255,0,255})); + connect(staSetCon.yBoi, dowProCon.uBoiSet) annotation (Line(points={{-188,-10}, + {86,-10},{86,38},{118,38}}, color={255,0,255})); + connect(staSetCon.ySta, upProCon.uStaSet) annotation (Line(points={{-188,6},{ + 20,6},{20,86},{118,86}}, + color={255,127,0})); + connect(staSetCon.ySta, dowProCon.uStaSet) annotation (Line(points={{-188,6},{ + 20,6},{20,30},{118,30}}, + color={255,127,0})); + connect(staSetCon.yStaTyp, upProCon.uStaTyp) annotation (Line(points={{-188,10}, + {24,10},{24,89},{118,89}},color={255,127,0})); + connect(staSetCon.yChaUpEdg, upProCon.uStaUpPro) annotation (Line(points={{-188,2}, + {58,2},{58,92},{118,92}}, color={255,0,255})); + connect(conSet.yMinBypValPos, bypValPos.uMinBypValPos) annotation (Line( + points={{-38,-96},{110,-96},{110,-46},{118,-46}},color={0,0,127})); + connect(staSetCon.yStaTyp, conSet.uStaTyp) annotation (Line(points={{-188,10}, + {-90,10},{-90,-108},{-62,-108}}, + color={255,127,0})); + connect(staSetCon.yChaUpEdg, lat.u) annotation (Line(points={{-188,2},{-64,2}, + {-64,360},{-52,360}}, + color={255,0,255})); + connect(staSetCon.yChaDowEdg, lat.clr) annotation (Line(points={{-188,-6},{-60, + -6},{-60,354},{-52,354}}, + color={255,0,255})); + connect(lat.y, logSwi.u2) annotation (Line(points={{-28,360},{10,360},{10,330}, + {20,330}}, color={255,0,255})); + connect(upProCon.yOnOff, logSwi.u1) annotation (Line(points={{142,96},{150,96}, + {150,150},{0,150},{0,338},{20,338}}, color={255,0,255})); + connect(dowProCon.yOnOff, logSwi.u3) annotation (Line(points={{142,40},{154,40}, + {154,144},{14,144},{14,322},{20,322}}, color={255,0,255})); + connect(lat.y, intSwi.u2) annotation (Line(points={{-28,360},{10,360},{10,380}, + {18,380}}, color={255,0,255})); + connect(upProCon.yLasDisBoi, intSwi.u1) annotation (Line(points={{142,88},{146, + 88},{146,72},{-12,72},{-12,388},{18,388}}, color={255,127,0})); + connect(dowProCon.yLasDisBoi, intSwi.u3) annotation (Line(points={{142,32},{150, + 32},{150,68},{-6,68},{-6,372},{18,372}}, color={255,127,0})); + connect(lat1.y, hotWatSupTemRes.uStaCha) + annotation (Line(points={{-166,180},{-142,180}}, + color={255,0,255})); + connect(staSetCon.yStaTyp, hotWatSupTemRes.uTyp) annotation (Line(points={{-188,10}, + {-144,10},{-144,176},{-142,176}}, color={255,127,0})); + connect(minBoiFloSet1.VHotWatMinSet_flow, staSetCon.VMinSet_flow) annotation ( + Line(points={{-318,10},{-274,10},{-274,5},{-212,5}}, + color={0,0,127})); + connect(conInt.y, minBoiFloSet1.uLasDisBoi) annotation (Line(points={{-368,30}, + {-360,30},{-360,16},{-342,16}}, color={255,127,0})); + connect(con.y, minBoiFloSet1.uOnOff) annotation (Line(points={{-368,0},{-360,0}, + {-360,12},{-342,12}}, color={255,0,255})); + connect(con.y, minBoiFloSet1.uStaChaPro) annotation (Line(points={{-368,0},{-360, + 0},{-360,8},{-342,8}}, color={255,0,255})); + connect(conInt2.y, priPumCon.uPumLeaLag) annotation (Line(points={{82,-128},{ + 86,-128},{86,-152.933},{118,-152.933}}, + color={255,127,0})); + connect(plaReq, plaEna.supResReq) annotation (Line(points={{-420,350},{-360,350}, + {-360,334},{-342,334}}, color={255,127,0})); + connect(reaToInt.u, triSam.y) + annotation (Line(points={{-130,-40},{-138,-40}}, + color={0,0,127})); + connect(triSam.u, intToRea.y) + annotation (Line(points={{-162,-40},{-168,-40}}, + color={0,0,127})); + connect(reaToInt.y, staSetCon.u) annotation (Line(points={{-106,-40},{-80,-40}, + {-80,-60},{-220,-60},{-220,-13},{-212,-13}}, + color={255,127,0})); + connect(TOut, plaEna.TOut) annotation (Line(points={{-420,310},{-360,310},{-360, + 326},{-342,326}}, + color={0,0,127})); + connect(TSupPri, staSetCon.THotWatSup) annotation (Line(points={{-420,270},{-240, + 270},{-240,8},{-212,8}}, color={0,0,127})); + connect(TRetPri, staSetCon.THotWatRet) annotation (Line(points={{-420,230},{-260, + 230},{-260,14},{-212,14}}, color={0,0,127})); + connect(TRetPri, conSet.THotWatRet) annotation (Line(points={{-420,230},{-260, + 230},{-260,-96},{-62,-96}}, color={0,0,127})); + connect(VHotWatPri_flow, staSetCon.VHotWat_flow) annotation (Line(points={{-420, + 190},{-270,190},{-270,11},{-212,11}}, color={0,0,127})); + connect(VHotWatPri_flow, upProCon.VHotWat_flow) annotation (Line(points={{-420, + 190},{-270,190},{-270,110},{114,110},{114,115},{118,115}}, + color={0,0,127})); + connect(VHotWatPri_flow, dowProCon.VHotWat_flow) annotation (Line(points={{-420, + 190},{-270,190},{-270,110},{114,110},{114,58},{118,58}}, + color={0,0,127})); + connect(VHotWatPri_flow, bypValPos.VHotWat_flow) annotation (Line(points={{-420, + 190},{-270,190},{-270,110},{114,110},{114,-38},{118,-38}}, + color={0,0,127})); + connect(VHotWatPri_flow, priPumCon.VHotWat_flow) annotation (Line(points={{-420, + 190},{-270,190},{-270,110},{114,110},{114,-164.133},{118,-164.133}}, + color={0,0, + 127})); + connect(dpHotWatPri_rem, priPumCon.dpHotWat_remote) annotation (Line(points={{-420, + 110},{-280,110},{-280,-144},{-4,-144},{-4,-187.467},{118,-187.467}}, + color={0,0,127})); + connect(dpHotWatSet.y, priPumCon.dpHotWatSet) annotation (Line(points={{82,-170}, + {104,-170},{104,-190.267},{118,-190.267}}, + color={0,0,127})); + connect(upProCon.yBoi, logSwi1.u1) annotation (Line(points={{142,108},{148,108}, + {148,278},{178,278}}, color={255,0,255})); + connect(dowProCon.yBoi, logSwi1.u3) annotation (Line(points={{142,52},{156,52}, + {156,262},{178,262}}, color={255,0,255})); + connect(lat.y, booRep.u) annotation (Line(points={{-28,360},{-16,360},{-16,270}, + {118,270}}, color={255,0,255})); + connect(booRep.y, logSwi1.u2) annotation (Line(points={{142,270},{178,270}}, + color={255,0,255})); + connect(upProCon.yHotWatIsoVal, swi.u1) annotation (Line(points={{142,100},{172, + 100},{172,238},{178,238}}, + color={0,0,127})); + connect(dowProCon.yHotWatIsoVal, swi.u3) annotation (Line(points={{142,44},{164, + 44},{164,222},{178,222}}, + color={0,0,127})); + connect(booRep.y, swi.u2) annotation (Line(points={{142,270},{160,270},{160,230}, + {178,230}}, color={255,0,255})); + connect(priPumCon.yPumSpe, yPriPumSpe) annotation (Line(points={{142,-183.733}, + {264,-183.733},{264,-170},{420,-170}}, + color={0,0,127})); + connect(bypValPos.yBypValPos, yBypValPos) annotation (Line(points={{142,-40},{ + 148,-40},{148,-30},{420,-30}}, color={0,0,127})); + connect(staSetCon.ySta, intToRea1.u) annotation (Line(points={{-188,6},{20,6}, + {20,300},{-250,300},{-250,370},{-242,370}}, + color={255,127,0})); + connect(reaToInt1.y, minBoiFloSet.uStaSet) annotation (Line(points={{-158,370}, + {-148,370},{-148,314},{248,314}}, + color={255,127,0})); + connect(plaEna.yPla, staSetCon.uPla) annotation (Line(points={{-318,330},{-230, + 330},{-230,-10},{-212,-10}}, color={255,0,255})); + connect(staSetCon.yChaEdg, pre4.u) annotation (Line(points={{-188,-2},{-180,-2}, + {-180,150},{-220,150},{-220,180},{-218,180}}, + color={255,0,255})); + connect(pre4.y, lat1.u) annotation (Line(points={{-194,180},{-190,180}}, + color={255,0,255})); + connect(hotWatSupTemRes.TPlaHotWatSupSet, staSetCon.THotWatSupSet) + annotation (Line(points={{-118,184},{-100,184},{-100,90},{-226,90},{-226,17}, + {-212,17}}, + color={0,0,127})); + connect(reaToInt.y, conSet.uCurSta) annotation (Line(points={{-106,-40},{-80,-40}, + {-80,-102},{-62,-102}}, color={255,127,0})); + connect(reaToInt1.y, intToRea.u) annotation (Line(points={{-158,370},{-148,370}, + {-148,-22},{-196,-22},{-196,-40},{-192,-40}}, + color={255,127,0})); + connect(reaToInt1.y, hotWatSupTemRes.uCurStaSet) annotation (Line(points={{-158, + 370},{-148,370},{-148,172},{-142,172}}, color={255,127,0})); + connect(minBoiFloSet.VHotWatMinSet_flow, upProCon.VMinHotWatSet_flow) + annotation (Line(points={{272,320},{280,320},{280,290},{110,290},{110,111},{ + 118,111}}, color={0,0,127})); + connect(minBoiFloSet.VHotWatMinSet_flow, dowProCon.VMinHotWatSet_flow) + annotation (Line(points={{272,320},{280,320},{280,290},{110,290},{110,54},{118, + 54}}, color={0,0,127})); + connect(minBoiFloSet.VHotWatMinSet_flow, bypValPos.VHotWatMinSet_flow) + annotation (Line(points={{272,320},{280,320},{280,290},{110,290},{110,-34},{ + 118,-34}}, color={0,0,127})); + connect(logSwi.y, pre6.u) + annotation (Line(points={{44,330},{58,330}}, color={255,0,255})); + connect(pre6.y, minBoiFloSet.uOnOff) annotation (Line(points={{82,330},{94,330}, + {94,322},{248,322}}, color={255,0,255})); + connect(intSwi.y, intToRea2.u) annotation (Line(points={{42,380},{58,380}}, + color={255,127,0})); + connect(reaToInt2.y, minBoiFloSet.uLasDisBoi) annotation (Line(points={{142,380}, + {150,380},{150,326},{248,326}}, color={255,127,0})); + connect(upProCon.yStaChaPro, or2.u1) annotation (Line(points={{142,104},{168,104}, + {168,70},{178,70}}, color={255,0, + 255})); + connect(dowProCon.yStaChaPro, or2.u2) annotation (Line(points={{142,48},{158,48}, + {158,62},{178,62}}, color={255,0,255})); + connect(pre1.y, triSam.trigger) annotation (Line(points={{322,-10},{372,-10}, + {372,-64},{-150,-64},{-150,-52}}, + color={255,0,255})); + connect(pre1.y, staSetCon.uStaChaProEnd) annotation (Line(points={{322,-10},{372, + -10},{372,-64},{-209,-64},{-209,-20}}, + color={255,0,255})); + connect(pre1.y, minBoiFloSet.uStaChaPro) annotation (Line(points={{322,-10},{372, + -10},{372,300},{140,300},{140,318},{248,318}}, + color={255,0,255})); + connect(pre1.y, lat1.clr) annotation (Line(points={{322,-10},{372,-10},{372,164}, + {-192,164},{-192,174},{-190,174}}, + color={255,0,255})); + connect(priPumCon.yHotWatPum, yPriPum) + annotation (Line(points={{142,-176.267},{260,-176.267},{260,-130},{420,-130}}, + color={255,0,255})); + + connect(uBoiAva, staSetCon.uBoiAva) annotation (Line(points={{-420,70},{-300,70}, + {-300,-16},{-212,-16}}, color={255,0,255})); + connect(plaEna.yPla, upProCon.uPlaEna) annotation (Line(points={{-318,330},{ + -230,330},{-230,83},{118,83}}, color={255, + 0,255})); + connect(plaDis.yHotWatIsoVal, yHotWatIsoVal) annotation (Line(points={{262,68}, + {300,68},{300,120},{420,120}}, color={0,0,127})); + connect(plaDis.yBoi, yBoi) annotation (Line(points={{262,76},{274,76},{274,200}, + {420,200}}, color={255,0,255})); + connect(or2.y, plaDis.uStaChaProEnd) annotation (Line(points={{202,70},{208,70}, + {208,62},{238,62}}, color={255,0,255})); + connect(swi.y, plaDis.uHotWatIsoVal) annotation (Line(points={{202,230},{220,230}, + {220,70},{238,70}}, color={0,0,127})); + connect(logSwi1.y, plaDis.uBoi) annotation (Line(points={{202,270},{230,270},{ + 230,74},{238,74}}, color={255,0,255})); + connect(plaDis.yStaChaPro, pre1.u) annotation (Line(points={{262,64},{266,64}, + {266,-10},{298,-10}}, color={255,0,255})); + connect(plaEna.yPla, plaDis.uPla) annotation (Line(points={{-318,330},{-230,330}, + {-230,140},{226,140},{226,78},{238,78}}, color={255, + 0,255})); + connect(plaEna.yPla, priPumCon.uPlaEna) annotation (Line(points={{-318,330},{ + -230,330},{-230,-78},{90,-78},{90,-158.533},{118,-158.533}}, + color={255,0,255})); + connect(hotWatSupTemRes.TPlaHotWatSupSet, upProCon.THotWatSupSet) annotation + (Line(points={{-118,184},{-100,184},{-100,107},{118,107}}, color={0,0,127})); + connect(TRetPri, staSetCon.THotWatRetPri) annotation (Line(points={{-420,230}, + {-260,230},{-260,-1},{-212,-1}}, color={0,0,127})); + connect(TRetSec, staSetCon.THotWatRetSec) annotation (Line(points={{-420,150}, + {-290,150},{-290,-4},{-212,-4}}, color={0,0,127})); + connect(upProCon.yNexEnaBoi, intSwi1.u1) annotation (Line(points={{142,92},{160, + 92},{160,160},{56,160},{56,298},{62,298}}, color={255,127,0})); + connect(dowProCon.yNexEnaBoi, intSwi1.u3) annotation (Line(points={{142,36},{152, + 36},{152,200},{44,200},{44,282},{62,282}}, color={255,127,0})); + connect(lat.y, intSwi1.u2) annotation (Line(points={{-28,360},{-16,360},{-16,290}, + {62,290}}, color={255,0,255})); + connect(intSwi1.y, priPumCon.uNexEnaBoi) annotation (Line(points={{86,290},{ + 96,290},{96,-178.133},{118,-178.133}}, + color={255,127,0})); + connect(staSetCon.yChaUpEdg, priPumCon.uStaUp) annotation (Line(points={{-188,2}, + {58,2},{58,-74},{92,-74},{92,-169.733},{118,-169.733}}, + color={255,0,255})); + connect(logSwi.y, priPumCon.uOnOff) annotation (Line(points={{44,330},{50,330}, + {50,-76},{98,-76},{98,-172.533},{118,-172.533}}, color={255,0,255})); + connect(plaDis.yBoi, priPumCon.uBoiSta) annotation (Line(points={{262,76},{ + 274,76},{274,-88},{112,-88},{112,-166.933},{118,-166.933}}, + color={255,0,255})); + connect(conSet.yMinPriPumSpe, priPumCon.uMinPriPumSpeCon) annotation (Line( + points={{-38,-102},{88,-102},{88,-193.067},{118,-193.067}}, + color={0,0,127})); + connect(conInt3.y, secPumCon.uPumLeaLag) annotation (Line(points={{82,-280},{90, + -280},{90,-341.8},{118,-341.8}}, color={255,127,0})); + connect(VHotWatSec_flow, priPumCon.VHotWatSec_flow) annotation (Line(points={{-420, + -70},{8,-70},{8,-224},{114,-224},{114,-195.867},{118,-195.867}}, + color={0,0,127})); + connect(VHotWatDec_flow, priPumCon.VHotWatDec_flow) annotation (Line(points={{-420, + -110},{-190,-110},{-190,-212},{6,-212},{6,-226},{116,-226},{116, + -198.667},{118,-198.667}}, + color={0,0,127})); + connect(TSupPri, priPumCon.THotWatPri) annotation (Line(points={{-420,270},{ + -240,270},{-240,-84},{0,-84},{0,-186},{112,-186},{112,-201.467},{118, + -201.467}}, color={0,0,127})); + connect(TSupSec, priPumCon.THotWatSec) annotation (Line(points={{-420,-150},{ + -186,-150},{-186,-214},{2,-214},{2,-230},{108,-230},{108,-204.267},{ + 118,-204.267}}, + color={0,0,127})); + connect(TSupBoi, priPumCon.THotWatBoiSup) annotation (Line(points={{-420,-190}, + {-184,-190},{-184,-216},{0,-216},{0,-232},{110,-232},{110,-207.067},{ + 118,-207.067}}, + color={0,0,127})); + connect(secPumCon.yHotWatPum, ySecPum) + annotation (Line(points={{142,-360},{220,-360},{220,-340},{420,-340}}, + color={255,0,255})); + connect(plaReq, secPumCon.supResReq) annotation (Line(points={{-420,350},{-154, + 350},{-154,20},{14,20},{14,-354},{118,-354}}, color={255,127,0})); + connect(plaEna.yPla, secPumCon.uPlaEna) annotation (Line(points={{-318,330},{-230, + 330},{-230,-78},{12,-78},{12,-350},{118,-350}}, color={255,0,255})); + connect(VHotWatSec_flow, secPumCon.VHotWat_flow) annotation (Line(points={{-420, + -70},{8,-70},{8,-358},{118,-358}}, color={0,0,127})); + connect(conSet.yMaxSecPumSpe, secPumCon.uMaxSecPumSpeCon) annotation (Line( + points={{-38,-108},{94,-108},{94,-378},{118,-378}},color={0,0,127})); + connect(dpHotWatSet1.y, secPumCon.dpHotWatSet) annotation (Line(points={{82,-380}, + {86,-380},{86,-374},{118,-374}}, color={0,0,127})); + connect(dpHotWatSec_rem, secPumCon.dpHotWat_remote) annotation (Line(points={{-420, + -230},{-190,-230},{-190,-300},{86,-300},{86,-370},{118,-370}}, + color={0,0,127})); + connect(dpHotWatPri_loc, priPumCon.dpHotWat_local) annotation (Line(points={{-420, + -270},{-180,-270},{-180,-234},{96,-234},{96,-184.667},{118,-184.667}}, + color={0,0,127})); + connect(dpHotWatSec_loc, secPumCon.dpHotWat_local) annotation (Line(points={{-420, + -310},{100,-310},{100,-366},{118,-366}}, color={0,0,127})); + connect(reaToInt2.y, priPumCon.uLasDisBoi) annotation (Line(points={{142,380}, + {150,380},{150,340},{288,340},{288,-210},{102,-210},{102,-181.867},{ + 118,-181.867}}, color={255,127,0})); + connect(conInt1.y, minBoiFloSet1.uStaSet) annotation (Line(points={{-368,-30}, + {-350,-30},{-350,4},{-342,4}}, color={255,127,0})); + connect(pre1.y, dowProCon.uStaChaPro) annotation (Line(points={{322,-10},{372, + -10},{372,-64},{78,-64},{78,26},{118,26}}, color={255,0,255})); + connect(pre1.y, upProCon.uStaChaPro) annotation (Line(points={{322,-10},{372, + -10},{372,-64},{78,-64},{78,80},{118,80}}, color={255,0,255})); + connect(upProCon.yPumChaPro, or1.u1) annotation (Line(points={{142,84},{160,84}, + {160,14},{32,14},{32,-210},{56,-210}}, color={255,0,255})); + connect(dowProCon.yPumChaPro, or1.u2) annotation (Line(points={{142,28},{156,28}, + {156,18},{28,18},{28,-218},{56,-218}}, color={255,0,255})); + connect(or1.y, priPumCon.uPumChaPro) annotation (Line(points={{80,-210},{100, + -210},{100,-175.333},{118,-175.333}}, + color={255,0,255})); + connect(staSetCon.yChaDowEdg, and2.u2) annotation (Line(points={{-188,-6},{-40, + -6},{-40,52},{-30,52}}, color={255,0,255})); + connect(plaEna.yPla, and2.u1) annotation (Line(points={{-318,330},{-230,330},{ + -230,60},{-30,60}}, color={255,0,255})); + connect(and2.y, dowProCon.uStaDowPro) annotation (Line(points={{-6,60},{74,60}, + {74,34},{118,34}}, color={255,0,255})); + connect(TSupResReq, hotWatSupTemRes.nHotWatSupResReq) annotation (Line(points= + {{-420,380},{-256,380},{-256,200},{-144,200},{-144,184},{-142,184}}, + color={255,127,0})); + connect(uBoi, upProCon.uBoi) annotation (Line(points={{-420,-360},{-34,-360},{ + -34,99},{118,99}}, color={255,0,255})); + connect(uBoi, dowProCon.uBoi) annotation (Line(points={{-420,-360},{-34,-360}, + {-34,42},{118,42}}, color={255,0,255})); + connect(uPriPum, hotWatSupTemRes.uHotWatPumSta) annotation (Line(points={{-420, + -400},{-28,-400},{-28,28},{-158,28},{-158,188},{-142,188}}, color={255, + 0,255})); + connect(uPriPum, priPumCon.uHotWatPum) annotation (Line(points={{-420,-400},{ + -28,-400},{-28,-155.733},{118,-155.733}}, + color={255,0,255})); + connect(uPriPum, bypValPos.uPumSta) annotation (Line(points={{-420,-400},{-28, + -400},{-28,-42},{118,-42}}, color={255,0,255})); + connect(uPriPum, secPumCon.uPriPumSta) annotation (Line(points={{-420,-400},{-28, + -400},{-28,-362},{118,-362}}, color={255,0,255})); + connect(uPriPum, cha.u) annotation (Line(points={{-420,-400},{-28,-400},{-28,-420}, + {158,-420}}, color={255,0,255})); + connect(cha.y, mulOr.u[1:nPumPri]) annotation (Line(points={{182,-420},{190,-420},{190, + -420},{198,-420}}, color={255,0,255})); + connect(mulOr.y, plaDis.uPumChaPro) annotation (Line(points={{222,-420},{232,-420}, + {232,66},{238,66}}, color={255,0,255})); + connect(mulOr.y, upProCon.uPumChaPro) annotation (Line(points={{222,-420},{232, + -420},{232,-20},{70,-20},{70,77},{118,77}}, color={255,0,255})); + connect(mulOr.y, dowProCon.uPumChaPro) annotation (Line(points={{222,-420},{232, + -420},{232,-20},{70,-20},{70,22},{118,22}}, color={255,0,255})); + connect(uSecPum, secPumCon.uHotWatPum) annotation (Line(points={{-420,-440},{-20, + -440},{-20,-346},{118,-346}}, color={255,0,255})); + connect(uPriPumSpe, mulMax.u[1:2]) annotation (Line(points={{-420,-560},{-402, + -560},{-402,-560},{-382,-560}}, color={0,0,127})); + connect(mulMax.y, staSetCon.uPumSpe) annotation (Line(points={{-358,-560},{-262, + -560},{-262,-7},{-212,-7}}, color={0,0,127})); + connect(uHotWatIsoVal, upProCon.uHotWatIsoVal) annotation (Line(points={{-420, + -480},{38,-480},{38,103},{118,103}}, color={0,0,127})); + connect(uHotWatIsoVal, dowProCon.uHotWatIsoVal) annotation (Line(points={{-420, + -480},{38,-480},{38,46},{118,46}}, color={0,0,127})); + connect(uHotWatIsoVal, priPumCon.uHotIsoVal) annotation (Line(points={{-420, + -480},{38,-480},{38,-150},{110,-150},{110,-161.333},{118,-161.333}}, + color={ + 0,0,127})); + connect(uBypValPos, staSetCon.uBypValPos) annotation (Line(points={{-420,-520}, + {-258,-520},{-258,2},{-212,2}}, color={0,0,127})); + connect(secPumCon.yPumSpe, ySecPumSpe) annotation (Line(points={{142,-370},{ + 260,-370},{260,-390},{420,-390}}, color={0,0,127})); + connect(hotWatSupTemRes.TBoiHotWatSupSet, TBoiHotWatSupSet) annotation (Line( + points={{-118,176},{360,176},{360,170},{420,170}}, color={0,0,127})); + connect(intWitRes.y, reaToInt1.u) + annotation (Line(points={{-188,370},{-182,370}}, color={0,0,127})); + connect(intToRea1.y, intWitRes.y_reset_in) annotation (Line(points={{-218,370}, + {-216,370},{-216,362},{-212,362}}, color={0,0,127})); + connect(reaToInt2.u, intWitRes1.y) + annotation (Line(points={{118,380},{112,380}}, color={0,0,127})); + connect(intToRea2.y, intWitRes1.y_reset_in) annotation (Line(points={{82,380}, + {84,380},{84,372},{88,372}}, color={0,0,127})); + connect(con1.y, intWitRes.u) annotation (Line(points={{-108,370},{-100,370},{ + -100,392},{-214,392},{-214,370},{-212,370}}, color={0,0,127})); + connect(con1.y, intWitRes1.u) annotation (Line(points={{-108,370},{-100,370}, + {-100,398},{88,398},{88,380}}, color={0,0,127})); + connect(cha1.y, intWitRes.trigger) annotation (Line(points={{-198,330},{-190, + 330},{-190,352},{-200,352},{-200,358}}, color={255,0,255})); + connect(staSetCon.ySta, cha1.u) annotation (Line(points={{-188,6},{20,6},{20, + 300},{-226,300},{-226,330},{-222,330}}, color={255,127,0})); + connect(intSwi.y, cha2.u) annotation (Line(points={{42,380},{54,380},{54,354}, + {74,354}}, color={255,127,0})); + connect(cha2.y, intWitRes1.trigger) annotation (Line(points={{98,354},{100, + 354},{100,368}}, color={255,0,255})); + connect(hotWatSupTemRes.TPlaHotWatSupSet, TPlaHotWatSupSet) annotation (Line( + points={{-118,184},{320,184},{320,240},{420,240}}, color={0,0,127})); + connect(plaEna.yPla, yPla) annotation (Line(points={{-318,330},{-230,330},{-230, + 252},{-80,252},{-80,192},{380,192},{380,300},{420,300}}, color={255,0, + 255})); + annotation (defaultComponentName="boiPlaCon", + Icon(coordinateSystem(extent={{-100,-340},{100,340}}), + graphics={ + Rectangle( + extent={{-100,-340},{100,340}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,378},{100,338}}, + 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={{-400,-620},{400,400}}), + graphics={ + Rectangle( + extent={{-394,392},{-266,290}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-362,304},{-298,288}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + textString="Enable boiler plant"), + Rectangle( + extent={{-242,60},{-72,-70}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-140,56},{-76,40}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + textString="Calculate stage setpoint"), + Rectangle( + extent={{-226,238},{-108,162}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-226,236},{-156,218}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + textString="Calculate hot water supply +temperature setpoint", + horizontalAlignment=TextAlignment.Left), + Rectangle( + extent={{-98,-76},{-2,-138}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-94,-118},{0,-136}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Calculate condensation +control setpoints"), + Rectangle( + extent={{52,-106},{224,-226}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{146,-106},{224,-114}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Primary pump controller"), + Rectangle( + extent={{34,-260},{206,-398}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{122,-386},{200,-394}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Secondary pump controller"), + Rectangle( + extent={{82,136},{264,-12}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{152,4},{226,-8}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Staging process controllers"), + Rectangle( + extent={{-70,398},{226,216}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{152,392},{226,354}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Pass signal from +up-staging or down-staging +process controller based +on the appropriate process"), + Rectangle( + extent={{238,362},{358,282}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{292,362},{366,324}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Calculate minimum flow +setpoint for current status"), + Rectangle( + extent={{-396,48},{-292,-54}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-366,-26},{-292,-64}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Calculate minimum flow +setpoint for all stages"), + Rectangle( + extent={{108,-22},{186,-60}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{156,-34},{192,-58}}, + pattern=LinePattern.None, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Bypass +valve +controller")}), +Documentation(info=" +

+Block that controls the boiler plant components according to section 5.3 +in ASHRAE RP-1711, March 2020 draft. It consists of the following components: +

+ +

+The parameter values for valid boiler plant configurations are as follows: +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Boolean Parameters/Plant configurations1234567891011121314151617181920
have_priOnlTrueTrueFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse
have_heaPriPumTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueFalseFalseFalseFalseFalseFalseFalseFalseFalse
have_varPriPumTrueTrueTrueTrueTrueTrueTrueTrueFalseFalseFalseTrueTrueTrueTrueTrueTrueFalseFalseFalse
have_varSecPumNANATrueTrueFalseTrueTrueFalseTrueTrueFalseTrueTrueFalseTrueTrueFalseTrueTrueFalse
speConTypPrilocalDPremoteDPflowrateflowrateflowratetemperaturetemperaturetemperatureNANANAflowrateflowrateflowratetemperaturetemperaturetemperatureNANANA
speConTypSecNANAlocalDPremoteDPNAlocalDPremoteDPNAlocalDPremoteDPNAlocalDPremoteDPNAlocalDPremoteDPNAlocalDPremoteDPNA
+")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/ControllerTwo.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/ControllerTwo.mo new file mode 100644 index 00000000000..435721c6d50 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/ControllerTwo.mo @@ -0,0 +1,347 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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 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")); + + 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 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))); + + 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.BoilerPlant.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.BoilerPlant.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 boilers, isolation valves, or HW 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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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})); + + connect(uLeaStaSet, leaRunTim.uDevStaSet[1]) annotation (Line(points={{-180,0}, + {-140,0},{-140,12},{0,12},{0,-73},{38,-73}}, color={255,0,255})); + connect(uLagStaSet, leaRunTim.uDevStaSet[2]) annotation (Line(points={{-180, + -80},{-140,-80},{-140,-54},{0,-54},{0,-71},{38,-71}}, 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=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {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 boilers, 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 RP-1711, March 2020 Draft, section 5.1.2.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.BoilerPlant.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 RP-1711, this model allows the user to: +

+ +", revisions=" + +")); +end ControllerTwo; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/ContinuousLeadSwapTwo.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/ContinuousLeadSwapTwo.mo new file mode 100644 index 00000000000..27f30ef2de1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/ContinuousLeadSwapTwo.mo @@ -0,0 +1,69 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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 boilers, isolation valves, HW 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=DynamicSelect({235,235,235}, if y then {0,255,0} else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} else {235,235,235}), + fillPattern=FillPattern.Solid), Ellipse( extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} else {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 March 2020 Draft RP-1711, section 5.1.2.4.2. +

+", revisions=" + +"), + Diagram(coordinateSystem(extent={{-60,-40},{60,40}}))); +end ContinuousLeadSwapTwo; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo new file mode 100644 index 00000000000..87cbda05ac8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo @@ -0,0 +1,201 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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 uDevStaSet[nDev] if lag + "Device status setpoint: true = ON, false = OFF" + annotation (Placement(transformation(extent={{-200,20},{-160,60}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevSta[nDev] + "Device status: true = proven ON, false = proven OFF" + annotation (Placement(transformation(extent={{-200,-20},{-160,20}}), + 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={{-60,50},{-40,70}}))); + +protected + final parameter Integer nDev = 2 + "Total number of devices, such as boilers, isolation valves, or HW pumps"; + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nDev]( + final k=fill(false, nDev)) + "Constant" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Greater longer1 + "Runtime of the first device is longer than runtime of the second device" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Greater longer2 + "Runtime of the second device is longer than the runtime of the first device" + annotation (Placement(transformation(extent={{-20,20},{0,40}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nDev) + "Multiple or" + annotation (Placement(transformation(extent={{130,-10},{150,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 if lag + "Logical not" + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 if lag + "Logical not" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3[nDev] if lag + "Logical not" + annotation (Placement(transformation(extent={{6,-50},{26,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And3 and3[nDev] if lag + "Logical not" + annotation (Placement(transformation(extent={{100,10},{120,30}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1[nDev] if not lag + "Logical and" + annotation (Placement(transformation(extent={{100,-70},{120,-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={{-100,-70},{-80,-50}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nDev) if lag + "Boolean replicator" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1( + final nin=nDev) if lag + "Multi Or" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 if lag + "Identify when component turns on after they have all been turned off" + annotation (Placement(transformation(extent={{-70,-30},{-50,-10}}))); + +equation + connect(uDevSta, accTim.u) + annotation (Line(points={{-180,0},{-120,0},{-120,60},{-62,60}}, + color={255,0,255})); + connect(accTim[1].y, longer1.u1) + annotation (Line(points={{-38,60},{-22,60}}, color={0,0,127})); + connect(accTim[2].y, longer1.u2) annotation (Line(points={{-38,60},{-30,60},{-30, + 52},{-22,52}}, color={0,0,127})); + connect(accTim[1].y, longer2.u2) annotation (Line(points={{-38,60},{-30,60},{-30, + 22},{-22,22}}, color={0,0,127})); + connect(accTim[2].y, longer2.u1) annotation (Line(points={{-38,60},{-30,60},{-30, + 30},{-22,30}}, color={0,0,127})); + connect(yRot, yRot) + annotation (Line(points={{180,0},{180,0}}, color={255,0,255})); + connect(longer2.y, not2.u) + annotation (Line(points={{2,30},{18,30}}, color={255,0,255})); + connect(longer1.y, not1.u) + annotation (Line(points={{2,60},{18,60}}, color={255,0,255})); + connect(uPreDevRolSig, not3.u) + annotation (Line(points={{-180,-40},{4,-40}}, color={255,0,255})); + connect(not1.y, and3[1].u1) annotation (Line(points={{42,60},{80,60},{80,28},{ + 98,28}}, color={255,0,255})); + connect(not2.y, and3[2].u1) annotation (Line(points={{42,30},{80,30},{80,28},{ + 98,28}}, color={255,0,255})); + connect(mulOr.y, yRot) + annotation (Line(points={{152,0},{180,0}}, color={255,0,255})); + connect(longer1.y, and1[1].u1) annotation (Line(points={{2,60},{10,60},{10,-20}, + {80,-20},{80,-60},{98,-60}}, color={255,0,255})); + connect(longer2.y, and1[2].u1) annotation (Line(points={{2,30},{10,30},{10,-20}, + {80,-20},{80,-60},{98,-60}}, color={255,0,255})); + connect(con.y, accTim.reset) annotation (Line(points={{-78,30},{-70,30},{-70,52}, + {-62,52}}, color={255,0,255})); + connect(falEdg.y, and1.u2) annotation (Line(points={{-78,-60},{70,-60},{70,-68}, + {98,-68}}, color={255,0,255})); + connect(and3.y, mulOr.u) annotation (Line(points={{122,20},{124,20},{124, + 0},{128,0}}, color={255,0,255})); + connect(and1.y, mulOr.u) annotation (Line(points={{122,-60},{124,-60},{ + 124,0},{128,0}}, color={255,0,255})); + connect(booRep.y, and3.u3) annotation (Line(points={{-18,-20},{-10,-20},{-10,12}, + {98,12}}, color={255,0,255})); + connect(not3.y, and3.u2) annotation (Line(points={{28,-40},{90,-40},{90,20},{98, + 20}}, color={255,0,255})); + connect(uDevStaSet, mulOr1.u[1:2]) annotation (Line(points={{-180,40},{-130,40}, + {-130,-23.5},{-102,-23.5}}, color={255,0,255})); + connect(mulOr1.y, edg1.u) + annotation (Line(points={{-78,-20},{-72,-20}}, color={255,0,255})); + connect(edg1.y, booRep.u) + annotation (Line(points={{-48,-20},{-42,-20}}, color={255,0,255})); + + connect(uDevSta, falEdg.u) annotation (Line(points={{-180,0},{-120,0},{-120,-60}, + {-102,-60}}, 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.2.3. and 5.1.2.4.1. of RP1711 March 2020 draft when applied to +two devices or groups of devices. +

+", revisions=" + +")); +end LeastRuntime; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/MinimumLeadRuntime.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/MinimumLeadRuntime.mo new file mode 100644 index 00000000000..c2de9d8cb6b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/MinimumLeadRuntime.mo @@ -0,0 +1,148 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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 boilers, isolation valves, or HW 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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo new file mode 100644 index 00000000000..0d2cbda85b3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo @@ -0,0 +1,251 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.Subsequences; +block Scheduler + "Equipment rotation signal based on a scheduler for equipment that runs continuously" + + 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 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 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)); + + 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 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)); + + 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.Continuous.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 y then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {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 RP 1711 5.1.2.4.2, except 5.1.2.4.2 a. +

+

+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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Two.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Two.mo new file mode 100644 index 00000000000..24df5aa6b91 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Two.mo @@ -0,0 +1,114 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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 boilers, isolation valves, or HW 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.BoilerPlant.Generic.EquipmentRotation.ControllerTwo. +

+", revisions=" + +")); +end Two; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mo new file mode 100644 index 00000000000..a3584c93d9c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mo @@ -0,0 +1,174 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model ContinuousLeadSwapTwo_uDevSta + "Validation sequence for lead device swap at continuous lead operation" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/ContinuousLeadSwapTwo_uDevSta.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mo new file mode 100644 index 00000000000..762c67b92cb --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mo @@ -0,0 +1,177 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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})); + connect(logSwi.y, leaRunTim.uDevStaSet) annotation (Line(points={{22,50},{30, + 50},{30,58},{38,58}}, color={255,0,255})); + connect(logSwi1.y, leaRunTim1.uDevStaSet) + annotation (Line(points={{22,0},{30,0},{30,8},{38,8}}, color={255,0,255})); + connect(logSwi2.y, leaRunTim2.uDevStaSet) annotation (Line(points={{22,-50},{ + 30,-50},{30,-42},{38,-42}}, color={255,0,255})); + annotation ( + experiment(StopTime=100000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/LeastRuntime_uDevRol.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mo new file mode 100644 index 00000000000..b20f295bba6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mo @@ -0,0 +1,155 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model MinimumLeadRuntime_uDevRol + "Validate lead/lag and lead/standby switching signal based on device runtime" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/MinimumLeadRuntime_uDevRol.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mo new file mode 100644 index 00000000000..e3b3641318d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mo @@ -0,0 +1,121 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.Subsequences.Validation; +model Scheduler + "Validation sequence for the device swap scheduler in case of continuous lead device operation" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Scheduler.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mo new file mode 100644 index 00000000000..d073ee1b29c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mo @@ -0,0 +1,55 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/Two_uRot.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..a3ca57267d0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/Validation/package.order new file mode 100644 index 00000000000..7b775d54c4e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/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/BoilerPlant/Generic/EquipmentRotation/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/package.mo new file mode 100644 index 00000000000..ed9f6d78a4b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/package.order new file mode 100644 index 00000000000..8a7466fd0ea --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Subsequences/package.order @@ -0,0 +1,6 @@ +ContinuousLeadSwapTwo +LeastRuntime +MinimumLeadRuntime +Scheduler +Two +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mo new file mode 100644 index 00000000000..2651fe2ae23 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mo @@ -0,0 +1,165 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.Generic.EquipmentRotation.ControllerTwo + conLeaSch( + final lag=false, + final continuous=true, + final minLim=false, + final simTimSta=false, + final weeInt=false, + final zerTim=Buildings.Controls.OBC.CDL.Types.ZeroTime.Custom, + final yearRef=2020, + final houOfDay=2, + final weekday=3, + final 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/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mo new file mode 100644 index 00000000000..49eb08cc8c5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mo @@ -0,0 +1,109 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Validation/ControllerTwo_MinimumLeadRuntime.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/package.mo new file mode 100644 index 00000000000..3e49b77ab6a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Generic/EquipmentRotation/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/package.order new file mode 100644 index 00000000000..cfbefbf6d93 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/Validation/package.order @@ -0,0 +1,2 @@ +ControllerTwo +ControllerTwo_MinimumLeadRuntime diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/package.mo new file mode 100644 index 00000000000..6d42ebb5672 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/package.mo @@ -0,0 +1,48 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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 RP1711. +March 2020 draft, section 5.1.2. 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/BoilerPlant/Generic/EquipmentRotation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/package.order new file mode 100644 index 00000000000..d6215f892f4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/EquipmentRotation/package.order @@ -0,0 +1,3 @@ +ControllerTwo +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/PlantDisable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/PlantDisable.mo new file mode 100644 index 00000000000..e48efb69b1d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/PlantDisable.mo @@ -0,0 +1,309 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic; +block PlantDisable + "Sequence to disable boiler plant components when plant has to be disabled" + + parameter Boolean have_priOnl = false + "True: Boiler plant is primary-only; False: Boiler plant is not primary-only"; + + parameter Boolean have_heaPriPum = true + "True: Boiler plant has headered pump configuration; False: Boiler plant has dedicated pump configuration"; + + parameter Integer nBoi=3 + "Total number of boilers in the plant"; + + parameter Real chaHotWatIsoRat( + final unit="1/s", + final displayUnit="1/s") = 1/60 + "Rate at which to slowly change isolation valve, should be determined in the field"; + + parameter Real delBoiDis=180 + "Time delay after boilers have been disabled before completing disabling process"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable/disable signal from plant enabler" + annotation (Placement(transformation(extent={{-200,100},{-160,140}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoi[nBoi] + "Boiler enable status signal" + annotation (Placement(transformation(extent={{-200,30},{-160,70}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal from staging process controller indicating stage-up/stage-down has been completed" + annotation (Placement(transformation(extent={{-200,-140},{-160,-100}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPumChaPro if not have_priOnl + "Signal from pump controller indicating stage-up/stage-down has been completed" + annotation (Placement(transformation(extent={{-200,-100},{-160,-60}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal[nBoi] if have_heaPriPum + "Boiler hot water isolation valve position vector" + annotation (Placement(transformation(extent={{-200,-60},{-160,-20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler enable status vector" + annotation (Placement(transformation(extent={{180,30},{220,70}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaChaPro + "Signal indicating end of stage change/plant disable process" + annotation (Placement(transformation(extent={{180,-140},{220,-100}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal[nBoi] if have_heaPriPum + "Boiler hot water isolation valve position vector" + annotation (Placement(transformation(extent={{180,-70},{220,-30}}), + iconTransformation(extent={{100,-40},{140,0}}))); + +protected + parameter Integer boiInd[nBoi]={i for i in 1:nBoi} + "Boiler index vector"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Subsequences.HWIsoVal disHotWatIsoVal[nBoi]( + final chaHotWatIsoRat=fill(chaHotWatIsoRat, nBoi)) if have_heaPriPum + "Disable boiler hot water isolation valve for all disabled boilers simultaneously" + annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nBoi] + "Pass input boiler enable status when plant is enabled and disable all boilers when plant is disabled" + annotation (Placement(transformation(extent={{140,40},{160,60}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-130,-20},{-110,0}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nBoi) if have_heaPriPum + "Boolean replicator" + annotation (Placement(transformation(extent={{-20,-20},{0,0}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=delBoiDis, + final delayOnInit=true) + "Delay after all boilers have been disabled" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Pass through stage change completion signal from staging process controller when plant is enabled" + annotation (Placement(transformation(extent={{-10,-130},{10,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Logical Or" + annotation (Placement(transformation(extent={{120,-130},{140,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd1( + final nin=nBoi) if have_priOnl and have_heaPriPum + "Multi And" + annotation (Placement(transformation(extent={{80,-126},{100,-106}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 if not have_priOnl + "Hold pump change status after receiving signal from primary pump controller" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 if not have_priOnl and have_heaPriPum + "Signal stage change completion when both pump stage change and isolation valve change are complete" + annotation (Placement(transformation(extent={{120,-100},{140,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre if not have_priOnl + "Logical pre block" + annotation (Placement(transformation(extent={{-140,-110},{-120,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Rising edge detector" + annotation (Placement(transformation(extent={{150,-130},{170,-110}}))); + + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd2( + final nin=nBoi) if not have_priOnl and have_heaPriPum + "Multi And" + annotation (Placement(transformation(extent={{80,-100},{100,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1( + final nin=1) if not have_priOnl and not have_heaPriPum + "Multi Or" + annotation (Placement(transformation(extent={{-10,-100},{10,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nBoi] if have_heaPriPum + "Real switch" + annotation (Placement(transformation(extent={{140,-60},{160,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 if not have_priOnl + "Indicate pump change completion only when plant is disabled" + annotation (Placement(transformation(extent={{-90,-80},{-70,-60}}))); + +equation + connect(uBoi, logSwi.u1) annotation (Line(points={{-180,50},{-120,50},{-120, + 58},{138,58}}, color={255,0,255})); + + connect(booRep1.y, logSwi.u3) annotation (Line(points={{-18,120},{-10,120},{ + -10,70},{60,70},{60,42},{138,42}}, + color={255,0,255})); + + connect(booRep2.u, truDel.y) + annotation (Line(points={{-22,-10},{-38,-10}}, color={255,0,255})); + + connect(and2.y, or2.u2) annotation (Line(points={{12,-120},{60,-120},{60,-128}, + {118,-128}}, color={255,0,255})); + + connect(mulAnd1.y, or2.u1) annotation (Line(points={{102,-116},{110,-116},{110, + -120},{118,-120}}, color={255,0,255})); + + connect(uStaChaProEnd, and2.u1) + annotation (Line(points={{-180,-120},{-12,-120}}, color={255,0,255})); + + connect(lat1.y, and1.u1) annotation (Line(points={{-38,-80},{-20,-80},{-20,-72}, + {114,-72},{114,-90},{118,-90}}, color={255,0,255})); + + connect(and1.y, or2.u1) annotation (Line(points={{142,-90},{152,-90},{152,-104}, + {116,-104},{116,-120},{118,-120}}, color={255,0,255})); + + connect(pre.y, lat1.clr) annotation (Line(points={{-118,-100},{-110,-100},{-110, + -86},{-62,-86}}, color={255,0,255})); + + connect(or2.y, edg1.u) + annotation (Line(points={{142,-120},{148,-120}}, color={255,0,255})); + + connect(edg1.y, yStaChaPro) + annotation (Line(points={{172,-120},{200,-120}}, color={255,0,255})); + + connect(edg1.y, pre.u) annotation (Line(points={{172,-120},{174,-120},{174,-132}, + {-150,-132},{-150,-100},{-142,-100}}, color={255,0,255})); + + connect(mulAnd2.y, and1.u2) annotation (Line(points={{102,-90},{108,-90},{108, + -98},{118,-98}}, color={255,0,255})); + + connect(lat1.y, mulOr1.u[1]) annotation (Line(points={{-38,-80},{-20,-80},{-20, + -90},{-12,-90}},color={255,0,255})); + + connect(mulOr1.y, or2.u1) annotation (Line(points={{12,-90},{48,-90},{48,-136}, + {110,-136},{110,-120},{118,-120}}, color={255,0,255})); + + connect(booRep1.y, logSwi.u2) annotation (Line(points={{-18,120},{-10,120},{ + -10,70},{60,70},{60,50},{138,50}}, + color={255,0,255})); + + connect(logSwi.y, yBoi) + annotation (Line(points={{162,50},{200,50}}, color={255,0,255})); + + connect(not1.y, truDel.u) + annotation (Line(points={{-108,-10},{-62,-10}},color={255,0,255})); + + connect(swi.y, yHotWatIsoVal) + annotation (Line(points={{162,-50},{200,-50}}, color={0,0,127})); + + connect(uPla, booRep1.u) + annotation (Line(points={{-180,120},{-42,120}}, color={255,0,255})); + connect(uPla, not1.u) annotation (Line(points={{-180,120},{-140,120},{-140, + -10},{-132,-10}}, + color={255,0,255})); + connect(uPla, and2.u2) annotation (Line(points={{-180,120},{-140,120},{-140, + 10},{-34,10},{-34,-128},{-12,-128}}, + color={255,0,255})); + connect(uHotWatIsoVal, disHotWatIsoVal.uHotWatIsoVal) annotation (Line(points={{-180, + -40},{0,-40},{0,-44},{18,-44}}, color={0,0,127})); + connect(disHotWatIsoVal.yDisHotWatIsoVal, mulAnd2.u[1:nBoi]) annotation (Line( + points={{42,-44},{60,-44},{60,-90},{78,-90}}, color={255,0,255})); + connect(disHotWatIsoVal.yDisHotWatIsoVal, mulAnd1.u[1:nBoi]) annotation (Line( + points={{42,-44},{60,-44},{60,-116},{78,-116}}, color={255,0,255})); + connect(disHotWatIsoVal.yHotWatIsoVal, swi.u1) annotation (Line(points={{42,-56}, + {100,-56},{100,-42},{138,-42}}, color={0,0,127})); + connect(uHotWatIsoVal, swi.u3) annotation (Line(points={{-180,-40},{0,-40},{0, + -32},{130,-32},{130,-58},{138,-58}}, color={0,0,127})); + connect(booRep2.y, disHotWatIsoVal.uUpsDevSta) annotation (Line(points={{2,-10}, + {10,-10},{10,-50},{18,-50}}, color={255,0,255})); + connect(booRep2.y, swi.u2) annotation (Line(points={{2,-10},{10,-10},{10,-20}, + {120,-20},{120,-50},{138,-50}}, color={255,0,255})); + connect(and3.y, lat1.u) annotation (Line(points={{-68,-70},{-66,-70},{-66,-80}, + {-62,-80}}, color={255,0,255})); + connect(uPumChaPro, and3.u2) annotation (Line(points={{-180,-80},{-100,-80},{ + -100,-78},{-92,-78}}, color={255,0,255})); + connect(not1.y, and3.u1) annotation (Line(points={{-108,-10},{-100,-10},{-100, + -70},{-92,-70}}, color={255,0,255})); + connect(booRep2.y, disHotWatIsoVal.chaPro) annotation (Line(points={{2,-10},{10, + -10},{10,-56},{18,-56}}, color={255,0,255})); + annotation (defaultComponentName="plaDis", + Icon(graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineThickness=0.1), + 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")}, + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-160,-140},{180,140}})), + Documentation( + info=" +

+ Block that controls boiler plant disable process according to ASHRAE RP-1711, + March, 2020 draft, section 5.3.2.5. +

+

+ When the boiler plant is disabled by the plant enable controller + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable, + the controller performs the following actions: +

+
    +
  1. + All the enabled boilers are disabled, ie, yBoi[nBoi]=false. +
  2. +
  3. + A time period delBoiDis after the boilers have been disabled,any + open hot water isolation valves are closed (if present) and any enabled pumps are disabled. +
  4. +
+ ", + revisions=" + + ")); +end PlantDisable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/PlantEnable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/PlantEnable.mo new file mode 100644 index 00000000000..fee4e54e247 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/PlantEnable.mo @@ -0,0 +1,303 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic; +block PlantEnable + "Sequence to enable/disable boiler plant based on heating hot-water requirements" + + parameter Integer nIgnReq( + final min=0) = 0 + "Number of hot-water requests to be ignored before enablng boiler plant loop"; + + parameter Integer nSchRow( + final min=1) = 4 + "Number of rows to be created for plant schedule table"; + + parameter Real schTab[nSchRow,2] = [0,1; 6,1; 18,1; 24,1] + "Table defining schedule for enabling plant"; + + parameter Real TOutLoc( + final unit="K", + final displayUnit="K") = 300 + "Boiler lock-out temperature for outdoor air"; + + parameter Real plaOffThrTim( + final unit="s", + final displayUnit="s") = 900 + "Minimum time for which the plant has to stay off once it has been disabled"; + + parameter Real plaOnThrTim( + final unit="s", + final displayUnit="s") = plaOffThrTim + "Minimum time for which the boiler plant has to stay on once it has been enabled"; + + parameter Real staOnReqTim( + final unit="s", + final displayUnit="s") = 180 + "Time-limit for receiving hot-water requests to maintain enabled plant on"; + + parameter Real locDt( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") = 1 + "Temperature deadband for boiler lockout" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput supResReq + "Number of heating hot-water requests" + annotation (Placement(transformation(extent={{-200,30},{-160,70}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured outdoor air temperature" + annotation (Placement(transformation(extent={{-200,-40},{-160,0}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPla + "Plant enable signal" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.TimeTable enaSch( + final table=schTab, + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + final timeScale=3600) + "Table defining when plant can be enabled" + annotation (Placement(transformation(extent={{-150,-120},{-130,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim(t=plaOnThrTim) + "Time since plant has been enabled" + annotation (Placement(transformation(extent={{10,0},{30,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim2(t=plaOffThrTim) + "Time since plant has been disabled" + annotation (Placement(transformation(extent={{10,60},{30,80}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=-1) + "Invert signal for subtraction" + annotation (Placement(transformation(extent={{-152,-30},{-132,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr( + final t=0.5) + "Check if schedule lets the controller enable the plant or not" + annotation (Placement(transformation(extent={{-120,-120},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr( + final t=nIgnReq) + "Check if number of requests is greater than number of requests to be ignored" + annotation (Placement(transformation(extent={{-120,40},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Maintain plant status till the conditions to change it are met" + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=4) + "Check if all the conditions for enabling plant have been met" + annotation (Placement(transformation(extent={{80,110},{100,130}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=3) + "Check if any conditions except plant-on time have been satisfied to disable plant" + annotation (Placement(transformation(extent={{30,-80},{50,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Check if all conditions have been met to disable the plant" + annotation (Placement(transformation(extent={{80,-40},{100,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-10,-120},{10,-100}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=TOutLoc) + "Compare measured outdoor air temperature to boiler lockout temperature" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=-locDt, + final uHigh=0) + "Hysteresis loop to prevent cycling caused by measured value" + annotation (Placement(transformation(extent={{-120,-60},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical Not" + annotation (Placement(transformation(extent={{-70,-40},{-50,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim1(t=staOnReqTim) + "Time since number of requests was greater than number of ignores" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4 + "Logical Not" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Logical Not" + annotation (Placement(transformation(extent={{-10,-80},{10,-60}}))); + +equation + connect(yPla, yPla) + annotation (Line(points={{180,0},{180,0}}, color={255,0,255})); + connect(greThr.y, not1.u) + annotation (Line(points={{-98,-110},{-12,-110}}, color={255,0,255})); + connect(hys.u, addPar.y) annotation (Line(points={{-122,-50},{-128,-50},{-128, + -34},{-96,-34},{-96,-20},{-98,-20}}, color={0,0,127})); + connect(not3.y, tim1.u) + annotation (Line(points={{-48,-30},{-42,-30}}, color={255,0,255})); + connect(not4.y, tim2.u) + annotation (Line(points={{2,70},{8,70}}, color={255,0,255})); + connect(not2.u, hys.y) annotation (Line(points={{-12,-70},{-20,-70},{-20,-50}, + {-98,-50}}, color={255,0,255})); + connect(intGreThr.y, not3.u) annotation (Line(points={{-98,50},{-80,50},{-80,-30}, + {-72,-30}}, color={255,0,255})); + connect(pre1.y, not4.u) annotation (Line(points={{-38,50},{-30,50},{-30,70},{-22, + 70}}, color={255,0,255})); + connect(greThr.y, mulAnd.u[1]) annotation (Line(points={{-98,-110},{-92,-110}, + {-92,125.25},{78,125.25}}, + color={255,0,255})); + connect(hys.y, mulAnd.u[2]) annotation (Line(points={{-98,-50},{-86,-50},{-86, + 121.75},{78,121.75}}, color={255,0,255})); + connect(intGreThr.y, mulAnd.u[3]) annotation (Line(points={{-98,50},{-80,50},{ + -80,118.25},{78,118.25}}, color={255,0,255})); + connect(mulAnd.y, lat.u) annotation (Line(points={{102,120},{110,120},{110,0}, + {118,0}}, color={255,0,255})); + connect(and2.y, lat.clr) annotation (Line(points={{102,-30},{110,-30},{110,-6}, + {118,-6}}, color={255,0,255})); + connect(not2.y, mulOr.u[1]) annotation (Line(points={{12,-70},{20,-70},{20, + -65.3333},{28,-65.3333}}, + color={255,0,255})); + connect(not1.y, mulOr.u[2]) annotation (Line(points={{12,-110},{20,-110},{20,-70}, + {28,-70}}, color={255,0,255})); + connect(mulOr.y, and2.u2) annotation (Line(points={{52,-70},{70,-70},{70,-38}, + {78,-38}}, color={255,0,255})); + connect(intGreThr.u, supResReq) + annotation (Line(points={{-122,50},{-180,50}}, color={255,127,0})); + connect(lat.y, yPla) + annotation (Line(points={{142,0},{180,0}}, color={255,0,255})); + connect(lat.y, pre1.u) annotation (Line(points={{142,0},{150,0},{150,30},{-70, + 30},{-70,50},{-62,50}}, color={255,0,255})); + connect(pre1.y, tim.u) annotation (Line(points={{-38,50},{-30,50},{-30,10},{8, + 10}}, color={255,0,255})); + connect(enaSch.y[1], greThr.u) + annotation (Line(points={{-128,-110},{-122,-110}}, color={0,0,127})); + connect(tim2.passed, mulAnd.u[4]) annotation (Line(points={{32,62},{60,62},{60, + 114},{78,114},{78,114.75}}, color={255,0,255})); + connect(tim.passed, and2.u1) annotation (Line(points={{32,2},{70,2},{70,-30},{ + 78,-30}}, color={255,0,255})); + connect(tim1.passed, mulOr.u[3]) annotation (Line(points={{-18,-38},{20,-38}, + {20,-74.6667},{28,-74.6667}},color={255,0,255})); + connect(addPar.u, gai.y) + annotation (Line(points={{-122,-20},{-130,-20}}, color={0,0,127})); + connect(TOut, gai.u) + annotation (Line(points={{-180,-20},{-154,-20}}, color={0,0,127})); + annotation (defaultComponentName = "plaEna", + Icon(graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineThickness=0.1), + 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")}, + coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}})), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-160,-140},{160,140}})), + Documentation(info=" +

+ Block that generates boiler plant enable signal according to sections 5.3.2.1, + 5.3.2.2, and 5.3.2.3 in RP-1711, March 2020 draft. +

+

+ The boiler plant should be enabled and disabled according to the following + conditions: +

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

+ \"Validation +
+ Validation plot generated from model + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Validation.PlantEnable. +

+ ", + revisions=" + + ")); +end PlantEnable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/RotationController.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/RotationController.mo new file mode 100644 index 00000000000..23d991f52e3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/RotationController.mo @@ -0,0 +1,284 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic; +block RotationController + "Sequence to rotate components in lead/lag pairs" + + 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 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")); + + 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))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevStaSet[nDev] + "Device status setpoint from controller" + annotation (Placement(transformation(extent={{-140,30},{-100,70}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDevSta[nDev] + "Measured device status from plant" + annotation (Placement(transformation(extent={{-140,-50},{-100,-10}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDevStaSet[nDev] + "Device status setpoint from equipment rotation controller" + annotation (Placement(transformation(extent={{100,30},{140,70}}), + iconTransformation(extent={{100,30},{140,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaFee[nDev] + "Component status feedback signal back to main controller" + annotation (Placement(transformation(extent={{100,-80},{140,-40}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.ControllerTwo equRot( + final lag = lag, + final continuous = continuous, + final minLim = minLim, + final initRoles = initRoles, + final simTimSta = simTimSta, + final weeInt = weeInt, + final rotationPeriod = rotationPeriod, + final minLeaRuntime = minLeaRuntime, + final offset = offset, + final zerTim = zerTim, + final yearRef = yearRef, + final houOfDay = houOfDay, + final weeCou = weeCou, + final weekday = weekday, + final dayCou = dayCou) + "Equipment rotation controller" + annotation (Placement(transformation(extent={{-70,30},{-50,50}}))); + +protected + final parameter Integer nDev = 2 + "Number of devices in lead/lag relationship"; + + 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.CDL.Conversions.BooleanToInteger booToInt[nDev] + "Boolean to Integer conversion" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nDev) + "Integer Multi-sum" + annotation (Placement(transformation(extent={{10,-10},{30,10}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr + "Check if one component is enabled" + annotation (Placement(transformation(extent={{50,20},{70,40}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr1( + final t=1) + "Check if both components are enabled" + annotation (Placement(transformation(extent={{50,-10},{70,10}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep[nDev]( + final nout=fill(nDev, nDev)) + "Boolean replicator" + annotation (Placement(transformation(extent={{-30,-50},{-10,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nDev] + "Logical switch" + annotation (Placement(transformation(extent={{10,-90},{30,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nDev]( + final k={true,false}) + "Constant Boolean source" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nDev]( + final k={false,false}) + "Constant Boolean source" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nDev] + "Logical switch" + annotation (Placement(transformation(extent={{50,-70},{70,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nDev]( + final k={true,true}) + "Constant Boolean source" + annotation (Placement(transformation(extent={{10,-50},{30,-30}}))); + +equation + connect(uDevStaSet[1], equRot.uLeaStaSet) annotation (Line(points={{-120,40},{ + -120,50},{-80,50},{-80,46},{-72,46}}, + color={255,0,255})); + connect(uDevSta, equRot.uDevSta) annotation (Line(points={{-120,-30},{-80,-30}, + {-80,34},{-72,34}}, color={255,0,255})); + connect(equRot.yDevStaSet, yDevStaSet) annotation (Line(points={{-48,46},{-30, + 46},{-30,50},{120,50}}, color={255,0,255})); + connect(booToInt.y, mulSumInt.u[1:2]) + annotation (Line(points={{2,0},{8,0},{8,-3.5}}, color={255,127,0})); + connect(mulSumInt.y, intGreThr.u) annotation (Line(points={{32,0},{40,0},{40,30}, + {48,30}}, color={255,127,0})); + connect(mulSumInt.y, intGreThr1.u) + annotation (Line(points={{32,0},{48,0}}, color={255,127,0})); + connect(intGreThr.y, booRep[1].u) annotation (Line(points={{72,30},{80,30},{80, + -20},{-40,-20},{-40,-40},{-32,-40}}, color={255,0,255})); + connect(intGreThr1.y, booRep[2].u) annotation (Line(points={{72,0},{80,0},{80, + -20},{-40,-20},{-40,-40},{-32,-40}}, color={255,0,255})); + connect(booRep[1].y, logSwi.u2) annotation (Line(points={{-8,-40},{0,-40},{0,-80}, + {8,-80}}, color={255,0,255})); + connect(con.y, logSwi.u1) annotation (Line(points={{-58,-50},{-48,-50},{-48,-72}, + {8,-72}}, color={255,0,255})); + connect(con1.y, logSwi.u3) annotation (Line(points={{-58,-80},{-54,-80},{-54,-88}, + {8,-88}}, color={255,0,255})); + connect(logSwi.y, logSwi1.u3) annotation (Line(points={{32,-80},{40,-80},{40,-68}, + {48,-68}}, color={255,0,255})); + connect(booRep[2].y, logSwi1.u2) annotation (Line(points={{-8,-40},{0,-40},{0, + -60},{48,-60}}, color={255,0,255})); + connect(con2.y, logSwi1.u1) annotation (Line(points={{32,-40},{40,-40},{40,-52}, + {48,-52}}, color={255,0,255})); + connect(logSwi1.y, yStaFee) + annotation (Line(points={{72,-60},{120,-60}}, color={255,0,255})); + connect(uDevSta, booToInt.u) annotation (Line(points={{-120,-30},{-80,-30},{-80, + 0},{-22,0}}, color={255,0,255})); + connect(uDevStaSet[2], equRot.uLagStaSet) annotation (Line(points={{-120,60},{ + -120,50},{-80,50},{-80,40},{-72,40}}, color={255,0,255})); + annotation (defaultComponentName="rotCon", + Icon(graphics={ + Text( + extent={{-120,146},{100,108}}, + textColor={0,0,255}, + textString="%name"), + 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 y then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + origin={-26.667,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,-81.379}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-53.3333,1.37927},{-13.3329,41.3792}}), + Ellipse( + origin={-26.667,-81.379}, + 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})}, + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Documentation( + info=" +

+ Block that controls equipment rotation process according to ASHRAE RP-1711, + March, 2020 draft, section 5.1.2.3. +

+

+ The implemented block acts as a wrapper for the equipment rotation controller + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.EquipmentRotation.ControllerTwo. + In addition to the inputs and outputs available from the above block, + the implemented sequence has an additional output yStaFee, + which is the device status feedback to the main controller. This vector + arranges the status vector in the lead/lag order and sends it back to the + main controller. + ", + revisions=" +

+ ")); +end RotationController; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/HWIsoVal.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/HWIsoVal.mo new file mode 100644 index 00000000000..bd575cb02be --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/HWIsoVal.mo @@ -0,0 +1,313 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Subsequences; +block HWIsoVal + "Sequence of enable or disable hot water isolation valve" + + parameter Real chaHotWatIsoRat( + final unit="1/s", + displayUnit="1/s") = 1/60 + "Rate at which to slowly close isolation valve, should be determined in the field"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of device reset before enabling or disabling isolation valve" + annotation (Placement(transformation(extent={{-200,-160},{-160,-120}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "Indicate if there is a stage up or stage down command" + annotation (Placement(transformation(extent={{-200,-200},{-160,-160}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal( + final unit="1", + displayUnit="1", + final min=0, + final max=1) + "Hot water isolation valve position" + annotation (Placement(transformation(extent={{-200,-120},{-160,-80}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDisHotWatIsoVal + "Status of hot water isolation valve control: true=disabled valve is fully closed" + annotation (Placement(transformation(extent={{180,120},{220,160}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal( + final unit="1", + displayUnit="1", + final min=0, + final max=1) + "Hot water isolation valve position" + annotation (Placement(transformation(extent={{180,-60},{220,-20}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=1/chaHotWatIsoRat) + "Find remaining time for valve position change" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Sample valve position at start of shutdown process" + annotation (Placement(transformation(extent={{-70,40},{-50,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) + "Determine time required to change valve position" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Greater gre + "Check if time required for changing valve position has elapsed" + annotation (Placement(transformation(extent={{60,110},{80,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con9( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line lin1 + "Hot water isolation valve setpoint" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim + "Count the time after changing up-stream device status" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Check if it is time to change isolation valve position" + annotation (Placement(transformation(extent={{-80,-180},{-60,-160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{140,-50},{160,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys3( + final uLow=0.025, + final uHigh=0.05) + "Check if isolation valve is disabled" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys4( + final uLow=0.925, + final uHigh=0.975) + "Check if isolation valve is open more than 95%" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical not" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4 + "Logical not" + annotation (Placement(transformation(extent={{-40,150},{-20,170}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4 + "Logical and" + annotation (Placement(transformation(extent={{0,180},{20,200}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical and" + annotation (Placement(transformation(extent={{0,210},{20,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Logical or" + annotation (Placement(transformation(extent={{40,210},{60,230}}))); + + Buildings.Controls.OBC.CDL.Logical.And3 and5 + "Check if the isolation valve has been fully open" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + +equation + connect(con9.y, lin1.x1) + annotation (Line(points={{22,100},{30,100},{30,88},{38,88}}, + color={0,0,127})); + + connect(tim.y, lin1.u) + annotation (Line(points={{-78,100},{-20,100},{-20,80},{38,80}}, + color={0,0,127})); + + connect(chaPro, and2.u2) + annotation (Line(points={{-180,-180},{-132,-180},{-132,-178},{-82,-178}}, + color={255,0,255})); + + connect(swi.y,yHotWatIsoVal) + annotation (Line(points={{162,-40},{200,-40}}, color={0,0,127})); + + connect(uHotWatIsoVal, hys4.u) + annotation (Line(points={{-180,-100},{-140,-100},{-140,160},{-122,160}}, + color={0,0,127})); + + connect(uHotWatIsoVal, 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(and5.y,yDisHotWatIsoVal) + annotation (Line(points={{162,140},{200,140}}, color={255,0,255})); + + connect(uUpsDevSta, and5.u2) + annotation (Line(points={{-180,-140},{-130,-140},{-130,140},{138,140}}, + color={255,0,255})); + + connect(uUpsDevSta, and2.u1) annotation (Line(points={{-180,-140},{-100,-140}, + {-100,-170},{-82,-170}},color={255,0,255})); + + connect(tim.u, and2.y) annotation (Line(points={{-102,100},{-120,100},{-120, + -200},{-50,-200},{-50,-170},{-58,-170}}, color={255,0,255})); + + connect(addPar.y, lin1.x2) annotation (Line(points={{42,20},{80,20},{80,100},{ + 34,100},{34,76},{38,76}}, + color={0,0,127})); + + connect(tim.y, gre.u1) annotation (Line(points={{-78,100},{-20,100},{-20,120}, + {58,120}}, + color={0,0,127})); + + connect(addPar.y, gre.u2) annotation (Line(points={{42,20},{80,20},{80,100},{34, + 100},{34,112},{58,112}}, color={0,0,127})); + + connect(gre.y, and5.u3) annotation (Line(points={{82,120},{120,120},{120,132}, + {138,132}}, color={255,0,255})); + + connect(con9.y, lin1.f2) annotation (Line(points={{22,100},{30,100},{30,72},{38, + 72}}, color={0,0,127})); + connect(triSam.y, lin1.f1) annotation (Line(points={{-48,50},{-40,50},{-40,84}, + {38,84}}, color={0,0,127})); + connect(or2.y, and5.u1) annotation (Line(points={{62,220},{120,220},{120,148}, + {138,148}}, color={255,0,255})); + connect(uHotWatIsoVal, triSam.u) annotation (Line(points={{-180,-100},{-100,-100}, + {-100,50},{-72,50}}, color={0,0,127})); + connect(lin1.y, swi.u1) annotation (Line(points={{62,80},{100,80},{100,-32},{138, + -32}}, color={0,0,127})); + connect(uHotWatIsoVal, swi.u3) annotation (Line(points={{-180,-100},{110,-100}, + {110,-48},{138,-48}}, color={0,0,127})); + + connect(and2.y, swi.u2) annotation (Line(points={{-58,-170},{-50,-170},{-50,-40}, + {138,-40}}, color={255,0,255})); + connect(and2.y, triSam.trigger) annotation (Line(points={{-58,-170},{-50,-170}, + {-50,20},{-60,20},{-60,38}}, color={255,0,255})); + connect(addPar.u, gai.y) + annotation (Line(points={{18,20},{2,20}}, color={0,0,127})); + connect(gai.u, triSam.y) annotation (Line(points={{-22,20},{-40,20},{-40,50},{ + -48,50}}, color={0,0,127})); +annotation ( + defaultComponentName="enaHotWatIsoVal", + 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 HW 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,-54},{-60,-66}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + Text( + extent={{-96,8},{-66,-6}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uUpsDevSta"), + Text( + extent={{-96,68},{-42,56}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uHotWatIsoVal"), + Text( + extent={{32,70},{96,54}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yEnaHotWatIsoVal"), + 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="yHotWatIsoVal")}), + Documentation(info=" +

+ Block updates boiler hot water isolation valve position when + there is stage change command (chaPro=true). It will also generate + status yDisHotWatIsoVal=true to indicate if the valve reset process has finished. + This block is not based on any specific section in RP-1711, but has been designed + to carry out the hot water isolation valve operations in the plant disable sequences + defined in 5.3.2.5. +

+ +

+ This sequence will generate real signal yHoyWatIsoVal which indicates + hot water isolation valve position. +

+ ", revisions=" + + ")); +end HWIsoVal; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/HWIsoVal.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/HWIsoVal.mo new file mode 100644 index 00000000000..df33788b487 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/HWIsoVal.mo @@ -0,0 +1,108 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Subsequences.Validation; +model HWIsoVal + "Validate isolation valve disable sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Subsequences.HWIsoVal + cloHotIsoVal( + final chaHotWatIsoRat=1/60) "Close isolation valve" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Subsequences.HWIsoVal + cloHotIsoVal1( + final chaHotWatIsoRat=1/60) + "Close isolation valve" + annotation (Placement(transformation(extent={{120,0},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel( + final samplePeriod=1, + final y_start=1) + "Unit delay" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel1( + final samplePeriod=1, + final y_start=0.75) + "Unit delay" + annotation (Placement(transformation(extent={{160,-10},{180,10}}))); + + 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}}))); + +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(upsDevSta.y,cloHotIsoVal. uUpsDevSta) annotation (Line(points={{-138,-30}, + {-120,-30},{-120,10},{-102,10}}, color={255,0,255})); + + connect(upsDevSta.y, cloHotIsoVal1.uUpsDevSta) annotation (Line(points={{-138, + -30},{100,-30},{100,10},{118,10}}, + color={255,0,255})); + + connect(staCha.y,cloHotIsoVal. chaPro) annotation (Line(points={{-138,-70},{-110, + -70},{-110,4},{-102,4}}, color={255,0,255})); + + connect(staCha.y, cloHotIsoVal1.chaPro) annotation (Line(points={{-138,-70},{110, + -70},{110,4},{118,4}}, color={255,0,255})); + + connect(cloHotIsoVal.yHotWatIsoVal, uniDel.u) annotation (Line(points={{-78,4}, + {-70,4},{-70,0},{-62,0}}, color={0,0,127})); + connect(cloHotIsoVal1.yHotWatIsoVal, uniDel1.u) annotation (Line(points={{142, + 4},{150,4},{150,0},{158,0}}, color={0,0,127})); + connect(uniDel.y, cloHotIsoVal.uHotWatIsoVal) annotation (Line(points={{-38,0}, + {-30,0},{-30,40},{-110,40},{-110,16},{-102,16}}, color={0,0,127})); + connect(uniDel1.y, cloHotIsoVal1.uHotWatIsoVal) annotation (Line(points={{182, + 0},{190,0},{190,40},{110,40},{110,16},{118,16}}, color={0,0,127})); +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/HWIsoVal.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Subsequences.HWIsoVal. +

+ ", 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 HWIsoVal; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..49b62337d33 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.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.BoilerPlant.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/BoilerPlant/Generic/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/package.order new file mode 100644 index 00000000000..aba504acb16 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/Validation/package.order @@ -0,0 +1 @@ +HWIsoVal diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/package.mo new file mode 100644 index 00000000000..dcfcddaf236 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic; +package Subsequences "Package of subsequences for generic boiler plant sequences" + + + +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/BoilerPlant/Generic/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/package.order new file mode 100644 index 00000000000..d1a998767ef --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Subsequences/package.order @@ -0,0 +1,2 @@ +HWIsoVal +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantDisable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantDisable.mo new file mode 100644 index 00000000000..adcf1a3ebb4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantDisable.mo @@ -0,0 +1,240 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Validation; +model PlantDisable + "Validation model for PlantDisable sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantDisable + plaDis( + final have_priOnl=true, + final have_heaPriPum=true, + final nBoi=2, + final chaHotWatIsoRat=1/60, + final delBoiDis=180) + "Plant disable for primary-only plants with headered pumps" + annotation (Placement(transformation(extent={{10,80},{30,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantDisable + plaDis1( + final have_priOnl=false, + final have_heaPriPum=true, + final nBoi=2, + final chaHotWatIsoRat=1/60, + final delBoiDis=180) + "Plant disable for primary-secondary plants with headered pumps" + annotation (Placement(transformation(extent={{10,-10},{30,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantDisable + plaDis2( + final have_priOnl=false, + final have_heaPriPum=false, + final nBoi=2, + final chaHotWatIsoRat=1/60, + final delBoiDis=180) + "Plant disable for primary-secondary plants with dedicated pumps" + annotation (Placement(transformation(extent={{10,-110},{30,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold rising edge signal for visualization" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold rising edge signal for visualization" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold rising edge signal for visualization" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=true) + "Constant Boolean source" + annotation (Placement(transformation(extent={{-50,-20},{-30,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[2]( + final k={false,true}) + "Boiler status before plant disable" + annotation (Placement(transformation(extent={{-90,0},{-70,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.1, + final period=900, + final shift=1) + "Boolean pulse" + annotation (Placement(transformation(extent={{-90,110},{-70,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge detector" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Falling edge detector" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Logical Or" + annotation (Placement(transformation(extent={{-28,80},{-8,100}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel[2]( + final samplePeriod=fill(1, 2), + final y_start={0,1}) + "Unit delay for valve position" + annotation (Placement(transformation(extent={{-90,-30},{-70,-10}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel1[2]( + final samplePeriod=fill(1, 2), + final y_start={0,1}) + "Unit delay for valve position" + annotation (Placement(transformation(extent={{-90,70},{-70,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1[2]( + final k={0,1}) + "Valve position when plant is enabled" + annotation (Placement(transformation(extent={{-90,-60},{-70,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[2] + "Real switch" + annotation (Placement(transformation(extent={{-50,-60},{-30,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=2) + "Boolean replicator" + annotation (Placement(transformation(extent={{-90,40},{-70,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[2] + "Real switch" + annotation (Placement(transformation(extent={{-30,40},{-10,60}}))); + +equation + connect(con.y, plaDis.uBoi) annotation (Line(points={{-68,10},{0,10},{0,94},{ + 8,94}}, color={255,0,255})); + + connect(con.y, plaDis1.uBoi) annotation (Line(points={{-68,10},{0,10},{0,4},{ + 8,4}}, color={255,0,255})); + + connect(con.y, plaDis2.uBoi) annotation (Line(points={{-68,10},{0,10},{0,-96}, + {8,-96}}, color={255,0,255})); + + connect(booPul.y, plaDis.uPla) annotation (Line(points={{-68,120},{6,120},{6, + 98},{8,98}}, color={255,0,255})); + + connect(booPul.y, plaDis1.uPla) annotation (Line(points={{-68,120},{6,120},{6, + 8},{8,8}}, color={255,0,255})); + + connect(booPul.y, plaDis2.uPla) annotation (Line(points={{-68,120},{6,120},{6, + -92},{8,-92}}, color={255,0,255})); + + connect(plaDis.yStaChaPro, truFalHol.u) annotation (Line(points={{32,84},{36,84}, + {36,70},{38,70}}, color={255,0,255})); + + connect(plaDis1.yStaChaPro, truFalHol1.u) annotation (Line(points={{32,-6},{36, + -6},{36,-20},{38,-20}}, color={255,0,255})); + + connect(plaDis2.yStaChaPro, truFalHol2.u) annotation (Line(points={{32,-106},{ + 36,-106},{36,-120},{38,-120}}, + color={255,0,255})); + + connect(booPul.y, edg.u) annotation (Line(points={{-68,120},{-64,120},{-64, + 100},{-62,100}}, + color={255,0,255})); + + connect(booPul.y, falEdg.u) annotation (Line(points={{-68,120},{-64,120},{-64, + 70},{-62,70}}, + color={255,0,255})); + + connect(falEdg.y, or2.u2) annotation (Line(points={{-38,70},{-36,70},{-36,82}, + {-30,82}}, color={255,0,255})); + + connect(edg.y, or2.u1) annotation (Line(points={{-38,100},{-36,100},{-36,90}, + {-30,90}}, + color={255,0,255})); + + connect(or2.y, plaDis.uStaChaProEnd) annotation (Line(points={{-6,90},{-4,90}, + {-4,82},{8,82}}, color={255,0,255})); + + connect(or2.y, plaDis1.uStaChaProEnd) annotation (Line(points={{-6,90},{-4,90}, + {-4,-8},{8,-8}}, color={255,0,255})); + + connect(or2.y, plaDis2.uStaChaProEnd) annotation (Line(points={{-6,90},{-4,90}, + {-4,-108},{8,-108}}, color={255,0,255})); + + connect(plaDis.yHotWatIsoVal, uniDel1.u) annotation (Line(points={{32,88},{36, + 88},{36,136},{-96,136},{-96,80},{-92,80}}, + color={0,0,127})); + + connect(plaDis1.yHotWatIsoVal, uniDel.u) annotation (Line(points={{32,-2},{34, + -2},{34,28},{-96,28},{-96,-20},{-92,-20}}, color={0,0,127})); + + connect(con1.y, swi.u1) annotation (Line(points={{-68,-50},{-60,-50},{-60,-42}, + {-52,-42}}, color={0,0,127})); + + connect(uniDel.y, swi.u3) annotation (Line(points={{-68,-20},{-64,-20},{-64, + -58},{-52,-58}}, color={0,0,127})); + + connect(booPul.y, booRep.u) annotation (Line(points={{-68,120},{-64,120},{-64, + 68},{-96,68},{-96,50},{-92,50}}, color={255,0,255})); + + connect(booRep.y, swi.u2) annotation (Line(points={{-68,50},{-56,50},{-56,-50}, + {-52,-50}}, color={255,0,255})); + + connect(swi.y, plaDis1.uHotWatIsoVal) annotation (Line(points={{-28,-50},{-12, + -50},{-12,0},{8,0}}, color={0,0,127})); + + connect(uniDel1.y, swi1.u3) annotation (Line(points={{-68,80},{-66,80},{-66, + 42},{-32,42}}, color={0,0,127})); + + connect(swi1.y, plaDis.uHotWatIsoVal) + annotation (Line(points={{-8,50},{2,50},{2,90},{8,90}}, color={0,0,127})); + + connect(con1.y, swi1.u1) annotation (Line(points={{-68,-50},{-60,-50},{-60,58}, + {-32,58}}, color={0,0,127})); + + connect(booRep.y, swi1.u2) + annotation (Line(points={{-68,50},{-32,50}}, color={255,0,255})); + + connect(con2.y, plaDis1.uPumChaPro) annotation (Line(points={{-28,-10},{-20,-10}, + {-20,-4},{8,-4}}, color={255,0,255})); + connect(con2.y, plaDis2.uPumChaPro) annotation (Line(points={{-28,-10},{-20,-10}, + {-20,-104},{8,-104}}, color={255,0,255})); + annotation ( + 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}})), + experiment( + StopTime=900, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantDisable.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantDisable. +

+ ", revisions=" + + ")); +end PlantDisable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantEnable.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantEnable.mo new file mode 100644 index 00000000000..3f64d5b9f4b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantEnable.mo @@ -0,0 +1,191 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Validation; +model PlantEnable "Validation model for PlantEnable sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable + plaEna( + final nIgnReq=2, + final plaOffThrTim=15*60, + final plaOnThrTim=15*60, + final schTab=[0,0; 1,1; 18,1; 24,1]) + "Testing time-variance for all inputs" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable + plaEna1( + final nIgnReq=2) + "Testing time-varying number of requests" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable + plaEna2( + final nIgnReq=2) + "Testing time-varying outdoor air temperature" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable + plaEna3( + final nIgnReq=2, + final schTab=[0,0; 1,1; 18,1; 24,1]) + "Testing time-varying boiler plant enable schedule" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=2, + final freqHz=1/(6*60), + final offset=2, + final startTime=1) + "Input for number of requests" + annotation (Placement(transformation(extent={{-90,70},{-70,90}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Rounding real input to nearest integer" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final amplitude=2/1.8, + final freqHz=1/700, + final phase=3.1415926535898, + final offset=300, + final startTime=1) + "Input for outdoor air temperature" + annotation (Placement(transformation(extent={{-90,30},{-70,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin2( + final amplitude=2, + final freqHz=1/(6*60), + final offset=2, + final startTime=1) + "Input for number of requests" + annotation (Placement(transformation(extent={{-90,-30},{-70,-10}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Rounding real input to nearest integer" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Rounding real input to nearest integer" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin5( + final amplitude=2/1.8, + final freqHz=1/700, + final phase=3.1415926535898, + final offset=300, + final startTime=1) + "Input for outdoor air temperature" + annotation (Placement(transformation(extent={{10,30},{30,50}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Rounding real input to nearest integer" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=3) + "Input for number of requests" + annotation (Placement(transformation(extent={{10,70},{30,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=297) + "Input for outdoor air temperature" + annotation (Placement(transformation(extent={{-90,-70},{-70,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=3) + "Input for number of requests" + annotation (Placement(transformation(extent={{10,-30},{30,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=297) + "Input for outdoor air temperature" + annotation (Placement(transformation(extent={{10,-70},{30,-50}}))); + +equation + connect(sin.y, reaToInt.u) + annotation (Line(points={{-68,80},{-62,80}}, + color={0,0,127})); + connect(sin2.y, reaToInt1.u) + annotation (Line(points={{-68,-20},{-62,-20}}, + color={0,0,127})); + connect(con.y, reaToInt2.u) + annotation (Line(points={{32,80},{38,80}}, + color={0,0,127})); + connect(reaToInt3.u, con2.y) + annotation (Line(points={{38,-20},{32,-20}}, + color={0,0,127})); + connect(plaEna1.supResReq, reaToInt1.y) + annotation (Line(points={{-22,-36},{-30,-36},{-30,-20},{-38,-20}}, + color={255,127,0})); + connect(plaEna2.supResReq, reaToInt2.y) + annotation (Line(points={{78,64},{70,64},{70,80},{62,80}}, + color={255,127,0})); + connect(plaEna2.TOut, sin5.y) + annotation (Line(points={{78,56},{70,56},{70,40},{32,40}}, + color={0,0,127})); + connect(plaEna3.supResReq, reaToInt3.y) + annotation (Line(points={{78,-36},{70,-36},{70,-20},{62,-20}}, + color={255,127,0})); + connect(plaEna3.TOut, con3.y) + annotation (Line(points={{78,-44},{70,-44},{70,-60},{32,-60}}, + color={0,0,127})); + connect(reaToInt.y, plaEna.supResReq) + annotation (Line(points={{-38,80},{-30,80},{-30,64},{-22,64}}, + color={255,127,0})); + connect(sin1.y, plaEna.TOut) + annotation (Line(points={{-68,40},{-30,40},{-30,56},{-22,56}}, + color={0,0,127})); + connect(con1.y, plaEna1.TOut) + annotation (Line(points={{-68,-60},{-30,-60},{-30,-44},{-22,-44}}, + color={0,0,127})); + annotation ( + 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), + graphics={Text( + extent={{-72,26},{-24,18}}, + textColor={28,108,200}, + textString="Combination of all inputs"), + Text( + extent={{32,26},{80,18}}, + textColor={28,108,200}, + textString="Changing outdoor temperature"), + Text( + extent={{-80,-74},{-16,-82}}, + textColor={28,108,200}, + textString="Changing number of hot-water requests"), + Text( + extent={{26,-74},{74,-82}}, + textColor={28,108,200}, + textString="Changing boiler-enable schedule")}), + experiment( + StopTime=7200, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/PlantEnable.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.PlantEnable. +

+ ", revisions=" + + ")); +end PlantEnable; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/RotationController.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/RotationController.mo new file mode 100644 index 00000000000..a4047c4cdda --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/RotationController.mo @@ -0,0 +1,117 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.Validation; +model RotationController + "Validation model for RotationController sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.RotationController + rotCon( + final lag=true, + final minLim=false) + "Scenario-1: Only lead device being enabled and disabled" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.RotationController + rotCon1( + final lag=true, + final minLim=false) + "Scenario-2: Lead device continuously enabled, lag device enabled and disabled" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel[2](final delayTime=fill( + 15, 2)) + "Delay representing component being enabled" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre[2] + "Logical Pre block" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) + "Constant Boolean source" + annotation (Placement(transformation(extent={{-90,50},{-70,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=120, + final shift=5) + "Boolean pulse generator" + annotation (Placement(transformation(extent={{-90,20},{-70,40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1[2](final delayTime=fill( + 15, 2)) + "Delay representing component being enabled" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] + "Logical Pre block" + annotation (Placement(transformation(extent={{40,-40},{60,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final period=120, + final shift=5) + "Boolean pulse generator" + annotation (Placement(transformation(extent={{-90,-60},{-70,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final period=1200, + final shift=3) + "Boolean pulse generator" + annotation (Placement(transformation(extent={{-90,-30},{-70,-10}}))); + +equation + connect(rotCon.yDevStaSet, truDel.u) annotation (Line(points={{-18,55},{-14,55}, + {-14,50},{-2,50}}, color={255,0,255})); + connect(truDel.y, pre.u) + annotation (Line(points={{22,50},{38,50}}, color={255,0,255})); + connect(pre.y, rotCon.uDevSta) annotation (Line(points={{62,50},{70,50},{70,20}, + {-60,20},{-60,45},{-42,45}}, color={255,0,255})); + connect(rotCon1.yDevStaSet, truDel1.u) annotation (Line(points={{-18,-25},{-14, + -25},{-14,-30},{-2,-30}}, color={255,0,255})); + connect(truDel1.y, pre1.u) + annotation (Line(points={{22,-30},{38,-30}}, color={255,0,255})); + connect(pre1.y, rotCon1.uDevSta) annotation (Line(points={{62,-30},{70,-30},{70, + -60},{-60,-60},{-60,-35},{-42,-35}}, color={255,0,255})); + connect(booPul1.y, rotCon1.uDevStaSet[2]) annotation (Line(points={{-68,-50},{ + -64,-50},{-64,-25},{-42,-25}}, color={255,0,255})); + connect(booPul.y, rotCon.uDevStaSet[1]) annotation (Line(points={{-68,30},{-64, + 30},{-64,55},{-42,55}}, color={255,0,255})); + connect(con.y, rotCon.uDevStaSet[2]) annotation (Line(points={{-68,60},{-60,60}, + {-60,55},{-42,55}}, color={255,0,255})); + connect(booPul2.y, rotCon1.uDevStaSet[1]) annotation (Line(points={{-68,-20},{ + -50,-20},{-50,-25},{-42,-25}}, color={255,0,255})); + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,120}}), + 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}})), + experiment( + StopTime=600, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/RotationController.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic.RotationController. +

+ ", revisions=" + + ")); +end RotationController; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/package.mo new file mode 100644 index 00000000000..7b7d3b96857 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Generic; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

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

+

+ 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/BoilerPlant/Generic/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/package.order new file mode 100644 index 00000000000..cbfd9cb3843 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/Validation/package.order @@ -0,0 +1,3 @@ +PlantDisable +PlantEnable +RotationController diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/package.mo new file mode 100644 index 00000000000..9f5fb23b9c0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/package.mo @@ -0,0 +1,42 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package Generic "Generic control sequences" + annotation(Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Ellipse( + origin={10,10}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10,10}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10,10}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10,10}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})}), + Documentation(info=" +

+ This package contains generic boiler plant control sequences. +

+ ")); +end Generic; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/package.order new file mode 100644 index 00000000000..a2175baf07d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Generic/package.order @@ -0,0 +1,6 @@ +PlantDisable +PlantEnable +RotationController +EquipmentRotation +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/ChangeStatus.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/ChangeStatus.mo new file mode 100644 index 00000000000..6b39b6f0096 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/ChangeStatus.mo @@ -0,0 +1,210 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic; +block ChangeStatus "Sequence to change pump status" + + parameter Integer nPum = 2 + "Total number of pumps"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uNexLagPumSta + "Status of next lag pump" + annotation (Placement(transformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLasLagPumSta + "Status of last lag pump" + annotation (Placement(transformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uNexLagPum + "Index of next lag pump" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uLasLagPum + "Index of last lag pump" + annotation (Placement(transformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{100,-20},{140,20}}))); + +protected + parameter Integer pumInd[nPum]={i for i in 1:nPum} + "Pump index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nPum) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nPum) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu2[nPum] + "Check next lag pump" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu3[nPum] + "Check last lag pump" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch nexLagPumSta[nPum] + "Next lag pump status" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch lasLagPumSta[nPum] + "Last lag pump status" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Or enaPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{10,-50},{30,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And pumSta[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch remPum[nPum] + "Remove pump" + annotation (Placement(transformation(extent={{50,-70},{70,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch addPum[nPum] + "Add pump" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nPum) + "Integer replicator" + annotation (Placement(transformation(extent={{-90,-50},{-70,-30}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1( + final nout=nPum) + "Integer replicator" + annotation (Placement(transformation(extent={{-90,-90},{-70,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nPum]( + final k=pumInd) + "Pump index" + annotation (Placement(transformation(extent={{-90,10},{-70,30}}))); + +equation + connect(nexLagPumSta.u2, intEqu2.y) + annotation (Line(points={{-22,-40},{-38,-40}}, color={255,0,255})); + + connect(intEqu3.y, lasLagPumSta.u2) + annotation (Line(points={{-38,-80},{-22,-80}}, color={255,0,255})); + + connect(uNexLagPumSta, booRep1.u) + annotation (Line(points={{-120,80},{-82,80}}, color={255,0,255})); + + connect(uLasLagPumSta, booRep2.u) + annotation (Line(points={{-120,50},{-82,50}}, color={255,0,255})); + + connect(intRep.y, intEqu2.u1) + annotation (Line(points={{-68,-40},{-62,-40}}, color={255,127,0})); + + connect(intRep1.y, intEqu3.u1) + annotation (Line(points={{-68,-80},{-62,-80}}, color={255,127,0})); + + connect(uNexLagPum, intRep.u) + annotation (Line(points={{-120,-40},{-92,-40}}, color={255,127,0})); + + connect(uLasLagPum, intRep1.u) + annotation (Line(points={{-120,-80},{-92,-80}}, color={255,127,0})); + + connect(booRep2.y, lasLagPumSta.u1) annotation (Line(points={{-58,50},{-36,50}, + {-36,-72},{-22,-72}}, color={255,0,255})); + + connect(booRep1.y, nexLagPumSta.u1) annotation (Line(points={{-58,80},{-24,80}, + {-24,-32},{-22,-32}}, color={255,0,255})); + + connect(uHotWatPum, nexLagPumSta.u3) annotation (Line(points={{-120,0},{-30,0}, + {-30,-48},{-22,-48}}, color={255,0,255})); + + connect(uHotWatPum, lasLagPumSta.u3) annotation (Line(points={{-120,0},{-30,0}, + {-30,-88},{-22,-88}}, color={255,0,255})); + + connect(nexLagPumSta.y, enaPum.u1) + annotation (Line(points={{2,-40},{8,-40}}, color={255,0,255})); + + connect(uHotWatPum, enaPum.u2) annotation (Line(points={{-120,0},{4,0},{4,-48}, + {8,-48}}, color={255,0,255})); + + connect(uHotWatPum, remPum.u1) annotation (Line(points={{-120,0},{4,0},{4,-52}, + {48,-52}}, color={255,0,255})); + + connect(enaPum.y, addPum.u1) annotation (Line(points={{32,-40},{40,-40},{40,8}, + {58,8}}, color={255,0,255})); + + connect(lasLagPumSta.y, pumSta.u1) + annotation (Line(points={{2,-80},{18,-80}}, color={255,0,255})); + + connect(enaPum.y, pumSta.u2) annotation (Line(points={{32,-40},{40,-40},{40, + -56},{10,-56},{10,-88},{18,-88}}, + color={255,0,255})); + + connect(pumSta.y, remPum.u3) annotation (Line(points={{42,-80},{46,-80},{46,-68}, + {48,-68}}, color={255,0,255})); + + connect(booRep2.y, remPum.u2) annotation (Line(points={{-58,50},{-36,50},{-36, + -60},{48,-60}}, color={255,0,255})); + + connect(booRep1.y, addPum.u2) annotation (Line(points={{-58,80},{50,80},{50,0}, + {58,0}}, color={255,0,255})); + + connect(remPum.y, addPum.u3) annotation (Line(points={{72,-60},{80,-60},{80,-40}, + {50,-40},{50,-8},{58,-8}}, color={255,0,255})); + + connect(addPum.y, yHotWatPum) annotation (Line(points={{82,0},{120,0}}, + color={255,0,255})); + + connect(conInt.y, intEqu2.u2) annotation (Line(points={{-68,20},{-66,20},{-66, + -48},{-62,-48}}, color={255,127,0})); + + connect(conInt.y, intEqu3.u2) annotation (Line(points={{-68,20},{-66,20},{-66, + -88},{-62,-88}}, color={255,127,0})); + +annotation ( + defaultComponentName="chaSta", + Icon(coordinateSystem(preserveAspectRatio=false, + extent={{-100,-100},{120,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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}})), +Documentation(info=" +

+Block that changes the status of pumps. This sequence is not directly specified +in RP-1711. It provides a side calculation pertaining to generalization of the staging +sequences for any number of pumps and stages provided by the user. +

+
    +
  1. +When the block receives the index of next lag pump to be enabled uNexLagPum +and a true pulse on the next lag pump status uNexLagPumSta, +it changes the pump status yHotWatPum[uNexLagPum] to true. +
  2. +
  3. +When the block receives the index of last lag pump to be disabled uLasLagPum +and a false pulse on the last lag pump status uLasLagPumSta, it changes +the pump status yHotWatPum[uLasLagPum] to false. +
  4. +
+", revisions=" + +")); +end ChangeStatus; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/EnableLag_flowrate.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/EnableLag_flowrate.mo new file mode 100644 index 00000000000..5b71e3d685e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/EnableLag_flowrate.mo @@ -0,0 +1,287 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic; +block EnableLag_flowrate + "Sequences for enabling and disabling lag pumps using measured volue flow-rate" + + parameter Integer nPum = 2 + "Total number of pumps"; + + 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 timPer( + final unit="s", + displayUnit="s", + final quantity="time") = 600 + "Delay time period for enabling and disabling lag pumps"; + + parameter Real staCon( + final unit="1", + displayUnit="1") = -0.03 + "Constant used in the staging equation" + annotation (Dialog(tab="Advanced")); + + parameter Real relFloHys( + final unit="1", + displayUnit="1") = 0.01 + "Constant value used in hysteresis for checking relative flow rate" + annotation (Dialog(tab="Advanced")); + + parameter Real VHotWat_flow_nominal( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate")=0.5 + "Total plant design hot water flow rate" + annotation (Dialog(group="Nominal conditions")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{-180,-20},{-140,20}}), + iconTransformation(extent={{-140,-58},{-100,-18}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured hot water flow rate" + annotation (Placement(transformation(extent={{-180,60},{-140,100}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yUp + "Next lag pump status" + annotation (Placement(transformation(extent={{140,20},{180,60}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDown + "Last lag pump status" + annotation (Placement(transformation(extent={{140,-100},{180,-60}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=(-1)*relFloHys, + final uHigh=relFloHys) + "Check if condition for enabling next lag pump is satisfied" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=(-1)*relFloHys, + final uHigh=relFloHys) + "Check if condition for disabling last lag pump is satisfied" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter hotWatFloRat( + final k=1/VHotWat_flow_nominal) + "Boiler hot water flow ratio" + annotation (Placement(transformation(extent={{-120,70},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar2( + final p=staCon) + "Add parameter" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=timPer) + "Count time" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim1( + final t=timPer) + "Count time" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=1/nPum_nominal) + "Divide by nominal number of pumps" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical Not" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=staCon) + "Add parameter" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nPum] + "Convert boolean input to integer number" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum numOpePum( + final nin=nPum) + "Total number of operating pumps" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Convert Integer to Real" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar1( + final p=-1) + "Add real inputs" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Difference between current flowrate ratio and limit for staging up" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + "Difference between current flowrate ratio and limit for staging down" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha[nPum] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{-120,120},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Multi Or" + annotation (Placement(transformation(extent={{-80,120},{-60,140}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-40,120},{-20,140}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Restart timer whenever change in pump status is detected" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Restart timer whenever change in pump status is detected" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai1( + final k=1/nPum_nominal) + "Divide by nominal number of pumps" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + +equation + connect(VHotWat_flow,hotWatFloRat. u) + annotation (Line(points={{-160,80},{-122,80}}, color={0,0,127})); + + connect(uHotWatPum,booToInt. u) + annotation (Line(points={{-160,0},{-82,0}}, color={255,0,255})); + + connect(booToInt.y,numOpePum. u) + annotation (Line(points={{-58,0},{-42,0}}, + color={255,127,0})); + + connect(numOpePum.y,intToRea. u) + annotation (Line(points={{-18,0},{-2,0}}, color={255,127,0})); + + connect(sub2.y,hys. u) + annotation (Line(points={{-58,40},{-42,40}}, color={0,0,127})); + + connect(sub1.y,hys1. u) + annotation (Line(points={{-58,-80},{-42,-80}}, color={0,0,127})); + + connect(addPar.y,sub2. u2) + annotation (Line(points={{102,0},{120,0},{120,20},{-90,20},{-90,34},{-82,34}}, + color={0,0,127})); + + connect(intToRea.y, addPar1.u) + annotation (Line(points={{22,0},{30,0},{30,-20},{-90,-20},{-90,-40},{-82,-40}}, + color={0,0,127})); + + connect(addPar2.y,sub1. u1) + annotation (Line(points={{102,-40},{120,-40},{120,-60},{-90,-60},{-90,-74},{ + -82,-74}}, + color={0,0,127})); + + connect(hotWatFloRat.y,sub2. u1) + annotation (Line(points={{-98,80},{-90,80},{-90,46},{-82,46}}, color={0,0,127})); + + connect(hotWatFloRat.y,sub1. u2) + annotation (Line(points={{-98,80},{-90,80},{-90,60},{-100,60},{-100,-86}, + {-82,-86}}, color={0,0,127})); + + connect(not3.y, yDown) + annotation (Line(points={{122,-80},{160,-80}}, color={255,0,255})); + + connect(uHotWatPum, cha.u) annotation (Line(points={{-160,0},{-130,0},{-130,130}, + {-122,130}}, color={255,0,255})); + connect(cha.y, mulOr.u[1:nPum]) annotation (Line(points={{-98,130},{-90,130},{-90, + 130},{-82,130}}, color={255,0,255})); + connect(tim.passed, yUp) annotation (Line(points={{62,32},{80,32},{80,40},{160, + 40}}, color={255,0,255})); + connect(tim1.passed, not3.u) annotation (Line(points={{62,-88},{80,-88},{80,-80}, + {98,-80}}, color={255,0,255})); + connect(mulOr.y, not1.u) + annotation (Line(points={{-58,130},{-42,130}}, color={255,0,255})); + connect(hys.y, and2.u1) + annotation (Line(points={{-18,40},{-2,40}}, color={255,0,255})); + connect(and2.y, tim.u) + annotation (Line(points={{22,40},{38,40}}, color={255,0,255})); + connect(not1.y, and2.u2) annotation (Line(points={{-18,130},{-12,130},{-12,32}, + {-2,32}}, color={255,0,255})); + connect(hys1.y, and1.u1) + annotation (Line(points={{-18,-80},{-2,-80}}, color={255,0,255})); + connect(and1.y, tim1.u) + annotation (Line(points={{22,-80},{38,-80}}, color={255,0,255})); + connect(not1.y, and1.u2) annotation (Line(points={{-18,130},{-12,130},{-12,-88}, + {-2,-88}}, color={255,0,255})); + connect(intToRea.y, gai.u) + annotation (Line(points={{22,0},{38,0}}, color={0,0,127})); + connect(gai.y, addPar.u) + annotation (Line(points={{62,0},{78,0}}, color={0,0,127})); + connect(addPar1.y, gai1.u) + annotation (Line(points={{-58,-40},{38,-40}}, color={0,0,127})); + connect(gai1.y, addPar2.u) + annotation (Line(points={{62,-40},{78,-40}}, color={0,0,127})); +annotation ( + defaultComponentName="enaLagPriPum", + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-160},{140,160}})), + Documentation(info=" +

+Block that enables and disables lag hot water pump according to ASHRAE RP-1711, +March, 2020 draft, section 5.3.6.4 and section 5.3.7.3. +

+

+Hot water pump shall be staged as a function of hot water flow ratio (HWFR), +i.e. the ratio of current hot water flow VHotWat_flow to design +flow VHotWat_flow_nominal, and the number of pumps num_nominal +that operate at design conditions. Pumps are assumed to be equally sized. +

+
+                  VHotWat_flow
+      HWFR = ---------------------- 
+              VHotWat_flow_nominal
+
+

+1. Start the next lag pump yNexLagPum whenever the following is +true for time timPer: +

+
        
+      HWFR > Number_of_operating_pumps/num_nominal - 0.03                  
+
+

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

+
           
+      HWFR ≤ (Number_of_operating_pumps - 1)/num_nominal - 0.03
+
+", revisions=" + +")); +end EnableLag_flowrate; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Speed_localDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Speed_localDp.mo new file mode 100644 index 00000000000..0f06ef75f57 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Speed_localDp.mo @@ -0,0 +1,311 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic; +block Speed_localDp + "Pump speed control plants where the remote DP sensor(s) is not hardwired to the plant controller, but a local DP sensor is hardwired" + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(group="Speed controller")); + + parameter Integer nSen = 2 + "Total number of remote differential pressure sensors"; + + parameter Integer nPum = 2 + "Total number of hot water pumps"; + + parameter Real minLocDp( + final min=0, + displayUnit="Pa", + final unit= "Pa", + final quantity="PressureDifference")=5*6894.75 + "Minimum hot water loop local differential pressure setpoint"; + + parameter Real maxLocDp( + final min=minLocDp, + displayUnit="Pa", + final unit="Pa", + final quantity="PressureDifference") = 15*6894.75 + "Maximum hot water loop local differential pressure setpoint"; + + parameter Real minPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpe) = 0.1 + "Minimum pump speed"; + + parameter Real maxPumSpe( + final unit="1", + displayUnit="1", + final min=minPumSpe, + final max=1) = 1 + "Maximum pump speed"; + + 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")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{-180,-70},{-140,-30}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat_local( + final unit="Pa", + final quantity="PressureDifference") + "Hot water differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-180,70},{-140,110}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen), + displayUnit=fill("Pa", nSen)) + "Hot water differential static pressure from remote sensor" + annotation (Placement(transformation(extent={{-180,-110},{-140,-70}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatSet( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa") + "Hot 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 yHotWatPumSpe( + final min=minPumSpe, + final max=maxPumSpe, + final unit="1") + "Hot water pump speed" + annotation (Placement(transformation(extent={{140,70},{180,110}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMax maxRemDP( + nin=nSen) + "Highest output from differential pressure control loops" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line locDpSet + "Local differential pressure setpoint" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_remoteDp hotPumSpe( + controllerType=controllerType, + final nSen=1, + final nPum=nPum, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final k=k, + final Ti=Ti, + final Td=Td) + "Calculate pump speed based on pressure setpoint" + annotation (Placement(transformation(extent={{60,80},{80,100}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.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)) + "PID controller for regulating local differential pressure setpoint" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Reset PID loop when it is activated" + annotation (Placement(transformation(extent={{-70,-60},{-50,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Check if any hot water pumps are enabled" + annotation (Placement(transformation(extent={{-110,-60},{-90,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nSen) + "Replicate real input" + annotation (Placement(transformation(extent={{-120,-130},{-100,-110}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nSen) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-30,-60},{-10,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant locDp_min( + final k=minLocDp) + "Minimum local differential pressure" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one( + final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant locDp_max( + final k=maxLocDp) + "Maximum local differential pressure " + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div[nSen] + "Normalized pressure difference" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1( + final nout=nSen) + "Replicate real input" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + +equation + connect(dpHotWatSet, reaRep.u) + annotation (Line(points={{-160,-120},{-122,-120}}, color={0,0,127})); + + 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(dpHotWat_remote, div.u1) + annotation (Line(points={{-160,-90},{-80,-90},{-80,-94},{-42,-94}}, + color={0,0,127})); + + connect(reaRep.y, div.u2) + annotation (Line(points={{-98,-120},{-80,-120},{-80,-106},{-42,-106}}, + 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(hotPumSpe.yHotWatPumSpe, yHotWatPumSpe) + annotation (Line(points={{82,90},{160,90}}, color={0,0,127})); + connect(uHotWatPum, mulOr.u[1:nPum]) annotation (Line(points={{-160,-50},{-112, + -50}}, color={255,0,255})); + connect(uHotWatPum, hotPumSpe.uHotWatPum) annotation (Line(points={{-160,-50}, + {-130,-50},{-130,98},{58,98}}, color={255,0,255})); + connect(locDpSet.y, hotPumSpe.dpHotWatSet) annotation (Line(points={{122,-20}, + {130,-20},{130,72},{40,72},{40,82},{58,82}}, color={0,0,127})); + connect(dpHotWat_local, hotPumSpe.dpHotWat[1]) + annotation (Line(points={{-160,90},{58,90}}, color={0,0,127})); + + connect(mulOr.y, edg.u) + annotation (Line(points={{-88,-50},{-72,-50}}, color={255,0,255})); + connect(edg.y, booRep.u) + annotation (Line(points={{-48,-50},{-32,-50}}, color={255,0,255})); + connect(booRep.y, conPID.trigger) + annotation (Line(points={{-8,-50},{4,-50},{4,-32}}, color={255,0,255})); + connect(div.y, conPID.u_m) + annotation (Line(points={{-18,-100},{10,-100},{10,-32}}, 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(conPID.y, maxRemDP.u[1:nSen]) annotation (Line(points={{22,-20},{30,-20}, + {30,-20},{38,-20}}, color={0,0,127})); + +annotation ( + defaultComponentName="hotPumSpe", + 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="uHotWatPum"), + Text( + extent={{-98,-30},{-30,-52}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpHotWat_remote"), + Text( + extent={{22,12},{98,-10}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yHotWatPumSpe"), + Text( + extent={{-98,-68},{-34,-90}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpHotWatSet"), + Text( + extent={{-98,92},{-30,70}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpHotWat_local")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-140},{140,140}})), + Documentation(info=" +

+Block that controls speed of enabled hot water pumps for 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 RP-1711, March, 2020 draft, sections 5.3.6.7, 5.3.6.8, 5.3.6.9, +5.3.7.7 , 5.3.7.8 and 5.3.7.9. +

+
    +
  1. +Remote dP dpHotWat_remote shall be maintained at setpoint dpHotWatSet +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 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 dP dpHotWat_local 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_localDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Speed_remoteDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Speed_remoteDp.mo new file mode 100644 index 00000000000..4eb29d22341 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Speed_remoteDp.mo @@ -0,0 +1,264 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic; +block Speed_remoteDp + "Pump speed control for plants where the remote DP sensor(s) is hardwired to the plant controller" + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(group="Speed controller")); + + parameter Integer nSen = 2 + "Total number of remote differential pressure sensors"; + + parameter Integer nPum = 2 + "Total number of hot water pumps"; + + parameter Real minPumSpe = 0.1 + "Minimum pump speed"; + + parameter Real maxPumSpe = 1 + "Maximum pump speed"; + + parameter Real k=1 + "Gain of controller" + annotation(Dialog(group="Speed controller")); + + parameter Real Ti( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.5 + "Time constant of integrator block" + annotation(Dialog(group="Speed controller")); + + parameter Real Td( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.1 + "Time constant of derivative block" + annotation (Dialog(group="Speed controller")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat[nSen]( + final unit=fill("Pa", nSen), + displayUnit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen)) + "Hot water differential static pressure" + annotation (Placement(transformation(extent={{-160,-80},{-120,-40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatSet( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference") + "Hot 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 yHotWatPumSpe( + final min=minPumSpe, + final max=maxPumSpe, + final unit="1", + displayUnit="1") + "Hot water pump speed" + annotation (Placement(transformation(extent={{120,80},{160,120}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMax maxLoo( + final nin=nSen) + "Maximum DP loop output" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line pumSpe + "Pump speed" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.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)) + "PID controller for regulating remote differential pressure" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Reset PID loop when it is activated" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Check if any hot water primary pumps are enabled" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nSen) + "Replicate real input" + annotation (Placement(transformation(extent={{-100,-110},{-80,-90}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nSen) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-10,-50},{10,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_min( + final k=minPumSpe) + "Minimum pump speed" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_max( + final k=maxPumSpe) + "Maximum pump speed" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one( + final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + +equation + connect(dpHotWatSet, reaRep.u) + annotation (Line(points={{-140,-100},{-102,-100}}, color={0,0,127})); + + 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},{10,40},{10,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(dpHotWat, div.u1) + annotation (Line(points={{-140,-60},{-40,-60},{-40,-74},{-22,-74}}, + color={0,0,127})); + + connect(reaRep.y, div.u2) + annotation (Line(points={{-78,-100},{-40,-100},{-40,-86},{-22,-86}}, + 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(pumSpe.y, swi.u1) + annotation (Line(points={{82,60},{100,60},{100,80},{60,80},{60,108},{78,108}}, + color={0,0,127})); + + connect(swi.y,yHotWatPumSpe) + annotation (Line(points={{102,100},{140,100}}, color={0,0,127})); + + connect(uHotWatPum, mulOr.u[1:nPum]) annotation (Line(points={{-140,0},{-122,0},{ + -122,0},{-102,0}}, 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(mulOr.y, edg.u) annotation (Line(points={{-78,0},{-50,0},{-50,-40},{-42, + -40}}, color={255,0,255})); + connect(edg.y, booRep.u) + annotation (Line(points={{-18,-40},{-12,-40}}, color={255,0,255})); + connect(booRep.y, conPID.trigger) + annotation (Line(points={{12,-40},{24,-40},{24,-12}}, color={255,0,255})); + connect(reaRep1.y, conPID.u_s) + annotation (Line(points={{2,0},{18,0}}, color={0,0,127})); + connect(div.y, conPID.u_m) + annotation (Line(points={{2,-80},{30,-80},{30,-12}}, color={0,0,127})); + connect(conPID.y, maxLoo.u[1:nSen]) + annotation (Line(points={{42,0},{50,0},{50,0},{58,0}}, color={0,0,127})); + connect(pumSpe_max.y, swi.u3) annotation (Line(points={{2,40},{10,40},{10,92}, + {78,92}}, color={0,0,127})); +annotation ( + defaultComponentName="hotPumSpe", + 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="uHotWatPum"), + Text( + extent={{-98,10},{-44,-12}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpHotWat"), + Text( + extent={{22,12},{98,-10}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yHotWatPumSpe"), + Text( + extent={{-98,-68},{-34,-90}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="dpHotWatSet")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}})), + Documentation(info=" +

+Block that outputs hot water pump speed setpoint for plants with +headered, variable-speed pumps where the remote pressure differential sensor is +hardwired to the plant controller, according to ASHRAE RP-1711, March, 2020 draft, +sections 5.3.6.5, 5.3.6.6, 5.3.7.5 and 5.3.7.6. +

+
    +
  1. +When any hot water pump is proven on, uHotWatPum = true, +pump speed will be controlled by a reverse acting PID loop maintaining the +differential pressure signal at a setpoint dpHotWatSet. 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. Hot water pumps shall be controlled to the maximum signal output +of all DP sensor loops. +
  4. +
+", revisions=" + +")); +end Speed_remoteDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/ChangeStatus.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/ChangeStatus.mo new file mode 100644 index 00000000000..b14b37d992c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/ChangeStatus.mo @@ -0,0 +1,141 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Validation; +model ChangeStatus + "Validate sequence for changing pump status" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta( + final nPum=3) + "Scenario testing pump status changer" + annotation (Placement(transformation(extent={{60,-10},{82,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Pre pre[3]( + final pre_u_start=fill(false, 3)) + "Logical pre block" + annotation (Placement(transformation(extent={{90,-10},{110,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger samTri( + final period=5, + final shift=1) + "Sample trigger" + annotation (Placement(transformation(extent={{-130,-10},{-110,10}}))); + + Buildings.Controls.OBC.CDL.Integers.OnCounter onCouInt + "Boolean True pulse counter" + annotation (Placement(transformation(extent={{-100,-6},{-88,6}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr( + final t=3) + "Switch pump staging to staging-down after 3 pump stage-ups" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Logical switch" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 + "Logical switch" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{-130,70},{-110,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-10,10},{10,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract subInt + "Generate stage setpoints for staging down processes" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=7) + "Constant Integer source" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + +equation + connect(pre.y, chaPumSta.uHotWatPum) annotation (Line(points={{112,0},{120,0}, + {120,20},{40,20},{40,0},{58,0}}, color={255,0,255})); + + connect(chaPumSta.yHotWatPum, pre.u) + annotation (Line(points={{82,0},{88,0}}, color={255,0,255})); + + connect(samTri.y, onCouInt.trigger) + annotation (Line(points={{-108,0},{-101.2,0}}, color={255,0,255})); + + connect(onCouInt.y, intGreThr.u) + annotation (Line(points={{-86.8,0},{-82,0}}, color={255,127,0})); + + connect(onCouInt.y, chaPumSta.uNexLagPum) annotation (Line(points={{-86.8,0},{ + -84,0},{-84,-20},{20,-20},{20,-4},{58,-4}}, color={255,127,0})); + + connect(samTri.y, logSwi1.u1) annotation (Line(points={{-108,0},{-106,0},{-106, + 28},{-42,28}}, color={255,0,255})); + + connect(samTri.y, logSwi.u3) annotation (Line(points={{-108,0},{-106,0},{-106, + 42},{-42,42}}, color={255,0,255})); + + connect(intGreThr.y, logSwi1.u2) annotation (Line(points={{-58,0},{-54,0},{-54, + 20},{-42,20}}, color={255,0,255})); + + connect(con.y, logSwi.u1) annotation (Line(points={{-108,80},{-50,80},{-50,58}, + {-42,58}}, color={255,0,255})); + + connect(con.y, logSwi1.u3) annotation (Line(points={{-108,80},{-50,80},{-50,12}, + {-42,12}}, color={255,0,255})); + + connect(intGreThr.y, logSwi.u2) annotation (Line(points={{-58,0},{-54,0},{-54, + 50},{-42,50}}, color={255,0,255})); + + connect(logSwi1.y, not1.u) + annotation (Line(points={{-18,20},{-12,20}}, color={255,0,255})); + + connect(not1.y, chaPumSta.uLasLagPumSta) annotation (Line(points={{12,20},{30, + 20},{30,5},{58,5}}, color={255,0,255})); + + connect(logSwi.y, chaPumSta.uNexLagPumSta) annotation (Line(points={{-18,50},{ + 50,50},{50,8},{58,8}}, color={255,0,255})); + + connect(subInt.y, chaPumSta.uLasLagPum) annotation (Line(points={{-18,-40},{52, + -40},{52,-8},{58,-8}}, color={255,127,0})); + + connect(con.y, onCouInt.reset) annotation (Line(points={{-108,80},{-104,80},{-104, + -14},{-94,-14},{-94,-7.2}}, color={255,0,255})); + + connect(conInt.y,subInt. u1) annotation (Line(points={{-78,-50},{-60,-50},{-60, + -34},{-42,-34}}, color={255,127,0})); + connect(onCouInt.y,subInt. u2) annotation (Line(points={{-86.8,0},{-84,0},{-84, + -20},{-50,-20},{-50,-46},{-42,-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/BoilerPlant/Pumps/Generic/Validation/ChangeStatus.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus. +

+", 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,-100},{140,100}}))); +end ChangeStatus; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/EnableLag_flowrate.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/EnableLag_flowrate.mo new file mode 100644 index 00000000000..18f31b15ccd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/EnableLag_flowrate.mo @@ -0,0 +1,87 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Validation; +model EnableLag_flowrate + "Validate sequence for enabling lag pump using measured volume flow-rate" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.EnableLag_flowrate + enaLagPriPum( + final nPum=3) + "Enable lag pump for primary-only plants with headered variable speed primary pumps" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold nexLagPum( + final trueHoldDuration=10) + "Hold pulse signal for easy visualization" + annotation (Placement(transformation(extent={{30,20},{50,40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold preLagPum( + final trueHoldDuration=10) + "Hold pulse signal for easy visualization" + annotation (Placement(transformation(extent={{30,-10},{50,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[2]( + final k=fill(true, 2)) + "Constant true" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=0.25, + final freqHz=1/3600, + final offset=0.25) + "Measured hot water flow rate" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + +equation + connect(con[1].y,enaLagPriPum. uHotWatPum[1]) annotation (Line(points={{-58,0}, + {-42,0},{-42,14.8667},{-22,14.8667}}, color={255,0,255})); + + connect(con[2].y,enaLagPriPum. uHotWatPum[2]) annotation (Line(points={{-58,0}, + {-42,0},{-42,16.2},{-22,16.2}}, color={255,0,255})); + + connect(con1.y,enaLagPriPum. uHotWatPum[3]) annotation (Line(points={{-58,-40}, + {-40,-40},{-40,17.5333},{-22,17.5333}}, color={255,0,255})); + + connect(sin.y,enaLagPriPum.VHotWat_flow) + annotation (Line(points={{-58,40},{-40,40},{-40,24},{-22,24}}, + color={0,0,127})); + + connect(enaLagPriPum.yUp, nexLagPum.u) annotation (Line(points={{2,24},{16,24}, + {16,30},{28,30}}, color={255,0,255})); + connect(enaLagPriPum.yDown, preLagPum.u) annotation (Line(points={{2,16},{16,16}, + {16,0},{28,0}}, color={255,0,255})); +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/EnableLag_flowrate.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.EnableLag_flowrate. +

+", 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_flowrate; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_localDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_localDp.mo new file mode 100644 index 00000000000..528617e7199 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_localDp.mo @@ -0,0 +1,96 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Validation; +model Speed_localDp + "Validate sequence of controlling hot water pump speed for plants with local DP sensor hardwired to the plant controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_localDp + hotPumSpe( + final nSen=2, + final nPum=2) + "Hot water pump speed control based on 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.95, 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.Continuous.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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}}))); + +equation + connect(locPreSen.y,hotPumSpe.dpHotWat_local) + annotation (Line(points={{-38,80},{0,80},{0,8},{18,8}}, + color={0,0,127})); + + connect(remPreSen1.y,hotPumSpe. dpHotWat_remote[1]) annotation (Line(points={ + {-38,0},{-20,0},{-20,-5},{18,-5}}, color={0,0,127})); + + connect(remPreSen2.y,hotPumSpe. dpHotWat_remote[2]) annotation (Line(points={ + {-38,-40},{-20,-40},{-20,-3},{18,-3}}, color={0,0,127})); + + connect(difPreSet.y,hotPumSpe.dpHotWatSet) + annotation (Line(points={{-38,-80},{0,-80},{0,-8},{18,-8}}, + color={0,0,127})); + + connect(pumSta.y,hotPumSpe.uHotWatPum) + annotation (Line(points={{-38,40},{-20,40},{-20,4},{18,4}}, + color={255,0,255})); + +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_localDp.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_localDp. +

+", 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_localDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_remoteDp.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_remoteDp.mo new file mode 100644 index 00000000000..78544886787 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_remoteDp.mo @@ -0,0 +1,85 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Validation; +model Speed_remoteDp + "Validate sequence of controlling hot water pump speed for plants with remote DP sensor hardwired to the plant controller" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_remoteDp + hotPumSpe( + nSen=2, + nPum=2) + "Hot water pump speed control based on remote hardwired differential pressure sensor" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumSta[2]( + final width=fill(0.95, 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.Continuous.Sources.Constant difPreSet( + final k=8.5) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine remPreSen1( + final offset=8.5, + final freqHz=1/10, + final amplitude=1.5) + "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine remPreSen2( + final offset=8.5, + final freqHz=1/10, + final startTime=2, + final amplitude=1) + "Remote pressure difference sensor reading" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + +equation + connect(difPreSet.y,hotPumSpe.dpHotWatSet) + annotation (Line(points={{-38,-80},{-20,-80},{-20,-8},{18,-8}}, + color={0,0,127})); + + connect(pumSta.y,hotPumSpe.uHotWatPum) + annotation (Line(points={{-38,40},{-20,40},{-20,8},{18,8}}, + color={255,0,255})); + + connect(remPreSen1.y, hotPumSpe.dpHotWat[1]) annotation (Line(points={{-38,0}, + {-10,0},{-10,-1},{18,-1}}, color={0,0,127})); + + connect(remPreSen2.y, hotPumSpe.dpHotWat[2]) annotation (Line(points={{-38,-40}, + {-28,-40},{-28,1},{18,1}}, color={0,0,127})); + +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/Speed_remoteDp.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_remoteDp. +

+", 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_remoteDp; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/package.mo new file mode 100644 index 00000000000..bd7537a37cc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/package.mo @@ -0,0 +1,39 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic; +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.BoilerPlant.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/BoilerPlant/Pumps/Generic/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/package.order new file mode 100644 index 00000000000..0e9cdaeeccf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/Validation/package.order @@ -0,0 +1,4 @@ +ChangeStatus +EnableLag_flowrate +Speed_localDp +Speed_remoteDp diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/package.mo new file mode 100644 index 00000000000..15a88df14b2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/package.mo @@ -0,0 +1,33 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps; +package Generic "Generic sequences for both primary and secondary hot water pump control" + + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for hot water pumps. +The implementations are based on section 5.2.6 Primary hot water pumps, +in ASHRAE RP-1711 (Draft 6 on July 25, 2019). +

+"), + 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={255,0,0}, + fillPattern=FillPattern.Solid)})); +end Generic; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/package.order new file mode 100644 index 00000000000..f6b02402f61 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/Generic/package.order @@ -0,0 +1,5 @@ +ChangeStatus +EnableLag_flowrate +Speed_localDp +Speed_remoteDp +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Controller.mo new file mode 100644 index 00000000000..e58ecf17cde --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Controller.mo @@ -0,0 +1,1401 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps; +block Controller + "Sequences to control hot water pumps in boiler plants" + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation (Dialog(tab="Pump control parameters", group="PID parameters")); + + parameter Boolean have_heaPriPum = true + "Flag of headered hot water pumps design: true=headered, false=dedicated" + annotation (Dialog(group="Plant parameters")); + + parameter Boolean have_priOnl = false + "True: Plant is primary-only; + False: Plant is primary-secondary" + annotation (Dialog(group="Plant parameters")); + + parameter Boolean have_varPriPum = false + "True: Variable-speed primary pumps; + False: Fixed-speed primary pumps" + annotation (Dialog(group="Plant parameters")); + + parameter Boolean have_secFloSen = true + "True: Flowrate sensors in primary and secondary loops; + False: Flowrate sensor in decoupler" + annotation (Dialog(tab="Pump control parameters", + group="Flowrate-based speed regulation", + enable= speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate)); + + parameter Boolean have_priSecTemSen = true + "True: Temperature sensors in primary and secondary loops; + False: Temperature sensors in boiler supply and secondary loop" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable= speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Integer nPum = 2 + "Total number of hot water pumps" + annotation (Dialog(group="Plant parameters")); + + parameter Integer nBoi = 2 + "Total number of boilers" + annotation (Dialog(group="Plant parameters")); + + parameter Integer nSen = 2 + "Total number of remote differential pressure sensors" + annotation (Dialog(group="Plant parameters")); + + parameter Integer numIgnReq = 0 + "Number of ignored requests" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable= speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Integer nPum_nominal( + final max=nPum, + final min=1) = nPum + "Total number of pumps that operate at design conditions" + annotation (Dialog(group="Plant parameters")); + + parameter Real minPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpe) = 0.1 + "Minimum pump speed" + annotation (Dialog(group="Pump parameters", enable=have_varPriPum)); + + parameter Real maxPumSpe( + final unit="1", + displayUnit="1", + final min=minPumSpe, + final max=1) = 1 + "Maximum pump speed" + annotation (Dialog(group="Pump parameters", enable=have_varPriPum)); + + parameter Real VHotWat_flow_nominal( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") = 0.5 + "Total plant design hot water flow rate" + annotation (Dialog(group="Plant parameters")); + + parameter Real boiDesFlo[nBoi]( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") = {0.5,0.5} + "Vector of design flowrates for all boilers in plant" + annotation (Dialog(group="Plant parameters")); + + parameter Real maxLocDp( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Maximum hot water loop local differential pressure setpoint" + annotation (Dialog(tab="Pump control parameters", group="DP-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP)); + + parameter Real minLocDp( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Minimum hot water loop local differential pressure setpoint" + annotation (Dialog(tab="Pump control parameters", + group="DP-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP)); + + parameter Real offTimThr( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 180 + "Threshold to check lead boiler off time" + annotation (Dialog(tab="Pump control parameters", group="Pump staging parameters")); + + parameter Real timPer( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 600 + "Delay time period for enabling and disabling lag pumps" + annotation (Dialog(tab="Pump control parameters", group="Pump staging parameters")); + + parameter Real delBoiDis( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=180 + "Time delay after boilers have been disabled before completing disabling process" + annotation (Dialog(tab="Pump control parameters", group="Pump staging parameters")); + + parameter Real staCon( + final unit="1", + displayUnit="1") = -0.03 + "Constant used in the staging equation" + annotation (Dialog(tab="Pump control parameters", group="Pump staging parameters")); + + parameter Real relFloHys( + final unit="1", + displayUnit="1") = 0.01 + "Constant value used in hysteresis for checking relative flow rate" + annotation (Dialog(tab="Pump control parameters", group="Pump staging parameters")); + + parameter Real delTim( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 900 + "Delay time" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real samPer( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 120 + "Sample period of component" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real triAmo( + final unit="1", + displayUnit="1") = -0.02 + "Trim amount" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real resAmo( + final unit="1", + displayUnit="1") = 0.03 + "Respond amount" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real maxRes( + final unit="1", + displayUnit="1") = 0.06 + "Maximum response per time interval" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real twoReqLimLow( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1.2 + "Lower limit of hysteresis loop sending two requests" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real twoReqLimHig( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 2 + "Higher limit of hysteresis loop sending two requests" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real oneReqLimLow( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 0.2 + "Lower limit of hysteresis loop sending one request" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real oneReqLimHig( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1 + "Higher limit of hysteresis loop sending one request" + annotation (Dialog(tab="Pump control parameters", + group="Temperature-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature)); + + parameter Real k( + final unit="1", + displayUnit="1", + final min=0) = 1 + "Gain of controller" + annotation (Dialog(tab="Pump control parameters", group="PID parameters")); + + parameter Real Ti( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Pump control parameters", group="PID parameters")); + + parameter Real Td( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Pump control parameters", group="PID parameters")); + + parameter Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes + speConTyp = Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP + "Speed regulation method" + annotation (Dialog(group="Plant parameters", enable=have_varPriPum)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp if not have_priOnl + "Stage up signal" + annotation (Placement(transformation(extent={{-320,-210},{-280,-170}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff if not have_priOnl + "Signal indicating stage change with simultaneous enabling and disabling of boilers" + annotation (Placement(transformation(extent={{-320,-240},{-280,-200}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pumps operating status" + annotation (Placement(transformation(extent={{-320,120},{-280,160}}), + iconTransformation(extent={{-140,240},{-100,280}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPlaEna + "Plant enabling status" + annotation (Placement(transformation(extent={{-320,90},{-280,130}}), + iconTransformation(extent={{-140,210},{-100,250}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiSta[nBoi] if not have_priOnl + "Boiler status vector" + annotation (Placement(transformation(extent={{-320,-90},{-280,-50}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPumChaPro if not have_priOnl + "Signal indicating start of pump change process" + annotation (Placement(transformation(extent={{-320,-270},{-280,-230}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uNexEnaBoi if not have_heaPriPum + "Index of next enabled boiler" + annotation (Placement(transformation(extent={{-320,-320},{-280,-280}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uLasDisBoi if not have_heaPriPum + "Index of last disabled boiler" + annotation (Placement(transformation(extent={{-320,-360},{-280,-320}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uPumLeaLag[nPum] if have_heaPriPum + "Hot water pump lead-lag order" + annotation (Placement(transformation(extent={{-320,210},{-280,250}}), + iconTransformation(extent={{-140,270},{-100,310}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotIsoVal[nBoi]( + final unit="1", + displayUnit="1") if have_heaPriPum + "Hot water isolation valve status" + annotation (Placement(transformation(extent={{-320,50},{-280,90}}), + iconTransformation(extent={{-140,180},{-100,220}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMinPriPumSpeCon( + final unit="1", + displayUnit="1") if have_varPriPum and not have_priOnl + "Minimum allowed pump speed for non-condensing boilers" + annotation (Placement(transformation(extent={{-320,-560},{-280,-520}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat_local( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference") if have_priOnl and have_varPriPum + and locDPReg + "Hot water differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-320,-460},{-280,-420}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen)) if have_priOnl and + have_varPriPum and (locDPReg or remDPReg) + "Hot water differential static pressure from remote sensor" + annotation (Placement(transformation(extent={{-320,-500},{-280,-460}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatSet( + final unit="Pa", + final quantity="PressureDifference") if have_priOnl and have_varPriPum + and (locDPReg or remDPReg) + "Hot water differential static pressure setpoint" + annotation (Placement(transformation(extent={{-320,-530},{-280,-490}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Hot water flow" + annotation (Placement(transformation(extent={{-320,-40},{-280,0}}), + iconTransformation(extent={{-140,150},{-100,190}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatSec_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if not have_priOnl and have_varPriPum + and floReg and have_secFloSen + "Measured hot water flowrate through secondary loop" + annotation (Placement(transformation(extent={{-320,-600},{-280,-560}}), + iconTransformation(extent={{-140,-190},{-100,-150}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatDec_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if not have_priOnl and have_varPriPum + and floReg and not have_secFloSen + "Measured hot water flowrate through decoupler" + annotation (Placement(transformation(extent={{-320,-630},{-280,-590}}), + iconTransformation(extent={{-140,-220},{-100,-180}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatPri( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl and + have_varPriPum and temReg and + have_priSecTemSen + "Measured hot water temperature at primary loop supply" + annotation (Placement(transformation(extent={{-320,-660},{-280,-620}}), + iconTransformation(extent={{-140,-250},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSec( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl and + have_varPriPum and temReg + "Measured hot water temperature at secondary loop supply" + annotation (Placement(transformation(extent={{-320,-690},{-280,-650}}), + iconTransformation(extent={{-140,-280},{-100,-240}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatBoiSup[nBoi]( + final unit=fill("K", nBoi), + displayUnit=fill("K",nBoi), + final quantity=fill("ThermodynamicTemperature",nBoi)) if not have_priOnl + and have_varPriPum and temReg and not + have_priSecTemSen + "Measured hot water temperature at boiler supply" + annotation (Placement(transformation(extent={{-320,-720},{-280,-680}}), + iconTransformation(extent={{-140,-310},{-100,-270}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{280,-20},{320,20}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumSpe( + final min=0, + final max=1, + final unit="1") if have_varPriPum + "Hot water pump speed" + annotation (Placement(transformation(extent={{280,-566},{320,-526}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.EnableLag_flowrate + enaLagHotPum( + final nPum=nPum, + final nPum_nominal=nPum_nominal, + final timPer=timPer, + final staCon=staCon, + final relFloHys=relFloHys, + final VHotWat_flow_nominal=VHotWat_flow_nominal) if have_priOnl and + have_heaPriPum + "Enable lag pump for primary-only plants using differential pressure pump speed control" + annotation (Placement(transformation(extent={{-200,-10},{-180,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_localDp + pumSpeLocDp( + final controllerType=controllerType, + final nSen=nSen, + final nPum=nPum, + final minLocDp=minLocDp, + final maxLocDp=maxLocDp, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final k=k, + final Ti=Ti, + final Td=Td) if have_priOnl and have_varPriPum and locDPReg + "Hot water pump speed control with local DP sensor" + annotation (Placement(transformation(extent={{-60,-490},{-40,-470}}))); + +protected + parameter Boolean remDPReg = (speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP) + "Boolean flag for pump speed control with remote differential pressure"; + + parameter Boolean locDPReg = (speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP) + "Boolean flag for pump speed control with local differential pressure"; + + parameter Boolean temReg = (speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Boolean flag for pump speed control with temperature readings"; + + parameter Boolean floReg = (speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate) + "Boolean flag for pump speed control with flowrate readings"; + + parameter Integer pumInd[nPum]={i for i in 1:nPum} + "Pump index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=0) if have_priOnl + "Constant Real zero signal" + annotation (Placement(transformation(extent={{40,-466},{60,-446}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr( + final t=0, + final h=0) if not have_heaPriPum + "Check if the lead boiler is turned on" + annotation (Placement(transformation(extent={{-192,-80},{-172,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if not have_heaPriPum + "Logical And" + annotation (Placement(transformation(extent={{-46,-294},{-26,-274}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or3 if not have_heaPriPum + "Logical Or" + annotation (Placement(transformation(extent={{-48,-328},{-28,-308}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr1( + final t=1) + "Ensure module does not enable lead pump" + annotation (Placement(transformation(extent={{-30,22},{-10,42}}))); + + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr1( + final t=1) + "Ensure module does not disable lead pump" + annotation (Placement(transformation(extent={{18,-20},{38,0}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 if have_heaPriPum + "Logical And" + annotation (Placement(transformation(extent={{70,22},{90,42}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or4 if have_heaPriPum + "Logical Or" + annotation (Placement(transformation(extent={{72,-20},{92,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max if have_varPriPum + "Pass higher value" + annotation (Placement(transformation(extent={{134,-556},{154,-536}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.EnableLead_dedicated + enaDedLeaPum( + final offTimThr=offTimThr) if not have_heaPriPum + "Enable lead pump of dedicated pumps" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.EnableLead_headered + enaHeaLeaPum( + final nBoi=nBoi) if have_heaPriPum "Enable lead pump of headered pumps" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_remoteDp + pumSpeRemDp( + final controllerType=controllerType, + final nSen=nSen, + final nPum=nPum, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final k=k, + final Ti=Ti, + final Td=Td) if have_priOnl and have_varPriPum and remDPReg + "Hot water pump speed control with remote DP sensor" + annotation (Placement(transformation(extent={{-60,-530},{-40,-510}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_flow + pumSpeFlo( + final controllerType=controllerType, + final primarySecondarySensors=have_secFloSen, + final nPum=nPum, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final k=k, + final Ti=Ti, + final Td=Td, + final VHotWat_flow_nominal=VHotWat_flow_nominal) if not have_priOnl and + have_varPriPum and floReg + "Pump speed control using flow sensors" + annotation (Placement(transformation(extent={{-60,-574},{-40,-554}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_temperature + pumSpeTem( + final primarySecondarySensors=have_priSecTemSen, + final nBoi=nBoi, + final nPum=nPum, + final numIgnReq=numIgnReq, + final boiDesFlo=boiDesFlo, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final delTim=delTim, + final samPer=samPer, + final triAmo=triAmo, + final resAmo=resAmo, + final maxRes=maxRes, + final twoReqLimLow=twoReqLimLow, + final twoReqLimHig=twoReqLimHig, + final oneReqLimLow=oneReqLimLow, + final oneReqLimHig=oneReqLimHig) if not have_priOnl and have_varPriPum + and temReg "Pump speed control using temperature sensors" + annotation (Placement(transformation(extent={{-60,-608},{-40,-588}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nBoi] if not have_heaPriPum + "Boolean to Real conversion" + annotation (Placement(transformation(extent={{-252,-80},{-232,-60}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nBoi) if not have_heaPriPum + "Identify status of lead boiler" + annotation (Placement(transformation(extent={{-222,-80},{-202,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-274,190},{-254,210}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nPum] if have_heaPriPum + "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_heaPriPum + "Lead pump index" + annotation (Placement(transformation(extent={{-80,220},{-60,240}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt if have_heaPriPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,220},{-20,240}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor nexLagPum( + final nin=nPum) if have_heaPriPum + "Next lag pump" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 if have_heaPriPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor lasLagPum( + final nin=nPum) if have_heaPriPum + "Last lag pump" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 if have_heaPriPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nPum] + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-250,-130},{-230,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nPum) + "Sum of integer inputs" + annotation (Placement(transformation(extent={{-200,-130},{-180,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt if have_heaPriPum + "Integer add" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nPum] if + have_heaPriPum and (not have_priOnl) + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-250,-166},{-230,-146}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt1( + final nin=nBoi) if have_heaPriPum and (not have_priOnl) + "Sum of integer inputs" + annotation (Placement(transformation(extent={{-200,-166},{-180,-146}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt2[nPum] if + have_heaPriPum and (not have_priOnl) + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-248,-250},{-228,-230}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt2( + final nin=nBoi) if have_heaPriPum and (not have_priOnl) + "Sum of integer inputs" + annotation (Placement(transformation(extent={{-202,-250},{-182,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 if not have_priOnl + "Logical or" + annotation (Placement(transformation(extent={{-250,-200},{-230,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt1 if have_heaPriPum and (not have_priOnl) + "Increase number of enabled boilers by one to initiate pump enable" + annotation (Placement(transformation(extent={{-130,-170},{-110,-150}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi if have_heaPriPum and (not have_priOnl) + "Integer switch" + annotation (Placement(transformation(extent={{-96,-200},{-76,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Greater intGre if have_heaPriPum and (not + have_priOnl) + "Check if more boilers than pumps are enabled" + annotation (Placement(transformation(extent={{-40,-200},{-20,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Less intLes if have_heaPriPum and (not + have_priOnl) + "Check if less boilers than pumps are enabled" + annotation (Placement(transformation(extent={{-38,-250},{-18,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat if not have_priOnl + "Hold true signal when a pump needs to be enabled for stage change" + annotation (Placement(transformation(extent={{-200,-200},{-180,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4 if have_heaPriPum and (not + have_priOnl) + "Initiate the pump enable process" + annotation (Placement(transformation(extent={{0,-200},{20,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.And and5 if have_heaPriPum and (not + have_priOnl) + "Initiate the pump disable process" + annotation (Placement(transformation(extent={{0,-250},{20,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 if have_heaPriPum and (not + have_priOnl) + "Logical not" + annotation (Placement(transformation(extent={{50,-250},{70,-230}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta(final nPum=nPum) if + not have_heaPriPum + "Change lead pump status for dedicated primary pumps" + annotation (Placement(transformation(extent={{58,100},{80,120}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta1( + final nPum=nPum) if have_heaPriPum + "Change lead pump status for headered primary pumps" + annotation (Placement(transformation(extent={{58,66},{80,86}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta2( + final nPum=nPum) if have_priOnl and have_heaPriPum + "Change lag pump status for headered primary pumps in a plant that is primary-only" + annotation (Placement(transformation(extent={{128,-42},{150,-22}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta3( + final nPum=nPum) if have_heaPriPum and (not have_priOnl) + "Change lag pump status for headered primary pumps in a plant that is not primary-only" + annotation (Placement(transformation(extent={{130,-182},{152,-162}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 if not have_heaPriPum + "Lag pump enable" + annotation (Placement(transformation(extent={{-148,-294},{-128,-274}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 if not have_heaPriPum + "Logical not" + annotation (Placement(transformation(extent={{-148,-330},{-128,-310}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta4( + final nPum=nPum) if not have_heaPriPum + "Change lag pump status for dedicated primary pumps" + annotation (Placement(transformation(extent={{62,-314},{84,-294}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 if not have_heaPriPum + "Lag pump disable" + annotation (Placement(transformation(extent={{-110,-312},{-90,-292}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical Not" + annotation (Placement(transformation(extent={{-200,30},{-180,50}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=delBoiDis) + "Delay pump disable after boilers have been disabled" + annotation (Placement(transformation(extent={{-120,30},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nPum] + "Logical switch" + annotation (Placement(transformation(extent={{182,-42},{202,-22}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nPum) + "Boolean replicator" + annotation (Placement(transformation(extent={{142,30},{162,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nPum]( + final k=fill(false, nPum)) + "Boolean False signal" + annotation (Placement(transformation(extent={{128,0},{148,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 if not have_priOnl + "Latch to hold process completion signal" + annotation (Placement(transformation(extent={{-60,-400},{-40,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.Xor xor[nPum] if not have_priOnl + "Check if all pumps are enabled and disabled as required" + annotation (Placement(transformation(extent={{-180,-400},{-160,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4[nPum] if not have_priOnl + "True signal for pumps that are at correct state" + annotation (Placement(transformation(extent={{-140,-400},{-120,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd(nin=nPum) if not have_priOnl + "Check if all pumps are at desired status" + annotation (Placement(transformation(extent={{-100,-400},{-80,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[nPum] if not have_priOnl + "Logical pre block" + annotation (Placement(transformation(extent={{-220,-400},{-200,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not5 if not have_priOnl + "Generate true signal when process is incomplete" + annotation (Placement(transformation(extent={{-20,-400},{0,-380}}))); + +equation + connect(enaDedLeaPum.uPlaEna, uPlaEna) annotation (Line(points={{-202,115},{-240, + 115},{-240,110},{-300,110}}, 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={{-252,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(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(lasLagPum.y, reaToInt2.u) + annotation (Line(points={{-58,-100},{-42,-100}}, color={0,0,127})); + + connect(enaLagHotPum.VHotWat_flow,VHotWat_flow) + annotation (Line(points={{-202,4},{-266,4},{-266,-20},{-300,-20}}, + color={0,0,127})); + + connect(uHotWatPum,enaLagHotPum.uHotWatPum) + annotation (Line(points={{-300,140},{-260,140},{-260,-3.8},{-202,-3.8}}, + color={255,0,255})); + + connect(intToRea.y, lasLagPum.u) + annotation (Line(points={{-198,230},{-160,230},{-160,-100},{-82,-100}}, + color={0,0,127})); + + connect(pumSpeLocDp.dpHotWat_local,dpHotWat_local) + annotation (Line(points={{-62,-472},{-230,-472},{-230,-440},{-300,-440}}, + color={0,0,127})); + + connect(pumSpeLocDp.dpHotWat_remote,dpHotWat_remote) + annotation (Line(points={{-62,-484},{-200,-484},{-200,-480},{-300,-480}}, + color={0,0,127})); + + connect(pumSpeLocDp.dpHotWatSet,dpHotWatSet) + annotation (Line(points={{-62,-488},{-220,-488},{-220,-510},{-300,-510}}, + color={0,0,127})); + + connect(dpHotWat_remote,pumSpeRemDp.dpHotWat) + annotation (Line(points={{-300,-480},{-200,-480},{-200,-520},{-62,-520}}, + color={0,0,127})); + + connect(dpHotWatSet,pumSpeRemDp.dpHotWatSet) + annotation (Line(points={{-300,-510},{-220,-510},{-220,-528},{-62,-528}}, + color={0,0,127})); + + connect(uHotWatPum, booToInt.u) + annotation (Line(points={{-300,140},{-260,140},{-260,-120},{-252,-120}}, + color={255,0,255})); + + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-228,-120},{-202,-120}}, color={255,127,0})); + + connect(addInt.y, nexLagPum.index) + annotation (Line(points={{-98,-70},{-70,-70},{-70,-62}}, color={255,127,0})); + + connect(mulSumInt.y, addInt.u2) + annotation (Line(points={{-178,-120},{-128,-120},{-128,-76},{-122,-76}}, + color={255,127,0})); + + connect(conInt.y, addInt.u1) + annotation (Line(points={{-252,200},{-140,200},{-140,-64},{-122,-64}}, + color={255,127,0})); + + connect(mulSumInt.y, lasLagPum.index) + annotation (Line(points={{-178,-120},{-70,-120},{-70,-112}}, color={255,127,0})); + + connect(uHotIsoVal, enaHeaLeaPum.uHotWatIsoVal) annotation (Line(points={{-300,70}, + {-202,70}}, color={0,0,127})); + + connect(VHotWat_flow,pumSpeFlo. VHotWatPri_flow) annotation (Line(points={{-300, + -20},{-266,-20},{-266,-564},{-62,-564}}, color={0,0,127})); + + connect(VHotWatSec_flow,pumSpeFlo. VHotWatSec_flow) annotation (Line(points={{-300, + -580},{-240,-580},{-240,-569},{-62,-569}}, color={0,0,127})); + + connect(VHotWatDec_flow,pumSpeFlo. VHotWatDec_flow) annotation (Line(points={{-300, + -610},{-240,-610},{-240,-569},{-62,-569}}, color={0,0,127})); + + connect(THotWatPri, pumSpeTem.THotWatPri) annotation (Line(points={{-300,-640}, + {-80,-640},{-80,-594},{-62,-594}}, color={0,0,127})); + + connect(THotWatSec, pumSpeTem.THotWatSec) annotation (Line(points={{-300,-670}, + {-76,-670},{-76,-598},{-62,-598}}, color={0,0,127})); + + connect(THotWatBoiSup, pumSpeTem.THotWatBoiSup) annotation (Line(points={{-300, + -700},{-68,-700},{-68,-606},{-62,-606}}, color={0,0,127})); + + connect(uBoiSta, pumSpeTem.uBoiSta) annotation (Line(points={{-300,-70},{-270, + -70},{-270,-602},{-62,-602}}, color={255,0,255})); + + connect(uBoiSta, booToRea.u) + annotation (Line(points={{-300,-70},{-254,-70}}, color={255,0,255})); + + connect(booToRea.y, extIndSig.u) + annotation (Line(points={{-230,-70},{-224,-70}}, color={0,0,127})); + + connect(conInt.y, extIndSig.index) annotation (Line(points={{-252,200},{-140,200}, + {-140,-88},{-212,-88},{-212,-82}}, color={255,127,0})); + + connect(uBoiSta, booToInt1.u) annotation (Line(points={{-300,-70},{-270,-70},{ + -270,-156},{-252,-156}}, color={255,0,255})); + + connect(booToInt1.y, mulSumInt1.u[1:nPum]) annotation (Line(points={{-228,-156}, + {-202,-156}}, color={255,127,0})); + + connect(booToInt2.y,mulSumInt2. u[1:nPum]) annotation (Line(points={{-226,-240}, + {-204,-240}}, color={255,127,0})); + + connect(uHotWatPum, booToInt2.u) annotation (Line(points={{-300,140},{-260,140}, + {-260,-240},{-250,-240}}, color={255,0,255})); + + connect(or1.u1, uStaUp) + annotation (Line(points={{-252,-190},{-300,-190}}, color={255,0,255})); + + connect(uOnOff, or1.u2) annotation (Line(points={{-300,-220},{-256,-220},{-256, + -198},{-252,-198}}, color={255,0,255})); + + connect(conInt.y, addInt1.u1) annotation (Line(points={{-252,200},{-140,200},{ + -140,-154},{-132,-154}}, color={255,127,0})); + + connect(mulSumInt1.y, addInt1.u2) annotation (Line(points={{-178,-156},{-154,-156}, + {-154,-166},{-132,-166}}, color={255,127,0})); + + connect(addInt1.y, intSwi.u1) annotation (Line(points={{-108,-160},{-104,-160}, + {-104,-182},{-98,-182}}, color={255,127,0})); + + connect(mulSumInt1.y, intSwi.u3) annotation (Line(points={{-178,-156},{-154,-156}, + {-154,-198},{-98,-198}}, color={255,127,0})); + + connect(intSwi.y, intGre.u1) + annotation (Line(points={{-74,-190},{-42,-190}}, color={255,127,0})); + + connect(mulSumInt2.y, intGre.u2) annotation (Line(points={{-180,-240},{-72,-240}, + {-72,-198},{-42,-198}}, color={255,127,0})); + + connect(intSwi.y, intLes.u1) annotation (Line(points={{-74,-190},{-56,-190},{-56, + -240},{-40,-240}}, color={255,127,0})); + + connect(mulSumInt2.y, intLes.u2) annotation (Line(points={{-180,-240},{-72,-240}, + {-72,-248},{-40,-248}}, color={255,127,0})); + + connect(or1.y, lat.u) + annotation (Line(points={{-228,-190},{-202,-190}}, color={255,0,255})); + + connect(lat.y, intSwi.u2) + annotation (Line(points={{-178,-190},{-98,-190}}, color={255,0,255})); + + connect(intGre.y, and4.u1) + annotation (Line(points={{-18,-190},{-2,-190}}, color={255,0,255})); + + connect(intLes.y, and5.u1) + annotation (Line(points={{-16,-240},{-2,-240}}, color={255,0,255})); + + connect(not1.u, and5.y) + annotation (Line(points={{48,-240},{22,-240}}, color={255,0,255})); + + connect(pumSpeRemDp.yHotWatPumSpe, max.u2) annotation (Line(points={{-38,-520}, + {96,-520},{96,-552},{132,-552}}, color={0,0,127})); + + connect(pumSpeLocDp.yHotWatPumSpe, max.u2) annotation (Line(points={{-38,-480}, + {96,-480},{96,-552},{132,-552}}, color={0,0,127})); + + connect(pumSpeFlo.yHotWatPumSpe, max.u2) annotation (Line(points={{-38,-564},{ + 96,-564},{96,-552},{132,-552}}, color={0,0,127})); + + connect(pumSpeTem.yHotWatPumSpe, max.u2) annotation (Line(points={{-38,-598},{ + 96,-598},{96,-552},{132,-552}}, color={0,0,127})); + + connect(uMinPriPumSpeCon, max.u1) + annotation (Line(points={{-300,-540},{132,-540}}, color={0,0,127})); + + connect(enaDedLeaPum.yLea, chaPumSta.uNexLagPumSta) annotation (Line(points={ + {-178,110},{22,110},{22,118},{56,118}}, color={255,0,255})); + + connect(enaDedLeaPum.yLea, chaPumSta.uLasLagPumSta) annotation (Line(points={ + {-178,110},{22,110},{22,115},{56,115}}, color={255,0,255})); + + connect(reaToInt.y, chaPumSta1.uNexLagPum) annotation (Line(points={{-18,230}, + {46,230},{46,72},{56,72}}, color={255,127,0})); + + connect(reaToInt.y, chaPumSta1.uLasLagPum) annotation (Line(points={{-18,230}, + {46,230},{46,68},{56,68}}, color={255,127,0})); + + connect(enaHeaLeaPum.yLea, chaPumSta1.uNexLagPumSta) annotation (Line(points= + {{-178,70},{36,70},{36,84},{56,84}}, color={255,0,255})); + + connect(enaHeaLeaPum.yLea, chaPumSta1.uLasLagPumSta) annotation (Line(points= + {{-178,70},{36,70},{36,81},{56,81}}, color={255,0,255})); + + connect(uHotWatPum, chaPumSta.uHotWatPum) annotation (Line(points={{-300,140}, + {26,140},{26,110},{56,110}}, color={255,0,255})); + + connect(uHotWatPum, chaPumSta1.uHotWatPum) annotation (Line(points={{-300,140}, + {26,140},{26,76},{56,76}}, color={255,0,255})); + + connect(reaToInt1.y, chaPumSta2.uNexLagPum) annotation (Line(points={{-18,-50}, + {30,-50},{30,-36},{126,-36}},color={255,127,0})); + + connect(reaToInt2.y, chaPumSta2.uLasLagPum) annotation (Line(points={{-18, + -100},{34,-100},{34,-40},{126,-40}},color={255,127,0})); + + connect(reaToInt1.y, chaPumSta3.uNexLagPum) annotation (Line(points={{-18,-50}, + {30,-50},{30,-176},{128,-176}},color={255,127,0})); + + connect(reaToInt2.y, chaPumSta3.uLasLagPum) annotation (Line(points={{-18, + -100},{34,-100},{34,-180},{128,-180}},color={255,127,0})); + + connect(lat.y, and1.u1) annotation (Line(points={{-178,-190},{-170,-190},{ + -170,-284},{-150,-284}}, color={255,0,255})); + + connect(lat.y, or2.u1) annotation (Line(points={{-178,-190},{-170,-190},{-170, + -302},{-112,-302}}, color={255,0,255})); + + connect(not2.y, or2.u2) annotation (Line(points={{-126,-320},{-118,-320},{ + -118,-310},{-112,-310}}, color={255,0,255})); + + connect(uNexEnaBoi, chaPumSta4.uNexLagPum) annotation (Line(points={{-300, + -300},{-188,-300},{-188,-334},{26,-334},{26,-308},{60,-308}}, color={ + 255,127,0})); + + connect(uLasDisBoi, chaPumSta4.uLasLagPum) annotation (Line(points={{-300, + -340},{32,-340},{32,-312},{60,-312}}, color={255,127,0})); + + connect(chaPumSta.yHotWatPum, chaPumSta4.uHotWatPum) annotation (Line(points= + {{80,110},{104,110},{104,-266},{52,-266},{52,-304},{60,-304}}, color= + {255,0,255})); + + connect(chaPumSta1.yHotWatPum, chaPumSta2.uHotWatPum) annotation (Line(points={{80,76}, + {100,76},{100,-32},{126,-32}}, color={255,0, + 255})); + connect(chaPumSta1.yHotWatPum, chaPumSta3.uHotWatPum) annotation (Line(points={{80,76}, + {100,76},{100,-172},{128,-172}}, color={ + 255,0,255})); + + connect(greThr.u, extIndSig.y) + annotation (Line(points={{-194,-70},{-200,-70}}, color={0,0,127})); + connect(greThr.y, enaDedLeaPum.uLeaBoiSta) annotation (Line(points={{-170,-70}, + {-166,-70},{-166,-42},{-218,-42},{-218,105},{-202,105}}, color={255,0, + 255})); + connect(and1.y, and2.u1) + annotation (Line(points={{-126,-284},{-48,-284}}, color={255,0,255})); + connect(or2.y, or3.u1) annotation (Line(points={{-88,-302},{-70,-302},{-70,-318}, + {-50,-318}},color={255,0,255})); + connect(and2.y, chaPumSta4.uNexLagPumSta) annotation (Line(points={{-24,-284}, + {-20,-284},{-20,-296},{60,-296}}, color={255,0,255})); + connect(or3.y, chaPumSta4.uLasLagPumSta) annotation (Line(points={{-26,-318},{ + 48,-318},{48,-299},{60,-299}}, color={255,0,255})); + connect(intGreEquThr1.y, and3.u1) + annotation (Line(points={{-8,32},{68,32}}, color={255,0,255})); + connect(enaLagHotPum.yUp, and3.u2) annotation (Line(points={{-178,4},{2,4},{2, + 24},{68,24}}, color={255,0,255})); + connect(or4.y, chaPumSta2.uLasLagPumSta) annotation (Line(points={{94,-10},{ + 108,-10},{108,-27},{126,-27}}, color={255,0,255})); + connect(and3.y, chaPumSta2.uNexLagPumSta) annotation (Line(points={{92,32},{ + 112,32},{112,-24},{126,-24}}, color={255,0,255})); + connect(intLesEquThr1.y, or4.u1) + annotation (Line(points={{40,-10},{70,-10}}, color={255,0,255})); + connect(enaLagHotPum.yDown, or4.u2) annotation (Line(points={{-178,-4},{2,-4}, + {2,-28},{66,-28},{66,-18},{70,-18}}, color={255,0,255})); + connect(and4.y, and3.u2) annotation (Line(points={{22,-190},{50,-190},{50,24}, + {68,24}}, color={255,0,255})); + connect(not1.y, or4.u2) annotation (Line(points={{72,-240},{76,-240},{76,-212}, + {54,-212},{54,-28},{66,-28},{66,-18},{70,-18}}, color={255,0,255})); + connect(or4.y, chaPumSta3.uLasLagPumSta) annotation (Line(points={{94,-10},{ + 108,-10},{108,-167},{128,-167}}, color={255,0,255})); + connect(and3.y, chaPumSta3.uNexLagPumSta) annotation (Line(points={{92,32},{ + 112,32},{112,-164},{128,-164}}, color={255,0,255})); + connect(mulSumInt.y, intGreEquThr1.u) annotation (Line(points={{-178,-120},{ + -48,-120},{-48,32},{-32,32}}, color={255,127,0})); + connect(mulSumInt.y, intLesEquThr1.u) annotation (Line(points={{-178,-120},{8, + -120},{8,-10},{16,-10}}, color={255,127,0})); + connect(con.y, max.u1) annotation (Line(points={{62,-456},{82,-456},{82,-540}, + {132,-540}}, color={0,0,127})); + connect(uPlaEna, not3.u) annotation (Line(points={{-300,110},{-240,110},{-240, + 40},{-202,40}}, color={255,0,255})); + connect(not3.y, truDel.u) + annotation (Line(points={{-178,40},{-122,40}}, color={255,0,255})); + connect(truDel.y, booRep.u) annotation (Line(points={{-98,40},{-48,40},{-48,54}, + {122,54},{122,40},{140,40}}, color={255,0,255})); + connect(chaPumSta2.yHotWatPum, logSwi.u3) annotation (Line(points={{150,-32},{ + 166,-32},{166,-40},{180,-40}}, color={255,0,255})); + connect(booRep.y, logSwi.u2) annotation (Line(points={{164,40},{174,40},{174,-32}, + {180,-32}}, color={255,0,255})); + connect(con1.y, logSwi.u1) annotation (Line(points={{150,10},{166,10},{166,-24}, + {180,-24}}, color={255,0,255})); + connect(logSwi.y, yHotWatPum) annotation (Line(points={{204,-32},{248,-32},{248, + 0},{300,0}}, color={255,0,255})); + connect(chaPumSta3.yHotWatPum, logSwi.u3) annotation (Line(points={{152,-172}, + {166,-172},{166,-40},{180,-40}}, color={255,0,255})); + connect(chaPumSta4.yHotWatPum, logSwi.u3) annotation (Line(points={{84,-304},{ + 166,-304},{166,-40},{180,-40}}, color={255,0,255})); + connect(uNexEnaBoi, chaPumSta.uNexLagPum) annotation (Line(points={{-300,-300}, + {-278,-300},{-278,98},{22,98},{22,106},{56,106}}, color={255,127,0})); + connect(uLasDisBoi, chaPumSta.uLasLagPum) annotation (Line(points={{-300,-340}, + {-264,-340},{-264,96},{28,96},{28,102},{56,102}}, color={255,127,0})); + connect(uHotWatPum, pumSpeLocDp.uHotWatPum) annotation (Line(points={{-300,140}, + {-260,140},{-260,-476},{-62,-476}}, color={255,0,255})); + connect(uHotWatPum, pumSpeRemDp.uHotWatPum) annotation (Line(points={{-300,140}, + {-260,140},{-260,-512},{-62,-512}}, color={255,0,255})); + connect(uHotWatPum, pumSpeFlo.uHotWatPum) annotation (Line(points={{-300,140}, + {-260,140},{-260,-559},{-62,-559}}, color={255,0,255})); + connect(uHotWatPum, pumSpeTem.uHotWatPum) annotation (Line(points={{-300,140}, + {-260,140},{-260,-590},{-62,-590}}, color={255,0,255})); + connect(max.y, yPumSpe) + annotation (Line(points={{156,-546},{300,-546}}, color={0,0,127})); + connect(xor.y, not4.u) + annotation (Line(points={{-158,-390},{-142,-390}}, color={255,0,255})); + connect(not4.y, mulAnd.u[1:nPum]) annotation (Line(points={{-118,-390},{-110,-390}, + {-110,-390},{-102,-390}}, color={255,0,255})); + connect(mulAnd.y, lat1.u) + annotation (Line(points={{-78,-390},{-62,-390}}, color={255,0,255})); + connect(pre1.y, xor.u1) + annotation (Line(points={{-198,-390},{-182,-390}}, color={255,0,255})); + connect(logSwi.y, pre1.u) annotation (Line(points={{204,-32},{248,-32},{248,-370}, + {-240,-370},{-240,-390},{-222,-390}}, color={255,0,255})); + connect(uHotWatPum, xor.u2) annotation (Line(points={{-300,140},{-260,140},{-260, + -360},{-190,-360},{-190,-398},{-182,-398}}, color={255,0,255})); + connect(uPumChaPro, lat1.clr) annotation (Line(points={{-300,-250},{-274,-250}, + {-274,-410},{-70,-410},{-70,-396},{-62,-396}}, color={255,0,255})); + connect(lat1.y, not5.u) + annotation (Line(points={{-38,-390},{-22,-390}}, color={255,0,255})); + connect(intGreEquThr1.y, and2.u2) annotation (Line(points={{-8,32},{58,32},{58, + -206},{82,-206},{82,-260},{-58,-260},{-58,-292},{-48,-292}}, color={255, + 0,255})); + connect(intLesEquThr1.y, or3.u2) annotation (Line(points={{40,-10},{62,-10},{62, + -200},{88,-200},{88,-342},{-64,-342},{-64,-326},{-50,-326}}, color={255, + 0,255})); + connect(lat1.y, lat.clr) annotation (Line(points={{-38,-390},{-34,-390},{-34, + -366},{-176,-366},{-176,-206},{-216,-206},{-216,-196},{-202,-196}}, + color={255,0,255})); + connect(not5.y, not2.u) annotation (Line(points={{2,-390},{20,-390},{20,-360}, + {-160,-360},{-160,-320},{-150,-320}}, color={255,0,255})); + connect(not5.y, and1.u2) annotation (Line(points={{2,-390},{20,-390},{20,-360}, + {-160,-360},{-160,-292},{-150,-292}}, color={255,0,255})); + connect(not5.y, and4.u2) annotation (Line(points={{2,-390},{20,-390},{20,-360}, + {-160,-360},{-160,-266},{-10,-266},{-10,-198},{-2,-198}}, color={255, + 0,255})); + connect(not5.y, and5.u2) annotation (Line(points={{2,-390},{20,-390},{20,-360}, + {-160,-360},{-160,-266},{-10,-266},{-10,-248},{-2,-248}}, color={255, + 0,255})); +annotation (defaultComponentName="priPumCon", + Diagram(coordinateSystem(preserveAspectRatio=false,extent={{-280,-720},{280,260}}), + graphics={ + Rectangle( + extent={{-276,256},{274,60}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{206,248},{270,232}}, + 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},{274,-136}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{192,52},{270,36}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable next lag pump"), + Text( + extent={{188,-126},{266,-136}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable last lag pump"), + Rectangle( + extent={{-278,-420},{272,-714}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{220,-422},{266,-434}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Pump speed"), + Rectangle( + extent={{-276,-268},{274,-356}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{74,-272},{262,-286}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable/Disable lag pumps for dedicated primary pumps"), + Rectangle( + extent={{-276,-140},{274,-264}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{178,-146},{264,-202}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Enable/Disable lag pumps +for headered pumps in +plants that are not +primary-only")}), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-300},{100,300}}), + graphics={ + Rectangle( + extent={{-100,-300},{100,300}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,350},{100,310}}, + 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 hot water pump control sequence per ASHRAE RP-1711, March, 2020 draft, +section 5.3.6. It consists of: +

+ +

+The parameter values for valid pump configurations are as follows: +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameters/Pump configurations123456789101112
have_priOnlTRUETRUEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSE
have_heaPriPumTRUETRUETRUETRUETRUETRUETRUEFALSEFALSEFALSEFALSEFALSE
have_varPriPumTRUETRUETRUETRUETRUETRUEFALSETRUETRUETRUETRUEFALSE
speConTypremoteDPlocalDPflowrateflowratetemperaturetemperatureNAflowrateflowratetemperaturetemperatureNA
have_secFloSenNANATRUEFALSENANANATRUEFALSENANANA
have_priSecTemSenNANANANATRUEFALSENANANATRUEFALSENA
+", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/EnableLead_dedicated.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/EnableLead_dedicated.mo new file mode 100644 index 00000000000..55a7b9fa0b7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/EnableLead_dedicated.mo @@ -0,0 +1,109 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences; +block EnableLead_dedicated + "Sequence to enable or disable the lead pump of plants with dedicated primary hot water pumps" + + parameter Real offTimThr( + final unit="s", + displayUnit="s", + final quantity="time") = 180 + "Threshold to check lead boiler off time"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPlaEna + "Plant enabling status" + annotation (Placement(transformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uLeaBoiSta + "Lead boiler status" + annotation (Placement(transformation(extent={{-140,-70},{-100,-30}}))); + + 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.Latch leaPumSta + "Lead pump status" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Logical not" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=offTimThr) + "Check if boiler disable time is greater than threshold" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Detect plant being disabled" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical And" + annotation (Placement(transformation(extent={{-30,-60},{-10,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Boolean latch" + annotation (Placement(transformation(extent={{-50,-20},{-30,0}}))); + +equation + connect(uPlaEna, leaPumSta.u) + annotation (Line(points={{-120,50},{50,50},{50,0},{58,0}}, + color={255,0,255})); + + connect(leaPumSta.y, yLea) + annotation (Line(points={{82,0},{120,0}}, color={255,0,255})); + + connect(uLeaBoiSta, not2.u) + annotation (Line(points={{-120,-50},{-82,-50}}, + color={255,0,255})); + + connect(tim.passed, leaPumSta.clr) annotation (Line(points={{22,-58},{50,-58}, + {50,-6},{58,-6}}, color={255,0,255})); + connect(uPlaEna, falEdg.u) annotation (Line(points={{-120,50},{-90,50},{-90, + -10},{-82,-10}}, color={255,0,255})); + connect(and2.y, tim.u) + annotation (Line(points={{-8,-50},{-2,-50}}, color={255,0,255})); + connect(not2.y, and2.u2) annotation (Line(points={{-58,-50},{-50,-50},{-50, + -58},{-32,-58}}, color={255,0,255})); + connect(falEdg.y, lat.u) + annotation (Line(points={{-58,-10},{-52,-10}}, color={255,0,255})); + connect(uPlaEna, lat.clr) annotation (Line(points={{-120,50},{-56,50},{-56, + -16},{-52,-16}}, color={255,0,255})); + connect(lat.y, and2.u1) annotation (Line(points={{-28,-10},{-20,-10},{-20,-30}, + {-40,-30},{-40,-50},{-32,-50}}, color={255,0,255})); +annotation ( + defaultComponentName="enaLeaPriPum_dedicated", + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that enable and disable leading primary hot water pump, for plants +with dedicated primary hot water pumps, according to ASHRAE RP-1711, March 2020 draft, +section 5.3.6.3. +

+

+The lead primary hot water pump status yLea should be enabled when +boiler plant is enabled (uPlaEna = true). It should be disabled when +the lead boiler is disabled and has been proven off (uLeaBoiSta += false) for time offTimThr. +

+", revisions=" + +")); +end EnableLead_dedicated; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/EnableLead_headered.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/EnableLead_headered.mo new file mode 100644 index 00000000000..0b2aca9a262 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/EnableLead_headered.mo @@ -0,0 +1,110 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences; +block EnableLead_headered + "Sequence to enable or disable the lead primary pump of plants with headered + primary hot water pumps" + + parameter Integer nBoi=3 + "Total number of hot water isolation valves (same as number of boilers)"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal[nBoi]( + final unit=fill("1",nBoi), + displayUnit=fill("1",nBoi), + final min=fill(0,nBoi), + final max=fill(1,nBoi)) + "Hot water isolation valve status" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea + "Lead pump status" + annotation (Placement(transformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr[nBoi]( + final t=fill(0.975,nBoi), + final h=fill(0.025,nBoi)) + "Determine if the isolation valve is open based on valve position" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch leaPumSta + "Lead pump status" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) + "Logical true" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Logical false" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nBoi) + "Check if there are any hot water isolation valves opened" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + +equation + connect(con.y,leaPumSta. u1) + annotation (Line(points={{-18,40},{30,40},{30,8},{38,8}},color={255,0,255})); + + connect(con1.y,leaPumSta. u3) + annotation (Line(points={{-18,-40},{30,-40},{30,-8},{38,-8}}, + color={255,0,255})); + + connect(leaPumSta.y, yLea) + annotation (Line(points={{62,0},{120,0}}, color={255,0,255})); + + connect(mulOr.y, leaPumSta.u2) + annotation (Line(points={{-18,0},{38,0}}, color={255,0,255})); + + connect(uHotWatIsoVal, greThr.u) + annotation (Line(points={{-120,0},{-82,0}}, color={0,0,127})); + connect(greThr.y, mulOr.u[1:nBoi]) annotation (Line(points={{-58,0},{-50,0},{-50, + 0},{-42,0}}, color={255,0,255})); +annotation ( + defaultComponentName="enaLeaPriPum_headered", + 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={{-94,12},{-40,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uHotIsoVal"), + Text( + extent={{42,12},{96,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yLeaPum")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+Block that enables and disables lead primary hot water pump, for plants +with headered primary hot water pumps, according to ASHRAE RP-1711, March 2020 draft, +section 5.3.6.2. +

+ +", revisions=" + +")); +end EnableLead_headered; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Speed_flow.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Speed_flow.mo new file mode 100644 index 00000000000..e68d3c4f1fa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Speed_flow.mo @@ -0,0 +1,267 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences; +block Speed_flow + "Pump speed control for primary-secondary plants where flowrate sensors are available in the hot water circuit" + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(group="Speed controller")); + + parameter Boolean primarySecondarySensors = true + "True: Flowrate sensors in primary and secondary circuits; + False: Flowrate sensor in decoupler"; + + parameter Integer nPum = 2 + "Total number of hot water pumps"; + + parameter Real minPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpe) = 0.1 + "Minimum pump speed"; + + parameter Real maxPumSpe( + final unit="1", + displayUnit="1", + final min=minPumSpe, + final max=1) = 1 + "Maximum pump speed"; + + parameter Real k( + final unit="1", + displayUnit="1")=1 + "Gain of controller" + annotation(Dialog(group="Speed controller")); + + parameter Real Ti( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.5 + "Time constant of integrator block" + annotation(Dialog(group="Speed controller")); + + parameter Real Td( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.1 + "Time constant of derivative block" + annotation (Dialog(group="Speed controller")); + + parameter Real VHotWat_flow_nominal( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate")=0.5 + "Total plant design hot water flow rate"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatPri_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if primarySecondarySensors + "Measured hot water flow rate through primary circuit" + annotation (Placement(transformation(extent={{-160,-50},{-120,-10}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatSec_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if primarySecondarySensors + "Measured hot water flow rate through secondary circuit" + annotation (Placement(transformation(extent={{-160,-80},{-120,-40}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWatDec_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if not primarySecondarySensors + "Measured hot water flow rate through decoupler" + annotation (Placement(transformation(extent={{-160,-120},{-120,-80}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatPumSpe( + final min=minPumSpe, + final max=maxPumSpe, + final unit="1", + displayUnit="1") + "Hot water pump speed" + annotation (Placement(transformation(extent={{120,80},{160,120}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.PIDWithReset conPID( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + final Td=Td, + final yMax=1, + final yMin=0) + "PID loop to regulate flow through decoupler leg" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Reset PID loop when it is activated" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line pumSpe + "Pump speed" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 if primarySecondarySensors + "Compare measured flowrate in primary and secondary loops" + annotation (Placement(transformation(extent={{-100,-50},{-80,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div if primarySecondarySensors + "Normalize flow-rate value" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Check if any hot water primary pumps are enabled" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_min( + final k=minPumSpe) + "Minimum pump speed" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_max( + final k=maxPumSpe) + "Maximum pump speed" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one( + final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-80,80},{-60,100}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) if primarySecondarySensors + "Ensure divisor is non-zero" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=1/VHotWat_flow_nominal) if not primarySecondarySensors + "Normalize flowrate" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + +equation + connect(zer.y, pumSpe.x1) + annotation (Line(points={{-58,90},{-30,90},{-30,68},{58,68}}, + color={0,0,127})); + + connect(pumSpe_min.y, pumSpe.f1) + annotation (Line(points={{-58,60},{-40,60},{-40,64},{58,64}}, color={0,0,127})); + + connect(one.y, pumSpe.x2) + annotation (Line(points={{-58,30},{-40,30},{-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(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={{-58,90},{-30,90},{-30,92},{78,92}}, + color={0,0,127})); + + connect(swi.y,yHotWatPumSpe) + annotation (Line(points={{102,100},{140,100}}, color={0,0,127})); + + connect(uHotWatPum, mulOr.u[1:nPum]) annotation (Line(points={{-140,0},{-122,0},{ + -122,0},{-102,0}}, 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(VHotWatPri_flow,sub2. u1) annotation (Line(points={{-140,-30},{-110,-30}, + {-110,-34},{-102,-34}}, color={0,0,127})); + connect(VHotWatSec_flow,sub2. u2) annotation (Line(points={{-140,-60},{-106,-60}, + {-106,-46},{-102,-46}}, color={0,0,127})); + connect(sub2.y, div.u1) annotation (Line(points={{-78,-40},{-70,-40},{-70,-64}, + {-62,-64}}, color={0,0,127})); + connect(addPar.y, div.u2) annotation (Line(points={{-78,-70},{-70,-70},{-70,-76}, + {-62,-76}}, color={0,0,127})); + connect(VHotWatPri_flow, addPar.u) annotation (Line(points={{-140,-30},{-110,-30}, + {-110,-70},{-102,-70}}, color={0,0,127})); + + connect(VHotWatDec_flow, gai.u) + annotation (Line(points={{-140,-100},{-62,-100}}, color={0,0,127})); + connect(zer.y, conPID.u_s) annotation (Line(points={{-58,90},{-30,90},{-30,0}, + {18,0}}, color={0,0,127})); + connect(mulOr.y, edg.u) annotation (Line(points={{-78,0},{-50,0},{-50,-20},{ + -42,-20}}, color={255,0,255})); + connect(edg.y, conPID.trigger) + annotation (Line(points={{-18,-20},{24,-20},{24,-12}}, color={255,0,255})); + connect(div.y, conPID.u_m) + annotation (Line(points={{-38,-70},{30,-70},{30,-12}}, color={0,0,127})); + connect(gai.y, conPID.u_m) + annotation (Line(points={{-38,-100},{30,-100},{30,-12}}, color={0,0,127})); + connect(conPID.y, pumSpe.u) + annotation (Line(points={{42,0},{50,0},{50,60},{58,60}}, color={0,0,127})); +annotation ( + defaultComponentName="hotPumSpe", + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}})), +Documentation(info=" +

+Block that outputs hot water pump speed setpoint for primary-secondary plants with +variable-speed primary pumps with flow sensors present in the primary and secondary +loops, or in the decoupler, according to ASHRAE RP-1711, March, 2020 draft, +sections 5.3.6.12 and 5.3.6.13. +

+

+When any hot water pump is proven on, uHotWatPum = true, +pump speedyHotWatPumSpe will be controlled by a reverse acting PID +loop maintaining the flowrate through the decoupler at zero. PID loop output +shall be mapped from minimum pump speed (minPumSpe) at 0% to maximum +pump speed(maxPumSpe) at 100%. +

+
    +
  1. +When the plant has flowrate sensors in the primary and secondary loops, +primarySecondarySensors = true, the measured flowrate in primary +loop VHotWatPri_flow and the measured flowrate in secondary loop +VHotWatSec_flow is used to calculate the flow through the decoupler +(VHotWatPri_flow - VHotWatSec_flow) and generate the control signal. +
  2. +
  3. +When the plant has a flowrate sensor in the decoupler, +primarySecondarySensors = false, the measured flowrate through the +decoupler is used to calculate the control signal. +
  4. +
+", revisions=" + +")); +end Speed_flow; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Speed_temperature.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Speed_temperature.mo new file mode 100644 index 00000000000..341245aaed5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Speed_temperature.mo @@ -0,0 +1,399 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences; +block Speed_temperature + "Pump speed control for primary-secondary plants where temperature sensors are available in the hot water circuit" + + parameter Boolean primarySecondarySensors = true + "True: Temperature sensors in primary and secondary circuits; + False: Temperature sensors at boiler supply and in secondary circuit"; + + parameter Integer nBoi = 2 + "Total number of boilers"; + + parameter Integer nPum = 2 + "Total number of hot water pumps" + annotation(Dialog(group="Pump parameters")); + + parameter Integer numIgnReq=0 + "Number of ignored requests" + annotation(Dialog(group="Trim-and-Respond parameters")); + + parameter Real boiDesFlo[nBoi]={0.5,0.5} + "Vector of design flowrates for all boilers in plant"; + + parameter Real minPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpe) = 0.1 + "Minimum pump speed" + annotation(Dialog(group="Pump parameters")); + + parameter Real maxPumSpe( + final unit="1", + displayUnit="1", + final min=minPumSpe, + final max=1) = 1 + "Maximum pump speed" + annotation(Dialog(group="Pump parameters")); + + parameter Real delTim( + final unit="s", + displayUnit="s", + final quantity="time")=900 + "Delay time" + annotation(Dialog(group="Trim-and-Respond parameters")); + + parameter Real samPer( + final unit="s", + displayUnit="s", + final quantity="time")=120 + "Sample period of component" + annotation(Dialog(group="Trim-and-Respond parameters")); + + parameter Real triAmo( + final unit="1", + displayUnit="1")=-0.02 + "Trim amount" + annotation(Dialog(group="Trim-and-Respond parameters")); + + parameter Real resAmo( + final unit="1", + displayUnit="1")=0.03 + "Respond amount" + annotation(Dialog(group="Trim-and-Respond parameters")); + + parameter Real maxRes( + final unit="1", + displayUnit="1")=0.06 + "Maximum response per time interval" + annotation(Dialog(group="Trim-and-Respond parameters")); + + parameter Real twoReqLimLow( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference")=1.2 + "Lower limit of hysteresis loop sending two requests" + annotation(Dialog(group="Hysteresis loop parameters for request generation")); + + parameter Real twoReqLimHig( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference")=2 + "Higher limit of hysteresis loop sending two requests" + annotation(Dialog(group="Hysteresis loop parameters for request generation")); + + parameter Real oneReqLimLow( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference")=0.2 + "Lower limit of hysteresis loop sending one request" + annotation(Dialog(group="Hysteresis loop parameters for request generation")); + + parameter Real oneReqLimHig( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference")=1 + "Higher limit of hysteresis loop sending one request" + annotation(Dialog(group="Hysteresis loop parameters for request generation")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiSta[nBoi] if not primarySecondarySensors + "Boiler status vector" + annotation (Placement(transformation(extent={{-160,-70},{-120,-30}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{-160,80},{-120,120}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatPri( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if primarySecondarySensors + "Measured hot water temperature in primary circuit" + annotation (Placement(transformation(extent={{-160,30},{-120,70}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSec( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water temperature in secondary circuit" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatBoiSup[nBoi]( + final unit=fill("K",nBoi), + displayUnit=fill("K",nBoi), + final quantity=fill("ThermodynamicTemperature",nBoi)) if not primarySecondarySensors + "Measured hot water temperature at boiler supply" + annotation (Placement(transformation(extent={{-160,-130},{-120,-90}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatPumSpe( + final min=minPumSpe, + final max=maxPumSpe, + final unit="1", + displayUnit="1") + "Hot water pump speed" + annotation (Placement(transformation(extent={{120,80},{160,120}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 + "Integer switch" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum1( + final k=fill(1, nBoi), + final nin=nBoi) if not primarySecondarySensors + "Weighted average of boiler supply temperatures" + annotation (Placement(transformation(extent={{80,-90},{100,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=twoReqLimLow, + final uHigh=twoReqLimHig) + "Hysteresis loop for sending two requests" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=oneReqLimLow, + final uHigh=oneReqLimHig) + "Hysteresis loop for sending one request" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Integer switch" + annotation (Placement(transformation(extent={{10,0},{30,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant integer source" + annotation (Placement(transformation(extent={{-30,20},{-10,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=0) + "Constant integer source" + annotation (Placement(transformation(extent={{-30,-20},{-10,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2( + final k=2) + "Constant integer source" + annotation (Placement(transformation(extent={{-30,60},{-10,80}}))); + + Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond triRes( + final iniSet=maxPumSpe, + final minSet=minPumSpe, + final maxSet=maxPumSpe, + final delTim=delTim, + final samplePeriod=samPer, + final numIgnReq=numIgnReq, + final triAmo=triAmo, + final resAmo=resAmo, + final maxRes=maxRes) + "Pump speed calculator" + annotation (Placement(transformation(extent={{80,40},{100,60}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nBoi] if not + primarySecondarySensors + "Boolean to Real converter" + annotation (Placement(transformation(extent={{-100,-60},{-80,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con[nBoi]( + final k=boiDesFlo) if not primarySecondarySensors + "Vector of boiler design flowrates" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[nBoi] if not + primarySecondarySensors + "Vector of design flowrates only for enabled boilers; Zero for disabled boilers" + annotation (Placement(transformation(extent={{-70,-70},{-50,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum( + final k=fill(1, nBoi), + final nin=nBoi) if not primarySecondarySensors + "Sum of flowrates of all enabled boilers" + annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Compare measured temperature in primary and secondary loops" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Check if any hot water primary pumps are enabled" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nBoi) if not primarySecondarySensors + "Real replicator" + annotation (Placement(transformation(extent={{20,-100},{40,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div[nBoi] if not primarySecondarySensors + "Calculate weights for average based on design flowrate" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[nBoi] if not primarySecondarySensors + "Calculate weighted boiler supply temperatures" + annotation (Placement(transformation(extent={{50,-90},{70,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) + if not primarySecondarySensors + "Pass non-zero divisor in case sum is zero" + annotation (Placement(transformation(extent={{-10,-100},{10,-80}}))); + +equation + connect(zer.y, swi.u3) + annotation (Line(points={{-38,80},{-34,80},{-34,92},{78,92}}, + color={0,0,127})); + + connect(swi.y,yHotWatPumSpe) + annotation (Line(points={{102,100},{140,100}}, color={0,0,127})); + + connect(uHotWatPum, mulOr.u[1:nPum]) annotation (Line(points={{-140,100},{-102, + 100}}, color={255,0,255})); + + connect(mulOr.y, swi.u2) annotation (Line(points={{-78,100},{78,100}}, + color={255,0,255})); + + connect(THotWatPri,sub2. u1) annotation (Line(points={{-140,50},{-114,50},{-114, + 36},{-102,36}}, color={0,0,127})); + + connect(THotWatSec,sub2. u2) annotation (Line(points={{-140,0},{-110,0},{-110, + 24},{-102,24}}, color={0,0,127})); + + connect(sub2.y, hys.u) annotation (Line(points={{-78,30},{-70,30},{-70,50},{-62, + 50}}, color={0,0,127})); + + connect(sub2.y, hys1.u) annotation (Line(points={{-78,30},{-70,30},{-70,10},{-62, + 10}}, color={0,0,127})); + + connect(hys1.y, intSwi.u2) + annotation (Line(points={{-38,10},{8,10}}, color={255,0,255})); + + connect(conInt.y, intSwi.u1) annotation (Line(points={{-8,30},{-4,30},{-4,18}, + {8,18}}, color={255,127,0})); + + connect(conInt1.y, intSwi.u3) annotation (Line(points={{-8,-10},{-4,-10},{-4,2}, + {8,2}}, color={255,127,0})); + + connect(hys.y, intSwi1.u2) + annotation (Line(points={{-38,50},{38,50}}, color={255,0,255})); + + connect(intSwi.y, intSwi1.u3) annotation (Line(points={{32,10},{36,10},{36,42}, + {38,42}}, color={255,127,0})); + + connect(conInt2.y, intSwi1.u1) annotation (Line(points={{-8,70},{36,70},{36,58}, + {38,58}}, color={255,127,0})); + + connect(intSwi1.y, triRes.numOfReq) annotation (Line(points={{62,50},{68,50},{ + 68,42},{78,42}}, color={255,127,0})); + + connect(mulOr.y, triRes.uDevSta) annotation (Line(points={{-78,100},{68,100},{ + 68,58},{78,58}}, color={255,0,255})); + + connect(triRes.y, swi.u1) annotation (Line(points={{102,50},{110,50},{110,80}, + {70,80},{70,108},{78,108}},color={0,0,127})); + + connect(uBoiSta, booToRea.u) + annotation (Line(points={{-140,-50},{-102,-50}}, color={255,0,255})); + + connect(booToRea.y, pro1.u1) annotation (Line(points={{-78,-50},{-74,-50},{-74, + -54},{-72,-54}}, color={0,0,127})); + + connect(con.y, pro1.u2) annotation (Line(points={{-78,-80},{-74,-80},{-74,-66}, + {-72,-66}}, color={0,0,127})); + + connect(reaRep.y, div.u2) annotation (Line(points={{42,-90},{44,-90},{44,-74}, + {16,-74},{16,-66},{18,-66}}, + color={0,0,127})); + + connect(pro1.y, div.u1) annotation (Line(points={{-48,-60},{-46,-60},{-46,-54}, + {18,-54}}, color={0,0,127})); + + connect(div.y, pro.u1) annotation (Line(points={{42,-60},{46,-60},{46,-74},{48, + -74}}, color={0,0,127})); + + connect(THotWatBoiSup, pro.u2) annotation (Line(points={{-140,-110},{46,-110}, + {46,-86},{48,-86}}, color={0,0,127})); + + connect(mulSum1.u[1:nBoi], pro.y) annotation (Line(points={{78,-80},{76,-80},{76, + -80},{72,-80}}, color={0,0,127})); + + connect(mulSum1.y,sub2. u1) annotation (Line(points={{102,-80},{110,-80},{110, + -30},{-114,-30},{-114,36},{-102,36}}, color={0,0,127})); + + connect(mulSum.y, addPar.u) + annotation (Line(points={{-18,-90},{-12,-90}}, color={0,0,127})); + connect(reaRep.u, addPar.y) + annotation (Line(points={{18,-90},{12,-90}}, color={0,0,127})); + connect(pro1.y, mulSum.u[1:nBoi]) annotation (Line(points={{-48,-60},{-46,-60}, + {-46,-90},{-42,-90}}, + color={0,0,127})); + +annotation ( + defaultComponentName="hotPumSpe", + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-120,-120},{120,120}})), +Documentation(info=" +

+Block that outputs hot water pump speed setpoint for primary-secondary plants with +variable-speed primary pumps where the temperature sensors are present in the primary +and secondary loops, or in the secondary loop and at the boiler supply, according +to ASHRAE RP-1711, March, 2020 draft, sections 5.3.6.14, 5.3.6.15 and 5.3.6.16. +

+

+When any hot water pump is proven on, uHotWatPum = true, +pump speed will be controlled by a Trim-and-Respond logic controller. The number +of requests to the controller is calculated as follows: +

+ +

+When there is no single temperature sensor in the primary loop and instead there +are temperature sensors at each boiler supply outlet THotWatBoiSup, +primarySecondarySensors = false, the primary loop temperature is +calculated as the weighted average of THotWatBoiSup, weighted by the +boiler design flowrates boiDesFlo of the enabled boilers +uBoiSta. +

+", revisions=" + +")); +end Speed_temperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_dedicated.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_dedicated.mo new file mode 100644 index 00000000000..2480332f5f7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_dedicated.mo @@ -0,0 +1,54 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Validation; +model EnableLead_dedicated + "Validate sequence for enabling lead pump of plants with dedicated primary hot water pumps" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.EnableLead_dedicated + enaLeaPriPum + "Enable and disable lead hot water primary pump" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=3600, + final shift=300) + "Boolean pulse source" + annotation (Placement(transformation(extent={{-50,-10},{-30,10}}))); + +equation + connect(booPul.y,enaLeaPriPum. uPlaEna) annotation (Line(points={{-28,0},{20,0}, + {20,5},{38,5}}, color={255,0,255})); + + connect(booPul.y,enaLeaPriPum.uLeaBoiSta) + annotation (Line(points={{-28,0},{20,0},{20,-5},{38,-5}}, color={255,0,255})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_dedicated.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.EnableLead_dedicated. +

+", 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/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_headered.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_headered.mo new file mode 100644 index 00000000000..ae3d5bc66b8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_headered.mo @@ -0,0 +1,59 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Validation; +model EnableLead_headered + "Validate sequence for enabling lead pump of plants with headered primary hot water pumps" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.EnableLead_headered + enaLeaPriPum( + final nBoi=2) + "Enable lead hot water pump based on the status of hot water isolation valves" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final period=600, + final shift=300) + "Real pulse signal" + annotation (Placement(transformation(extent={{-50,20},{-30,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul1( + final period=1000, + final shift=500) + "Real pulse signal" + annotation (Placement(transformation(extent={{-50,-40},{-30,-20}}))); + +equation + connect(pul.y, enaLeaPriPum.uHotWatIsoVal[1]) annotation (Line(points={{-28,30}, + {-16,30},{-16,-1},{-2,-1}}, color={0,0,127})); + connect(pul1.y, enaLeaPriPum.uHotWatIsoVal[2]) annotation (Line(points={{-28,-30}, + {-16,-30},{-16,1},{-2,1}}, color={0,0,127})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/EnableLead_headered.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.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/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_flow.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_flow.mo new file mode 100644 index 00000000000..47b437fb9fc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_flow.mo @@ -0,0 +1,91 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Validation; +model Speed_flow + "Validate sequence of controlling hot water pump speed for primary-secondary plants with flowrate sensors" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_flow + hotPumSpe( + final primarySecondarySensors=true, + final nPum=2, + final VHotWat_flow_nominal=0.5) + "Scenario testing speed control using flowrate sensors in primary and secondary circuits" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_flow + hotPumSpe1( + final primarySecondarySensors=false, + final nPum=2, + final VHotWat_flow_nominal=0.5) + "Scenario testing speed control using flowrate sensor in decoupler" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumSta[2]( + final width=fill(0.95, 2), + final period=fill(10, 2), + final shift=fill(1, 2)) + "Pump status" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant secFloSen( + final k=8.5) + "Flowrate sensor reading from secondary circuit" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine priFloSen( + final offset=8.5, + final freqHz=1/10, + final amplitude=1.5) + "Flowrate sensor reading from primary circuit" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine decFloSen( + final offset=0, + final freqHz=1/10, + final amplitude=0.5) + "Flowrate sensor reading from decoupler" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + +equation + connect(pumSta.y, hotPumSpe.uHotWatPum) annotation (Line(points={{-58,40},{-50, + 40},{-50,5},{-42,5}}, color={255,0,255})); + connect(priFloSen.y, hotPumSpe.VHotWatPri_flow) + annotation (Line(points={{-58,0},{-42,0}}, color={0,0,127})); + connect(secFloSen.y, hotPumSpe.VHotWatSec_flow) annotation (Line(points={{-58, + -40},{-50,-40},{-50,-5},{-42,-5}}, color={0,0,127})); + connect(pumSta.y, hotPumSpe1.uHotWatPum) annotation (Line(points={{-58,40},{30, + 40},{30,5},{38,5}}, color={255,0,255})); + connect(decFloSen.y, hotPumSpe1.VHotWatDec_flow) + annotation (Line(points={{22,-40},{30,-40},{30,-5},{38,-5}}, + color={0,0,127})); + +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_flow.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_flow. +

+", 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_flow; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_temperature.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_temperature.mo new file mode 100644 index 00000000000..4ade05c7d3b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_temperature.mo @@ -0,0 +1,118 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Validation; +model Speed_temperature + "Validate sequence of controlling hot water pump speed for primary-secondary plants with temperature sensors" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_temperature + hotPumSpe( + final primarySecondarySensors=true, + final nBoi=2, + final nPum=2, + final boiDesFlo={0.25,0.5}, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1) + "Testing controller for plant with temperature sensors in primary and secondary loops" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_temperature + hotPumSpe1( + final primarySecondarySensors=false, + final nBoi=2, + final nPum=2, + final boiDesFlo={0.25,0.5}, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1) + "Testing controller for plant with temperature sensors in secondary loop and boiler supply terminals" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumSta[2]( + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(1, 2)) + "Pump status" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TSecSup( + final k=8.5) + "Temperature sensor reading from secondary circuit" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine TPriSup( + phase=3.1415926535898, + final offset=8.5, + final freqHz=1/3600, + final amplitude=2.5) + "Temperature sensor reading from primary circuit" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine TBoiSup2( + phase=3.1415926535898, + final offset=8, + final freqHz=1/3600, + final amplitude=2.5) + "Flowrate sensor reading from decoupler" + annotation (Placement(transformation(extent={{-10,-70},{10,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pumSta1( + final width=0.5, + final period=1800, + final shift=1) + "Pump status" + annotation (Placement(transformation(extent={{-10,50},{10,70}}))); + +equation + + connect(pumSta.y, hotPumSpe.uHotWatPum) annotation (Line(points={{-58,40},{-50, + 40},{-50,8},{-42,8}}, color={255,0,255})); + connect(TPriSup.y, hotPumSpe.THotWatPri) annotation (Line(points={{-58,0},{-50, + 0},{-50,4},{-42,4}}, color={0,0,127})); + connect(TSecSup.y, hotPumSpe.THotWatSec) annotation (Line(points={{-58,-40},{-46, + -40},{-46,0},{-42,0}}, color={0,0,127})); + connect(TSecSup.y, hotPumSpe1.THotWatSec) annotation (Line(points={{-58,-40},{ + 30,-40},{30,0},{38,0}}, color={0,0,127})); + connect(pumSta.y, hotPumSpe1.uHotWatPum) annotation (Line(points={{-58,40},{28, + 40},{28,8},{38,8}}, color={255,0,255})); + connect(TPriSup.y, hotPumSpe1.THotWatBoiSup[1]) annotation (Line(points={{-58, + 0},{-50,0},{-50,-18},{34,-18},{34,-9},{38,-9}}, color={0,0,127})); + connect(TBoiSup2.y, hotPumSpe1.THotWatBoiSup[2]) annotation (Line(points={{12,-60}, + {36,-60},{36,-6},{38,-6},{38,-7}}, color={0,0,127})); + connect(pumSta[1].y, hotPumSpe1.uBoiSta[1]) annotation (Line(points={{-58,40}, + {28,40},{28,-4},{38,-4},{38,-5}}, color={255,0,255})); + connect(pumSta1.y, hotPumSpe1.uBoiSta[2]) annotation (Line(points={{12,60},{34, + 60},{34,-3},{38,-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/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/Speed_temperature.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Subsequences.Speed_temperature. +

+", 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_temperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..666c3fbd2b5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.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.BoilerPlant.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/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/package.order new file mode 100644 index 00000000000..0c35857da5a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/Validation/package.order @@ -0,0 +1,4 @@ +EnableLead_dedicated +EnableLead_headered +Speed_flow +Speed_temperature diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/package.mo new file mode 100644 index 00000000000..aea474b5233 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/package.mo @@ -0,0 +1,44 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps; +package Subsequences "Hot water pump control sequences" + + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for hot 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/BoilerPlant/Pumps/PrimaryPumps/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/package.order new file mode 100644 index 00000000000..b8b0f47c26c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Subsequences/package.order @@ -0,0 +1,5 @@ +EnableLead_dedicated +EnableLead_headered +Speed_flow +Speed_temperature +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/Controller.mo new file mode 100644 index 00000000000..cd99be3d9b0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/Controller.mo @@ -0,0 +1,2248 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Validation; +model Controller + "Validate boiler water pump control sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon( + final have_heaPriPum=true, + final have_priOnl=true, + final have_varPriPum=true, + final nPum=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=5*6894.75, + final minLocDp=5*6894.75, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=10, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP) + "Testing pump configuration 1" + annotation (Placement(transformation(extent={{-170,372},{-150,428}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon1( + final have_heaPriPum=true, + final have_priOnl=true, + final have_varPriPum=true, + final nPum=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP) + "Testing pump configuration 2" + annotation (Placement(transformation(extent={{190,362},{210,418}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon2( + final have_heaPriPum=true, + final have_priOnl=false, + final have_varPriPum=true, + final nPum=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate) + "Testing pump configuration 3" + annotation (Placement(transformation(extent={{-170,222},{-150,278}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon3( + final have_heaPriPum=true, + final have_priOnl=false, + final have_varPriPum=true, + final have_secFloSen=false, + final nPum=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate) + "Testing pump configuration 4" + annotation (Placement(transformation(extent={{190,202},{210,258}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon4( + final have_heaPriPum=true, + final have_priOnl=false, + final have_varPriPum=true, + final have_priSecTemSen=true, + final nPum=2, + final nBoi=2, + final nSen=2, + final numIgnReq=0, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final delTim=900, + final samPer=120, + final triAmo=-0.02, + final resAmo=0.03, + final maxRes=0.06, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Testing pump configuration 5" + annotation (Placement(transformation(extent={{-170,62},{-150,118}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon5( + final have_heaPriPum=true, + final have_priOnl=false, + final have_varPriPum=true, + final have_priSecTemSen=false, + final nPum=2, + final nBoi=2, + final nSen=2, + final numIgnReq=0, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final delTim=900, + final samPer=120, + final triAmo=-0.02, + final resAmo=0.03, + final maxRes=0.06, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Testing pump configuration 6" + annotation (Placement(transformation(extent={{190,42},{210,98}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon6( + final have_heaPriPum=true, + final have_priOnl=false, + final have_varPriPum=false, + final have_priSecTemSen=false, + final nPum=2, + final nBoi=2, + final nSen=2, + final numIgnReq=0, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final delTim=900, + final samPer=120, + final triAmo=-0.02, + final resAmo=0.03, + final maxRes=0.06, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Testing pump configuration 7" + annotation (Placement(transformation(extent={{-180,-118},{-160,-62}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon7( + final have_heaPriPum=false, + final have_priOnl=false, + final have_varPriPum=true, + final nPum=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate) + "Testing pump configuration 8" + annotation (Placement(transformation(extent={{210,-138},{230,-82}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon8( + final have_heaPriPum=false, + final have_priOnl=false, + final have_varPriPum=true, + final have_secFloSen=false, + final nPum=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate) + "Testing pump configuration 9" + annotation (Placement(transformation(extent={{-180,-298},{-160,-242}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon9( + final have_heaPriPum=false, + final have_priOnl=false, + final have_varPriPum=true, + final have_priSecTemSen=true, + final nPum=2, + final nBoi=2, + final nSen=2, + final numIgnReq=0, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final delTim=900, + final samPer=120, + final triAmo=-0.02, + final resAmo=0.03, + final maxRes=0.06, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Testing pump configuration 10" + annotation (Placement(transformation(extent={{210,-308},{230,-252}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon10( + final have_heaPriPum=false, + final have_priOnl=false, + final have_varPriPum=true, + final have_priSecTemSen=false, + final nPum=2, + final nBoi=2, + final nSen=2, + final numIgnReq=0, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final delTim=900, + final samPer=120, + final triAmo=-0.02, + final resAmo=0.03, + final maxRes=0.06, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Testing pump configuration 11" + annotation (Placement(transformation(extent={{-170,-458},{-150,-402}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.Controller + priPumCon11( + final have_heaPriPum=false, + final have_priOnl=false, + final have_varPriPum=false, + final have_priSecTemSen=false, + final nPum=2, + final nBoi=2, + final nSen=2, + final numIgnReq=0, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final boiDesFlo={0.5,0.5}, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final delTim=900, + final samPer=120, + final triAmo=-0.02, + final resAmo=0.03, + final maxRes=0.06, + final twoReqLimLow=1.2, + final twoReqLimHig=2, + final oneReqLimLow=0.2, + final oneReqLimHig=1, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.temperature) + "Testing pump configuration 12" + annotation (Placement(transformation(extent={{190,-488},{210,-432}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{-50,210},{-30,230}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{280,190},{300,210}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{-38,80},{-18,100}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol3( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{300,60},{320,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol4( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol5( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{320,-110},{340,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol6( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{-60,-280},{-40,-260}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol7( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{322,-290},{342,-270}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol8( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{-60,-440},{-40,-420}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol9( + final trueHoldDuration=10, + final falseHoldDuration=0) + "True-hold for signal visualization" + annotation (Placement(transformation(extent={{308,-450},{328,-430}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel6[2]( + final delayTime=fill(30, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{224,220},{244,240}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel7[2]( + final delayTime=fill(30, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{-140,80},{-120,100}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel8[2]( + final delayTime=fill(30, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{216,64},{236,84}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel9[2]( + final delayTime=fill(30, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{-152,-100},{-132,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel10[2]( + final delayTime=fill(5, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{236,-116},{256,-96}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel11[2]( + delayTime=fill(5, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{-152,-278},{-132,-258}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel12[2]( + final delayTime=fill(5, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{236,-286},{256,-266}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel13[2]( + final delayTime=fill(5, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{-144,-434},{-124,-414}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel14[2]( + final delayTime=fill(5, 2)) + "True delay to simulate pump proven on process" + annotation (Placement(transformation(extent={{218,-466},{238,-446}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol10( + final trueHoldDuration=3300, + final falseHoldDuration=0) + "Hold boiler on signal" + annotation (Placement(transformation(extent={{130,-110},{150,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol11( + final trueHoldDuration=3300, + final falseHoldDuration=0) + "Hold boiler on signal" + annotation (Placement(transformation(extent={{-260,-270},{-240,-250}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{-110,210},{-90,230}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{-78,210},{-58,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha6[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{220,190},{240,210}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{250,190},{270,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha7[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{-98,60},{-78,80}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr2( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{-68,60},{-48,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha8[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{240,60},{260,80}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr3( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{270,60},{290,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha9[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{-120,-100},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr4( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{-90,-100},{-70,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha10[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{260,-110},{280,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr5( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{290,-110},{310,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha11[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{-120,-280},{-100,-260}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr6( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{-90,-280},{-70,-260}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha22[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{262,-290},{282,-270}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr7( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{292,-290},{312,-270}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha23[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{-120,-440},{-100,-420}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr8( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{-90,-440},{-70,-420}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha24[2] + "Detect changes in pump status" + annotation (Placement(transformation(extent={{248,-450},{268,-430}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr9( + final nin=2) + "Multi Or" + annotation (Placement(transformation(extent={{278,-450},{298,-430}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel5[2]( + final delayTime=fill(1, 2)) + "True delay to represent pump turning on" + annotation (Placement(transformation(extent={{-140,240},{-120,260}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Integer switch" + annotation (Placement(transformation(extent={{280,-186},{300,-166}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 + "Integer switch" + annotation (Placement(transformation(extent={{-120,-340},{-100,-320}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 + "Integer switch" + annotation (Placement(transformation(extent={{280,-350},{300,-330}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi3 + "Integer switch" + annotation (Placement(transformation(extent={{-100,-500},{-80,-480}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi4 + "Integer switch" + annotation (Placement(transformation(extent={{260,-530},{280,-510}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=10) + "Signal delay for boiler-2 enable" + annotation (Placement(transformation(extent={{130,-150},{150,-130}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-220,440},{-200,460}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-130,390},{-110,410}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin[2]( + final amplitude=fill(0.5, 2), + final freqHz=fill(1/900, 2), + final phase=fill(0, 2), + final offset=fill(1, 2), + final startTime=fill(0, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{-220,360},{-200,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-270,390},{-250,410}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{140,430},{160,450}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{230,380},{250,400}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin2[2]( + final amplitude=fill(0.5, 2), + final freqHz=fill(1/900, 2), + final phase=fill(0, 2), + final offset=fill(1, 2), + final startTime=fill(0, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{146,348},{166,368}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin3( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{80,350},{100,370}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin4( + final amplitude=5, + final freqHz=1/450, + final offset=7.5) + "Sine signal" + annotation (Placement(transformation(extent={{150,310},{170,330}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-220,290},{-200,310}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-110,240},{-90,260}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con8( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{-310,190},{-290,210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin5( + final amplitude=0.1, + final freqHz=1/900, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-214,208},{-194,228}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin6( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-280,210},{-260,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final period=1800, + final shift=15) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-280,170},{-260,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con9( + final k=true) + "Boolean true source" + annotation (Placement(transformation(extent={{-250,210},{-230,230}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{140,270},{160,290}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre4[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{260,220},{280,240}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con12( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{50,170},{70,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin7( + final amplitude=0.1, + final freqHz=1/900, + final offset=0) + "Sine signal" + annotation (Placement(transformation(extent={{140,188},{160,208}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin8( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0) + "Sine signal" + annotation (Placement(transformation(extent={{80,190},{100,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3( + final period=1800, + final shift=60) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con13( + final k=true) + "Boolean true source" + annotation (Placement(transformation(extent={{110,190},{130,210}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-220,130},{-200,150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre5[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-98,100},{-78,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con16( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{-310,30},{-290,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin9( + final amplitude=1.5, + final freqHz=1/3600, + final phase=3.1415926535898, + final offset=1) + "Sine signal" + annotation (Placement(transformation(extent={{-214,48},{-194,68}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin10( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-280,50},{-260,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul5( + final period=1800, + final shift=60) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-280,10},{-260,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con17( + final k=true) + "Boolean true source" + annotation (Placement(transformation(extent={{-250,50},{-230,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con18( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{-310,-10},{-290,10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{140,110},{160,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre6[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{240,90},{260,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con21( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{50,10},{70,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin11[2]( + final amplitude=fill(1.5, 2), + final freqHz=fill(1/3600, 2), + final phase=fill(3.14, 2), + final offset=fill(1, 2), + final startTime=fill(0, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{150,30},{170,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin12( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul7( + final period=1800, + final shift=60) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con22( + final k=true) + "Boolean true source" + annotation (Placement(transformation(extent={{110,30},{130,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con23( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{50,-30},{70,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt6[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-230,-50},{-210,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre7[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin14( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-290,-130},{-270,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul9( + final period=1800, + final shift=60) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-290,-170},{-270,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con27( + final k=true) + "Boolean true source" + annotation (Placement(transformation(extent={{-260,-130},{-240,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7( + final k=2) + "Pump rotation index" + annotation (Placement(transformation(extent={{240,-170},{260,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre8[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{260,-80},{280,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con29( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{70,-170},{90,-150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin13( + final amplitude=0.5, + final freqHz=1/900, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{166,-152},{186,-132}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin15( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{100,-150},{120,-130}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul11( + final period=1800, + final shift=10) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{100,-190},{120,-170}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt8( + final k=2) + "Pump rotation index" + annotation (Placement(transformation(extent={{-160,-328},{-140,-308}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre9[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-120,-250},{-100,-230}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con32( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{-320,-330},{-300,-310}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin16( + final amplitude=0.5, + final freqHz=1/900, + final offset=0) + "Sine signal" + annotation (Placement(transformation(extent={{-230,-312},{-210,-292}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin17( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-290,-310},{-270,-290}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul13( + final period=1800, + final shift=10) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-290,-350},{-270,-330}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt9( + final k=2) + "Pump rotation index" + annotation (Placement(transformation(extent={{240,-338},{260,-318}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre10[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{254,-250},{274,-230}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con35( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{70,-340},{90,-320}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin18( + final amplitude=1.5, + final freqHz=1/3600, + final phase(displayUnit="deg") = 3.1415926535898, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{166,-322},{186,-302}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin19( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{100,-320},{120,-300}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul15( + final period=1800, + final shift=10) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{100,-360},{120,-340}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con37( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{70,-380},{90,-360}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt10( + final k=2) + "Pump rotation index" + annotation (Placement(transformation(extent={{-140,-488},{-120,-468}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre11[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-120,-410},{-100,-390}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con39( + final k=0.25) + "Constant Real source" + annotation (Placement(transformation(extent={{-310,-490},{-290,-470}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin20[2]( + final amplitude=fill(1.5, 2), + final freqHz=fill(1/3600, 2), + final phase=fill(3.14, 2), + final offset=fill(1, 2), + final startTime=fill(0, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{-214,-472},{-194,-452}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin21( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-280,-470},{-260,-450}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul17( + final period=1800, + final shift=10) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-280,-510},{-260,-490}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con41( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{-310,-530},{-290,-510}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt11( + final k=2) + "Pump rotation index" + annotation (Placement(transformation(extent={{220,-518},{240,-498}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre12[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{248,-420},{268,-400}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin22( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{80,-500},{100,-480}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul19( + final period=1800, + final shift=10) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{80,-540},{100,-520}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha12 + "Change detector" + annotation (Placement(transformation(extent={{-220,170},{-200,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha13 + "Change detector" + annotation (Placement(transformation(extent={{140,150},{160,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha14 + "Change detector" + annotation (Placement(transformation(extent={{-220,10},{-200,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha15 + "Change detector" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha16 + "Change detector" + annotation (Placement(transformation(extent={{-230,-170},{-210,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha17 + "Change detector" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha18 + "Change detector" + annotation (Placement(transformation(extent={{-260,-240},{-240,-220}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha19 + "Change detector" + annotation (Placement(transformation(extent={{130,-220},{150,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha20 + "Change detector" + annotation (Placement(transformation(extent={{-250,-380},{-230,-360}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha21 + "Change detector" + annotation (Placement(transformation(extent={{110,-400},{130,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Edge detector" + annotation (Placement(transformation(extent={{180,-360},{200,-340}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg2 + "Edge detector" + annotation (Placement(transformation(extent={{-210,-350},{-190,-330}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg3 + "Edge detector" + annotation (Placement(transformation(extent={{-210,-510},{-190,-490}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg4 + "Edge detector" + annotation (Placement(transformation(extent={{160,-540},{180,-520}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{-336,408},{-316,428}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{-270,360},{-250,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul1[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{0,400},{20,420}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{80,380},{100,400}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul2[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{-330,260},{-310,280}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul3[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{10,240},{30,260}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul4[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{-330,100},{-310,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul5[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{20,80},{40,100}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul6[2]( + final amplitude=fill(1, 2), + final width=fill(0.95, 2), + final period=fill(3600, 2), + final shift=fill(10, 2)) + "Real pulse signal" + annotation (Placement(transformation(extent={{-328,-80},{-308,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Logical Or" + annotation (Placement(transformation(extent={{170,-80},{190,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Logical Or" + annotation (Placement(transformation(extent={{-230,-220},{-210,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol12( + final trueHoldDuration=3300, + final falseHoldDuration=0) + "Hold boiler on signal" + annotation (Placement(transformation(extent={{130,-280},{150,-260}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or3 + "Logical Or" + annotation (Placement(transformation(extent={{170,-250},{190,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol13( + final trueHoldDuration=3300, + final falseHoldDuration=0) + "Hold boiler on signal" + annotation (Placement(transformation(extent={{-250,-430},{-230,-410}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or4 + "Logical Or" + annotation (Placement(transformation(extent={{-210,-400},{-190,-380}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol14( + final trueHoldDuration=3300, + final falseHoldDuration=0) + "Hold boiler on signal" + annotation (Placement(transformation(extent={{110,-460},{130,-440}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or5 + "Logical Or" + annotation (Placement(transformation(extent={{150,-430},{170,-410}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{-300,440},{-280,460}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{-260,440},{-240,460}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum1( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{30,440},{50,460}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr1( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{70,440},{90,460}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum2( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{-300,300},{-280,320}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr2( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{-270,300},{-250,320}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum3( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{50,280},{70,300}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr3( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{80,280},{100,300}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum4( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{-300,140},{-280,160}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr4( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{-270,140},{-250,160}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum5( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{60,120},{80,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr5( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{90,120},{110,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum6( + final nin=2) + "Sum of isolation valve positions" + annotation (Placement(transformation(extent={{-300,-40},{-280,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold lesThr6( + final t=0.05) + "Check if isolation valves are closed" + annotation (Placement(transformation(extent={{-270,-40},{-250,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt12( + final k=1) + "Pump rotation index" + annotation (Placement(transformation(extent={{240,-200},{260,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt13( + final k=1) + "Pump rotation index" + annotation (Placement(transformation(extent={{-160,-360},{-140,-340}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt14( + final k=1) + "Pump rotation index" + annotation (Placement(transformation(extent={{240,-370},{260,-350}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt15( + final k=1) + "Pump rotation index" + annotation (Placement(transformation(extent={{-140,-520},{-120,-500}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt16( + final k=1) + "Pump rotation index" + annotation (Placement(transformation(extent={{220,-550},{240,-530}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha1 + "Change detector" + annotation (Placement(transformation(extent={{120,-80},{140,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=10) + "Signal delay for boiler-2 enable" + annotation (Placement(transformation(extent={{-258,-314},{-238,-294}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha2 + "Change detector" + annotation (Placement(transformation(extent={{-260,-210},{-240,-190}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2( + final delayTime=10) + "Signal delay for boiler-2 enable" + annotation (Placement(transformation(extent={{130,-320},{150,-300}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha3 + "Change detector" + annotation (Placement(transformation(extent={{130,-254},{150,-234}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel3( + final delayTime=10) + "Signal delay for boiler-2 enable" + annotation (Placement(transformation(extent={{-250,-470},{-230,-450}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha4 + "Change detector" + annotation (Placement(transformation(extent={{-250,-404},{-230,-384}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel4( + final delayTime=10) + "Signal delay for boiler-2 enable" + annotation (Placement(transformation(extent={{120,-540},{140,-520}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha5 + "Change detector" + annotation (Placement(transformation(extent={{110,-430},{130,-410}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre13 "Logical pre block" + annotation (Placement(transformation(extent={{112,150},{132,170}}))); + +equation + connect(conInt.y, priPumCon.uPumLeaLag) annotation (Line(points={{-198,450},{ + -180,450},{-180,427.067},{-172,427.067}}, + color={255,127,0})); + + connect(priPumCon.yHotWatPum, pre1.u) + annotation (Line(points={{-148,403.733},{-140,403.733},{-140,400},{-132,400}}, + color={255,0,255})); + + connect(sin1.y, priPumCon.VHotWat_flow) annotation (Line(points={{-248,400},{ + -194,400},{-194,415.867},{-172,415.867}}, color={0,0,127})); + + connect(sin.y, priPumCon.dpHotWat_remote) annotation (Line(points={{-198,370}, + {-186,370},{-186,392.533},{-172,392.533}}, + color={0,0,127})); + + connect(conInt1.y, priPumCon1.uPumLeaLag) annotation (Line(points={{162,440}, + {180,440},{180,417.067},{188,417.067}}, + color={255,127,0})); + + connect(priPumCon1.yHotWatPum, pre2.u) + annotation (Line(points={{212,393.733},{220,393.733},{220,390},{228,390}}, + color={255,0,255})); + + connect(sin3.y, priPumCon1.VHotWat_flow) annotation (Line(points={{102,360},{ + 142,360},{142,394},{166,394},{166,405.867},{188,405.867}}, + color={0,0,127})); + + connect(sin2.y, priPumCon1.dpHotWat_remote) annotation (Line(points={{168,358}, + {174,358},{174,382.533},{188,382.533}}, + color={0,0,127})); + + connect(sin4.y, priPumCon1.dpHotWat_local) annotation (Line(points={{172,320}, + {184,320},{184,385.333},{188,385.333}}, + color={0,0,127})); + + connect(conInt2.y,priPumCon2. uPumLeaLag) annotation (Line(points={{-198,300}, + {-180,300},{-180,277.067},{-172,277.067}}, + color={255,127,0})); + + connect(con8.y,priPumCon2. uMinPriPumSpeCon) annotation (Line(points={{-288, + 200},{-180,200},{-180,236.933},{-172,236.933}}, + color={0,0,127})); + + connect(sin6.y,priPumCon2. VHotWat_flow) annotation (Line(points={{-258,220}, + {-256,220},{-256,238},{-218,238},{-218,254},{-194,254},{-194,265.867}, + {-172,265.867}}, color={0,0,127})); + + connect(sin5.y, priPumCon2.VHotWatSec_flow) annotation (Line(points={{-192, + 218},{-184,218},{-184,234.133},{-172,234.133}}, + color={0,0,127})); + + connect(booPul1.y, priPumCon2.uStaUp) annotation (Line(points={{-258,180},{ + -254,180},{-254,248},{-180,248},{-180,260.267},{-172,260.267}}, + color={255,0,255})); + + connect(booPul1.y, priPumCon2.uOnOff) annotation (Line(points={{-258,180},{ + -254,180},{-254,248},{-180,248},{-180,257.467},{-172,257.467}}, + color={255,0,255})); + + connect(booPul1.y, priPumCon2.uBoiSta[2]) annotation (Line(points={{-258,180}, + {-254,180},{-254,248},{-180,248},{-180,264},{-172,264}}, color={255,0, + 255})); + + connect(con9.y, priPumCon2.uBoiSta[1]) annotation (Line(points={{-228,220},{ + -226,220},{-226,244},{-188,244},{-188,262.133},{-172,262.133}}, + color={255,0,255})); + + connect(conInt3.y,priPumCon3. uPumLeaLag) annotation (Line(points={{162,280}, + {180,280},{180,257.067},{188,257.067}}, + color={255,127,0})); + + connect(con12.y, priPumCon3.uMinPriPumSpeCon) annotation (Line(points={{72,180}, + {180,180},{180,216.933},{188,216.933}}, + color={0,0,127})); + + connect(sin8.y,priPumCon3. VHotWat_flow) annotation (Line(points={{102,200},{ + 104,200},{104,218},{142,218},{142,234},{166,234},{166,245.867},{188, + 245.867}}, color={0,0,127})); + + connect(booPul3.y, priPumCon3.uStaUp) annotation (Line(points={{102,160},{106, + 160},{106,228},{180,228},{180,240.267},{188,240.267}}, + color={255,0,255})); + + connect(booPul3.y, priPumCon3.uOnOff) annotation (Line(points={{102,160},{106, + 160},{106,228},{180,228},{180,237.467},{188,237.467}}, + color={255,0,255})); + + connect(booPul3.y, priPumCon3.uBoiSta[2]) annotation (Line(points={{102,160},{ + 106,160},{106,228},{180,228},{180,244},{188,244}}, color={255,0,255})); + + connect(con13.y, priPumCon3.uBoiSta[1]) annotation (Line(points={{132,200},{ + 134,200},{134,224},{172,224},{172,242.133},{188,242.133}}, + color={255,0,255})); + + connect(sin7.y, priPumCon3.VHotWatDec_flow) annotation (Line(points={{162,198}, + {176,198},{176,211.333},{188,211.333}}, + color={0,0,127})); + + connect(conInt4.y,priPumCon4. uPumLeaLag) annotation (Line(points={{-198,140}, + {-180,140},{-180,117.067},{-172,117.067}}, + color={255,127,0})); + + connect(con16.y, priPumCon4.uMinPriPumSpeCon) annotation (Line(points={{-288,40}, + {-180,40},{-180,76.9333},{-172,76.9333}}, + color={0,0,127})); + + connect(sin10.y, priPumCon4.VHotWat_flow) annotation (Line(points={{-258,60}, + {-256,60},{-256,78},{-218,78},{-218,94},{-194,94},{-194,105.867},{ + -172,105.867}}, + color={0,0,127})); + + connect(booPul5.y, priPumCon4.uStaUp) annotation (Line(points={{-258,20},{ + -254,20},{-254,88},{-180,88},{-180,100.267},{-172,100.267}}, + color={255,0,255})); + + connect(booPul5.y, priPumCon4.uOnOff) annotation (Line(points={{-258,20},{ + -254,20},{-254,88},{-180,88},{-180,97.4667},{-172,97.4667}}, + color={255,0,255})); + + connect(booPul5.y, priPumCon4.uBoiSta[2]) annotation (Line(points={{-258,20},{ + -254,20},{-254,88},{-180,88},{-180,104},{-172,104}}, color={255,0,255})); + + connect(con17.y, priPumCon4.uBoiSta[1]) annotation (Line(points={{-228,60},{ + -226,60},{-226,84},{-188,84},{-188,102.133},{-172,102.133}}, + color={255,0,255})); + + connect(sin9.y, priPumCon4.THotWatPri) annotation (Line(points={{-192,58},{ + -182,58},{-182,68.5333},{-172,68.5333}}, + color={0,0,127})); + + connect(con18.y, priPumCon4.THotWatSec) annotation (Line(points={{-288,0},{ + -224,0},{-224,38},{-176,38},{-176,65.7333},{-172,65.7333}}, + color={0,0,127})); + + connect(conInt5.y,priPumCon5. uPumLeaLag) annotation (Line(points={{162,120}, + {180,120},{180,97.0667},{188,97.0667}}, + color={255,127,0})); + + connect(con21.y, priPumCon5.uMinPriPumSpeCon) annotation (Line(points={{72,20}, + {180,20},{180,56.9333},{188,56.9333}}, + color={0,0,127})); + + connect(sin12.y, priPumCon5.VHotWat_flow) annotation (Line(points={{102,40},{ + 104,40},{104,58},{142,58},{142,74},{166,74},{166,85.8667},{188, + 85.8667}}, color={0,0, + 127})); + + connect(booPul7.y, priPumCon5.uStaUp) annotation (Line(points={{102,0},{106,0}, + {106,68},{180,68},{180,80.2667},{188,80.2667}}, + color={255,0,255})); + + connect(booPul7.y, priPumCon5.uOnOff) annotation (Line(points={{102,0},{106,0}, + {106,68},{180,68},{180,77.4667},{188,77.4667}}, + color={255,0,255})); + + connect(booPul7.y, priPumCon5.uBoiSta[2]) annotation (Line(points={{102,0},{106, + 0},{106,68},{180,68},{180,84},{188,84}}, color={255,0,255})); + + connect(con22.y, priPumCon5.uBoiSta[1]) annotation (Line(points={{132,40},{ + 134,40},{134,64},{172,64},{172,82.1333},{188,82.1333}}, + color={255,0,255})); + + connect(sin11.y, priPumCon5.THotWatBoiSup) annotation (Line(points={{172,40}, + {178,40},{178,42.9333},{188,42.9333}}, + color={0,0,127})); + + connect(con23.y, priPumCon5.THotWatSec) annotation (Line(points={{72,-20},{ + 136,-20},{136,18},{184,18},{184,45.7333},{188,45.7333}}, + color={0,0,127})); + + connect(conInt6.y,priPumCon6. uPumLeaLag) annotation (Line(points={{-208,-40}, + {-190,-40},{-190,-62.9333},{-182,-62.9333}}, + color={255,127,0})); + + connect(sin14.y, priPumCon6.VHotWat_flow) annotation (Line(points={{-268,-120}, + {-266,-120},{-266,-102},{-228,-102},{-228,-86},{-204,-86},{-204, + -74.1333},{-182,-74.1333}}, + color={0,0,127})); + + connect(booPul9.y, priPumCon6.uStaUp) annotation (Line(points={{-268,-160},{ + -264,-160},{-264,-92},{-190,-92},{-190,-79.7333},{-182,-79.7333}}, + color={255,0,255})); + + connect(booPul9.y, priPumCon6.uOnOff) annotation (Line(points={{-268,-160},{ + -264,-160},{-264,-92},{-190,-92},{-190,-82.5333},{-182,-82.5333}}, + color={255,0,255})); + + connect(booPul9.y, priPumCon6.uBoiSta[2]) annotation (Line(points={{-268,-160}, + {-264,-160},{-264,-92},{-190,-92},{-190,-76},{-182,-76}}, color={255,0, + 255})); + + connect(con27.y, priPumCon6.uBoiSta[1]) annotation (Line(points={{-238,-120}, + {-236,-120},{-236,-96},{-198,-96},{-198,-77.8667},{-182,-77.8667}}, + color={255,0, + 255})); + + connect(con29.y, priPumCon7.uMinPriPumSpeCon) annotation (Line(points={{92,-160}, + {200,-160},{200,-123.067},{208,-123.067}}, + color={0,0,127})); + + connect(sin15.y, priPumCon7.VHotWat_flow) annotation (Line(points={{122,-140}, + {124,-140},{124,-122},{160,-122},{160,-106},{186,-106},{186,-94.1333}, + {208,-94.1333}}, + color={0,0,127})); + + connect(sin13.y, priPumCon7.VHotWatSec_flow) annotation (Line(points={{188, + -142},{198,-142},{198,-125.867},{208,-125.867}}, + color={0,0,127})); + + connect(con32.y, priPumCon8.uMinPriPumSpeCon) annotation (Line(points={{-298, + -320},{-190,-320},{-190,-283.067},{-182,-283.067}}, + color={0,0,127})); + + connect(sin17.y, priPumCon8.VHotWat_flow) annotation (Line(points={{-268,-300}, + {-266,-300},{-266,-282},{-228,-282},{-228,-266},{-204,-266},{-204, + -254.133},{-182,-254.133}}, + color={0,0,127})); + + connect(sin16.y, priPumCon8.VHotWatDec_flow) annotation (Line(points={{-208, + -302},{-194,-302},{-194,-288.667},{-182,-288.667}}, + color={0,0,127})); + + connect(con35.y, priPumCon9.uMinPriPumSpeCon) annotation (Line(points={{92,-330}, + {200,-330},{200,-293.067},{208,-293.067}}, + color={0,0,127})); + + connect(sin19.y, priPumCon9.VHotWat_flow) annotation (Line(points={{122,-310}, + {124,-310},{124,-292},{162,-292},{162,-276},{186,-276},{186,-264.133}, + {208,-264.133}}, + color={0,0,127})); + + connect(sin18.y, priPumCon9.THotWatPri) annotation (Line(points={{188,-312},{ + 198,-312},{198,-301.467},{208,-301.467}}, + color={0,0,127})); + + connect(con37.y, priPumCon9.THotWatSec) annotation (Line(points={{92,-370},{ + 156,-370},{156,-332},{204,-332},{204,-304.267},{208,-304.267}}, + color={0,0,127})); + + connect(con39.y, priPumCon10.uMinPriPumSpeCon) annotation (Line(points={{-288, + -480},{-180,-480},{-180,-443.067},{-172,-443.067}}, + color={0,0,127})); + + connect(sin21.y, priPumCon10.VHotWat_flow) annotation (Line(points={{-258, + -460},{-256,-460},{-256,-442},{-218,-442},{-218,-426},{-194,-426},{ + -194,-414.133},{-172,-414.133}}, + color={0,0,127})); + + connect(sin20.y, priPumCon10.THotWatBoiSup) annotation (Line(points={{-192, + -462},{-182,-462},{-182,-457.067},{-172,-457.067}}, + color={0,0,127})); + + connect(con41.y, priPumCon10.THotWatSec) annotation (Line(points={{-288,-520}, + {-224,-520},{-224,-482},{-174,-482},{-174,-454.267},{-172,-454.267}}, + color={0,0,127})); + + connect(sin22.y, priPumCon11.VHotWat_flow) annotation (Line(points={{102,-490}, + {104,-490},{104,-472},{142,-472},{142,-456},{166,-456},{166,-444.133}, + {188,-444.133}}, + color={0,0,127})); + + connect(cha12.y, priPumCon2.uPumChaPro) annotation (Line(points={{-198,180},{ + -176,180},{-176,254.667},{-172,254.667}}, + color={255,0,255})); + + connect(cha13.y, priPumCon3.uPumChaPro) annotation (Line(points={{162,160},{ + 184,160},{184,234.667},{188,234.667}}, + color={255,0,255})); + + connect(cha14.y, priPumCon4.uPumChaPro) annotation (Line(points={{-198,20},{ + -178,20},{-178,94.6667},{-172,94.6667}}, + color={255,0,255})); + + connect(cha15.y, priPumCon5.uPumChaPro) annotation (Line(points={{162,0},{182, + 0},{182,74.6667},{188,74.6667}}, + color={255,0,255})); + + connect(cha16.y, priPumCon6.uPumChaPro) annotation (Line(points={{-208,-160}, + {-186,-160},{-186,-85.3333},{-182,-85.3333}}, + color={255,0,255})); + + connect(booPul1.y, cha12.u) + annotation (Line(points={{-258,180},{-222,180}}, color={255,0,255})); + + connect(booPul5.y, cha14.u) + annotation (Line(points={{-258,20},{-222,20}}, color={255,0,255})); + + connect(booPul7.y, cha15.u) + annotation (Line(points={{102,0},{138,0}}, color={255,0,255})); + + connect(booPul9.y, cha16.u) + annotation (Line(points={{-268,-160},{-232,-160}}, color={255,0,255})); + + connect(booPul13.y, cha18.u) + annotation (Line(points={{-268,-340},{-264,-340},{-264,-230},{-262,-230}}, + color={255,0,255})); + + connect(booPul15.y, cha19.u) + annotation (Line(points={{122,-350},{126,-350},{126,-210},{128,-210}}, + color={255,0,255})); + + connect(booPul17.y, cha20.u) + annotation (Line(points={{-258,-500},{-254,-500},{-254,-370},{-252,-370}}, + color={255,0,255})); + + connect(booPul19.y, cha21.u) + annotation (Line(points={{102,-530},{106,-530},{106,-390},{108,-390}}, + color={255,0,255})); + + connect(booPul15.y, edg.u) annotation (Line(points={{122,-350},{126,-350},{ + 126,-366},{170,-366},{170,-350},{178,-350}}, color={255,0,255})); + + connect(edg.y, priPumCon9.uStaUp) annotation (Line(points={{202,-350},{202, + -269.733},{208,-269.733}}, + color={255,0,255})); + + connect(edg.y, priPumCon9.uOnOff) annotation (Line(points={{202,-350},{202, + -272.533},{208,-272.533}}, + color={255,0,255})); + + connect(booPul13.y, edg2.u) annotation (Line(points={{-268,-340},{-264,-340}, + {-264,-354},{-214,-354},{-214,-340},{-212,-340}}, color={255,0,255})); + + connect(edg2.y, priPumCon8.uStaUp) annotation (Line(points={{-188,-340},{-186, + -340},{-186,-259.733},{-182,-259.733}}, + color={255,0,255})); + + connect(edg2.y, priPumCon8.uOnOff) annotation (Line(points={{-188,-340},{-186, + -340},{-186,-262.533},{-182,-262.533}}, + color={255,0,255})); + + connect(booPul17.y, edg3.u) annotation (Line(points={{-258,-500},{-254,-500}, + {-254,-514},{-214,-514},{-214,-500},{-212,-500}}, color={255,0,255})); + + connect(edg3.y, priPumCon10.uStaUp) annotation (Line(points={{-188,-500},{ + -178,-500},{-178,-419.733},{-172,-419.733}}, + color={255,0,255})); + + connect(edg3.y, priPumCon10.uOnOff) annotation (Line(points={{-188,-500},{ + -178,-500},{-178,-422.533},{-172,-422.533}}, + color={255,0,255})); + + connect(booPul19.y, edg4.u) annotation (Line(points={{102,-530},{106,-530},{ + 106,-550},{150,-550},{150,-530},{158,-530}}, color={255,0,255})); + + connect(edg4.y, priPumCon11.uStaUp) annotation (Line(points={{182,-530},{186, + -530},{186,-449.733},{188,-449.733}}, + color={255,0,255})); + + connect(edg4.y, priPumCon11.uOnOff) annotation (Line(points={{182,-530},{186, + -530},{186,-452.533},{188,-452.533}}, + color={255,0,255})); + + connect(pul.y, priPumCon.uHotIsoVal) annotation (Line(points={{-314,418},{ + -244,418},{-244,418.667},{-172,418.667}}, + color={0,0,127})); + + connect(con1.y, priPumCon.dpHotWatSet) annotation (Line(points={{-248,370},{ + -234,370},{-234,389.733},{-172,389.733}}, + color={0,0,127})); + + connect(pre1.y, priPumCon.uHotWatPum) annotation (Line(points={{-108,400},{ + -100,400},{-100,440},{-190,440},{-190,424.267},{-172,424.267}}, + color={255,0, + 255})); + + connect(pre2.y, priPumCon1.uHotWatPum) annotation (Line(points={{252,390},{ + 272,390},{272,460},{110,460},{110,414.267},{188,414.267}}, + color={255,0,255})); + + connect(pul1.y, priPumCon1.uHotIsoVal) annotation (Line(points={{22,410},{116, + 410},{116,408.667},{188,408.667}}, + color={0,0,127})); + + connect(con3.y, priPumCon1.dpHotWatSet) annotation (Line(points={{102,390},{ + 160,390},{160,379.733},{188,379.733}}, + color={0,0,127})); + + connect(pul2.y, priPumCon2.uHotIsoVal) annotation (Line(points={{-308,270},{ + -224,270},{-224,268.667},{-172,268.667}}, + color={0,0,127})); + + connect(pre3.y, priPumCon2.uHotWatPum) annotation (Line(points={{-88,250},{ + -86,250},{-86,320},{-240,320},{-240,274.267},{-172,274.267}}, + color={255,0, + 255})); + + connect(pul3.y, priPumCon3.uHotIsoVal) annotation (Line(points={{32,250},{136, + 250},{136,248.667},{188,248.667}}, + color={0,0,127})); + + connect(pre4.y, priPumCon3.uHotWatPum) annotation (Line(points={{282,230},{ + 290,230},{290,300},{130,300},{130,254.267},{188,254.267}}, + color={255,0,255})); + + connect(pul4.y, priPumCon4.uHotIsoVal) annotation (Line(points={{-308,110},{ + -224,110},{-224,108.667},{-172,108.667}}, + color={0,0,127})); + + connect(pre5.y, priPumCon4.uHotWatPum) annotation (Line(points={{-76,110},{ + -70,110},{-70,160},{-230,160},{-230,114.267},{-172,114.267}}, + color={255,0, + 255})); + + connect(pre6.y, priPumCon5.uHotWatPum) annotation (Line(points={{262,100},{ + 270,100},{270,140},{130,140},{130,94.2667},{188,94.2667}}, + color={255,0,255})); + + connect(pul5.y, priPumCon5.uHotIsoVal) annotation (Line(points={{42,90},{136, + 90},{136,88.6667},{188,88.6667}}, + color={0,0,127})); + + connect(pre7.y, priPumCon6.uHotWatPum) annotation (Line(points={{-98,-60},{ + -90,-60},{-90,-20},{-240,-20},{-240,-65.7333},{-182,-65.7333}}, + color={255,0, + 255})); + + connect(pul6.y, priPumCon6.uHotIsoVal) annotation (Line(points={{-306,-70},{ + -220,-70},{-220,-71.3333},{-182,-71.3333}}, + color={0,0,127})); + + connect(pre8.y, priPumCon7.uHotWatPum) annotation (Line(points={{282,-70},{ + 300,-70},{300,-32},{164,-32},{164,-86},{186,-86},{186,-85.7333},{208, + -85.7333}}, color={255,0,255})); + + connect(pre9.y, priPumCon8.uHotWatPum) annotation (Line(points={{-98,-240},{ + -88,-240},{-88,-210},{-190,-210},{-190,-245.733},{-182,-245.733}}, + color={ + 255,0,255})); + + connect(pre10.y, priPumCon9.uHotWatPum) annotation (Line(points={{276,-240},{ + 280,-240},{280,-220},{200,-220},{200,-255.733},{208,-255.733}}, + color={255,0, + 255})); + + connect(pre11.y, priPumCon10.uHotWatPum) annotation (Line(points={{-98,-400}, + {-80,-400},{-80,-370},{-220,-370},{-220,-406},{-196,-406},{-196, + -405.733},{-172,-405.733}}, color={ + 255,0,255})); + + connect(pre12.y, priPumCon11.uHotWatPum) annotation (Line(points={{270,-410}, + {280,-410},{280,-392},{180,-392},{180,-436},{184,-436},{184,-435.733}, + {188,-435.733}}, color={255,0, + 255})); + + connect(conInt7.y, priPumCon7.uLasDisBoi) annotation (Line(points={{262,-160}, + {270,-160},{270,-140},{202,-140},{202,-111.867},{208,-111.867}}, + color={255,127,0})); + + connect(conInt8.y, priPumCon8.uLasDisBoi) annotation (Line(points={{-138,-318}, + {-130,-318},{-130,-300},{-188,-300},{-188,-271.867},{-182,-271.867}}, + color={255,127,0})); + + connect(conInt9.y, priPumCon9.uLasDisBoi) annotation (Line(points={{262,-328}, + {270,-328},{270,-314},{196,-314},{196,-281.867},{208,-281.867}}, + color={255,127,0})); + + connect(conInt10.y, priPumCon10.uLasDisBoi) annotation (Line(points={{-118, + -478},{-110,-478},{-110,-460},{-176,-460},{-176,-431.867},{-172, + -431.867}}, color={255,127,0})); + + connect(booPul11.y, truFalHol10.u) annotation (Line(points={{122,-180},{126,-180}, + {126,-100},{128,-100}}, color={255,0,255})); + + connect(truFalHol10.y, priPumCon7.uBoiSta[1]) annotation (Line(points={{152, + -100},{192,-100},{192,-97.8667},{208,-97.8667}}, + color={255,0,255})); + + connect(booPul13.y, truFalHol11.u) annotation (Line(points={{-268,-340},{-264, + -340},{-264,-260},{-262,-260}}, color={255,0,255})); + + connect(truFalHol11.y, priPumCon8.uBoiSta[1]) annotation (Line(points={{-238, + -260},{-236,-260},{-236,-257.867},{-182,-257.867}}, + color={255,0,255})); + + connect(booPul15.y, truFalHol12.u) annotation (Line(points={{122,-350},{126,-350}, + {126,-270},{128,-270}}, color={255,0,255})); + + connect(truFalHol12.y, priPumCon9.uBoiSta[1]) annotation (Line(points={{152, + -270},{160,-270},{160,-267.867},{208,-267.867}}, + color={255,0,255})); + + connect(booPul17.y, truFalHol13.u) annotation (Line(points={{-258,-500},{-254, + -500},{-254,-420},{-252,-420}}, color={255,0,255})); + + connect(truFalHol13.y, priPumCon10.uBoiSta[1]) annotation (Line(points={{-228, + -420},{-220,-420},{-220,-417.867},{-172,-417.867}}, + color={255,0,255})); + + connect(booPul19.y, truFalHol14.u) annotation (Line(points={{102,-530},{106,-530}, + {106,-450},{108,-450}}, color={255,0,255})); + + connect(truFalHol14.y, priPumCon11.uBoiSta[1]) annotation (Line(points={{132, + -450},{140,-450},{140,-447.867},{188,-447.867}}, + color={255,0,255})); + + connect(pul.y, mulSum.u[1:2]) annotation (Line(points={{-314,418},{-308,418},{ + -308,449},{-302,449}}, color={0,0,127})); + + connect(mulSum.y, lesThr.u) + annotation (Line(points={{-278,450},{-262,450}}, color={0,0,127})); + + connect(lesThr.y, priPumCon.uPlaEna) annotation (Line(points={{-238,450},{ + -230,450},{-230,421.467},{-172,421.467}}, + color={255,0,255})); + + connect(mulSum1.y, lesThr1.u) + annotation (Line(points={{52,450},{68,450}}, color={0,0,127})); + + connect(pul1.y, mulSum1.u[1:2]) annotation (Line(points={{22,410},{26,410},{26, + 449},{28,449}}, color={0,0,127})); + + connect(lesThr1.y, priPumCon1.uPlaEna) annotation (Line(points={{92,450},{100, + 450},{100,411.467},{188,411.467}}, + color={255,0,255})); + + connect(mulSum2.y, lesThr2.u) + annotation (Line(points={{-278,310},{-272,310}}, color={0,0,127})); + + connect(pul2.y, mulSum2.u[1:2]) annotation (Line(points={{-308,270},{-304,270}, + {-304,309},{-302,309}}, color={0,0,127})); + + connect(lesThr2.y, priPumCon2.uPlaEna) annotation (Line(points={{-248,310},{ + -242,310},{-242,271.467},{-172,271.467}}, + color={255,0,255})); + + connect(mulSum3.y, lesThr3.u) + annotation (Line(points={{72,290},{78,290}}, color={0,0,127})); + + connect(pul3.y, mulSum3.u[1:2]) annotation (Line(points={{32,250},{40,250},{40, + 289},{48,289}}, color={0,0,127})); + + connect(lesThr3.y, priPumCon3.uPlaEna) annotation (Line(points={{102,290},{ + 120,290},{120,251.467},{188,251.467}}, + color={255,0,255})); + + connect(mulSum4.y, lesThr4.u) + annotation (Line(points={{-278,150},{-272,150}}, color={0,0,127})); + + connect(pul4.y, mulSum4.u[1:2]) annotation (Line(points={{-308,110},{-304,110}, + {-304,149},{-302,149}}, color={0,0,127})); + + connect(lesThr4.y, priPumCon4.uPlaEna) annotation (Line(points={{-248,150},{ + -240,150},{-240,111.467},{-172,111.467}}, + color={255,0,255})); + + connect(mulSum5.y, lesThr5.u) + annotation (Line(points={{82,130},{88,130}}, color={0,0,127})); + + connect(pul5.y, mulSum5.u[1:2]) annotation (Line(points={{42,90},{50,90},{50,129}, + {58,129}}, color={0,0,127})); + + connect(lesThr5.y, priPumCon5.uPlaEna) annotation (Line(points={{112,130},{ + 120,130},{120,91.4667},{188,91.4667}}, + color={255,0,255})); + + connect(mulSum6.y, lesThr6.u) + annotation (Line(points={{-278,-30},{-272,-30}}, color={0,0,127})); + + connect(pul6.y, mulSum6.u[1:2]) annotation (Line(points={{-306,-70},{-304,-70}, + {-304,-31},{-302,-31}}, color={0,0,127})); + + connect(lesThr6.y, priPumCon6.uPlaEna) annotation (Line(points={{-248,-30},{ + -244,-30},{-244,-68.5333},{-182,-68.5333}}, + color={255,0,255})); + + connect(conInt7.y, intSwi.u1) annotation (Line(points={{262,-160},{270,-160}, + {270,-168},{278,-168}},color={255,127,0})); + + connect(conInt12.y, intSwi.u3) annotation (Line(points={{262,-190},{270,-190}, + {270,-184},{278,-184}}, color={255,127,0})); + + connect(intSwi.y, priPumCon7.uNexEnaBoi) annotation (Line(points={{302,-176}, + {310,-176},{310,-144},{194,-144},{194,-108.133},{208,-108.133}},color= + {255,127,0})); + + connect(conInt13.y, intSwi1.u3) annotation (Line(points={{-138,-350},{-130,-350}, + {-130,-338},{-122,-338}}, color={255,127,0})); + + connect(conInt14.y, intSwi2.u3) annotation (Line(points={{262,-360},{264,-360}, + {264,-348},{278,-348}}, color={255,127,0})); + + connect(conInt15.y, intSwi3.u3) annotation (Line(points={{-118,-510},{-110,-510}, + {-110,-498},{-102,-498}}, color={255,127,0})); + + connect(conInt16.y, intSwi4.u3) annotation (Line(points={{242,-540},{250,-540}, + {250,-528},{258,-528}}, color={255,127,0})); + + connect(conInt8.y, intSwi1.u1) annotation (Line(points={{-138,-318},{-130, + -318},{-130,-322},{-122,-322}}, + color={255,127,0})); + + connect(intSwi1.y, priPumCon8.uNexEnaBoi) annotation (Line(points={{-98,-330}, + {-90,-330},{-90,-302},{-192,-302},{-192,-268.133},{-182,-268.133}}, + color={255,127,0})); + + connect(intSwi2.u1, conInt9.y) annotation (Line(points={{278,-332},{270,-332}, + {270,-328},{262,-328}}, color={255,127,0})); + + connect(intSwi2.y, priPumCon9.uNexEnaBoi) annotation (Line(points={{302,-340}, + {308,-340},{308,-310},{192,-310},{192,-278.133},{208,-278.133}}, + color={255,127,0})); + + connect(conInt10.y, intSwi3.u1) annotation (Line(points={{-118,-478},{-110, + -478},{-110,-482},{-102,-482}}, + color={255,127,0})); + + connect(intSwi3.y, priPumCon10.uNexEnaBoi) annotation (Line(points={{-78,-490}, + {-70,-490},{-70,-464},{-184,-464},{-184,-428.133},{-172,-428.133}}, + color={255,127,0})); + + connect(conInt11.y, intSwi4.u1) annotation (Line(points={{242,-508},{250,-508}, + {250,-512},{258,-512}}, color={255,127,0})); + + connect(intSwi4.y, priPumCon11.uNexEnaBoi) annotation (Line(points={{282,-520}, + {292,-520},{292,-492},{176,-492},{176,-458.133},{188,-458.133}}, + color={255,127,0})); + + connect(conInt11.y, priPumCon11.uLasDisBoi) annotation (Line(points={{242, + -508},{250,-508},{250,-494},{182,-494},{182,-461.867},{188,-461.867}}, + color={255,127,0})); + + connect(booPul11.y, truDel.u) annotation (Line(points={{122,-180},{126,-180},{ + 126,-140},{128,-140}}, color={255,0,255})); + + connect(truDel.y, priPumCon7.uBoiSta[2]) annotation (Line(points={{152,-140},{ + 156,-140},{156,-96},{208,-96}}, color={255,0,255})); + + connect(truFalHol10.y, priPumCon7.uPlaEna) annotation (Line(points={{152,-100}, + {180,-100},{180,-88.5333},{208,-88.5333}}, color={255,0,255})); + + connect(truDel.y, intSwi.u2) annotation (Line(points={{152,-140},{156,-140},{ + 156,-164},{234,-164},{234,-176},{278,-176}}, color={255,0,255})); + + connect(booPul11.y, cha1.u) annotation (Line(points={{122,-180},{126,-180},{ + 126,-86},{108,-86},{108,-70},{118,-70}}, color={255,0,255})); + + connect(truDel.y, cha17.u) annotation (Line(points={{152,-140},{156,-140},{ + 156,-82},{112,-82},{112,-40},{118,-40}}, color={255,0,255})); + + connect(cha1.y, or2.u1) + annotation (Line(points={{142,-70},{168,-70}}, color={255,0,255})); + + connect(cha17.y, or2.u2) annotation (Line(points={{142,-40},{160,-40},{160, + -78},{168,-78}}, color={255,0,255})); + + connect(or2.y, priPumCon7.uPumChaPro) annotation (Line(points={{192,-70},{198, + -70},{198,-105.333},{208,-105.333}}, color={255,0,255})); + + connect(truFalHol11.y, priPumCon8.uPlaEna) annotation (Line(points={{-238, + -260},{-236,-260},{-236,-248.533},{-182,-248.533}}, color={255,0,255})); + + connect(booPul13.y, truDel1.u) annotation (Line(points={{-268,-340},{-264, + -340},{-264,-304},{-260,-304}}, color={255,0,255})); + + connect(cha2.y, or1.u1) annotation (Line(points={{-238,-200},{-236,-200},{ + -236,-210},{-232,-210}}, color={255,0,255})); + + connect(cha18.y, or1.u2) annotation (Line(points={{-238,-230},{-236,-230},{ + -236,-218},{-232,-218}}, color={255,0,255})); + + connect(truDel1.y, cha2.u) annotation (Line(points={{-236,-304},{-234,-304},{ + -234,-280},{-270,-280},{-270,-200},{-262,-200}}, color={255,0,255})); + + connect(or1.y, priPumCon8.uPumChaPro) annotation (Line(points={{-208,-210},{ + -200,-210},{-200,-265.333},{-182,-265.333}}, color={255,0,255})); + + connect(truDel1.y, intSwi1.u2) annotation (Line(points={{-236,-304},{-234, + -304},{-234,-324},{-166,-324},{-166,-330},{-122,-330}}, color={255,0, + 255})); + connect(truDel1.y, priPumCon8.uBoiSta[2]) annotation (Line(points={{-236,-304}, + {-234,-304},{-234,-270},{-194,-270},{-194,-256},{-182,-256}}, color={ + 255,0,255})); + connect(booPul15.y, truDel2.u) annotation (Line(points={{122,-350},{126,-350}, + {126,-310},{128,-310}}, color={255,0,255})); + + connect(truFalHol12.y, priPumCon9.uPlaEna) annotation (Line(points={{152,-270}, + {160,-270},{160,-258.533},{208,-258.533}}, color={255,0,255})); + + connect(or3.y, priPumCon9.uPumChaPro) annotation (Line(points={{192,-240},{ + 196,-240},{196,-275.333},{208,-275.333}}, color={255,0,255})); + + connect(cha19.y, or3.u1) annotation (Line(points={{152,-210},{160,-210},{160, + -240},{168,-240}}, color={255,0,255})); + + connect(truDel2.y, priPumCon9.uBoiSta[2]) annotation (Line(points={{152,-310}, + {158,-310},{158,-266},{208,-266}}, color={255,0,255})); + + connect(truDel2.y, cha3.u) annotation (Line(points={{152,-310},{158,-310},{ + 158,-286},{120,-286},{120,-244},{128,-244}}, color={255,0,255})); + + connect(cha3.y, or3.u2) annotation (Line(points={{152,-244},{160,-244},{160, + -248},{168,-248}}, color={255,0,255})); + + connect(booPul17.y, truDel3.u) annotation (Line(points={{-258,-500},{-254, + -500},{-254,-460},{-252,-460}}, color={255,0,255})); + + connect(cha20.y, or4.u1) annotation (Line(points={{-228,-370},{-224,-370},{ + -224,-390},{-212,-390}}, color={255,0,255})); + + connect(cha4.y, or4.u2) annotation (Line(points={{-228,-394},{-220,-394},{ + -220,-398},{-212,-398}}, color={255,0,255})); + + connect(truDel3.y, priPumCon10.uBoiSta[2]) annotation (Line(points={{-228,-460}, + {-222,-460},{-222,-416},{-172,-416}}, color={255,0,255})); + + connect(truDel3.y, cha4.u) annotation (Line(points={{-228,-460},{-222,-460},{ + -222,-406},{-260,-406},{-260,-394},{-252,-394}}, color={255,0,255})); + + connect(or4.y, priPumCon10.uPumChaPro) annotation (Line(points={{-188,-390},{ + -180,-390},{-180,-425.333},{-172,-425.333}}, color={255,0,255})); + + connect(truFalHol13.y, priPumCon10.uPlaEna) annotation (Line(points={{-228, + -420},{-220,-420},{-220,-408.533},{-172,-408.533}}, color={255,0,255})); + + connect(truDel2.y, intSwi2.u2) annotation (Line(points={{152,-310},{158,-310}, + {158,-334},{238,-334},{238,-340},{278,-340}}, color={255,0,255})); + + connect(truDel3.y, intSwi3.u2) annotation (Line(points={{-228,-460},{-222, + -460},{-222,-484},{-144,-484},{-144,-490},{-102,-490}}, color={255,0, + 255})); + connect(truFalHol14.y, priPumCon11.uPlaEna) annotation (Line(points={{132, + -450},{140,-450},{140,-438.533},{188,-438.533}}, color={255,0,255})); + + connect(booPul19.y, truDel4.u) + annotation (Line(points={{102,-530},{118,-530}}, color={255,0,255})); + + connect(or5.y, priPumCon11.uPumChaPro) annotation (Line(points={{172,-420},{ + 176,-420},{176,-455.333},{188,-455.333}}, color={255,0,255})); + + connect(truDel4.y, priPumCon11.uBoiSta[2]) annotation (Line(points={{142,-530}, + {146,-530},{146,-446},{188,-446}}, color={255,0,255})); + + connect(truDel4.y, intSwi4.u2) annotation (Line(points={{142,-530},{146,-530}, + {146,-500},{200,-500},{200,-520},{258,-520}}, color={255,0,255})); + + connect(cha21.y, or5.u1) annotation (Line(points={{132,-390},{140,-390},{140, + -420},{148,-420}}, color={255,0,255})); + + connect(cha5.y, or5.u2) annotation (Line(points={{132,-420},{138,-420},{138, + -428},{148,-428}}, color={255,0,255})); + + connect(truDel4.y, cha5.u) annotation (Line(points={{142,-530},{146,-530},{ + 146,-432},{100,-432},{100,-420},{108,-420}}, color={255,0,255})); + + connect(cha.y, mulOr.u[1:2]) annotation (Line(points={{-88,220},{-84,220},{ + -84,216.5},{-80,216.5}}, + color={255,0,255})); + connect(mulOr.y, truFalHol.u) + annotation (Line(points={{-56,220},{-52,220}}, color={255,0,255})); + connect(cha6.y, mulOr1.u[1:2]) annotation (Line(points={{242,200},{244,200},{244, + 196.5},{248,196.5}}, color={255,0,255})); + connect(mulOr1.y, truFalHol1.u) + annotation (Line(points={{272,200},{278,200}}, color={255,0,255})); + connect(cha8.y, mulOr3.u[1:2]) annotation (Line(points={{262,70},{264,70},{ + 264,66.5},{268,66.5}}, color={255,0,255})); + connect(cha9.y, mulOr4.u[1:2]) annotation (Line(points={{-98,-90},{-96,-90},{ + -96,-93.5},{-92,-93.5}}, color={255,0,255})); + connect(cha10.y, mulOr5.u[1:2]) annotation (Line(points={{282,-100},{284,-100}, + {284,-103.5},{288,-103.5}}, color={255,0,255})); + connect(cha11.y, mulOr6.u[1:2]) annotation (Line(points={{-98,-270},{-94,-270}, + {-94,-273.5},{-92,-273.5}}, color={255,0,255})); + connect(cha22.y, mulOr7.u[1:2]) annotation (Line(points={{284,-280},{278,-280}, + {278,-283.5},{290,-283.5}}, color={255,0,255})); + connect(cha23.y, mulOr8.u[1:2]) annotation (Line(points={{-98,-430},{-96,-430}, + {-96,-433.5},{-92,-433.5}}, color={255,0,255})); + connect(cha24.y, mulOr9.u[1:2]) annotation (Line(points={{270,-440},{272,-440}, + {272,-443.5},{276,-443.5}}, color={255,0,255})); + connect(mulOr2.y, truFalHol2.u) + annotation (Line(points={{-46,70},{-44,70},{-44,90},{-40,90}}, + color={255,0,255})); + connect(mulOr3.y, truFalHol3.u) + annotation (Line(points={{292,70},{298,70}}, color={255,0,255})); + connect(mulOr4.y, truFalHol4.u) + annotation (Line(points={{-68,-90},{-62,-90}}, color={255,0,255})); + connect(mulOr5.y, truFalHol5.u) + annotation (Line(points={{312,-100},{318,-100}}, color={255,0,255})); + connect(mulOr6.y, truFalHol6.u) + annotation (Line(points={{-68,-270},{-62,-270}}, color={255,0,255})); + connect(mulOr7.y, truFalHol7.u) + annotation (Line(points={{314,-280},{320,-280}}, color={255,0,255})); + connect(mulOr8.y, truFalHol8.u) + annotation (Line(points={{-68,-430},{-62,-430}}, color={255,0,255})); + connect(mulOr9.y, truFalHol9.u) + annotation (Line(points={{300,-440},{306,-440}}, color={255,0,255})); + connect(priPumCon2.yHotWatPum, truDel5.u) annotation (Line(points={{-148, + 253.733},{-146,253.733},{-146,250},{-142,250}}, + color={255,0,255})); + connect(truDel5.y, pre3.u) + annotation (Line(points={{-118,250},{-112,250}}, color={255,0,255})); + connect(truDel5.y, cha.u) annotation (Line(points={{-118,250},{-116,250},{ + -116,220},{-112,220}}, color={255,0,255})); + connect(cha7.y, mulOr2.u[1:2]) annotation (Line(points={{-76,70},{-74,70},{ + -74,66.5},{-70,66.5}}, color={255,0,255})); + connect(cha13.u, pre13.y) + annotation (Line(points={{138,160},{134,160}}, color={255,0,255})); + connect(booPul3.y, pre13.u) + annotation (Line(points={{102,160},{110,160}}, color={255,0,255})); + connect(truDel6.u, priPumCon3.yHotWatPum) annotation (Line(points={{222,230}, + {218,230},{218,233.733},{212,233.733}}, color={255,0,255})); + connect(truDel6.y, pre4.u) + annotation (Line(points={{246,230},{258,230}}, color={255,0,255})); + connect(truDel6.y, cha6.u) annotation (Line(points={{246,230},{252,230},{252, + 214},{214,214},{214,200},{218,200}}, color={255,0,255})); + connect(priPumCon4.yHotWatPum, truDel7.u) annotation (Line(points={{-148, + 93.7333},{-147,93.7333},{-147,90},{-142,90}}, color={255,0,255})); + connect(truDel7.y, pre5.u) annotation (Line(points={{-118,90},{-108,90},{-108, + 110},{-100,110}}, color={255,0,255})); + connect(truDel7.y, cha7.u) annotation (Line(points={{-118,90},{-108,90},{-108, + 70},{-100,70}}, color={255,0,255})); + connect(priPumCon5.yHotWatPum, truDel8.u) annotation (Line(points={{212, + 73.7333},{214,73.7333},{214,74}}, color={255,0,255})); + connect(truDel8.y, pre6.u) + annotation (Line(points={{238,74},{238,100}}, color={255,0,255})); + connect(truDel8.y, cha8.u) + annotation (Line(points={{238,74},{238,70}}, color={255,0,255})); + connect(priPumCon6.yHotWatPum, truDel9.u) annotation (Line(points={{-158, + -86.2667},{-156,-86.2667},{-156,-90},{-154,-90}}, color={255,0,255})); + connect(truDel9.y, cha9.u) annotation (Line(points={{-130,-90},{-122,-90},{ + -122,-90}}, color={255,0,255})); + connect(truDel9.y, pre7.u) annotation (Line(points={{-130,-90},{-128,-90},{ + -128,-60},{-122,-60}}, color={255,0,255})); + connect(booPul11.y, priPumCon7.uStaUp) annotation (Line(points={{122,-180},{ + 204,-180},{204,-99.7333},{208,-99.7333}}, color={255,0,255})); + connect(booPul11.y, priPumCon7.uOnOff) annotation (Line(points={{122,-180},{ + 204,-180},{204,-102.533},{208,-102.533}}, color={255,0,255})); + connect(priPumCon7.yHotWatPum, truDel10.u) annotation (Line(points={{232, + -106.267},{234,-106.267},{234,-106}}, color={255,0,255})); + connect(truDel10.y, pre8.u) + annotation (Line(points={{258,-106},{258,-70}}, color={255,0,255})); + connect(truDel10.y, cha10.u) + annotation (Line(points={{258,-106},{258,-100}}, color={255,0,255})); + connect(priPumCon8.yHotWatPum, truDel11.u) annotation (Line(points={{-158, + -266.267},{-156,-266.267},{-156,-268},{-154,-268}}, color={255,0,255})); + connect(truDel11.y, cha11.u) annotation (Line(points={{-130,-268},{-128,-268}, + {-128,-272},{-122,-272},{-122,-270}}, color={255,0,255})); + connect(truDel11.y, pre9.u) annotation (Line(points={{-130,-268},{-126,-268}, + {-126,-240},{-122,-240}}, color={255,0,255})); + connect(priPumCon9.yHotWatPum, truDel12.u) annotation (Line(points={{232, + -276.267},{234,-276.267},{234,-276}}, color={255,0,255})); + connect(truDel12.y, cha22.u) annotation (Line(points={{258,-276},{260,-276},{ + 260,-280},{260,-280}}, color={255,0,255})); + connect(truDel12.y, pre10.u) annotation (Line(points={{258,-276},{256,-276},{ + 256,-240},{252,-240}}, color={255,0,255})); + connect(priPumCon10.yHotWatPum, truDel13.u) annotation (Line(points={{-148, + -426.267},{-148,-425.133},{-146,-425.133},{-146,-424}}, color={255,0, + 255})); + connect(truDel13.y, cha23.u) annotation (Line(points={{-122,-424},{-122,-430}, + {-122,-430}}, color={255,0,255})); + connect(truDel13.y, pre11.u) annotation (Line(points={{-122,-424},{-122,-400}, + {-122,-400}}, color={255,0,255})); + connect(priPumCon11.yHotWatPum, truDel14.u) annotation (Line(points={{212, + -456.267},{214,-456.267},{214,-456},{216,-456}}, color={255,0,255})); + connect(truDel14.y, pre12.u) annotation (Line(points={{240,-456},{244,-456},{ + 244,-410},{246,-410}}, color={255,0,255})); + connect(truDel14.y, cha24.u) annotation (Line(points={{240,-456},{244,-456},{ + 244,-440},{246,-440}}, color={255,0,255})); +annotation ( + experiment( + StopTime=3600, + Interval=0.5, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps.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={{-340,-560},{340,480}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/package.mo new file mode 100644 index 00000000000..3f910e4f5da --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.PrimaryPumps; +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.BoilerPlant.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/BoilerPlant/Pumps/PrimaryPumps/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/package.mo new file mode 100644 index 00000000000..e2611e3aa1d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/package.mo @@ -0,0 +1,33 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps; +package PrimaryPumps "Sequences for primary hot water pump control" + + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for primary hot water pumps. +The implementations are based on section 5.3.6, +in ASHRAE RP-1711, March 2020 draft. +

+"), + 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={255,0,0}, + fillPattern=FillPattern.Solid)})); +end PrimaryPumps; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/PrimaryPumps/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Controller.mo new file mode 100644 index 00000000000..5261b8728dc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Controller.mo @@ -0,0 +1,924 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps; +block Controller + "Sequences to control hot water pumps in boiler plants" + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType= Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="Pump control parameters", group="PID parameters")); + + parameter Boolean have_varSecPum = false + "True: Variable-speed secondary pumps; + False: Fixed-speed secondary pumps" + annotation (Dialog(group="Plant parameters")); + + parameter Boolean have_secFloSen = true + "True: Flow sensor in secondary loop; + False: No flow sensor in secondary loop" + annotation (Dialog(group="Plant parameters", + enable=have_varSecPum)); + + parameter Integer nPum = 2 + "Total number of secondary hot water pumps" + annotation (Dialog(group="Plant parameters")); + + parameter Integer nPumPri = 2 + "Total number of primary hot water pumps" + annotation (Dialog(group="Plant parameters", + enable=not have_varSecPum)); + + parameter Integer nBoi = 2 + "Total number of boilers" + annotation (Dialog(group="Plant parameters")); + + parameter Integer nSen=2 + "Total number of remote differential pressure sensors" + annotation (Dialog(group="Plant parameters")); + + parameter Integer nPum_nominal( + final max=nPum, + final min=1) = nPum + "Total number of pumps that operate at design conditions" + annotation (Dialog(group="Plant parameters")); + + parameter Real minPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=maxPumSpe) = 0.1 + "Minimum pump speed" + annotation (Dialog(group="Pump parameters", enable=have_varSecPum)); + + parameter Real maxPumSpe( + final unit="1", + displayUnit="1", + final min=minPumSpe, + final max=1) = 1 + "Maximum pump speed" + annotation (Dialog(group="Pump parameters", enable=have_varSecPum)); + + parameter Real VHotWat_flow_nominal( + final min=1e-6, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") = 0.5 + "Total plant design hot water flow rate" + annotation (Dialog(group="Plant parameters")); + + parameter Real maxLocDp( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Maximum hot water loop local differential pressure setpoint" + annotation (Dialog(tab="Pump control parameters", group="DP-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP)); + + parameter Real minLocDp( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference", + final min=1e-6) = 5*6894.75 + "Minimum hot water loop local differential pressure setpoint" + annotation (Dialog(tab="Pump control parameters", + group="DP-based speed regulation", + enable = speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.localDP)); + + parameter Real offTimThr( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 180 + "Threshold to check lead boiler off time" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real delBoiDis( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=180 + "Time delay after boilers have been disabled before completing disabling process" + annotation (Dialog(tab="Pump control parameters", group="Pump staging parameters")); + + parameter Real timPer( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 600 + "Delay time period for enabling and disabling lag pumps" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real staCon( + final unit="1", + displayUnit="1") = -0.03 + "Constant used in the staging equation" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real relFloHys( + final unit="1", + displayUnit="1") = 0.01 + "Constant value used in hysteresis for checking relative flow rate" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and have_secFloSen)); + + parameter Real speLim( + final unit="1", + displayUnit="1") = 0.9 + "Speed limit with longer enable delay for enabling next lag pump" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real speLim1( + final unit="1", + displayUnit="1") = 0.99 + "Speed limit with shorter enable delay for enabling next lag pump" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real speLim2( + final unit="1", + displayUnit="1") = 0.4 + "Speed limit for disabling last lag pump" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real timPer1( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Delay time period for enabling next lag pump at speed limit speLim" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real timPer2( + final unit="s", + displayUnit="s", + final quantity="time") = 60 + "Delay time period for enabling next lag pump at speed limit speLim1" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real timPer3( + final unit="s", + displayUnit="s", + final quantity="time") = 600 + "Delay time period for disabling last lag pump" + annotation (Dialog(tab="Pump control parameters", + group="Pump staging parameters", + enable=have_varSecPum and not have_secFloSen)); + + parameter Real k( + final unit="1", + displayUnit="1", + final min=0) = 1 + "Gain of controller" + annotation (Dialog(tab="Pump control parameters", + group="PID parameters", + enable=have_varSecPum)); + + parameter Real Ti( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.5 + "Time constant of integrator block" + annotation (Dialog(tab="Pump control parameters", + group="PID parameters", + enable=have_varSecPum)); + + parameter Real Td( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0) = 0.1 + "Time constant of derivative block" + annotation (Dialog(tab="Pump control parameters", + group="PID parameters", + enable=have_varSecPum)); + + parameter Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes + speConTyp = Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP + "Speed regulation method" + annotation (Dialog(group="Plant parameters", enable=have_varSecPum)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPum[nPum] + "Secondary pumps operating status" + annotation (Placement(transformation(extent={{-320,120},{-280,160}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPlaEna + "Plant enable signal" + annotation (Placement(transformation(extent={{-320,70},{-280,110}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPriPumSta[nPumPri] if not have_varSecPum + "Primary pumps operating status" + annotation (Placement(transformation(extent={{-320,-176},{-280,-136}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uPumLeaLag[nPum] + "Hot water pump lead-lag order" + annotation (Placement(transformation(extent={{-320,210},{-280,250}}), + iconTransformation(extent={{-140,162},{-100,202}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput supResReq + "Hot water supply reset requests" + annotation (Placement(transformation(extent={{-320,20},{-280,60}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uMaxSecPumSpeCon( + final unit="1", + displayUnit="1") if have_varSecPum + "Maximum allowed pump speed for non-condensing boilers" + annotation (Placement(transformation(extent={{-320,-410},{-280,-370}}), + iconTransformation(extent={{-140,-200},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat_local( + final unit="Pa", + displayUnit="Pa", + final quantity="PressureDifference") if have_varSecPum and locDPReg + "Hot water differential static pressure from local sensor" + annotation (Placement(transformation(extent={{-320,-310},{-280,-270}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWat_remote[nSen]( + final unit=fill("Pa", nSen), + final quantity=fill("PressureDifference", nSen), + displayUnit=fill("Pa", nSen)) if have_varSecPum and (locDPReg or remDPReg) + "Hot water differential static pressure from remote sensor" + annotation (Placement(transformation(extent={{-320,-350},{-280,-310}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHotWatSet( + final unit="Pa", + final quantity="PressureDifference", + displayUnit="Pa") if have_varSecPum and (locDPReg or remDPReg) + "Hot water differential static pressure setpoint" + annotation (Placement(transformation(extent={{-320,-380},{-280,-340}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") if have_varSecPum and have_secFloSen + "Hot water flow" + annotation (Placement(transformation(extent={{-320,-40},{-280,0}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yHotWatPum[nPum] + "Hot water pump status" + annotation (Placement(transformation(extent={{280,-20},{320,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumSpe( + final min=0, + final max=1, + final unit="1", + displayUnit="1") if have_varSecPum "Hot water pump speed" + annotation (Placement(transformation(extent={{280,-420},{320,-380}}), + iconTransformation(extent={{100,-120},{140,-80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.EnableLag_flowrate + enaLagHotPum( + final nPum=nPum, + final nPum_nominal=nPum_nominal, + final timPer=timPer, + final staCon=staCon, + final relFloHys=relFloHys, + final VHotWat_flow_nominal=VHotWat_flow_nominal) if have_varSecPum and + have_secFloSen + "Enable lag pump for primary-only plants using differential pressure pump speed control" + annotation (Placement(transformation(extent={{-200,-10},{-180,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_localDp + pumSpeLocDp( + controllerType=controllerType, + final nSen=nSen, + final nPum=nPum, + final minLocDp=minLocDp, + final maxLocDp=maxLocDp, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final k=k, + final Ti=Ti, + final Td=Td) if have_varSecPum and locDPReg + "Hot water pump speed control with local DP sensor" + annotation (Placement(transformation(extent={{-60,-340},{-40,-320}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.EnableLag_pumpSpeed + enaLagSecPum( + final speLim=speLim, + final speLim1=speLim1, + final speLim2=speLim2, + final timPer=timPer1, + final timPer1=timPer2, + final timPer2=timPer3) if have_varSecPum and not have_secFloSen + "Enable and disable secondary lag pumps in secondary loop with no flow sensor" + annotation (Placement(transformation(extent={{-120,28},{-100,48}}))); + +protected + parameter Boolean remDPReg = (speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP) + "Boolean flag for pump speed control with remote differential pressure"; + + parameter Boolean locDPReg = (speConTyp == Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.localDP) + "Boolean flag for pump speed control with local differential pressure"; + + parameter Integer pumInd[nPum]={i for i in 1:nPum} + "Pump index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel( + final samplePeriod=1) if have_varSecPum and not have_secFloSen + "Unit delay for pump speed" + annotation (Placement(transformation(extent={{-200,28},{-180,48}}))); + + Buildings.Controls.OBC.CDL.Continuous.Min min if have_varSecPum + "Ensure pump speed is below maximum speed for condensation control" + annotation (Placement(transformation(extent={{160,-410},{180,-390}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.EnableLead + enaHeaLeaPum "Enable lead pump of headered pumps" + annotation (Placement(transformation(extent={{-200,76},{-180,96}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.Speed_remoteDp + pumSpeRemDp( + controllerType=controllerType, + final nSen=nSen, + final nPum=nPum, + final minPumSpe=minPumSpe, + final maxPumSpe=maxPumSpe, + final k=k, + final Ti=Ti, + final Td=Td) if have_varSecPum and remDPReg + "Hot water pump speed control with remote DP sensor" + annotation (Placement(transformation(extent={{-60,-380},{-40,-360}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-274,190},{-254,210}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nPum] + "Convert integer to real number" + annotation (Placement(transformation(extent={{-220,220},{-200,240}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor leaPum( + final nin=nPum) + "Lead pump index" + annotation (Placement(transformation(extent={{-80,220},{-60,240}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,220},{-20,240}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor nexLagPum( + final allowOutOfRange=true, + final nin=nPum, + final outOfRangeValue=0) + "Next lag pump" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-8,-60},{12,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor lasLagPum( + final allowOutOfRange=true, + final nin=nPum, + final outOfRangeValue=0) + "Last lag pump" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-8,-110},{12,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nPum] + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-250,-130},{-230,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nPum) + "Sum of integer inputs" + annotation (Placement(transformation(extent={{-200,-130},{-180,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt + "Integer add" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nPumPri] if not have_varSecPum + "Convert boolean to integer" + annotation (Placement(transformation(extent={{-250,-166},{-230,-146}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt1( + final nin=nPumPri) if not have_varSecPum + "Sum of integer inputs" + annotation (Placement(transformation(extent={{-200,-166},{-180,-146}}))); + + Buildings.Controls.OBC.CDL.Integers.Greater intGre if not have_varSecPum + "Check if more boilers than pumps are enabled" + annotation (Placement(transformation(extent={{-60,-200},{-40,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Less intLes if not have_varSecPum + "Check if less boilers than pumps are enabled" + annotation (Placement(transformation(extent={{-50,-250},{-30,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 if not have_varSecPum + "Logical not" + annotation (Placement(transformation(extent={{2,-250},{22,-230}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta1(final nPum=nPum) + "Change lead pump status for headered primary pumps" + annotation (Placement(transformation(extent={{58,68},{80,88}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta2(final nPum=nPum) if have_varSecPum and have_secFloSen + "Change lag pump status for headered primary pumps in a plant that is primary-only" + annotation (Placement(transformation(extent={{60,-44},{82,-24}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta3(final nPum=nPum) if not have_varSecPum + "Change lag pump status for headered primary pumps in a plant that is not primary-only" + annotation (Placement(transformation(extent={{62,-182},{84,-162}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.Generic.ChangeStatus + chaPumSta4(final nPum=nPum) if have_varSecPum and not have_secFloSen + "Change pump status of secondary lag pumps in secondary loop with no flow sensor" + annotation (Placement(transformation(extent={{58,8},{80,28}}))); + + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr( + final t=1) + "Prevent status changer from disabling lead pump" + annotation (Placement(transformation(extent={{-158,-228},{-138,-208}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 if not have_varSecPum + "Logical Or" + annotation (Placement(transformation(extent={{34,-228},{54,-208}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if not have_varSecPum + "Logical And" + annotation (Placement(transformation(extent={{0,-174},{20,-154}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr( + final t=1) + "Prevent status changer from enabling lead pump" + annotation (Placement(transformation(extent={{-112,-160},{-92,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 if have_varSecPum + "Logical And" + annotation (Placement(transformation(extent={{-30,32},{-10,52}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or3 if have_varSecPum + "Logical Or" + annotation (Placement(transformation(extent={{-20,-8},{0,12}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical Not" + annotation (Placement(transformation(extent={{-200,108},{-180,128}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=delBoiDis) + "Delay pump disable after boilers have been disabled" + annotation (Placement(transformation(extent={{-120,108},{-100,128}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nPum) + "Boolean replicator" + annotation (Placement(transformation(extent={{-66,108},{-46,128}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nPum] + "Logical switch" + annotation (Placement(transformation(extent={{192,-10},{212,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nPum]( + final k=fill(false,nPum)) + "Boolean False signal" + annotation (Placement(transformation(extent={{132,38},{152,58}}))); + +equation + 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={{-252,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(intToRea.y, nexLagPum.u) + annotation (Line(points={{-198,230},{-160,230},{-160,-50},{-82,-50}}, + color={0,0,127})); + + connect(enaLagHotPum.VHotWat_flow,VHotWat_flow) + annotation (Line(points={{-202,4},{-266,4},{-266,-20},{-300,-20}}, + color={0,0,127})); + + connect(uHotWatPum,enaLagHotPum.uHotWatPum) + annotation (Line(points={{-300,140},{-260,140},{-260,-3.8},{-202,-3.8}}, + color={255,0,255})); + + connect(intToRea.y, lasLagPum.u) + annotation (Line(points={{-198,230},{-160,230},{-160,-100},{-82,-100}}, + color={0,0,127})); + + connect(pumSpeLocDp.dpHotWat_local,dpHotWat_local) + annotation (Line(points={{-62,-322},{-230,-322},{-230,-290},{-300,-290}}, + color={0,0,127})); + + connect(pumSpeLocDp.dpHotWat_remote,dpHotWat_remote) + annotation (Line(points={{-62,-334},{-200,-334},{-200,-330},{-300,-330}}, + color={0,0,127})); + + connect(pumSpeLocDp.dpHotWatSet,dpHotWatSet) + annotation (Line(points={{-62,-338},{-220,-338},{-220,-360},{-300,-360}}, + color={0,0,127})); + + connect(dpHotWat_remote,pumSpeRemDp.dpHotWat) + annotation (Line(points={{-300,-330},{-200,-330},{-200,-370},{-62,-370}}, + color={0,0,127})); + + connect(dpHotWatSet,pumSpeRemDp.dpHotWatSet) + annotation (Line(points={{-300,-360},{-220,-360},{-220,-378},{-62,-378}}, + color={0,0,127})); + + connect(uHotWatPum, booToInt.u) + annotation (Line(points={{-300,140},{-260,140},{-260,-120},{-252,-120}}, + color={255,0,255})); + + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-228,-120},{-202,-120}}, color={255,127,0})); + + connect(addInt.y, nexLagPum.index) + annotation (Line(points={{-98,-70},{-70,-70},{-70,-62}}, color={255,127,0})); + + connect(mulSumInt.y, addInt.u2) + annotation (Line(points={{-178,-120},{-128,-120},{-128,-76},{-122,-76}}, + color={255,127,0})); + + connect(conInt.y, addInt.u1) + annotation (Line(points={{-252,200},{-140,200},{-140,-64},{-122,-64}}, + color={255,127,0})); + + connect(mulSumInt.y, lasLagPum.index) + annotation (Line(points={{-178,-120},{-70,-120},{-70,-112}}, color={255,127,0})); + + connect(reaToInt.y, chaPumSta1.uNexLagPum) annotation (Line(points={{-18,230}, + {46,230},{46,74},{56,74}}, color={255,127,0})); + + connect(reaToInt.y, chaPumSta1.uLasLagPum) annotation (Line(points={{-18,230}, + {46,230},{46,70},{56,70}}, color={255,127,0})); + + connect(enaHeaLeaPum.yLea, chaPumSta1.uNexLagPumSta) annotation (Line(points={{-178,86}, + {56,86}}, color={255,0,255})); + + connect(enaHeaLeaPum.yLea, chaPumSta1.uLasLagPumSta) annotation (Line(points={{-178,86}, + {36,86},{36,83},{56,83}}, color={255,0,255})); + + connect(uHotWatPum, chaPumSta1.uHotWatPum) annotation (Line(points={{-300,140}, + {26,140},{26,78},{56,78}}, color={255,0,255})); + + connect(chaPumSta1.yHotWatPum, chaPumSta2.uHotWatPum) annotation (Line(points={{80,78}, + {100,78},{100,-16},{46,-16},{46,-34},{58,-34}}, color={255,0, + 255})); + + connect(chaPumSta1.yHotWatPum, chaPumSta3.uHotWatPum) annotation (Line(points={{80,78}, + {100,78},{100,-154},{44,-154},{44,-172},{60,-172}}, color={ + 255,0,255})); + + connect(uMaxSecPumSpeCon, min.u1) + annotation (Line(points={{-300,-390},{-72,-390},{-72,-394},{158,-394}}, + color={0,0,127})); + + connect(pumSpeLocDp.yHotWatPumSpe, min.u2) annotation (Line(points={{-38,-330}, + {146,-330},{146,-406},{158,-406}}, color={0,0,127})); + + connect(pumSpeRemDp.yHotWatPumSpe, min.u2) annotation (Line(points={{-38,-370}, + {146,-370},{146,-406},{158,-406}}, color={0,0,127})); + + connect(uPriPumSta, booToInt1.u) annotation (Line(points={{-300,-156},{-252,-156}}, + color={255,0,255})); + + connect(mulSumInt1.y, intGre.u1) annotation (Line(points={{-178,-156},{-124,-156}, + {-124,-190},{-62,-190}}, color={255,127,0})); + + connect(mulSumInt1.y, intLes.u1) annotation (Line(points={{-178,-156},{-124,-156}, + {-124,-240},{-52,-240}}, color={255,127,0})); + + connect(intLes.y, not1.u) + annotation (Line(points={{-28,-240},{0,-240}}, color={255,0,255})); + + connect(supResReq, enaHeaLeaPum.supResReq) annotation (Line(points={{-300,40}, + {-220,40},{-220,82},{-202,82}}, color={255,127,0})); + + connect(min.y, uniDel.u) annotation (Line(points={{182,-400},{200,-400},{200,-418}, + {-210,-418},{-210,38},{-202,38}}, color={0,0,127})); + + connect(uniDel.y, enaLagSecPum.uPumSpe) + annotation (Line(points={{-178,38},{-122,38}}, color={0,0,127})); + + connect(chaPumSta1.yHotWatPum, chaPumSta4.uHotWatPum) annotation (Line(points={{80,78}, + {100,78},{100,42},{50,42},{50,18},{56,18}}, color={255,0,255})); + + connect(uPlaEna, enaHeaLeaPum.uPlaEna) + annotation (Line(points={{-300,90},{-202,90}}, color={255,0,255})); + + connect(reaToInt1.y, chaPumSta4.uNexLagPum) annotation (Line(points={{14,-50}, + {32,-50},{32,14},{56,14}}, color={255,127,0})); + + connect(reaToInt1.y, chaPumSta2.uNexLagPum) annotation (Line(points={{14,-50}, + {32,-50},{32,-38},{58,-38}}, color={255,127,0})); + + connect(reaToInt1.y, chaPumSta3.uNexLagPum) annotation (Line(points={{14,-50}, + {32,-50},{32,-176},{60,-176}}, color={255,127,0})); + + connect(reaToInt2.y, chaPumSta4.uLasLagPum) annotation (Line(points={{14,-100}, + {38,-100},{38,10},{56,10}}, color={255,127,0})); + + connect(reaToInt2.y, chaPumSta2.uLasLagPum) annotation (Line(points={{14,-100}, + {38,-100},{38,-42},{58,-42}}, color={255,127,0})); + + connect(reaToInt2.y, chaPumSta3.uLasLagPum) annotation (Line(points={{14,-100}, + {38,-100},{38,-180},{60,-180}}, color={255,127,0})); + + connect(intLesEquThr.y, or2.u1) + annotation (Line(points={{-136,-218},{32,-218}}, color={255,0,255})); + + connect(not1.y, or2.u2) annotation (Line(points={{24,-240},{28,-240},{28,-226}, + {32,-226}}, color={255,0,255})); + + connect(or2.y, chaPumSta3.uLasLagPumSta) annotation (Line(points={{56,-218},{58, + -218},{58,-167},{60,-167}}, color={255,0,255})); + + connect(nexLagPum.y, reaToInt1.u) + annotation (Line(points={{-58,-50},{-10,-50}}, color={0,0,127})); + + connect(lasLagPum.y, reaToInt2.u) + annotation (Line(points={{-58,-100},{-10,-100}}, color={0,0,127})); + + connect(mulSumInt.y, intLesEquThr.u) annotation (Line(points={{-178,-120},{-166, + -120},{-166,-218},{-160,-218}}, color={255,127,0})); + + connect(mulSumInt.y, intGre.u2) annotation (Line(points={{-178,-120},{-166,-120}, + {-166,-198},{-62,-198}}, color={255,127,0})); + + connect(mulSumInt.y, intLes.u2) annotation (Line(points={{-178,-120},{-166,-120}, + {-166,-248},{-52,-248}}, color={255,127,0})); + + connect(and2.y, chaPumSta3.uNexLagPumSta) + annotation (Line(points={{22,-164},{60,-164}}, color={255,0,255})); + + connect(intGre.y, and2.u2) annotation (Line(points={{-38,-190},{-10,-190},{-10, + -172},{-2,-172}}, color={255,0,255})); + + connect(intGreEquThr.y, and2.u1) + annotation (Line(points={{-90,-150},{-10,-150},{-10,-164},{-2,-164}}, + color={255,0,255})); + + connect(mulSumInt.y, intGreEquThr.u) annotation (Line(points={{-178,-120},{-166, + -120},{-166,-150},{-114,-150}},color={255,127,0})); + + connect(enaLagSecPum.yUp, and1.u1) + annotation (Line(points={{-98,42},{-32,42}}, color={255,0,255})); + connect(intGreEquThr.y, and1.u2) annotation (Line(points={{-90,-150},{-40,-150}, + {-40,34},{-32,34}}, color={255,0,255})); + connect(enaLagHotPum.yUp, and1.u1) annotation (Line(points={{-178,4},{-70,4},{ + -70,42},{-32,42}}, color={255,0,255})); + connect(intLesEquThr.y, or3.u2) annotation (Line(points={{-136,-218},{-28,-218}, + {-28,-6},{-22,-6}}, color={255,0,255})); + connect(enaLagSecPum.yDown, or3.u1) annotation (Line(points={{-98,34},{-48,34}, + {-48,2},{-22,2}}, color={255,0,255})); + connect(enaLagHotPum.yDown, or3.u1) annotation (Line(points={{-178,-4},{-48,-4}, + {-48,2},{-22,2}}, color={255,0,255})); + connect(and1.y, chaPumSta4.uNexLagPumSta) annotation (Line(points={{-8,42},{28, + 42},{28,26},{56,26}}, color={255,0,255})); + connect(or3.y, chaPumSta4.uLasLagPumSta) annotation (Line(points={{2,2},{20,2}, + {20,23},{56,23}}, color={255,0,255})); + connect(and1.y, chaPumSta2.uNexLagPumSta) annotation (Line(points={{-8,42},{28, + 42},{28,-26},{58,-26}}, color={255,0,255})); + connect(or3.y, chaPumSta2.uLasLagPumSta) annotation (Line(points={{2,2},{20,2}, + {20,-29},{58,-29}}, color={255,0,255})); + + connect(not3.y,truDel. u) + annotation (Line(points={{-178,118},{-122,118}}, + color={255,0,255})); + connect(truDel.y,booRep. u) annotation (Line(points={{-98,118},{-68,118}}, + color={255,0,255})); + connect(booRep.y,logSwi. u2) annotation (Line(points={{-44,118},{174,118},{174, + 0},{190,0}},color={255,0,255})); + connect(con1.y,logSwi. u1) annotation (Line(points={{154,48},{166,48},{166,8}, + {190,8}}, color={255,0,255})); + connect(uPlaEna, not3.u) annotation (Line(points={{-300,90},{-220,90},{-220,118}, + {-202,118}}, color={255,0,255})); + connect(chaPumSta3.yHotWatPum, logSwi.u3) annotation (Line(points={{84,-172},{ + 122,-172},{122,-174},{174,-174},{174,-8},{190,-8}}, color={255,0,255})); + connect(chaPumSta2.yHotWatPum, logSwi.u3) annotation (Line(points={{82,-34},{174, + -34},{174,-8},{190,-8}}, color={255,0,255})); + connect(chaPumSta4.yHotWatPum, logSwi.u3) annotation (Line(points={{80,18},{158, + 18},{158,-8},{190,-8}}, color={255,0,255})); + connect(logSwi.y, yHotWatPum) + annotation (Line(points={{214,0},{300,0}}, color={255,0,255})); + connect(logSwi.y, pumSpeLocDp.uHotWatPum) annotation (Line(points={{214,0},{274, + 0},{274,-264},{-74,-264},{-74,-326},{-62,-326}}, color={255,0,255})); + connect(logSwi.y, pumSpeRemDp.uHotWatPum) annotation (Line(points={{214,0},{274, + 0},{274,-264},{-74,-264},{-74,-362},{-62,-362}}, color={255,0,255})); + connect(booToInt1.y, mulSumInt1.u[1:2]) annotation (Line(points={{-228,-156},{ + -216,-156},{-216,-159.5},{-202,-159.5}}, color={255,127,0})); + connect(min.y, yPumSpe) + annotation (Line(points={{182,-400},{300,-400}}, color={0,0,127})); +annotation (defaultComponentName="secPumCon", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-280,-440},{280,260}}), + graphics={ + Rectangle( + extent={{-276,256},{274,60}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{206,248},{270,232}}, + 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},{274,-136}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{192,52},{270,36}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable next lag pump"), + Text( + extent={{188,-126},{266,-136}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable last lag pump"), + Rectangle( + extent={{-278,-270},{274,-436}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{220,-272},{266,-284}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Pump speed"), + Rectangle( + extent={{-276,-140},{274,-266}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{76,-142},{264,-156}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable/Disable lag pumps for fixed-speed secondary pumps")}), + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-200},{100,200}}), + graphics={ + Rectangle( + extent={{-100,-200},{100,200}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,250},{100,210}}, + 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=" +

+Secondary hot water pump control sequence per ASHRAE RP-1711, March, 2020 draft, +section 5.3.7. It consists of: +

+ +

+The parameter values for valid pump configurations are as follows: +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Boolean Parameters/Plant configurations12345
have_varSecPumTRUETRUETRUETRUEFALSE
have_secFloSenTRUETRUEFALSEFALSEFALSE
speConTyplocalDPremoteDPlocalDPremoteDPNA
+", +revisions=" + +")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/EnableLag_pumpSpeed.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/EnableLag_pumpSpeed.mo new file mode 100644 index 00000000000..3878a70d423 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/EnableLag_pumpSpeed.mo @@ -0,0 +1,267 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences; +block EnableLag_pumpSpeed + "Sequence for enabling and disabling lag pumps for variable-speed secondary pumps with no secondary loop flowrate sensor" + + parameter Real speLim( + final unit="1", + displayUnit="1") = 0.9 + "Speed limit with longer enable delay for enabling next lag pump"; + + parameter Real speLim1( + final unit="1", + displayUnit="1") = 0.99 + "Speed limit with shorter enable delay for enabling next lag pump"; + + parameter Real speLim2( + final unit="1", + displayUnit="1") = 0.4 + "Speed limit for disabling last lag pump"; + + parameter Real timPer( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Delay time period for enabling next lag pump at speed limit speLim"; + + parameter Real timPer1( + final unit="s", + displayUnit="s", + final quantity="time") = 60 + "Delay time period for enabling next lag pump at speed limit speLim1"; + + parameter Real timPer2( + final unit="s", + displayUnit="s", + final quantity="time") = 600 + "Delay time period for disabling last lag pump"; + + parameter Real sigDif( + final unit="1", + displayUnit="1") = 0.01 + "Constant value used in hysteresis for checking pump speed" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uPumSpe( + final unit="1", + displayUnit="1") + "Calculated pump speed" + annotation (Placement(transformation(extent={{-180,-20},{-140,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yUp + "Next lag pump status" + annotation (Placement(transformation(extent={{140,10},{180,50}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yDown + "Last lag pump status" + annotation (Placement(transformation(extent={{140,-110},{180,-70}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=timPer) + "Hysteresis loop enable timer" + annotation (Placement(transformation(extent={{-70,50},{-50,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim1( + final t=timPer1) + "Hysteresis loop enable timer" + annotation (Placement(transformation(extent={{-70,-10},{-50,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim2( + final t=timPer2) + "Hysteresis loop enable timer" + annotation (Placement(transformation(extent={{-50,-100},{-30,-80}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=speLim - sigDif, + final uHigh=speLim) + "Hysteresis for enabling next lag pump at speed limit speLim" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=speLim1 - sigDif, + final uHigh=speLim1) + "Hysteresis for enabling next lag pump at speed limit speLim1" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys2( + final uLow=speLim2, + final uHigh=speLim2 + sigDif) + "Hysteresis for disabling last lag pump" + annotation (Placement(transformation(extent={{-120,-100},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Edge detector" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{70,90},{90,110}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical And" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Logical Or" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Edge detector" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Logical Not" + annotation (Placement(transformation(extent={{70,-50},{90,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Logical And" + annotation (Placement(transformation(extent={{100,-50},{120,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical Not" + annotation (Placement(transformation(extent={{-90,-100},{-70,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Logical pre block" + annotation (Placement(transformation(extent={{10,-140},{30,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg2 + "Edge detector" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4 + "Logical Not" + annotation (Placement(transformation(extent={{70,-140},{90,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical And" + annotation (Placement(transformation(extent={{100,-140},{120,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not5 + "Logical Not" + annotation (Placement(transformation(extent={{70,-100},{90,-80}}))); + +equation + connect(uPumSpe, hys.u) annotation (Line(points={{-160,0},{-130,0},{-130,60},{ + -122,60}},color={0,0,127})); + + connect(uPumSpe, hys1.u) + annotation (Line(points={{-160,0},{-122,0}},color={0,0,127})); + + connect(uPumSpe, hys2.u) annotation (Line(points={{-160,0},{-130,0},{-130,-90}, + {-122,-90}},color={0,0,127})); + + connect(edg.y, not1.u) + annotation (Line(points={{62,100},{68,100}}, color={255,0,255})); + + connect(not1.y, and2.u1) + annotation (Line(points={{92,100},{98,100}}, color={255,0,255})); + + connect(hys.y, and2.u2) annotation (Line(points={{-98,60},{-90,60},{-90,80},{94, + 80},{94,92},{98,92}}, color={255,0,255})); + + connect(and2.y, tim.u) annotation (Line(points={{122,100},{132,100},{132,86},{ + -80,86},{-80,60},{-72,60}}, color={255,0,255})); + + connect(or2.y, yUp) + annotation (Line(points={{122,30},{160,30}}, color={255,0,255})); + + connect(edg1.y, not2.u) + annotation (Line(points={{62,-40},{68,-40}}, + color={255,0,255})); + + connect(not2.y, and1.u1) + annotation (Line(points={{92,-40},{98,-40}}, + color={255,0,255})); + + connect(and1.y, tim1.u) annotation (Line(points={{122,-40},{130,-40},{130,-16}, + {-80,-16},{-80,0},{-72,0}}, + color={255,0,255})); + + connect(hys1.y, and1.u2) annotation (Line(points={{-98,0},{-90,0},{-90,-20},{96, + -20},{96,-48},{98,-48}}, color={255,0,255})); + + connect(hys2.y, not3.u) + annotation (Line(points={{-98,-90},{-92,-90}}, color={255,0,255})); + + connect(not3.y, and3.u2) annotation (Line(points={{-68,-90},{-60,-90},{-60,-150}, + {94,-150},{94,-138},{98,-138}}, color={255,0,255})); + + connect(not4.y, and3.u1) + annotation (Line(points={{92,-130},{98,-130}}, color={255,0,255})); + + connect(and3.y, tim2.u) annotation (Line(points={{122,-130},{130,-130},{130,-110}, + {-56,-110},{-56,-90},{-52,-90}}, color={255,0,255})); + + connect(pre2.y, edg2.u) + annotation (Line(points={{32,-130},{38,-130}}, color={255,0,255})); + + connect(edg2.y, not4.u) + annotation (Line(points={{62,-130},{68,-130}}, color={255,0,255})); + + connect(not5.y, yDown) + annotation (Line(points={{92,-90},{160,-90}}, color={255,0,255})); + + connect(pre1.y, edg1.u) + annotation (Line(points={{22,-40},{38,-40}}, color={255,0,255})); + + connect(pre1.y, edg.u) annotation (Line(points={{22,-40},{30,-40},{30,100},{38, + 100}}, color={255,0,255})); + + connect(tim.passed, or2.u1) annotation (Line(points={{-48,52},{90,52},{90,30}, + {98,30}}, color={255,0,255})); + connect(tim1.passed, or2.u2) annotation (Line(points={{-48,-8},{90,-8},{90,22}, + {98,22}}, color={255,0,255})); + connect(tim2.passed, not5.u) annotation (Line(points={{-28,-98},{50,-98},{50, + -90},{68,-90}}, color={255,0,255})); + connect(or2.y, pre1.u) annotation (Line(points={{122,30},{130,30},{130,-12},{ + -20,-12},{-20,-40},{-2,-40}}, color={255,0,255})); + connect(tim2.passed, pre2.u) annotation (Line(points={{-28,-98},{0,-98},{0, + -130},{8,-130}}, color={255,0,255})); +annotation ( +defaultComponentName="enaLagSecPum", +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")}), +Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-140,-160},{140,160}})), +Documentation(info=" +

+Block that enables and disables lag secondary hot water pump, for plants with +variable-speed secondary pumps and no flowrate sensor in secondary loop, according +to ASHRAE RP-1711, March, 2020 draft, section 5.3.7.4. +

+
    +
  1. +Stage up yUp = true when speed uPumSpe exceeds speed limit +speLim for time period timPer or speLim1 +for timPer1. +
  2. +
  3. +Stage down yDown = false when uPumSpe falls below speLim2 +for timPer2. +
  4. +
+", revisions=" + +")); +end EnableLag_pumpSpeed; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/EnableLead.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/EnableLead.mo new file mode 100644 index 00000000000..267f360948b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/EnableLead.mo @@ -0,0 +1,77 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences; +block EnableLead + "Sequence to enable or disable the lead secondary pump of boiler plants" + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPlaEna + "Primary pump status signal" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput supResReq + "Hot water supply reset requests" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + 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.Integers.GreaterThreshold intGreThr + "Check if any hot water requests are being generated" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical And" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + +equation + connect(supResReq, intGreThr.u) + annotation (Line(points={{-120,-40},{-82,-40}}, color={255,127,0})); + + connect(intGreThr.y, and2.u2) annotation (Line(points={{-58,-40},{-40,-40},{-40, + -8},{-22,-8}}, color={255,0,255})); + + connect(and2.y, yLea) + annotation (Line(points={{2,0},{120,0}}, color={255,0,255})); + + connect(uPlaEna, and2.u1) annotation (Line(points={{-120,40},{-40,40},{-40,0}, + {-22,0}}, color={255,0,255})); + +annotation ( + defaultComponentName="enaLeaSecPum", + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

+ Block that enables and disables lead secondary hot water pump, for plants + with variable-speed hot water pumps, according to ASHRAE RP-1711, March 2020 draft, + section 5.3.7.2. +

+ + ", revisions=" + + ")); +end EnableLead; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLag_pumpSpeed.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLag_pumpSpeed.mo new file mode 100644 index 00000000000..583e97a0d70 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLag_pumpSpeed.mo @@ -0,0 +1,77 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.Validation; +model EnableLag_pumpSpeed + "Validate sequence for enabling variable-speed secondary lag pumps with no flowrate sensor in secondary loop" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.EnableLag_pumpSpeed + enaLagSecPum( + final speLim=0.9, + final speLim1=0.99, + final speLim2=0.4, + final timPer=300, + final timPer1=60, + final timPer2=600, + final sigDif=0.01) "Test instance for speed-limit speLim" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yUp( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold stage-up signal for easy visualization" + annotation (Placement(transformation(extent={{50,20},{70,40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yDow( + final trueHoldDuration=0, + final falseHoldDuration=10) + "Hold stage-down signal for easy visualization" + annotation (Placement(transformation(extent={{50,-40},{70,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram( + final height=1, + final duration=3500, + final offset=0, + final startTime=0) + "Ramp input" + annotation (Placement(transformation(extent={{-70,-10},{-50,10}}))); + +equation + connect(enaLagSecPum.yUp, yUp.u) annotation (Line(points={{12,4},{20,4},{20,30}, + {48,30}}, color={255,0,255})); + + connect(enaLagSecPum.yDown, yDow.u) annotation (Line(points={{12,-4},{20,-4},{ + 20,-30},{48,-30}}, color={255,0,255})); + + connect(ram.y, enaLagSecPum.uPumSpe) + annotation (Line(points={{-48,0},{-12,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/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLag_pumpSpeed.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.EnableLag_pumpSpeed. +

+", 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_pumpSpeed; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLead.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLead.mo new file mode 100644 index 00000000000..be81c0de799 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLead.mo @@ -0,0 +1,67 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.Validation; +model EnableLead + "Validate sequence for enabling lead secondary pump of boiler plants" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.EnableLead + enaLeaSecPum + "Enable lead hot water pump based on the status of plant and hot water requests" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=5) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-50,10},{-30,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final amplitude=1, + final period=10, + final offset=0) + "Real pulse signal" + annotation (Placement(transformation(extent={{-90,-30},{-70,-10}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-50,-30},{-30,-10}}))); + +equation + connect(pul.y, reaToInt.u) + annotation (Line(points={{-68,-20},{-52,-20}}, color={0,0,127})); + + connect(reaToInt.y, enaLeaSecPum.supResReq) annotation (Line(points={{-28,-20}, + {-10,-20},{-10,-4},{-2,-4}}, color={255,127,0})); + + connect(booPul.y, enaLeaSecPum.uPlaEna) annotation (Line(points={{-28,20},{ + -10,20},{-10,4},{-2,4}}, color={255,0,255})); + +annotation ( + experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/EnableLead.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Subsequences.EnableLead. +

+ ", 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; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..b778f494d9b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/package.mo @@ -0,0 +1,39 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.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.BoilerPlant.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/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/package.order new file mode 100644 index 00000000000..6cf6638457d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/Validation/package.order @@ -0,0 +1,2 @@ +EnableLag_pumpSpeed +EnableLead diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/package.mo new file mode 100644 index 00000000000..136ecf7adaa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps; +package Subsequences "Hot water pump control sequences" + + + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains subsequences for hot 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/BoilerPlant/Pumps/SecondaryPumps/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/package.order new file mode 100644 index 00000000000..49635de3cc6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Subsequences/package.order @@ -0,0 +1,3 @@ +EnableLag_pumpSpeed +EnableLead +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/Controller.mo new file mode 100644 index 00000000000..8bc06539057 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/Controller.mo @@ -0,0 +1,606 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Validation; +model Controller + "Validate boiler water pump control sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Controller + secPumCon( + final have_varSecPum=true, + final have_secFloSen=true, + final nPum=2, + final nPumPri=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final maxLocDp=5*6894.75, + final minLocDp=5*6894.75, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=10, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP) + "Testing pump configuration 1" + annotation (Placement(transformation(extent={{-100,140},{-80,180}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Controller + secPumCon1( + final have_varSecPum=true, + final have_secFloSen=true, + final nPum=2, + final nPumPri=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.localDP) + "Testing pump configuration 2" + annotation (Placement(transformation(extent={{200,130},{220,170}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Controller + secPumCon2( + final have_varSecPum=true, + final have_secFloSen=false, + final nPum=2, + final nPumPri=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final speLim=0.9, + final speLim1=0.99, + final speLim2=0.4, + final timPer1=300, + final timPer2=60, + final timPer3=600, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP) + "Testing pump configuration 3" + annotation (Placement(transformation(extent={{-100,-30},{-80,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Controller + secPumCon3( + final have_varSecPum=true, + final have_secFloSen=false, + final nPum=2, + final nPumPri=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final speLim=0.9, + final speLim1=0.99, + final speLim2=0.4, + final timPer1=300, + final timPer2=60, + final timPer3=600, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1, + final speConTyp=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.localDP) + "Testing pump configuration 4" + annotation (Placement(transformation(extent={{200,-50},{220,-10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.Controller + secPumCon4( + final have_varSecPum=false, + final nPum=2, + final nPumPri=2, + final nBoi=2, + final nSen=2, + final nPum_nominal=2, + final minPumSpe=0.1, + final maxPumSpe=1, + final VHotWat_flow_nominal=0.5, + final maxLocDp=10, + final minLocDp=5, + final offTimThr=180, + final timPer=600, + final staCon=-0.03, + final relFloHys=0.01, + final k=1, + final Ti=0.5, + final Td=0.1) "Testing pump configuration 5" + annotation (Placement(transformation(extent={{-100,-230},{-80,-190}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=1, + final period=3600, + final shift=10) + "Boolean pulse" + annotation (Placement(transformation(extent={{-260,190},{-240,210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final amplitude=2, + final width=1, + final period=3500, + final offset=0, + final shift=10) + "Real pulse" + annotation (Placement(transformation(extent={{-270,150},{-250,170}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-240,150},{-220,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=1, + final period=3600, + final shift=10) + "Boolean pulse" + annotation (Placement(transformation(extent={{50,200},{70,220}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{70,160},{90,180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul1( + final amplitude=2, + final width=1, + final period=3500, + final offset=0, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{40,160},{60,180}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.9, + final period=3600, + final shift=10) + "Boolean pulse" + annotation (Placement(transformation(extent={{-260,50},{-240,70}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-220,10},{-200,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul2( + final amplitude=2, + final width=1, + final period=3500, + final offset=0, + final shift=10) + "Real pulse" + annotation (Placement(transformation(extent={{-260,10},{-240,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3( + final width=0.9, + final period=3600, + final shift=10) + "Boolean pulse" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul3( + final amplitude=2, + final width=1, + final period=3500, + final offset=0, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul4( + final width=1, + final period=3600, + final shift=10) + "Boolean pulse" + annotation (Placement(transformation(extent={{-240,-180},{-220,-160}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt4 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-220,-220},{-200,-200}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul4( + final amplitude=2, + final width=1, + final period=3500, + final offset=0, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{-250,-220},{-230,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul5( + final width=0.5, + final period=900, + final shift=60) + "Boolean pulse" + annotation (Placement(transformation(extent={{-240,-260},{-220,-240}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul5( + final amplitude=0.6, + final width=0.5, + final period=3600, + final offset=0.35, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{-260,100},{-240,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul6( + final amplitude=0.6, + final width=0.5, + final period=3600, + final offset=0.35, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul7( + final amplitude=0.6, + final width=0.5, + final period=3600, + final offset=0.35, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{-260,-110},{-240,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul8( + final amplitude=0.6, + final width=0.5, + final period=3600, + final offset=0.35, + final shift=0) + "Real pulse" + annotation (Placement(transformation(extent={{40,-170},{60,-150}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-150,200},{-130,220}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin[2]( + final amplitude=fill(0.5, 2), + final freqHz=fill(1/1800, 2), + final offset=fill(1, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{-200,120},{-180,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{-200,150},{-180,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{150,190},{170,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{240,140},{260,160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin2[2]( + final amplitude=fill(0.5, 2), + final freqHz=fill(1/1800, 2), + final offset=fill(1, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin3( + final amplitude=0.1, + final freqHz=1/3600, + final offset=0.25) + "Sine signal" + annotation (Placement(transformation(extent={{40,130},{60,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin4( + final amplitude=5, + final freqHz=1/900, + final offset=7.5) + "Sine signal" + annotation (Placement(transformation(extent={{160,70},{180,90}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-150,20},{-130,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-40,-20},{-20,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{150,10},{170,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre4[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{240,-40},{260,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4[2]( + final k={2,1}) + "Pump rotation" + annotation (Placement(transformation(extent={{-150,-170},{-130,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre5[2]( + final pre_u_start=fill(false, 2)) + "Logical pre block" + annotation (Placement(transformation(extent={{-60,-220},{-40,-200}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{-190,200},{-170,220}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{120,110},{140,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con4( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{-260,-70},{-240,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin6[2]( + final amplitude=fill(0.5, 2), + final freqHz=fill(1/1800, 2), + final offset=fill(1, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{-260,-30},{-240,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin5( + final amplitude=5, + final freqHz=1/900, + final offset=7.5) + "Sine signal" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin7[2]( + final amplitude=fill(0.5, 2), + final freqHz=fill(1/1800, 2), + final offset=fill(1, 2)) + "Sine signal" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con6( + final k=1) + "Constant Real source" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + +equation + connect(conInt.y,secPumCon. uPumLeaLag) annotation (Line(points={{-128,210},{-110, + 210},{-110,178.2},{-102,178.2}}, + color={255,127,0})); + + connect(secPumCon.yHotWatPum, pre1.u) + annotation (Line(points={{-78,160},{-62,160}}, color={255,0,255})); + + connect(sin1.y,secPumCon. VHotWat_flow) annotation (Line(points={{-178,160},{-124, + 160},{-124,162},{-102,162}}, color={0,0,127})); + + connect(sin.y,secPumCon. dpHotWat_remote) annotation (Line(points={{-178,130}, + {-116,130},{-116,150},{-102,150}}, color={0,0,127})); + + connect(conInt1.y,secPumCon1. uPumLeaLag) annotation (Line(points={{172,200},{ + 190,200},{190,168.2},{198,168.2}}, + color={255,127,0})); + + connect(secPumCon1.yHotWatPum, pre2.u) + annotation (Line(points={{222,150},{238,150}}, color={255,0,255})); + + connect(sin3.y,secPumCon1. VHotWat_flow) annotation (Line(points={{62,140},{ + 70,140},{70,156},{160,156},{160,152},{198,152}}, + color={0,0,127})); + + connect(sin2.y,secPumCon1. dpHotWat_remote) annotation (Line(points={{102,140}, + {198,140}}, color={0,0,127})); + + connect(sin4.y,secPumCon1. dpHotWat_local) annotation (Line(points={{182,80},{ + 194,80},{194,144},{198,144}}, color={0,0,127})); + + connect(conInt2.y,secPumCon2. uPumLeaLag) annotation (Line(points={{-128,30}, + {-110,30},{-110,8.2},{-102,8.2}}, + color={255,127,0})); + + connect(conInt3.y,secPumCon3. uPumLeaLag) annotation (Line(points={{172,20},{190, + 20},{190,-11.8},{198,-11.8}}, color={255,127,0})); + + connect(secPumCon3.yHotWatPum,pre4. u) + annotation (Line(points={{222,-30},{238,-30}}, color={255,0,255})); + + connect(conInt4.y,secPumCon4. uPumLeaLag) annotation (Line(points={{-128,-160}, + {-110,-160},{-110,-191.8},{-102,-191.8}}, + color={255,127,0})); + + connect(secPumCon4.yHotWatPum,pre5. u) + annotation (Line(points={{-78,-210},{-62,-210}}, + color={255,0,255})); + + connect(con1.y,secPumCon. dpHotWatSet) annotation (Line(points={{-168,210},{-164, + 210},{-164,146},{-102,146}}, color={0,0,127})); + + connect(pre1.y,secPumCon. uHotWatPum) annotation (Line(points={{-38,160},{-30, + 160},{-30,200},{-114,200},{-114,174},{-102,174}}, color={255,0, + 255})); + + connect(pre2.y,secPumCon1. uHotWatPum) annotation (Line(points={{262,150},{270, + 150},{270,220},{120,220},{120,164},{198,164}}, color={255,0,255})); + + connect(con3.y,secPumCon1. dpHotWatSet) annotation (Line(points={{142,120},{170, + 120},{170,136},{198,136}}, color={0,0,127})); + + connect(pre3.y,secPumCon2. uHotWatPum) annotation (Line(points={{-18,-10},{ + -10,-10},{-10,60},{-160,60},{-160,4},{-102,4}}, color={255,0, + 255})); + + connect(pre4.y,secPumCon3. uHotWatPum) annotation (Line(points={{262,-30},{270, + -30},{270,40},{140,40},{140,-16},{198,-16}}, color={255,0,255})); + + connect(pre5.y,secPumCon4. uHotWatPum) annotation (Line(points={{-38,-210},{ + -30,-210},{-30,-140},{-160,-140},{-160,-196},{-102,-196}}, + color={255,0, + 255})); + + connect(sin6.y,secPumCon2. dpHotWat_remote) annotation (Line(points={{-238, + -20},{-102,-20}}, color={0,0,127})); + + connect(con4.y,secPumCon2. dpHotWatSet) annotation (Line(points={{-238,-60},{ + -140,-60},{-140,-24},{-102,-24}}, + color={0,0,127})); + + connect(sin5.y,secPumCon3. dpHotWat_local) annotation (Line(points={{62,-40}, + {150,-40},{150,-36},{198,-36}}, + color={0,0,127})); + + connect(sin7.y,secPumCon3. dpHotWat_remote) annotation (Line(points={{62,-80}, + {160,-80},{160,-40},{198,-40}}, color={0,0,127})); + + connect(con6.y,secPumCon3. dpHotWatSet) annotation (Line(points={{62,-120},{ + 174,-120},{174,-44},{198,-44}},color={0,0,127})); + + connect(booPul.y,secPumCon. uPlaEna) annotation (Line(points={{-238,200},{-200, + 200},{-200,190},{-120,190},{-120,170},{-102,170}}, color={255,0,255})); + + connect(reaToInt.u, pul.y) + annotation (Line(points={{-242,160},{-248,160}}, color={0,0,127})); + + connect(reaToInt.y,secPumCon. supResReq) annotation (Line(points={{-218,160},{ + -210,160},{-210,180},{-126,180},{-126,166},{-102,166}}, color={255, + 127,0})); + + connect(booPul1.y,secPumCon1. uPlaEna) annotation (Line(points={{72,210},{140, + 210},{140,160},{198,160}}, color={255,0,255})); + + connect(pul1.y, reaToInt1.u) + annotation (Line(points={{62,170},{68,170}}, color={0,0,127})); + + connect(reaToInt1.y,secPumCon1. supResReq) annotation (Line(points={{92,170}, + {164,170},{164,156},{198,156}}, color={255,127,0})); + + connect(booPul2.y,secPumCon2. uPlaEna) annotation (Line(points={{-238,60},{ + -164,60},{-164,0},{-102,0}}, + color={255,0,255})); + + connect(pul2.y, reaToInt2.u) + annotation (Line(points={{-238,20},{-222,20}}, color={0,0,127})); + + connect(reaToInt2.y,secPumCon2. supResReq) annotation (Line(points={{-198,20}, + {-168,20},{-168,-4},{-102,-4}}, color={255,127,0})); + + connect(booPul3.y,secPumCon3. uPlaEna) annotation (Line(points={{62,40},{134,40}, + {134,-20},{198,-20}}, + color={255,0,255})); + + connect(pul3.y, reaToInt3.u) + annotation (Line(points={{62,0},{78,0}}, color={0,0,127})); + + connect(reaToInt3.y,secPumCon3. supResReq) annotation (Line(points={{102,0},{ + 128,0},{128,-24},{198,-24}},color={255,127,0})); + + connect(booPul4.y,secPumCon4. uPlaEna) annotation (Line(points={{-218,-170},{ + -164,-170},{-164,-200},{-102,-200}}, + color={255,0,255})); + + connect(pul4.y, reaToInt4.u) + annotation (Line(points={{-228,-210},{-222,-210}}, color={0,0,127})); + + connect(reaToInt4.y,secPumCon4. supResReq) annotation (Line(points={{-198, + -210},{-180,-210},{-180,-204},{-102,-204}}, + color={255,127,0})); + + connect(booPul4.y,secPumCon4. uPriPumSta[1]) annotation (Line(points={{-218, + -170},{-164,-170},{-164,-213},{-102,-213}}, + color={255,0,255})); + + connect(booPul5.y,secPumCon4. uPriPumSta[2]) annotation (Line(points={{-218, + -250},{-170,-250},{-170,-211},{-102,-211}}, + color={255,0,255})); + + connect(pul5.y,secPumCon. uMaxSecPumSpeCon) annotation (Line(points={{-238,110}, + {-110,110},{-110,142},{-102,142}}, color={0,0,127})); + + connect(pul6.y,secPumCon1. uMaxSecPumSpeCon) annotation (Line(points={{82,100}, + {186,100},{186,132},{198,132}}, color={0,0,127})); + + connect(pul7.y,secPumCon2. uMaxSecPumSpeCon) annotation (Line(points={{-238, + -100},{-110,-100},{-110,-28},{-102,-28}}, + color={0,0,127})); + + connect(pul8.y,secPumCon3. uMaxSecPumSpeCon) annotation (Line(points={{62,-160}, + {190,-160},{190,-48},{198,-48}}, color={0,0,127})); + + connect(secPumCon2.yHotWatPum, pre3.u) + annotation (Line(points={{-78,-10},{-42,-10}}, color={255,0,255})); +annotation ( + experiment( + StopTime=3600, + Interval=0.5, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps.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={{-300,-300},{300,300}}))); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/package.mo new file mode 100644 index 00000000000..97dff2ffbf2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps.SecondaryPumps; +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.BoilerPlant.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/BoilerPlant/Pumps/SecondaryPumps/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/package.mo new file mode 100644 index 00000000000..c3e5c8d4819 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/package.mo @@ -0,0 +1,33 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Pumps; +package SecondaryPumps "Sequences for secondary hot water pump control" + + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for hot water pumps. +The implementations are based on section 5.2.6 Primary hot water pumps, +in ASHRAE RP-1711 (Draft 6 on July 25, 2019). +

+"), + 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={255,0,0}, + fillPattern=FillPattern.Solid)})); +end SecondaryPumps; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/package.order new file mode 100644 index 00000000000..9ffbffcb990 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/SecondaryPumps/package.order @@ -0,0 +1,3 @@ +Controller +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/package.mo new file mode 100644 index 00000000000..98b5cd792ee --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/package.mo @@ -0,0 +1,47 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package Pumps "Sequences for condenser water and boiler water pumps control" + + +annotation ( +preferredView="info", Documentation(info=" +

+This package contains control sequences for primary and secondary hot water pumps. +The implementations are based on sections 5.3.6 and 5.3.7 in ASHRAE RP-1711, +March 2020 draft. +

+"), +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/BoilerPlant/Pumps/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/package.order new file mode 100644 index 00000000000..cf1240b15f6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Pumps/package.order @@ -0,0 +1,3 @@ +Generic +PrimaryPumps +SecondaryPumps diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/CondensationControl.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/CondensationControl.mo new file mode 100644 index 00000000000..9dfbae29516 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/CondensationControl.mo @@ -0,0 +1,231 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints; +block CondensationControl + "Sequence to calculate setpoint limits for condensation control in non-condesing boilers" + + parameter Boolean have_priOnl = false + "True: Primary-only plant; False: Primary-secondary plant"; + + parameter Boolean have_varPriPum = true + "True: Variable speed pumps in primary loop; False: Constant speed pumps in primary loop" + annotation(Evaluate=true,Dialog(enable=(not have_priOnl))); + + parameter Integer nSta=5 + "Number of stages"; + + parameter Real TRetSet( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") = 60 + "Minimum hot water return temperature for optimal non-condensing boiler performance"; + + parameter Real TRetMinAll( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") = 57.2 + "Minimum allowed hot water return temperature for non-condensing boiler"; + + parameter Real minSecPumSpe( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) = 0 + "Minimum secondary pump speed"; + + parameter Real minPriPumSpeSta[nSta]( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) = {0,0,0,0,0} + "Vector of minimum primary pump speed for each stage"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uCurSta + "Current stage" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaTyp[nSta] + "Stage type vector" + annotation (Placement(transformation(extent={{-140,-90},{-100,-50}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatRet( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water return temperature" + annotation (Placement(transformation(extent={{-140,50},{-100,90}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinBypValPos( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) if have_priOnl + "Minimum allowed setpoint of bypass valve position" + annotation (Placement(transformation(extent={{100,30},{140,70}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinPriPumSpe( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) if (have_varPriPum and not have_priOnl) + "Minimum allowed primary pump speed" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMaxSecPumSpe( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) if not have_priOnl + "Maximum allowed secondary pump speed" + annotation (Placement(transformation(extent={{100,-70},{140,-30}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Pass 0 regulation signal if stage type is not non-condensing" + annotation (Placement(transformation(extent={{-50,40},{-30,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=0) + "Zero source" + annotation (Placement(transformation(extent={{-90,20},{-70,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.ProportionalRegulator proReg( + final TRetSet=TRetSet, + final TRetMinAll=TRetMinAll) + "Proportional regulator" + annotation (Placement(transformation(extent={{-90,60},{-70,80}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nSta) + "Identify stage type for current stage" + annotation (Placement(transformation(extent={{-50,-80},{-30,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta] + "Integer to Real conversion" + annotation (Placement(transformation(extent={{-90,-80},{-70,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr( + final t=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler) + "Identify if current stage is condensing type or non-condensing type" + annotation (Placement(transformation(extent={{-10,-80},{10,-60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.PumpSpeedLimits pumSpeLim( + final have_varPriPum=have_varPriPum, + final nSta=nSta, + final minSecPumSpe=minSecPumSpe, + final minPriPumSpeSta=minPriPumSpeSta) if not have_priOnl + "Block to calculate pump speed limits" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + +equation + connect(THotWatRet, proReg.THotWatRet) + annotation (Line(points={{-120,70},{-92,70}}, + color={0,0,127})); + + connect(yMinBypValPos, yMinBypValPos) + annotation (Line(points={{120,50},{120,50}}, color={0,0,127})); + + connect(uStaTyp, intToRea.u) + annotation (Line(points={{-120,-70},{-92,-70}}, + color={255,127,0})); + + connect(intToRea.y, extIndSig.u) + annotation (Line(points={{-68,-70},{-52,-70}}, + color={0,0,127})); + + connect(uCurSta, extIndSig.index) annotation (Line(points={{-120,0},{-60,0},{-60, + -90},{-40,-90},{-40,-82}}, + color={255,127,0})); + + connect(extIndSig.y, greThr.u) + annotation (Line(points={{-28,-70},{-12,-70}}, + color={0,0,127})); + + connect(proReg.yRegSig, swi.u1) annotation (Line(points={{-68,70},{-60,70},{-60, + 58},{-52,58}}, color={0,0,127})); + connect(greThr.y, swi.u2) annotation (Line(points={{12,-70},{20,-70},{20,-50}, + {-56,-50},{-56,50},{-52,50}}, color={255,0,255})); + connect(swi.y, yMinBypValPos) annotation (Line(points={{-28,50},{120,50}}, + color={0,0,127})); + connect(con.y, swi.u3) annotation (Line(points={{-68,30},{-60,30},{-60,42},{-52, + 42}}, color={0,0,127})); + connect(swi.y, pumSpeLim.uRegSig) annotation (Line(points={{-28,50},{-20,50},{ + -20,-5},{-12,-5}}, color={0,0,127})); + connect(uCurSta, pumSpeLim.uCurSta) annotation (Line(points={{-120,0},{-60,0}, + {-60,5},{-12,5}}, color={255,127,0})); + connect(pumSpeLim.yMinPriPumSpe, yMinPriPumSpe) + annotation (Line(points={{12,5},{30,5},{30,0},{120,0}},color={0,0,127})); + connect(pumSpeLim.yMaxSecPumSpe, yMaxSecPumSpe) annotation (Line(points={{12,-5}, + {30,-5},{30,-50},{120,-50}}, color={0,0,127})); + annotation (defaultComponentName= + "conSet", + Icon(graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineThickness=0.1), + 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)}, + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Documentation( + info=" +

+ Block that generates condensation control setpoints according to ASHRAE RP-1711, + March, 2020 draft, section 5.3.5. +

+

+ The sequence calculates the condensation control setpoints for minimum bypass + valve position yMinBypValPos, minimum primary pump speed yMinPriPumSpe + and maximum secondary pump speed yMaxSecPumSpe using the following calculations: +

    +
  1. + Block proReg implemented in the class + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.ProportionalRegulator + uses the measured hot water return temperature THotWatRet to generate a regulation signal with P-only control loop. +
  2. +
  3. + The regulation signal is used as is for yMinBypValPos. +
  4. +
  5. + The regulation signal is used by block pumSpeLim implemented in the class + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.PumpSpeedLimits + to generate the pump speed limits yMinPriPumSpe and yMaxSecPumSpe. +
  6. +
+ ", + revisions=" + + ")); +end CondensationControl; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/HotWaterSupplyTemperatureReset.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/HotWaterSupplyTemperatureReset.mo new file mode 100644 index 00000000000..332be685ed4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/HotWaterSupplyTemperatureReset.mo @@ -0,0 +1,445 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints; +block HotWaterSupplyTemperatureReset + "Block to calculate temperature setpoint for hot water supply temperature" + + parameter Integer nPum = 2 + "Number of pumps in the boiler plant loop" + annotation(Dialog(group="Plant parameters")); + + parameter Integer nSta = 3 + "Number of stages in the boiler plant" + annotation(Dialog(group="Plant parameters")); + + parameter Integer nBoi = 2 + "Number of boilers in the plant" + annotation(Dialog(group="Plant parameters")); + + parameter Integer nHotWatResReqIgn = 2 + "Number of hot-water supply temperature reset requests to be ignored" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Integer boiTyp[nBoi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler} + "Boiler type vector" + annotation(Dialog(group="Plant parameters")); + + parameter Real TPlaHotWatSetMax( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 353.15 + "The maximum allowed hot-water setpoint temperature for the plant" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real TConBoiHotWatSetMax( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 353.15 + "The maximum allowed hot water setpoint temperature for condensing boilers" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real TConBoiHotWatSetOff( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = -10 + "The offset for hot water setpoint temperature for condensing boilers in + non-condensing stage type" + annotation(Dialog(group="Plant parameters")); + + parameter Real THotWatSetMinNonConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 341.48 + "The minimum allowed hot-water setpoint temperature for non-condensing boilers" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real THotWatSetMinConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 305.37 + "The minimum allowed hot-water setpoint temperature for condensing boilers" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real delTimVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Delay time" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real samPerVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Sample period" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real triAmoVal( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = -2 + "Setpoint trim value" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real resAmoVal( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 3 + "Setpoint respond value" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real maxResVal( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 7 + "Setpoint maximum respond value" + annotation(Dialog(group="Trim-and-Respond Logic parameters")); + + parameter Real holTimVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 900 + "Minimum setpoint hold time for stage change process" + annotation(Dialog(group="Plant parameters")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaCha + "Signal indicating plant is in the staging process" + annotation (Placement(transformation(extent={{-180,-20},{-140,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uHotWatPumSta[nPum] + "Status of hot-water pumps" + annotation (Placement(transformation(extent={{-180,70},{-140,110}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nHotWatSupResReq + "Number of hot-water supply temperature reset requests" + annotation (Placement(transformation(extent={{-180,30},{-140,70}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uTyp[nSta] + "Stage type vector for boiler plant" + annotation (Placement(transformation(extent={{-180,-90},{-140,-50}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uCurStaSet + "Current stage setpoint index" + annotation (Placement(transformation(extent={{-180,-140},{-140,-100}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TPlaHotWatSupSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Hot-water supply temperature setpoint for the plant" + annotation (Placement(transformation(extent={{140,-20},{180,20}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TBoiHotWatSupSet[nBoi]( + final unit=fill("K",nBoi), + displayUnit=fill("K",nBoi), + final quantity=fill("ThermodynamicTemperature",nBoi)) + "Temperature setpoint vector for boilers" + annotation (Placement(transformation(extent={{140,-250},{180,-210}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + "Select plant setpoint based on stage type" + annotation (Placement(transformation(extent={{10,60},{30,80}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig(nin=nSta) + "Extract stage type for current stage" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta] + "Integer to Real conversion" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr( + final t=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler) + "Check for non-condensing stage type" + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + + Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond triRes( + final iniSet=TPlaHotWatSetMax, + final minSet=THotWatSetMinNonConBoi, + final maxSet=TPlaHotWatSetMax, + final delTim=delTimVal, + final samplePeriod=samPerVal, + final numIgnReq=nHotWatResReqIgn, + final triAmo=triAmoVal, + final resAmo=resAmoVal, + final maxRes=maxResVal) + "Trim and respond controller for non-condensing stage type" + annotation (Placement(transformation(extent={{-40,80},{-20,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Detect start of stage change process" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueHoldWithReset truHol(duration=holTimVal) + "Hold setpoint value for duration of stage change" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Retain last value before stage change initiates" + annotation (Placement(transformation(extent={{50,40},{70,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nPum) + "Check if any pumps are turned on" + annotation (Placement(transformation(extent={{-120,80},{-100,100}}))); + + Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond triRes1( + final iniSet=TPlaHotWatSetMax, + final minSet=THotWatSetMinConBoi, + final maxSet=TPlaHotWatSetMax, + final delTim=delTimVal, + final samplePeriod=samPerVal, + final numIgnReq=nHotWatResReqIgn, + final triAmo=triAmoVal, + final resAmo=resAmoVal, + final maxRes=maxResVal) + "Trim and respond controller for condensing stage type" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant boiTypVec[nBoi]( + final k=boiTyp) + "Boiler type vector" + annotation (Placement(transformation(extent={{-120,-260},{-100,-240}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold greThr1[nBoi]( + final t=fill(Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler,nBoi)) + "Identify non-condensing boilers in plant" + annotation (Placement(transformation(extent={{-80,-260},{-60,-240}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nBoi]( + final realTrue=fill(0, nBoi), + final realFalse=fill(1, nBoi)) + "Generate binary vector to identify condensing boilers" + annotation (Placement(transformation(extent={{-40,-240},{-20,-220}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[nBoi]( + final realTrue=fill(1, nBoi), + final realFalse=fill(0, nBoi)) + "Generate binary vector to identify non-condensing boilers" + annotation (Placement(transformation(extent={{-40,-280},{-20,-260}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nBoi) + "Convert temperature setpoint into vector" + annotation (Placement(transformation(extent={{10,-200},{30,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[nBoi] + "Element-wise product" + annotation (Placement(transformation(extent={{60,-200},{80,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 + "Logical Switch" + annotation (Placement(transformation(extent={{-40,-200},{-20,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Add add2[nBoi] + "Combine setpoint vectors for condensing and non-condensing boilers" + annotation (Placement(transformation(extent={{100,-240},{120,-220}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=TConBoiHotWatSetMax) + "Design setpoint for condensing boilers" + annotation (Placement(transformation(extent={{-120,-160},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=TConBoiHotWatSetOff) + "Boiler setpoint for condensing boilers in non-condensing type stage" + annotation (Placement(transformation(extent={{-120,-200},{-100,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Min min + "Ensure condensing boiler setpoint does not exceed design setpoint" + annotation (Placement(transformation(extent={{-80,-180},{-60,-160}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1( + final nout=nBoi) + "Convert temperature setpoint into vector" + annotation (Placement(transformation(extent={{10,-310},{30,-290}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[nBoi] + "Element-wise product" + annotation (Placement(transformation(extent={{60,-280},{80,-260}}))); + +equation + connect(uHotWatPumSta, mulOr.u[1:nPum]) annotation (Line(points={{-160,90},{-122, + 90}}, color={255,0,255})); + connect(mulOr.y, triRes.uDevSta) + annotation (Line(points={{-98,90},{-60,90},{-60,98},{-42,98}}, + color={255,0,255})); + connect(truHol.u, uStaCha) + annotation (Line(points={{-42,-30},{-50,-30},{-50,0},{-160,0}}, + color={255,0,255})); + connect(edg.u, uStaCha) annotation (Line(points={{-42,0},{-160,0}}, + color={255,0,255})); + connect(edg.y, triSam.trigger) annotation (Line(points={{-18,0},{60,0},{60,38}}, + color={255,0,255})); + connect(triSam.y, swi.u1) + annotation (Line(points={{72,50},{80,50},{80,8},{98,8}}, color={0,0,127})); + connect(truHol.y, swi.u2) annotation (Line(points={{-18,-30},{80,-30},{80,0},{ + 98,0}}, color={255,0,255})); + connect(triRes.numOfReq, nHotWatSupResReq) annotation (Line(points={{-42,82},{ + -50,82},{-50,50},{-160,50}}, + color={255,127,0})); + connect(swi.y, TPlaHotWatSupSet) + annotation (Line(points={{122,0},{160,0}}, color={0,0,127})); + connect(swi1.y, triSam.u) annotation (Line(points={{32,70},{40,70},{40,50},{48, + 50}}, color={0,0,127})); + connect(triRes.y, swi1.u1) annotation (Line(points={{-18,90},{0,90},{0,78},{8, + 78}}, color={0,0,127})); + connect(triRes1.y, swi1.u3) + annotation (Line(points={{-18,50},{0,50},{0,62},{8,62}}, color={0,0,127})); + connect(triRes1.numOfReq, nHotWatSupResReq) annotation (Line(points={{-42,42}, + {-50,42},{-50,50},{-160,50}}, color={255,127,0})); + connect(triRes1.uDevSta, mulOr.y) annotation (Line(points={{-42,58},{-60,58},{ + -60,90},{-98,90}}, color={255,0,255})); + connect(swi1.y, swi.u3) annotation (Line(points={{32,70},{40,70},{40,-8},{98,-8}}, + color={0,0,127})); + connect(uCurStaSet, extIndSig.index) annotation (Line(points={{-160,-120},{-70, + -120},{-70,-82}}, color={255,127,0})); + connect(extIndSig.u, intToRea.y) + annotation (Line(points={{-82,-70},{-98,-70}}, color={0,0,127})); + connect(intToRea.u, uTyp) + annotation (Line(points={{-122,-70},{-160,-70}}, color={255,127,0})); + connect(extIndSig.y, greThr.u) + annotation (Line(points={{-58,-70},{-42,-70}}, color={0,0,127})); + connect(greThr.y, swi1.u2) annotation (Line(points={{-18,-70},{-10,-70},{-10,70}, + {8,70}}, color={255,0,255})); + connect(boiTypVec.y, greThr1.u) + annotation (Line(points={{-98,-250},{-82,-250}}, color={0,0,127})); + connect(booToRea1.u, greThr1.y) annotation (Line(points={{-42,-270},{-50,-270}, + {-50,-250},{-58,-250}}, color={255,0,255})); + connect(booToRea.u, greThr1.y) annotation (Line(points={{-42,-230},{-50,-230}, + {-50,-250},{-58,-250}}, color={255,0,255})); + connect(add2.y, TBoiHotWatSupSet) + annotation (Line(points={{122,-230},{160,-230}}, color={0,0,127})); + connect(swi2.u2, greThr.y) annotation (Line(points={{-42,-190},{-50,-190},{-50, + -100},{-10,-100},{-10,-70},{-18,-70}}, + color={255,0,255})); + connect(swi2.u3, swi.y) annotation (Line(points={{-42,-198},{-46,-198},{-46,-210}, + {-130,-210},{-130,-130},{130,-130},{130,0},{122,0}}, + color={0,0,127})); + connect(addPar.u, swi.y) annotation (Line(points={{-122,-190},{-130,-190},{-130, + -130},{130,-130},{130,0},{122,0}}, color={0,0,127})); + connect(min.u1, con.y) annotation (Line(points={{-82,-164},{-90,-164},{-90,-150}, + {-98,-150}}, color={0,0,127})); + connect(min.u2, addPar.y) annotation (Line(points={{-82,-176},{-90,-176},{-90, + -190},{-98,-190}}, color={0,0,127})); + connect(min.y, swi2.u1) annotation (Line(points={{-58,-170},{-46,-170},{-46,-182}, + {-42,-182}}, color={0,0,127})); + connect(swi2.y, reaRep.u) + annotation (Line(points={{-18,-190},{8,-190}},color={0,0,127})); + connect(pro.u1, reaRep.y) annotation (Line(points={{58,-184},{50,-184},{50,-190}, + {32,-190}}, color={0,0,127})); + connect(reaRep1.u, swi.y) annotation (Line(points={{8,-300},{-130,-300},{-130, + -130},{130,-130},{130,0},{122,0}}, color={0,0,127})); + connect(booToRea.y, pro.u2) annotation (Line(points={{-18,-230},{50,-230},{50, + -196},{58,-196}}, color={0,0,127})); + connect(pro.y, add2.u1) annotation (Line(points={{82,-190},{90,-190},{90,-224}, + {98,-224}}, color={0,0,127})); + connect(reaRep1.y, pro1.u2) annotation (Line(points={{32,-300},{50,-300},{50,-276}, + {58,-276}}, color={0,0,127})); + connect(booToRea1.y, pro1.u1) annotation (Line(points={{-18,-270},{50,-270},{50, + -264},{58,-264}}, color={0,0,127})); + connect(pro1.y, add2.u2) annotation (Line(points={{82,-270},{90,-270},{90,-236}, + {98,-236}}, color={0,0,127})); + +annotation(defaultComponentName="hotWatSupTemRes", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-140,-320},{140,120}})), + Icon(coordinateSystem(preserveAspectRatio=false, + extent={{-100,-100},{100,100}}), + graphics={Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={28,108,200}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-50,20},{50,-20}}, + textColor={28,108,200}, + fillColor={255,255,255}, + fillPattern=FillPattern.None, + textString="hotWatSupTemRes"), + Text( + extent={{-100,150},{100,110}}, + textColor={0,0,255}, + textString="%name")}), + Documentation(info=" +

+Control sequence for hot-water supply temperature setpoint TPlaHotWatSupSet +for boiler plant loop as per section 5.3.4 in ASHRAE RP-1711, March 2020 draft. +

+ + + + + + + + + + + + + + +
Variable Value Definition
DeviceAny hot water pump Associated device
iniSetTPlaHotWatSetMaxInitial setpoint
minSetTHotWatSetMinConBoi for condensing boilers;
THotWatSetMinNonConBoi for non-condensing boilers
Minimum setpoint
maxSetTPlaHotWatSetMaxMaximum setpoint
delTimdelTimValDelay timer
samplePeriodsamPerValTime step
numIgnReqnHotWatResReqIgnNumber of ignored requests
numOfReqnHotWatSupResReqNumber of requests
triAmotriAmoValTrim amount
resAmoresAmoValRespond amount
maxResmaxResValMaximum response per time interval
+ +", +revisions=" + +")); +end HotWaterSupplyTemperatureReset; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/MinimumFlowSetPoint.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/MinimumFlowSetPoint.mo new file mode 100644 index 00000000000..3e3d1c94743 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/MinimumFlowSetPoint.mo @@ -0,0 +1,707 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints; +block MinimumFlowSetPoint "Hot water minimum flow setpoint" + + parameter Integer nBoi( + final min=1) = 3 + "Total number of boilers"; + + parameter Integer nSta( + final min=1) = 5 + "Total number of stages"; + + parameter Integer staMat[nSta, nBoi] = {{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}} + "Boiler staging matrix"; + + parameter Real minFloSet[nBoi]( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate", + final min=1e-6, + final max=maxFloSet) = {0.005, 0.005, 0.005} + "Design minimum hot water flow through each boiler"; + + parameter Real maxFloSet[nBoi]( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate", + final min=minFloSet) = {0.025, 0.025, 0.025} + "Design maximum hot water flow through each boiler"; + + parameter Real bypSetRat( + final unit="m3/s2", + displayUnit="m3/s2", + final min=0) = 0.001 + "Rate at which to reset bypass valve setpoint during stage change"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "Signal indicating stage change with boilers being both enabled and disabled" + annotation (Placement(transformation(extent={{-180,-30},{-140,10}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaPro + "Signal indicating completion of stage change process" + annotation (Placement(transformation(extent={{-180,-70},{-140,-30}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Staging setpoint" + annotation (Placement(transformation(extent={{-180,-110},{-140,-70}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uLasDisBoi + "Index of boiler being disabled" + annotation (Placement(transformation(extent={{-180,10},{-140,50}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput VHotWatMinSet_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Hot water minimum flow setpoint" + annotation (Placement(transformation(extent={{320,-90},{360,-50}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + parameter Integer boiInd[nBoi]={i for i in 1:nBoi} + "Boiler index, {1,2,...,n}"; + + parameter Integer staInd[nSta]={i for i in 1:nSta} + "Stage index, {1,2,...,n}"; + + parameter Real minFloSetMat[nSta, nBoi] = {minFloSet[i] for i in 1:nBoi, j in 1:nSta} + "Boiler minimum design flowrate expanded for element-wise multiplication + with the staging matrix"; + + parameter Real maxFloSetMat[nSta, nBoi] = {maxFloSet[i] for i in 1:nBoi, j in 1:nSta} + "Boiler maximum design flowrate expanded for element-wise multiplication + with the staging matrix"; + + Buildings.Controls.OBC.CDL.Continuous.IntegratorWithReset intWitRes + "Used to break algebraic loop and sample the minimum flow setpoint at the start + of stage change process to use as reference for calculations" + annotation (Placement(transformation(extent={{140,-110},{160,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=1/bypSetRat) + "Find time required for changing bypass position setpoint" + annotation (Placement(transformation(extent={{210,-260},{230,-240}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub3 + "Find difference between new and old setpoints" + annotation (Placement(transformation(extent={{230,-210},{250,-190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Abs abs + "Ensure time required is positive" + annotation (Placement(transformation(extent={{280,-260},{300,-240}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar1( + final p=1e-6) + "Calculate time required to reset setpoint" + annotation (Placement(transformation(extent={{250,-260},{270,-240}}))); + + Buildings.Controls.OBC.CDL.Continuous.Greater gre( + final h=0) + "Check if time required for setpoint change has elapsed" + annotation (Placement(transformation(extent={{200,-120},{220,-100}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con[nSta,nBoi]( + final k=minFloSetMat) + "Design minimum boiler flowrate" + annotation (Placement(transformation(extent={{-120,-150},{-100,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1[nSta,nBoi]( + final k=maxFloSetMat) + "Design maximum boiler flowrate" + annotation (Placement(transformation(extent={{-120,-190},{-100,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2[nSta,nBoi]( + final k=staMat) + "Boiler staging matrix" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha + "Detect change in stage setpoint" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Set minimum flow setpoint as per 5.3.8.2 if uOnOff=True, else as per 5.3.8.1" + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical And" + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[nSta,nBoi] + "Element-wise product" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[nSta,nBoi] + "Element-wise product" + annotation (Placement(transformation(extent={{-80,-190},{-60,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div[nSta,nBoi] + "Element-wise division" + annotation (Placement(transformation(extent={{-20,-160},{0,-140}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar[nSta,nBoi]( + final p=fill(1e-8,nSta,nBoi)) + "Prevent divison by zero" + annotation (Placement(transformation(extent={{-50,-190},{-30,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixMax matMax( + final rowMax=true, + final nRow=nSta, + final nCol=nBoi) + "Identify maximum flowrate ratio for all boilers operating in stage" + annotation (Placement(transformation(extent={{20,-160},{40,-140}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixGain matGai( + final K=staMat) + "Sum of maximum flowrates of operating boilers" + annotation (Placement(transformation(extent={{-40,-230},{-20,-210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3[nBoi]( + final k=maxFloSet) + "Design maximum boiler flowrate" + annotation (Placement(transformation(extent={{-80,-230},{-60,-210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro2 + "Product of flowrate ratio and maximum flowrate" + annotation (Placement(transformation(extent={{140,60},{160,80}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nSta) + "Extract flow ratio of current setpoint during stage-up or stage-down" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig1( + final allowOutOfRange=true, + final nin=nSta, + final outOfRangeValue=1e-6) + "Extract flow ratio of previous setpoint during stage-up" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract subInt + "Previous stage during stage change" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max + "Max flowrate as per 5.3.8.2" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig2( + final nin=nSta) + "Extract max flowrate of current setpoint during stage-up or stage-down" + annotation (Placement(transformation(extent={{0,-230},{20,-210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Add add2 + "Max flowrate as per 5.3.8.2" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig3( + final allowOutOfRange=true, + final nin=nBoi, + final outOfRangeValue=1e-6) + "Extract max flowrate of boiler being disabled during stage-up" + annotation (Placement(transformation(extent={{-20,40},{0,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Pass minimum flow setpoint based on whether stage-up involves a boiler being disabled" + annotation (Placement(transformation(extent={{140,0},{160,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro3 + "Product of flowrate ratio and maximum flowrate" + annotation (Placement(transformation(extent={{92,-100},{112,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + "Pass minimum flow setpoint based on whether the plant is being staged-up or staged-down" + annotation (Placement(transformation(extent={{290,-80},{310,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Logical And" + annotation (Placement(transformation(extent={{-80,-120},{-60,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Set minimum flow setpoint as per 5.3.8.2 if uOnOff=True, else as per 5.3.8.1" + annotation (Placement(transformation(extent={{-40,-120},{-20,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Set minimum flow setpoint as per 5.3.8.2 if uOnOff=True, else as per 5.3.8.1" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 + "Pass minimum flow setpoint based on whether stage-down involves a boiler being enabled" + annotation (Placement(transformation(extent={{140,-160},{160,-140}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{-130,-330},{-110,-310}}))); + + Buildings.Controls.OBC.CDL.Integers.Add addInt1 + "Previous stage during stage change" + annotation (Placement(transformation(extent={{-90,-310},{-70,-290}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig4( + final allowOutOfRange=true, + final nin=nSta, + final outOfRangeValue=1e-6) + "Extract flow ratio of previous setpoint during stage-down" + annotation (Placement(transformation(extent={{60,-280},{80,-260}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max1 + "Max flowrate as per 5.3.8.2" + annotation (Placement(transformation(extent={{100,-260},{120,-240}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig5( + final allowOutOfRange=true, + final nin=nBoi, + final outOfRangeValue=1e-6) + "Extract max flowrate of boiler being disabled during stage-down" + annotation (Placement(transformation(extent={{-40,-270},{-20,-250}}))); + + Buildings.Controls.OBC.CDL.Continuous.Add add1 + "Max flowrate as per 5.3.8.2" + annotation (Placement(transformation(extent={{100,-310},{120,-290}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro4 + "Product of flowrate ratio and maximum flowrate" + annotation (Placement(transformation(extent={{140,-280},{160,-260}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat3 + "Turn on timer for slow change of setpoint" + annotation (Placement(transformation(extent={{200,-50},{220,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line lin + "Change setpoint over a finite amnount of time during stage change" + annotation (Placement(transformation(extent={{260,-10},{280,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line lin1 + "Change setpoint over a finite amnount of time during stage change" + annotation (Placement(transformation(extent={{260,-150},{280,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con4( + final k=0) + "Constant Real source" + annotation (Placement(transformation(extent={{160,100},{180,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=0) + "Timer for change of setpoint" + annotation (Placement(transformation(extent={{228,-50},{248,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{228,-120},{248,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Detect start of change in minimum flow setpoint" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi3 + "Pass new minimum flow setpoint based on whether the plant is being staged-up or staged-down" + annotation (Placement(transformation(extent={{190,-210},{210,-190}}))); + +equation + connect(uStaSet, cha.u) + annotation (Line(points={{-160,-90},{-128,-90},{-128,-70},{-122,-70}}, + color={255,127,0})); + + connect(lat.u, and2.y) + annotation (Line(points={{-42,-30},{-58,-30}}, + color={255,0,255})); + + connect(uOnOff, and2.u1) + annotation (Line(points={{-160,-10},{-124,-10},{-124,-30},{-82,-30}}, + color={255,0,255})); + + connect(cha.up, and2.u2) annotation (Line(points={{-98,-64},{-90,-64},{-90,-38}, + {-82,-38}},color={255,0,255})); + + connect(uStaChaPro, lat.clr) annotation (Line(points={{-160,-50},{-50,-50},{-50, + -36},{-42,-36}}, + color={255,0,255})); + + connect(con.y, pro.u1) annotation (Line(points={{-98,-140},{-90,-140},{-90,-134}, + {-82,-134}},color={0,0,127})); + + connect(con2.y, pro.u2) annotation (Line(points={{-98,-220},{-90,-220},{-90,-146}, + {-82,-146}}, + color={0,0,127})); + + connect(con1.y, pro1.u1) annotation (Line(points={{-98,-180},{-92,-180},{-92,-174}, + {-82,-174}}, + color={0,0,127})); + + connect(con2.y, pro1.u2) annotation (Line(points={{-98,-220},{-90,-220},{-90,-186}, + {-82,-186}}, + color={0,0,127})); + + connect(pro.y, div.u1) + annotation (Line(points={{-58,-140},{-40,-140},{-40,-144},{-22,-144}}, + color={0,0,127})); + + connect(pro1.y, addPar.u) + annotation (Line(points={{-58,-180},{-52,-180}}, + color={0,0,127})); + + connect(addPar.y, div.u2) annotation (Line(points={{-28,-180},{-24,-180},{-24, + -156},{-22,-156}}, + color={0,0,127})); + + connect(con3.y, matGai.u) + annotation (Line(points={{-58,-220},{-42,-220}}, + color={0,0,127})); + + connect(div.y, matMax.u) + annotation (Line(points={{2,-150},{18,-150}}, + color={0,0,127})); + + connect(matMax.y, extIndSig.u) + annotation (Line(points={{42,-150},{52,-150},{52,-50},{58,-50}}, + color={0,0,127})); + + connect(uStaSet, extIndSig.index) annotation (Line(points={{-160,-90},{70,-90}, + {70,-62}}, color={255,127,0})); + + connect(matMax.y, extIndSig1.u) annotation (Line(points={{42,-150},{52,-150},{ + 52,80},{58,80}}, + color={0,0,127})); + + connect(conInt.y,subInt. u2) annotation (Line(points={{-98,70},{-72,70},{-72, + 74},{-62,74}}, + color={255,127,0})); + + connect(uStaSet,subInt. u1) annotation (Line(points={{-160,-90},{-128,-90},{ + -128,100},{-72,100},{-72,86},{-62,86}}, + color={255,127,0})); + + connect(subInt.y, extIndSig1.index) annotation (Line(points={{-38,80},{40,80}, + {40,60},{70,60},{70,68}},color={255,127,0})); + + connect(matGai.y, extIndSig2.u) + annotation (Line(points={{-18,-220},{-2,-220}}, + color={0,0,127})); + + connect(uStaSet, extIndSig2.index) annotation (Line(points={{-160,-90},{-128,-90}, + {-128,-240},{10,-240},{10,-232}}, color={255,127,0})); + + connect(con3.y, extIndSig3.u) annotation (Line(points={{-58,-220},{-54,-220},{ + -54,50},{-22,50}}, color={0,0,127})); + + connect(max.y, pro2.u1) annotation (Line(points={{122,100},{130,100},{130,76}, + {138,76}}, color={0,0,127})); + + connect(add2.y, pro2.u2) annotation (Line(points={{82,40},{130,40},{130,64},{138, + 64}}, color={0,0,127})); + + connect(pro3.y, swi.u3) annotation (Line(points={{114,-90},{120,-90},{120,2},{ + 138,2}}, color={0,0,127})); + + connect(pro2.y, swi.u1) annotation (Line(points={{162,70},{170,70},{170,30},{130, + 30},{130,18},{138,18}}, color={0,0,127})); + + connect(extIndSig.y, pro3.u1) annotation (Line(points={{82,-50},{88,-50},{88,-84}, + {90,-84}}, color={0,0,127})); + + connect(extIndSig2.y, pro3.u2) annotation (Line(points={{22,-220},{46,-220},{46, + -96},{90,-96}}, color={0,0,127})); + + connect(lat.y, swi.u2) annotation (Line(points={{-18,-30},{126,-30},{126,10},{ + 138,10}}, color={255,0,255})); + + connect(swi1.y, VHotWatMinSet_flow) + annotation (Line(points={{312,-70},{340,-70}}, color={0,0,127})); + + connect(cha.down, and1.u1) annotation (Line(points={{-98,-76},{-90,-76},{-90,-110}, + {-82,-110}}, color={255,0,255})); + + connect(and1.y, lat1.u) + annotation (Line(points={{-58,-110},{-42,-110}}, color={255,0,255})); + + connect(uStaChaPro, lat1.clr) annotation (Line(points={{-160,-50},{-50,-50},{-50, + -116},{-42,-116}}, color={255,0,255})); + + connect(cha.up, lat2.u) annotation (Line(points={{-98,-64},{-90,-64},{-90,-70}, + {-82,-70}}, color={255,0,255})); + + connect(cha.down, lat2.clr) + annotation (Line(points={{-98,-76},{-82,-76}}, color={255,0,255})); + + connect(lat2.y, swi1.u2) + annotation (Line(points={{-58,-70},{288,-70}}, color={255,0,255})); + + connect(lat1.y, swi2.u2) annotation (Line(points={{-18,-110},{126,-110},{126,-150}, + {138,-150}}, color={255,0,255})); + + connect(uOnOff, and1.u2) annotation (Line(points={{-160,-10},{-124,-10},{-124, + -118},{-82,-118}}, color={255,0,255})); + + connect(pro3.y, swi2.u3) annotation (Line(points={{114,-90},{120,-90},{120,-158}, + {138,-158}}, color={0,0,127})); + + connect(extIndSig3.y, add2.u1) annotation (Line(points={{2,50},{40,50},{40,46}, + {58,46}}, color={0,0,127})); + + connect(extIndSig2.y, add2.u2) annotation (Line(points={{22,-220},{46,-220},{46, + 34},{58,34}}, color={0,0,127})); + + connect(uLasDisBoi, extIndSig3.index) + annotation (Line(points={{-160,30},{-10,30},{-10,38}}, color={255,127,0})); + + connect(extIndSig.y, max.u2) annotation (Line(points={{82,-50},{88,-50},{88,94}, + {98,94}}, color={0,0,127})); + + connect(extIndSig1.y, max.u1) annotation (Line(points={{82,80},{84,80},{84,106}, + {98,106}}, color={0,0,127})); + + connect(conInt1.y, addInt1.u2) annotation (Line(points={{-108,-320},{-100,-320}, + {-100,-306},{-92,-306}}, color={255,127,0})); + + connect(uStaSet, addInt1.u1) annotation (Line(points={{-160,-90},{-128,-90},{-128, + -294},{-92,-294}}, color={255,127,0})); + + connect(matMax.y, extIndSig4.u) annotation (Line(points={{42,-150},{52,-150},{ + 52,-270},{58,-270}}, color={0,0,127})); + + connect(addInt1.y, extIndSig4.index) annotation (Line(points={{-68,-300},{70,-300}, + {70,-282}}, color={255,127,0})); + + connect(extIndSig4.y, max1.u2) annotation (Line(points={{82,-270},{88,-270},{88, + -256},{98,-256}}, color={0,0,127})); + + connect(extIndSig.y, max1.u1) annotation (Line(points={{82,-50},{88,-50},{88,-244}, + {98,-244}}, color={0,0,127})); + + connect(con3.y, extIndSig5.u) annotation (Line(points={{-58,-220},{-54,-220},{ + -54,-260},{-42,-260}}, color={0,0,127})); + + connect(extIndSig2.y, add1.u1) annotation (Line(points={{22,-220},{46,-220},{46, + -294},{98,-294}}, color={0,0,127})); + + connect(extIndSig5.y, add1.u2) annotation (Line(points={{-18,-260},{0,-260},{0, + -306},{98,-306}}, color={0,0,127})); + + connect(max1.y, pro4.u1) annotation (Line(points={{122,-250},{130,-250},{130,-264}, + {138,-264}}, color={0,0,127})); + + connect(add1.y, pro4.u2) annotation (Line(points={{122,-300},{130,-300},{130,-276}, + {138,-276}}, color={0,0,127})); + + connect(pro4.y, swi2.u1) annotation (Line(points={{162,-270},{166,-270},{166,-170}, + {132,-170},{132,-142},{138,-142}}, color={0,0,127})); + + connect(uLasDisBoi, extIndSig5.index) annotation (Line(points={{-160,30},{-134, + 30},{-134,-280},{-30,-280},{-30,-272}}, color={255,127,0})); + + connect(swi.y, lin.f2) annotation (Line(points={{162,10},{166,10},{166,-8},{258, + -8}}, color={0,0,127})); + connect(swi2.y, lin1.f2) annotation (Line(points={{162,-150},{254,-150},{254,-148}, + {258,-148}}, color={0,0,127})); + connect(lat3.y, tim.u) + annotation (Line(points={{222,-40},{226,-40}}, color={255,0,255})); + connect(tim.y, lin.u) annotation (Line(points={{250,-40},{254,-40},{254,0},{258, + 0}}, color={0,0,127})); + connect(tim.y, lin1.u) annotation (Line(points={{250,-40},{254,-40},{254,-140}, + {258,-140}}, color={0,0,127})); + connect(lin1.y, swi1.u3) annotation (Line(points={{282,-140},{286,-140},{286,-78}, + {288,-78}}, color={0,0,127})); + connect(lin.y, swi1.u1) annotation (Line(points={{282,0},{286,0},{286,-62},{288, + -62}}, color={0,0,127})); + connect(con4.y, lin.x1) annotation (Line(points={{182,110},{188,110},{188,8},{ + 258,8}}, color={0,0,127})); + connect(con4.y, lin1.x1) annotation (Line(points={{182,110},{188,110},{188,-132}, + {258,-132}}, color={0,0,127})); + connect(pre1.y, lat3.clr) annotation (Line(points={{250,-110},{260,-110},{260, + -60},{192,-60},{192,-46},{198,-46}}, color={255,0,255})); + connect(uStaChaPro, or2.u2) annotation (Line(points={{-160,-50},{-50,-50},{-50, + -8},{-42,-8}}, color={255,0,255})); + connect(cha.y, or2.u1) annotation (Line(points={{-98,-70},{-94,-70},{-94,0},{-42, + 0}}, color={255,0,255})); + connect(or2.y, lat3.u) annotation (Line(points={{-18,0},{100,0},{100,-20},{192, + -20},{192,-40},{198,-40}}, color={255,0,255})); + + connect(swi.y, swi3.u1) annotation (Line(points={{162,10},{166,10},{166,-8},{180, + -8},{180,-192},{188,-192}}, color={0,0,127})); + connect(swi2.y, swi3.u3) annotation (Line(points={{162,-150},{172,-150},{172,-208}, + {188,-208}}, color={0,0,127})); + connect(lat2.y, swi3.u2) annotation (Line(points={{-58,-70},{176,-70},{176,-200}, + {188,-200}}, color={255,0,255})); + connect(pre1.u, gre.y) + annotation (Line(points={{226,-110},{222,-110}}, color={255,0,255})); + connect(tim.y, gre.u1) annotation (Line(points={{250,-40},{254,-40},{254,-88}, + {192,-88},{192,-110},{198,-110}}, color={0,0,127})); + connect(addPar1.y, abs.u) + annotation (Line(points={{272,-250},{278,-250}}, color={0,0,127})); + connect(abs.y, lin1.x2) annotation (Line(points={{302,-250},{310,-250},{310,-180}, + {184,-180},{184,-144},{258,-144}}, color={0,0,127})); + connect(abs.y, gre.u2) annotation (Line(points={{302,-250},{310,-250},{310,-180}, + {184,-180},{184,-118},{198,-118}}, color={0,0,127})); + connect(abs.y, lin.x2) annotation (Line(points={{302,-250},{310,-250},{310,-180}, + {184,-180},{184,-4},{258,-4}}, color={0,0,127})); + + connect(sub3.y, gai.u) annotation (Line(points={{252,-200},{260,-200},{260,-230}, + {200,-230},{200,-250},{208,-250}}, color={0,0,127})); + connect(gai.y, addPar1.u) + annotation (Line(points={{232,-250},{248,-250}}, color={0,0,127})); + connect(swi3.y, sub3.u1) annotation (Line(points={{212,-200},{224,-200},{224,-194}, + {228,-194}}, color={0,0,127})); + connect(con4.y, intWitRes.u) annotation (Line(points={{182,110},{188,110},{188, + -80},{132,-80},{132,-100},{138,-100}}, color={0,0,127})); + connect(swi1.y, intWitRes.y_reset_in) annotation (Line(points={{312,-70},{316, + -70},{316,-164},{128,-164},{128,-108},{138,-108}}, color={0,0,127})); + connect(gre.y, intWitRes.trigger) annotation (Line(points={{222,-110},{224,-110}, + {224,-124},{150,-124},{150,-112}}, color={255,0,255})); + connect(intWitRes.y, lin.f1) annotation (Line(points={{162,-100},{172,-100},{172, + 4},{258,4}}, color={0,0,127})); + connect(intWitRes.y, lin1.f1) annotation (Line(points={{162,-100},{172,-100},{ + 172,-136},{258,-136}}, color={0,0,127})); + connect(intWitRes.y, sub3.u2) annotation (Line(points={{162,-100},{172,-100},{ + 172,-136},{220,-136},{220,-206},{228,-206}}, color={0,0,127})); +annotation ( + defaultComponentName="minBoiFloSet", + 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]")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-140,-340},{320,140}})), + Documentation(info=" +

+Block that outputs hot water minimum flow setpoint for primary-only plants with +a minimum flow bypass valve, according to ASHRAE RP-1711, March, 2020 draft, +sections 5.3.8.1 and 5.3.8.2. +

+
    +
  1. +For plants with parallel boilers, bypass valve shall modulate to maintain minimum +flow as measured by the hot water flow meter at a setpoint VHotWatMinSet_flow +that ensures minimum flow through all operating boilers, as follows: + + + + + + + + + + + + + + + + + + + + + + +
    Boiler Minimum flow Maximum flow
    1minFloSet[1]maxFloSet[1]
    2minFloSet[2]maxFloSet[2]
    .........
    +
    +
  2. +
  3. +If there is any stage change requiring a boiler on and another boiler off, +VHotWatMinSet_flow shall temporarily change to account for the +minFloSet of both the boiler to be enabled and to be disabled +prior to starting the newly enabled boiler. +
  4. +
+

+Note that when there is a stage change requiring a change in VHotWatMinSet_flow, +the change should be slowly made at a rate bypSetRat. +

+", revisions=" + +")); +end MinimumFlowSetPoint; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/ProportionalRegulator.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/ProportionalRegulator.mo new file mode 100644 index 00000000000..f30484653ce --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/ProportionalRegulator.mo @@ -0,0 +1,127 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences; +block ProportionalRegulator + "Sequence to calculate regulation signal with measured return temperature as input" + + parameter Real TRetSet( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") = 60 + "Minimum hot water return temperature for optimal non-condensing boiler performance"; + + parameter Real TRetMinAll( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") = 57.2 + "Minimum allowed hot water return temperature for non-condensing boiler"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatRet( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water return temperature" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRegSig( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) + "Regulation signal from P-only loop for condensation control" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Subtract sub + "Compare minimum return temperature setpoint to measured return temperature" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=TRetSet) + "Constant signal source for minimum return temperature setpoint" + annotation (Placement(transformation(extent={{-90,30},{-70,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Limiter lim( + final uMax=TRetSet - TRetMinAll, + final uMin=0) + "Limit input for calculating control signal" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=1/(TRetSet - TRetMinAll)) + "Calculate control signal" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +equation + + connect(lim.y, gai.u) + annotation (Line(points={{12,0},{38,0}}, color={0,0,127})); + + connect(gai.y, yRegSig) + annotation (Line(points={{62,0},{120,0}}, color={0,0,127})); + + connect(THotWatRet, sub.u2) annotation (Line(points={{-120,0},{-80,0},{-80,-6}, + {-62,-6}}, color={0,0,127})); + connect(con.y, sub.u1) annotation (Line(points={{-68,40},{-66,40},{-66,6},{-62, + 6}}, color={0,0,127})); + connect(sub.y, lim.u) + annotation (Line(points={{-38,0},{-12,0}}, color={0,0,127})); + annotation (defaultComponentName= + "proReg", + Icon(graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineThickness=0.1), + 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)}, + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Documentation(info=" +

+Block that generates proportional regulation signal for condensation control +in non-condensing boilers according to RP-1711, March, 2020 draft, section +5.3.5. +

+

+The minimum bypass valve position yProReg is calculated +as follows: +

+ +", +revisions=" + +")); +end ProportionalRegulator; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/PumpSpeedLimits.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/PumpSpeedLimits.mo new file mode 100644 index 00000000000..29fdfd0731a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/PumpSpeedLimits.mo @@ -0,0 +1,271 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences; +block PumpSpeedLimits + "Sequence to calculate pump speed limits from regulation signal" + + parameter Boolean have_varPriPum = true + "True: Variable speed pumps in primary loop; False: Constant speed pumps in primary loop"; + + parameter Integer nSta = 5 + "Number of stages" + annotation(Evaluate=true,Dialog(enable=have_varPriPum)); + + parameter Real minSecPumSpe( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) = 0 + "Minimum secondary pump speed"; + + parameter Real minPriPumSpeSta[nSta]( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) = {0,0,0,0,0} + "Vector of minimum primary pump speed for each stage" + annotation(Evaluate=true,Dialog(enable=have_varPriPum)); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uCurSta if have_varPriPum + "Current stage" + annotation (Placement(transformation(extent={{-140,30},{-100,70}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uRegSig( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") + "Regulation signal from proportional regulator" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinPriPumSpe( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) if have_varPriPum + "Minimum allowed primary pump speed" + annotation (Placement(transformation(extent={{100,10},{140,50}}), + iconTransformation(extent={{100,30},{140,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMaxSecPumSpe( + final unit="1", + final displayUnit="1", + final min=0, + final max=1) + "Maximum allowed secondary pump speed" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai2( + final k=-1) if have_varPriPum + "Invert signal for subtraction" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar2( + final p=-0.5) if have_varPriPum + "Extract secondary pump signal from regulation signal" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Limiter lim1( + final uMax=0.5, + final uMin=0) if have_varPriPum + "Limit signal between 0 and 0.5" + annotation (Placement(transformation(extent={{-30,-10},{-10,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai1( + final k=2) if have_varPriPum + "Multiply signal by 2" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar3( + final p=1) if have_varPriPum + "Generate secondary pump setpoint signal from regulation signal" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1) if not have_varPriPum + "Generate secondary pump setpoint signal from regulation signal" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Limiter lim2( + final uMax=1, + final uMin=0) if not have_varPriPum + "Limit signal between 0 and 1" + annotation (Placement(transformation(extent={{-30,-50},{-10,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Limiter lim( + final uMax=0.5, + final uMin=0) if have_varPriPum + "Limit signal between 0 and 0.5" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=2) if have_varPriPum + "Multiply signal by 2" + annotation (Placement(transformation(extent={{-30,20},{-10,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro if have_varPriPum + "Normalize regulation signal in terms of pump speed" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Add add2 if have_varPriPum + "Add minimum pump speed value to normalized regulation signal" + annotation (Placement(transformation(extent={{30,20},{50,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar1( + final p=1) if have_varPriPum + "Subtract minimum primary pump speed from 1" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig1( + final nin=nSta) if have_varPriPum + "Identify minimum primary pump speed for current stage" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2[nSta]( + final k=minPriPumSpeSta) if have_varPriPum + "Source signal for B-MinPriPumpSpdStage" + annotation (Placement(transformation(extent={{-90,70},{-70,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai3( + final k=minSecPumSpe - 1) if have_varPriPum + "Normalize signal for subtraction" + annotation (Placement(transformation(extent={{30,-10},{50,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai4( + final k=minSecPumSpe - 1) if not have_varPriPum + "Normalize signal for subtraction" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + +equation + + connect(uRegSig, addPar2.u) annotation (Line(points={{-120,0},{-62,0}}, + color={0,0,127})); + + connect(addPar2.y, lim1.u) + annotation (Line(points={{-38,0},{-32,0}}, color={0,0,127})); + + connect(lim1.y, gai1.u) + annotation (Line(points={{-8,0},{-2,0}}, color={0,0,127})); + + connect(addPar3.y, yMaxSecPumSpe) annotation (Line(points={{82,0},{120,0}}, + color={0,0,127})); + + connect(addPar.y, yMaxSecPumSpe) annotation (Line(points={{82,-40},{90,-40},{90, + 0},{120,0}}, color={0,0,127})); + + connect(uRegSig, lim2.u) annotation (Line(points={{-120,0},{-90,0},{-90,-40},{ + -32,-40}}, color={0,0,127})); + + connect(uRegSig, lim.u) annotation (Line(points={{-120,0},{-90,0},{-90,30},{-62, + 30}}, color={0,0,127})); + + connect(lim.y, gai.u) + annotation (Line(points={{-38,30},{-32,30}}, color={0,0,127})); + + connect(con2.y, extIndSig1.u) + annotation (Line(points={{-68,80},{-62,80}}, color={0,0,127})); + + connect(add2.u2, pro.y) annotation (Line(points={{28,24},{26,24},{26,30},{22,30}}, + color={0,0,127})); + + connect(gai.y, pro.u2) annotation (Line(points={{-8,30},{-6,30},{-6,24},{-2,24}}, + color={0,0,127})); + + connect(uCurSta, extIndSig1.index) + annotation (Line(points={{-120,50},{-50,50},{-50,68}}, color={255,127,0})); + + connect(add2.y, yMinPriPumSpe) + annotation (Line(points={{52,30},{120,30}}, color={0,0,127})); + + connect(addPar1.y, pro.u1) annotation (Line(points={{42,80},{50,80},{50,66},{-6, + 66},{-6,36},{-2,36}}, + color={0,0,127})); + connect(extIndSig1.y, add2.u1) annotation (Line(points={{-38,80},{-36,80},{ + -36,60},{26,60},{26,36},{28,36}}, color={0,0,127})); + connect(extIndSig1.y, gai2.u) + annotation (Line(points={{-38,80},{-22,80}}, color={0,0,127})); + connect(gai2.y, addPar1.u) + annotation (Line(points={{2,80},{18,80}}, color={0,0,127})); + connect(gai1.y, gai3.u) + annotation (Line(points={{22,0},{28,0}}, color={0,0,127})); + connect(gai3.y, addPar3.u) + annotation (Line(points={{52,0},{58,0}}, color={0,0,127})); + connect(lim2.y, gai4.u) + annotation (Line(points={{-8,-40},{18,-40}}, color={0,0,127})); + connect(gai4.y, addPar.u) + annotation (Line(points={{42,-40},{58,-40}}, color={0,0,127})); + annotation (defaultComponentName="pumSpeLim", + Icon(graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + lineThickness=0.1), + 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)}, + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Documentation( +info=" +

+Block that generates pump speed limits for condensation control +in non-condensing boilers according to RP-1711, March, 2020 draft, sections +5.3.5.3, 5.3.5.4, 5.3.5.5 and 5.3.5.6. +

+

+The maximum allowed secondary pump speed yMaxSecPumSpe is calculated +as follows: +

+
    +
  1. +if the primary pumps are constant speed have_varPriPum=false, +yMaxSecPumSpe is reset from 100% pump speed at 0% of regulation +signal uRegSig to minimum pump speed minSecPumSpe +at 100% of uRegSig. +
  2. +
  3. +if the primary pumps are variable speed have_varPriPum=true, +yMaxSecPumSpe is reset from 100% pump speed at 50% of uRegSig +to minSecPumSpe at 100% of uRegSig. +
  4. +
+

+If have_varPriPum=true, the minimum allowed primary pump speed +yMinPriPumSpe is calculated as follows: +

+ +", +revisions=" + +")); +end PumpSpeedLimits; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/ProportionalRegulator.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/ProportionalRegulator.mo new file mode 100644 index 00000000000..266d5451f24 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/ProportionalRegulator.mo @@ -0,0 +1,58 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.Validation; +model ProportionalRegulator + "Validation model for ProportionalRegulator sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.ProportionalRegulator + proReg( + final TRetSet=60, + final TRetMinAll=57.2) + "Test model for ProportionalRegulator" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=5, + final freqHz=1/60, + final offset=60) + "Sine input" + annotation (Placement(transformation(extent={{-50,-10},{-30,10}}))); + +equation + connect(sin.y, proReg.THotWatRet) + annotation (Line(points={{-28,0},{-12,0}}, color={0,0,127})); + + annotation ( + 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)), + experiment( + StopTime=60, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/ProportionalRegulator.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.ProportionalRegulator. +

+ ", revisions=" + + ")); +end ProportionalRegulator; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/PumpSpeedLimits.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/PumpSpeedLimits.mo new file mode 100644 index 00000000000..361b18c0455 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/PumpSpeedLimits.mo @@ -0,0 +1,78 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.Validation; +model PumpSpeedLimits + "Validation model for PumpSpeedLimits sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.PumpSpeedLimits + pumSpeLim( + final have_varPriPum=true, + final nSta=1, + final minSecPumSpe=0.1, + final minPriPumSpeSta={0.2}) + "Testing scenario with variable primary pumps" + annotation (Placement(transformation(extent={{10,10},{30,30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.PumpSpeedLimits + pumSpeLim1( + final have_varPriPum=false, + final nSta=1, + final minSecPumSpe=0.1, + final minPriPumSpeSta={0.2}) + "Testing scenario with fixed-speed primary pumps" + annotation (Placement(transformation(extent={{10,-30},{30,-10}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=0.6, + final freqHz=1/60, + final offset=0.50) + "Sine input" + annotation (Placement(transformation(extent={{-30,-30},{-10,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{-30,10},{-10,30}}))); + +equation + connect(conInt.y, pumSpeLim.uCurSta) annotation (Line(points={{-8,20},{0,20}, + {0,25},{8,25}}, color={255,127,0})); + connect(sin.y, pumSpeLim.uRegSig) annotation (Line(points={{-8,-20},{0,-20},{ + 0,15},{8,15}}, color={0,0,127})); + connect(sin.y, pumSpeLim1.uRegSig) annotation (Line(points={{-8,-20},{0,-20}, + {0,-25},{8,-25}}, color={0,0,127})); + annotation ( + 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)), + experiment( + StopTime=60, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/PumpSpeedLimits.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences.PumpSpeedLimits. +

+ ", revisions=" + + ")); +end PumpSpeedLimits; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..6eff51d8f77 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/package.mo @@ -0,0 +1,40 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Subsequences; +package Validation "Collection of validation models" + + + + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

+ This package contains validation models for the classes in + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.CondensationControl.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/BoilerPlant/SetPoints/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/package.order new file mode 100644 index 00000000000..d5ec19c87d3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/Validation/package.order @@ -0,0 +1,2 @@ +ProportionalRegulator +PumpSpeedLimits diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/package.mo new file mode 100644 index 00000000000..1008f1f94b3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints; +package Subsequences "Subsequences for setpoint calculations" + + + + +annotation(Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Ellipse( + origin={10,10}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10,10}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10,10}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10,10}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})}), + Documentation(info=" +

+ This package contains control subsequences for setpoint calculations. +

+ ")); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/package.order new file mode 100644 index 00000000000..4ef1857ac5c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Subsequences/package.order @@ -0,0 +1,3 @@ +ProportionalRegulator +PumpSpeedLimits +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/CondensationControl.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/CondensationControl.mo new file mode 100644 index 00000000000..b56fe7f52ca --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/CondensationControl.mo @@ -0,0 +1,197 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Validation; +model CondensationControl + "Validation model for CondensationControl sequence" + + parameter Integer nSta=1 + "Number of stages"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.CondensationControl + conSet( + final have_priOnl=true, + final have_varPriPum=false, + final nSta=nSta, + final TRetSet=60, + final TRetMinAll=57.2, + final minSecPumSpe=0.1, + final minPriPumSpeSta={0.2}) + "Setpoint generation for primary-only plant" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.CondensationControl + conSet1( + final have_priOnl=false, + final have_varPriPum=true, + final nSta=1, + final TRetSet=60, + final TRetMinAll=57.2, + final minSecPumSpe=0.1, + final minPriPumSpeSta={0.2}) + "Setpoint generation for primary-secondary plant with variable speed primary loop pumps" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.CondensationControl + conSet2( + final have_priOnl=false, + final have_varPriPum=false, + final nSta=1, + final TRetSet=60, + final TRetMinAll=57.2, + final minSecPumSpe=0.1, + final minPriPumSpeSta={0.2}) + "Setpoint generation for primary-secondary plant with constant speed primary loop pumps" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.CondensationControl + conSet3( + final have_priOnl=false, + final have_varPriPum=true, + final nSta=1, + final TRetSet=60, + final TRetMinAll=57.2, + final minSecPumSpe=0.1, + final minPriPumSpeSta={0.2}) + "Setpoint generation when only condensing boilers are operating" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=5, + final freqHz=1/60, + final offset=60) + "Sine input" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final amplitude=5, + final freqHz=1/60, + final offset=60) + "Sine input" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin2( + final amplitude=5, + final freqHz=1/60, + final offset=60) + "Sine input" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin3( + final amplitude=5, + final freqHz=1/60, + final offset=60) + "Sine input" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{20,40},{40,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3( + final k=1) + "Constant Integer source" + annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4[nSta]( + final k={2}) + "Stage type vector source" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5[nSta]( + final k={2}) + "Stage type vector source" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt6[nSta]( + final k={2}) + "Stage type vector source" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7[nSta]( + final k={1}) + "Stage type vector source" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + +equation + connect(sin.y, conSet.THotWatRet) annotation (Line(points={{-58,80},{-50,80},{ + -50,56},{-42,56}}, color={0,0,127})); + + connect(sin2.y, conSet2.THotWatRet) annotation (Line(points={{-58,-20},{-50,-20}, + {-50,-44},{-42,-44}}, color={0,0,127})); + + connect(sin3.y, conSet3.THotWatRet) annotation (Line(points={{42,-20},{50,-20}, + {50,-44},{58,-44}}, color={0,0,127})); + + connect(conInt.y, conSet.uCurSta) + annotation (Line(points={{-58,50},{-42,50}}, color={255,127,0})); + + connect(conInt1.y, conSet1.uCurSta) + annotation (Line(points={{42,50},{58,50}}, color={255,127,0})); + + connect(conInt2.y, conSet2.uCurSta) + annotation (Line(points={{-58,-50},{-42,-50}}, color={255,127,0})); + + connect(conInt3.y, conSet3.uCurSta) + annotation (Line(points={{42,-50},{58,-50}}, color={255,127,0})); + + connect(conInt4.y, conSet.uStaTyp) annotation (Line(points={{-58,20},{-50,20}, + {-50,44},{-42,44}}, color={255,127,0})); + + connect(conInt5.y, conSet1.uStaTyp) annotation (Line(points={{42,20},{50,20},{ + 50,44},{58,44}}, color={255,127,0})); + + connect(conInt6.y, conSet2.uStaTyp) annotation (Line(points={{-58,-80},{-50,-80}, + {-50,-56},{-42,-56}}, color={255,127,0})); + + connect(conInt7.y, conSet3.uStaTyp) annotation (Line(points={{42,-80},{50,-80}, + {50,-56},{58,-56}}, color={255,127,0})); + + connect(sin1.y, conSet1.THotWatRet) annotation (Line(points={{42,80},{50,80}, + {50,56},{58,56}}, color={0,0,127})); + + annotation ( + 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)), + experiment( + StopTime=60, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/CondensationControl.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.CondensationControl. +

+ ", revisions=" + + ")); +end CondensationControl; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/HotWaterSupplyTemperatureReset.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/HotWaterSupplyTemperatureReset.mo new file mode 100644 index 00000000000..d5051f013f6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/HotWaterSupplyTemperatureReset.mo @@ -0,0 +1,401 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Validation; +block HotWaterSupplyTemperatureReset + "Validates hot water supply temperature setpoint reset for boiler plants" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset + hotWatSupTemRes( + final nPum=2, + final nSta=1, + final nBoi=2, + final nHotWatResReqIgn=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final TPlaHotWatSetMax=353.15, + final TConBoiHotWatSetMax=353.15, + final TConBoiHotWatSetOff=-10, + final THotWatSetMinNonConBoi=341.48, + final THotWatSetMinConBoi=305.37, + final delTimVal=600, + final samPerVal=300, + final triAmoVal=-2, + final resAmoVal=3, + final maxResVal=7, + final holTimVal=900) + "Scenario testing lack of hot-water requests" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset + hotWatSupTemRes1( + final nPum=2, + final nSta=1, + final nBoi=2, + final nHotWatResReqIgn=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final TPlaHotWatSetMax=353.15, + final TConBoiHotWatSetMax=353.15, + final TConBoiHotWatSetOff=-10, + final THotWatSetMinNonConBoi=341.48, + final THotWatSetMinConBoi=305.37, + final delTimVal=600, + final samPerVal=300, + final triAmoVal=-2, + final resAmoVal=3, + final maxResVal=7, + final holTimVal=900) + "Scenario testing increasing number of requests" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset + hotWatSupTemRes2( + final nPum=2, + final nSta=1, + final nBoi=2, + final nHotWatResReqIgn=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final TPlaHotWatSetMax=353.15, + final TConBoiHotWatSetMax=353.15, + final TConBoiHotWatSetOff=-10, + final THotWatSetMinNonConBoi=341.48, + final THotWatSetMinConBoi=305.37, + final delTimVal=600, + final samPerVal=300, + final triAmoVal=-2, + final resAmoVal=3, + final maxResVal=7, + final holTimVal=900) + "Scenario testing lack of pumps proven on" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset + hotWatSupTemRes3( + final nPum=2, + final nSta=1, + final nBoi=2, + final nHotWatResReqIgn=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final TPlaHotWatSetMax=353.15, + final TConBoiHotWatSetMax=353.15, + final TConBoiHotWatSetOff=-10, + final THotWatSetMinNonConBoi=341.48, + final THotWatSetMinConBoi=305.37, + final delTimVal=600, + final samPerVal=300, + final triAmoVal=-2, + final resAmoVal=3, + final maxResVal=7, + final holTimVal=900) + "Scenario testing effect of stage change process" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset + hotWatSupTemRes4( + final nPum=2, + final nSta=3, + final nBoi=2, + final nHotWatResReqIgn=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler}, + final TPlaHotWatSetMax=353.15, + final TConBoiHotWatSetMax=353.15, + final TConBoiHotWatSetOff=-10, + final THotWatSetMinNonConBoi=341.48, + final THotWatSetMinConBoi=305.37, + final delTimVal=600, + final samPerVal=300, + final triAmoVal=-2, + final resAmoVal=3, + final maxResVal=7, + final holTimVal=900) + "Scenario testing switch between condensing and non-condensing stages" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) + "Constant source" + annotation (Placement(transformation(extent={{-150,150},{-130,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-150,120},{-130,140}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=2) + "Constant source" + annotation (Placement(transformation(extent={{-152,90},{-132,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-150,60},{-130,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3( + final k=true) + "Constant source" + annotation (Placement(transformation(extent={{60,150},{80,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con4( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{60,120},{80,140}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con5( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con6( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con7( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-60,120},{-40,140}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2( + final k=2) + "Constant source" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con8( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to integer converter" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram( + final height=8, + final duration=1800, + final offset=2, + final startTime=1100) + "Ramp signal" + annotation (Placement(transformation(extent={{30,90},{50,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con9( + final k=true) + "Constant source" + annotation (Placement(transformation(extent={{-150,-30},{-130,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con10( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-150,-60},{-130,-40}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to integer converter" + annotation (Placement(transformation(extent={{-150,-90},{-130,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram1( + final height=8, + final duration=1800, + final offset=2, + final startTime=1100) + "Ramp signal" + annotation (Placement(transformation(extent={{-180,-90},{-160,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=1200, + final shift=1100) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{-150,-120},{-130,-100}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1[1]( + final k={1}) + "Constant source" + annotation (Placement(transformation(extent={{-150,30},{-130,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3[1]( + final k={1}) + "Constant source" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-150,0},{-130,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt6[1]( + final k={1}) + "Constant source" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt8[1]( + final k={1}) + "Constant source" + annotation (Placement(transformation(extent={{-150,-150},{-130,-130}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt9( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-150,-180},{-130,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con11( + final k=true) + "Constant source" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con12( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Real to integer converter" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram2( + final height=8, + final duration=1800, + final offset=2, + final startTime=1100) + "Ramp signal" + annotation (Placement(transformation(extent={{-90,-90},{-70,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con13( + final k=false) + "Constant source" + annotation (Placement(transformation(extent={{-60,-120},{-40,-100}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt10[3]( + final k={2,1,2}) + "Constant source" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Real to integer converter" + annotation (Placement(transformation(extent={{-60,-180},{-40,-160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=1.25, + final freqHz=1/7200, + final offset=2) + "Sine signal" + annotation (Placement(transformation(extent={{-90,-180},{-70,-160}}))); + +equation + connect(ram.y, reaToInt.u) + annotation (Line(points={{52,100},{58,100}}, color={0,0,127})); + connect(ram1.y, reaToInt1.u) + annotation (Line(points={{-158,-80},{-152,-80}}, + color={0,0,127})); + connect(con.y, hotWatSupTemRes.uHotWatPumSta[1]) annotation (Line(points={{-128, + 160},{-126,160},{-126,107},{-122,107}}, color={255,0,255})); + connect(con1.y, hotWatSupTemRes.uHotWatPumSta[2]) annotation (Line(points={{-128, + 130},{-124,130},{-124,109},{-122,109}}, color={255,0,255})); + connect(conInt.y, hotWatSupTemRes.nHotWatSupResReq) annotation (Line(points={{-130, + 100},{-130,104},{-122,104}}, color={255,127,0})); + connect(con2.y, hotWatSupTemRes.uStaCha) annotation (Line(points={{-128,70},{-128, + 100},{-122,100}}, color={255,0,255})); + connect(conInt1.y, hotWatSupTemRes.uTyp) annotation (Line(points={{-128,40},{-126, + 40},{-126,96},{-122,96}}, color={255,127,0})); + connect(con6.y, hotWatSupTemRes2.uHotWatPumSta[1]) annotation (Line(points={{-38, + 160},{-30,160},{-30,107},{-22,107}}, color={255,0,255})); + connect(con7.y, hotWatSupTemRes2.uHotWatPumSta[2]) annotation (Line(points={{-38, + 130},{-30,130},{-30,109},{-22,109}}, color={255,0,255})); + connect(conInt2.y, hotWatSupTemRes2.nHotWatSupResReq) annotation (Line(points= + {{-38,100},{-30,100},{-30,104},{-22,104}}, color={255,127,0})); + connect(con8.y, hotWatSupTemRes2.uStaCha) annotation (Line(points={{-38,70},{-28, + 70},{-28,100},{-22,100}}, color={255,0,255})); + connect(conInt3.y, hotWatSupTemRes2.uTyp) annotation (Line(points={{-38,40},{-26, + 40},{-26,96},{-22,96}}, color={255,127,0})); + connect(conInt4.y, hotWatSupTemRes.uCurStaSet) annotation (Line(points={{-128, + 10},{-124,10},{-124,92},{-122,92}}, color={255,127,0})); + connect(conInt5.y, hotWatSupTemRes2.uCurStaSet) annotation (Line(points={{-38, + 10},{-24,10},{-24,92},{-22,92}}, color={255,127,0})); + connect(con3.y, hotWatSupTemRes1.uHotWatPumSta[1]) annotation (Line(points={{82, + 160},{92,160},{92,107},{98,107}}, color={255,0,255})); + connect(con4.y, hotWatSupTemRes1.uHotWatPumSta[2]) annotation (Line(points={{82, + 130},{92,130},{92,109},{98,109}}, color={255,0,255})); + connect(reaToInt.y, hotWatSupTemRes1.nHotWatSupResReq) annotation (Line( + points={{82,100},{88,100},{88,104},{98,104}}, color={255,127,0})); + connect(con5.y, hotWatSupTemRes1.uStaCha) annotation (Line(points={{82,70},{90, + 70},{90,100},{98,100}}, color={255,0,255})); + connect(conInt6.y, hotWatSupTemRes1.uTyp) annotation (Line(points={{82,40},{92, + 40},{92,96},{98,96}}, color={255,127,0})); + connect(conInt7.y, hotWatSupTemRes1.uCurStaSet) annotation (Line(points={{82, + 10},{96,10},{96,92},{98,92}}, color={255,127,0})); + connect(con9.y, hotWatSupTemRes3.uHotWatPumSta[1]) annotation (Line(points={{-128, + -20},{-124,-20},{-124,-73},{-122,-73}}, color={255,0,255})); + connect(con10.y, hotWatSupTemRes3.uHotWatPumSta[2]) annotation (Line(points={{ + -128,-50},{-126,-50},{-126,-71},{-122,-71}}, color={255,0,255})); + connect(reaToInt1.y, hotWatSupTemRes3.nHotWatSupResReq) annotation (Line( + points={{-128,-80},{-128,-76},{-122,-76}}, color={255,127,0})); + connect(booPul.y, hotWatSupTemRes3.uStaCha) annotation (Line(points={{-128,-110}, + {-126,-110},{-126,-80},{-122,-80}}, color={255,0,255})); + connect(conInt8.y, hotWatSupTemRes3.uTyp) annotation (Line(points={{-128,-140}, + {-124,-140},{-124,-84},{-122,-84}}, color={255,127,0})); + connect(conInt9.y, hotWatSupTemRes3.uCurStaSet) annotation (Line(points={{-128, + -170},{-122,-170},{-122,-88}}, color={255,127,0})); + connect(con11.y, hotWatSupTemRes4.uHotWatPumSta[1]) annotation (Line(points={{ + -38,-20},{-30,-20},{-30,-73},{-22,-73}}, color={255,0,255})); + connect(con12.y, hotWatSupTemRes4.uHotWatPumSta[2]) annotation (Line(points={{ + -38,-50},{-30,-50},{-30,-71},{-22,-71}}, color={255,0,255})); + connect(ram2.y,reaToInt2. u) + annotation (Line(points={{-68,-80},{-62,-80}}, + color={0,0,127})); + connect(reaToInt2.y, hotWatSupTemRes4.nHotWatSupResReq) annotation (Line( + points={{-38,-80},{-30,-80},{-30,-76},{-22,-76}}, color={255,127,0})); + connect(con13.y, hotWatSupTemRes4.uStaCha) annotation (Line(points={{-38,-110}, + {-28,-110},{-28,-80},{-22,-80}}, color={255,0,255})); + connect(conInt10.y, hotWatSupTemRes4.uTyp) annotation (Line(points={{-38,-140}, + {-26,-140},{-26,-84},{-22,-84}}, color={255,127,0})); + connect(sin.y, reaToInt3.u) + annotation (Line(points={{-68,-170},{-62,-170}}, color={0,0,127})); + connect(reaToInt3.y, hotWatSupTemRes4.uCurStaSet) annotation (Line(points={{ + -38,-170},{-22,-170},{-22,-88}}, color={255,127,0})); + annotation ( + 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={{-200,-200},{180,180}})), + experiment( + StopTime=7200, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/HotWaterSupplyTemperatureReset.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.HotWaterSupplyTemperatureReset. +

+ ", revisions=" + + ")); +end HotWaterSupplyTemperatureReset; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/MinimumFlowSetPoint.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/MinimumFlowSetPoint.mo new file mode 100644 index 00000000000..f3966daa1ab --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/MinimumFlowSetPoint.mo @@ -0,0 +1,244 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.Validation; +model MinimumFlowSetPoint "Validation model for MinimumFlowSetPoint sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.MinimumFlowSetPoint + minBoiFloSet( + final nBoi=2, + final nSta=3, + final staMat={{1,0},{0,1},{1,1}}, + final minFloSet={0.1,0.3}, + final maxFloSet={0.25,0.9}, + bypSetRat=0.1) + "Test minimum flow setpoint reset for stage-up process" + annotation (Placement(transformation(extent={{70,50},{90,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.MinimumFlowSetPoint + minBoiFloSet1( + final nBoi=2, + final nSta=3, + final staMat={{1,0},{0,1},{1,1}}, + final minFloSet={0.1,0.3}, + final maxFloSet={0.25,0.9}, + bypSetRat=0.1) + "Test minimum flow setpoint reset for stage-down process" + annotation (Placement(transformation(extent={{70,-70},{90,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=5, + final falseHoldDuration=0) + "Hold pulse signal for visualization and to generate end of stage change signal" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=5, + final falseHoldDuration=0) + "Hold pulse signal for visualization and to generate end of stage change signal" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram( + final height=3, + final duration=45, + final offset=0, + final startTime=0) + "Ramp source for stage setpoint" + annotation (Placement(transformation(extent={{-90,10},{-70,30}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1[3]( + final k={0,1,0}) + "Last boiler being disabled during stage change" + annotation (Placement(transformation(extent={{-90,90},{-70,110}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final allowOutOfRange=true, + final nin=3, + final outOfRangeValue=0) + "Extract scalar out of vector" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr + "Check if current stage setpoint involves boilers being turned on and off" + annotation (Placement(transformation(extent={{-30,60},{-10,80}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha1 + "Detect change in setpoint" + annotation (Placement(transformation(extent={{-30,30},{-10,50}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Generate end of stage change signal at end of hold period" + annotation (Placement(transformation(extent={{30,30},{50,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram1( + final height=-3, + final duration=45, + final offset=4, + final startTime=0) "Ramp source for stage setpoint" + annotation (Placement(transformation(extent={{-90,-110},{-70,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2[3]( + final k={2,1,0}) + "Last boiler being disabled during stage change" + annotation (Placement(transformation(extent={{-90,-30},{-70,-10}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig1( + final allowOutOfRange=true, + final nin=3, + final outOfRangeValue=0) + "Extract scalar out of vector" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr1 + "Check if current stage setpoint involves boilers being turned on and off" + annotation (Placement(transformation(extent={{-30,-60},{-10,-40}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha2 + "Detect change in setpoint" + annotation (Placement(transformation(extent={{-30,-90},{-10,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg1 + "Generate end of stage change signal at end of hold period" + annotation (Placement(transformation(extent={{30,-90},{50,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3[3]( + final k={1,0,0}) + "Vector indicating if stage change involves boilers being turned on and off" + annotation (Placement(transformation(extent={{-90,-60},{-70,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig2( + final allowOutOfRange=true, + final nin=3, + final outOfRangeValue=0) + "Extract scalar out of vector" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + +equation + connect(ram.y, reaToInt.u) + annotation (Line(points={{-68,20},{-62,20}}, color={0,0,127})); + + connect(reaToInt.y, minBoiFloSet.uStaSet) annotation (Line(points={{-38,20},{64, + 20},{64,54},{68,54}}, color={255,127,0})); + + connect(con1.y, extIndSig.u) + annotation (Line(points={{-68,100},{-62,100}}, color={0,0,127})); + + connect(reaToInt.y, extIndSig.index) annotation (Line(points={{-38,20},{64,20}, + {64,86},{-50,86},{-50,88}}, color={255,127,0})); + + connect(extIndSig.y, reaToInt1.u) + annotation (Line(points={{-38,100},{18,100}}, color={0,0,127})); + + connect(reaToInt1.y, minBoiFloSet.uLasDisBoi) annotation (Line(points={{42,100}, + {66,100},{66,66},{68,66}}, color={255,127,0})); + + connect(extIndSig.y, greThr.u) annotation (Line(points={{-38,100},{-34,100},{-34, + 70},{-32,70}}, color={0,0,127})); + + connect(greThr.y, minBoiFloSet.uOnOff) annotation (Line(points={{-8,70},{60,70}, + {60,62},{68,62}}, color={255,0,255})); + + connect(reaToInt.y, cha1.u) annotation (Line(points={{-38,20},{-36,20},{-36,40}, + {-32,40}}, color={255,127,0})); + + connect(cha1.y, truFalHol.u) + annotation (Line(points={{-8,40},{-2,40}}, color={255,0,255})); + + connect(truFalHol.y, falEdg.u) + annotation (Line(points={{22,40},{28,40}}, color={255,0,255})); + + connect(falEdg.y, minBoiFloSet.uStaChaPro) annotation (Line(points={{52,40},{60, + 40},{60,58},{68,58}}, color={255,0,255})); + + connect(ram1.y, reaToInt2.u) + annotation (Line(points={{-68,-100},{-62,-100}}, color={0,0,127})); + + connect(reaToInt2.y, minBoiFloSet1.uStaSet) annotation (Line(points={{-38,-100}, + {64,-100},{64,-66},{68,-66}}, color={255,127,0})); + + connect(con2.y, extIndSig1.u) + annotation (Line(points={{-68,-20},{-62,-20}}, color={0,0,127})); + + connect(reaToInt2.y, extIndSig1.index) annotation (Line(points={{-38,-100},{64, + -100},{64,-34},{-50,-34},{-50,-32}}, color={255,127,0})); + + connect(extIndSig1.y, reaToInt3.u) + annotation (Line(points={{-38,-20},{18,-20}}, color={0,0,127})); + + connect(reaToInt3.y, minBoiFloSet1.uLasDisBoi) annotation (Line(points={{42,-20}, + {66,-20},{66,-54},{68,-54}}, color={255,127,0})); + + connect(greThr1.y, minBoiFloSet1.uOnOff) annotation (Line(points={{-8,-50},{60, + -50},{60,-58},{68,-58}}, color={255,0,255})); + + connect(reaToInt2.y, cha2.u) annotation (Line(points={{-38,-100},{-36,-100},{-36, + -80},{-32,-80}}, color={255,127,0})); + + connect(cha2.y, truFalHol1.u) + annotation (Line(points={{-8,-80},{-2,-80}}, color={255,0,255})); + + connect(truFalHol1.y, falEdg1.u) + annotation (Line(points={{22,-80},{28,-80}}, color={255,0,255})); + + connect(falEdg1.y, minBoiFloSet1.uStaChaPro) annotation (Line(points={{52,-80}, + {60,-80},{60,-62},{68,-62}}, color={255,0,255})); + + connect(con3.y, extIndSig2.u) + annotation (Line(points={{-68,-50},{-62,-50}}, color={0,0,127})); + + connect(extIndSig2.y, greThr1.u) + annotation (Line(points={{-38,-50},{-32,-50}}, color={0,0,127})); + + connect(reaToInt2.y, extIndSig2.index) annotation (Line(points={{-38,-100},{64, + -100},{64,-64},{-50,-64},{-50,-62}}, color={255,127,0})); + + annotation ( + 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}})), + experiment( + StopTime=10, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/MinimumFlowSetPoint.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints.MinimumFlowSetPoint. +

+ ", revisions=" + + ")); +end MinimumFlowSetPoint; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/package.mo new file mode 100644 index 00000000000..b546e2c19c4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.SetPoints; +package Validation "Collection of validation models" + + annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

+ This package contains validation models for the classes in + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/SetPoints/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/package.order new file mode 100644 index 00000000000..d2cc6d86ed8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/Validation/package.order @@ -0,0 +1,3 @@ +CondensationControl +HotWaterSupplyTemperatureReset +MinimumFlowSetPoint diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/package.mo new file mode 100644 index 00000000000..7ddc91c50c0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/package.mo @@ -0,0 +1,24 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package SetPoints "Control sequences for setpoint controllers" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S")}), + Documentation(info=" +

+ This package contains boiler plant setpoint control sequences. The implementation + is based on sections 5.3.4, 5.3.5, and 5.3.8 in ASHRAE RP-1711, Draft on March 23, 2020.

+")); +end SetPoints; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/package.order new file mode 100644 index 00000000000..6ff402de0c3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/SetPoints/package.order @@ -0,0 +1,5 @@ +CondensationControl +HotWaterSupplyTemperatureReset +MinimumFlowSetPoint +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Down.mo new file mode 100644 index 00000000000..7c2f9d43136 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Down.mo @@ -0,0 +1,623 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes; +block Down + "Sequence for control devices when there is stage-down command" + + parameter Boolean have_priOnl = false + "True: The boiler plant is primary-only" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Boolean have_heaPriPum = true + "True: Headered hot water pumps; + False: Dedicated hot water pumps" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Integer nBoi=3 + "Total number of boilers in the plant" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Integer nSta=5 + "Total number of stages" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Real delEnaMinFloSet( + final unit="s", + displayUnit="s", + final quantity="time")=60 + "Time delay after minimum flow setpoint is achieved in bypass valve" + annotation (Evaluate=true, + Dialog(group="Time and delay parameters", + enable=have_priOnl)); + + parameter Real chaIsoValTim( + final unit="s", + displayUnit="s", + final quantity="time") = 60 + "Time period to slowly change isolation valve position; Should be determined + in the field" + annotation (Evaluate=true, + Dialog(group="Time and delay parameters", + enable=have_heaPriPum)); + + parameter Real delPreBoiEna( + final unit="s", + displayUnit="s", + final quantity="time") = 30 + "Time delay after valve position change and pump stage change process has been + completed before starting boiler stage change process" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real boiChaProOnTim( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Minimum time period threshold for uninterrupted proven on signal from newly + enabled boiler during a staging process where one boiler is turned on and + another is turned off" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real delBoiEna( + final unit="s", + displayUnit="s", + final quantity="time") = 180 + "Time delay after boiler status change process has been completed before turning + off excess isolation valves and pumps" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real relFloDif( + final unit="1", + displayUnit="1")=0.05 + "Relative error to the flow setpoint for checking if it has been achieved" + annotation (Evaluate=true, + Dialog(tab="Advanced", + enable=have_priOnl)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDowPro + "Rising edge indicating start of stage up process" + annotation (Placement( + transformation(extent={{-280,-20},{-240,20}}), iconTransformation( + extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoi[nBoi] + "Boiler proven on status vector" + annotation (Placement(transformation(extent={{-280,60},{-240,100}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaPro + "Signal indicating final completion of stage change process" annotation ( + Placement(transformation(extent={{-280,-150},{-240,-110}}), + iconTransformation(extent={{-140,-160},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPumChaPro if not have_priOnl + "Rising edge indicating all pump change processes have been completed and pumps have been proved on" + annotation (Placement(transformation(extent={{-280,-210},{-240,-170}}), + iconTransformation(extent={{-140,-200},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiSet[nBoi] + "Boiler status setpoint vector from staging setpoint controller" + annotation (Placement(transformation(extent={{-280,20},{-240,60}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Boiler stage setpoint index from staging setpoint controller" + annotation (Placement(transformation(extent={{-280,-100},{-240,-60}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinHotWatSet_flow( + final quantity="VolumeFlowRate", + final unit="m3/s", + displayUnit="m3/s", + final min=0) if have_priOnl + "Minimum hot water flow rate setpoint" + annotation (Placement(transformation(extent={{-280,180},{-240,220}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final min=0, + final quantity="VolumeFlowRate", + final unit="m3/s", + displayUnit="m3/s") if have_priOnl + "Measured hot water flow rate through the minimum flow bypass valve" + annotation (Placement(transformation(extent={{-280,220},{-240,260}}), + iconTransformation(extent={{-140,160},{-100,200}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal[nBoi]( + final min=fill(0, nBoi), + final max=fill(1, nBoi), + final unit=fill("1", nBoi)) if have_heaPriPum + "Boiler hot water isolation valve position vector, indexed according to their + respective boilers" + annotation (Placement(transformation(extent={{-280,100},{-240,140}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler enable status vector" + annotation (Placement(transformation(extent={{280,90},{320,130}}), + iconTransformation(extent={{100,100},{140,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaChaPro + "Rising edge indicating end of stage change process" + annotation (Placement(transformation(extent={{280,30},{320,70}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPumChaPro if not + have_priOnl + "Rising edge indicating start of pump change process" + annotation (Placement(transformation(extent={{280,-260},{320,-220}}), + iconTransformation(extent={{100,-140},{140,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yOnOff + "Signal indicating whether stage change involves simultaneous turning on + and turning off of boilers" + annotation (Placement(transformation(extent={{280,-130},{320,-90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yNexEnaBoi + "Boiler index of next boiler being enabled" + annotation (Placement(transformation(extent={{280,-170},{320,-130}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yLasDisBoi + "Boiler index of last boiler enabled that will be disabled" + annotation (Placement(transformation(extent={{280,-210},{320,-170}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal[nBoi]( + final min=fill(0, nBoi), + final max=fill(1, nBoi), + final unit=fill("1", nBoi)) if have_heaPriPum + "Boiler hot water isolation valve position vector, indexed according to their + respective boilers" + annotation (Placement(transformation(extent={{280,-90},{320,-50}}), + iconTransformation(extent={{100,20},{140,60}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetMinBypass minBypRes( + final delEna=delEnaMinFloSet, + final relFloDif=relFloDif) if have_priOnl + "Reset process for minimum flow bypass valve setpoint" + annotation (Placement(transformation(extent={{-170,10},{-150,30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler nexBoi( + final nBoi=nBoi) + "Identify boiler indices to be turned on and off during the stage change process" + annotation (Placement(transformation(extent={{-170,-76},{-150,-56}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal enaHotWatIsoVal( + final nBoi=nBoi, + final chaHotWatIsoTim=chaIsoValTim, + final iniValPos=0, + final endValPos=1) if have_heaPriPum + "Open hot water isolation valve for boiler being enabled" + annotation (Placement(transformation(extent={{-70,-10},{-50,10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Check for completion of valve opening process and pump stage change process" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.DisableBoiler disBoi( + final nBoi=nBoi, + final proOnTim=boiChaProOnTim) + "Diable boiler status in boiler status vector as per required stage change" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal disHotWatIsoVal1( + final nBoi=nBoi, + final chaHotWatIsoTim=chaIsoValTim, + final iniValPos=1, + final endValPos=0) if have_heaPriPum + "Close hot water valve for boiler being disabled" + annotation (Placement(transformation(extent={{150,-10},{170,10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Check for completion of valve closing process and pump change process" + annotation (Placement(transformation(extent={{190,-10},{210,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Latch to retain stage-up edge signal till the stage change process is completed" + annotation (Placement(transformation(extent={{-222,-10},{-202,10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=delBoiEna) + "Time delay after boiler status has been changed" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat3 if not have_priOnl + "Hold process completion signal after pump enable process" + annotation (Placement(transformation(extent={{-140,-200},{-120,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat4 if not have_priOnl + "Hold process completion signal after pump disable process" + annotation (Placement(transformation(extent={{160,-200},{180,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4 if not have_priOnl + "Check for pump disable completion after start of pump disable process" + annotation (Placement(transformation(extent={{132,-200},{152,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Detect change in process completion status and send out pulse signal" + annotation (Placement(transformation(extent={{230,40},{250,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 if not have_priOnl + "Generate pulse to signal start of pump change process" + annotation (Placement(transformation(extent={{-40,-250},{-20,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg2 if not have_priOnl + "Generate pulse to signal start of pump change process" + annotation (Placement(transformation(extent={{140,-246},{160,-226}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 if not have_priOnl + "Check for pump change proces start signal" + annotation (Placement(transformation(extent={{210,-250},{230,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat5 if not have_heaPriPum + "Latch to short valve opening process in dedicated pump configuration plants" + annotation (Placement(transformation(extent={{-70,30},{-50,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat6 if not have_heaPriPum + "Latch to short valve closing process in dedicated pump configuration plants" + annotation (Placement(transformation(extent={{150,30},{170,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nBoi] if have_heaPriPum + "Pass valve position signal from valve opening controller once the opening process starts" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) if have_heaPriPum + "Boolean replicator" + annotation (Placement(transformation(extent={{0,-140},{20,-120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nBoi] if have_heaPriPum + "Pass valve position signal from valve closing controller once the closing process starts" + annotation (Placement(transformation(extent={{100,-120},{120,-100}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) if have_heaPriPum + "Boolean replicator" + annotation (Placement(transformation(extent={{70,-160},{90,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=delPreBoiEna) + "Time delay after valve has been opened and pump status has been changed" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Pass process completion signal based on whether stage change involves turning off larger boiler or not" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 if have_heaPriPum + "Hold process completion signal after valve has been opened" + annotation (Placement(transformation(extent={{-32,-120},{-12,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=1) if not have_priOnl + "Pass enable signal for plants that are not primary-only" + annotation (Placement(transformation(extent={{-170,50},{-150,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) if have_priOnl + "Boolean True signal" + annotation (Placement(transformation(extent={{-160,-170},{-140,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if not have_priOnl + "Logical And" + annotation (Placement(transformation(extent={{-80,-250},{-60,-230}}))); + +equation + connect(lat.y, minBypRes.uUpsDevSta) annotation (Line(points={{-200,0},{-196, + 0},{-196,28},{-172,28}}, + color={255,0,255})); + + connect(lat.y, nexBoi.chaPro) annotation (Line(points={{-200,0},{-196,0},{-196, + -73},{-172,-73}}, color={255,0,255})); + + connect(truDel.y,disHotWatIsoVal1. uUpsDevSta) annotation (Line(points={{122,0}, + {126,0},{126,-5},{148,-5}}, color={255,0,255})); + + connect(VHotWat_flow, minBypRes.VHotWat_flow) annotation (Line(points={{-260, + 240},{-176,240},{-176,16},{-172,16}}, + color={0,0,127})); + + connect(VMinHotWatSet_flow, minBypRes.VMinHotWatSet_flow) annotation (Line( + points={{-260,200},{-180,200},{-180,12},{-172,12}}, color={0,0,127})); + + connect(uHotWatIsoVal, enaHotWatIsoVal.uHotWatIsoVal) annotation (Line(points={{-260, + 120},{-80,120},{-80,5},{-72,5}}, color={0,0,127})); + + connect(nexBoi.uBoiSet, uBoiSet) annotation (Line(points={{-172,-66},{-190,-66}, + {-190,40},{-260,40}}, color={255,0,255})); + + connect(uStaSet, nexBoi.uStaSet) annotation (Line(points={{-260,-80},{-234,-80}, + {-234,-59},{-172,-59}}, color={255,127,0})); + + connect(uStaDowPro, lat.u) + annotation (Line(points={{-260,0},{-224,0}}, color={255,0,255})); + + connect(lat3.y, and1.u2) annotation (Line(points={{-118,-190},{-48,-190},{-48, + -26},{-10,-26},{-10,-8},{-2,-8}}, color={255,0,255})); + + connect(uPumChaPro, lat3.u) + annotation (Line(points={{-260,-190},{-142,-190}}, color={255,0,255})); + + connect(and4.y, lat4.u) + annotation (Line(points={{154,-190},{158,-190}}, color={255,0,255})); + + connect(truDel.y, and4.u1) annotation (Line(points={{122,0},{126,0},{126,-190}, + {130,-190}}, color={255,0,255})); + + connect(uPumChaPro, and4.u2) annotation (Line(points={{-260,-190},{-160,-190}, + {-160,-210},{120,-210},{120,-198},{130,-198}}, color={255,0,255})); + + connect(lat4.y, and3.u2) annotation (Line(points={{182,-190},{184,-190},{184, + -8},{188,-8}}, color={255,0,255})); + + connect(edg.y, yStaChaPro) + annotation (Line(points={{252,50},{300,50}}, color={255,0,255})); + + connect(edg2.y, or2.u1) annotation (Line(points={{162,-236},{200,-236},{200, + -240},{208,-240}}, color={255,0,255})); + + connect(edg1.y, or2.u2) annotation (Line(points={{-18,-240},{66,-240},{66,-248}, + {208,-248}}, color={255,0,255})); + + connect(or2.y, yPumChaPro) + annotation (Line(points={{232,-240},{300,-240}}, color={255,0,255})); + + connect(nexBoi.yOnOff, yOnOff) annotation (Line(points={{-148,-66},{144,-66},{ + 144,-110},{300,-110}}, color={255,0,255})); + + connect(truDel.y, edg2.u) annotation (Line(points={{122,0},{126,0},{126,-236}, + {138,-236}}, color={255,0,255})); + + connect(minBypRes.yMinBypRes, lat5.u) annotation (Line(points={{-148,20},{ + -110,20},{-110,40},{-72,40}}, + color={255,0,255})); + + connect(lat5.y, and1.u1) annotation (Line(points={{-48,40},{-6,40},{-6,0},{-2, + 0}}, color={255,0,255})); + + connect(truDel.y, lat6.u) annotation (Line(points={{122,0},{126,0},{126,40},{148, + 40}}, color={255,0,255})); + + connect(lat6.y, and3.u1) annotation (Line(points={{172,40},{180,40},{180,0},{188, + 0}}, color={255,0,255})); + + connect(enaHotWatIsoVal.yHotWatIsoVal, swi.u1) annotation (Line(points={{-48, + -6},{-30,-6},{-30,-90},{26,-90},{26,-122},{38,-122}}, color={0,0,127})); + + connect(uHotWatIsoVal, swi.u3) annotation (Line(points={{-260,120},{30,120},{ + 30,-138},{38,-138}}, color={0,0,127})); + + connect(booRep.y, swi.u2) + annotation (Line(points={{22,-130},{38,-130}}, color={255,0,255})); + + connect(swi.y, swi1.u3) annotation (Line(points={{62,-130},{92,-130},{92,-118}, + {98,-118}}, color={0,0,127})); + + connect(disHotWatIsoVal1.yHotWatIsoVal, swi1.u1) annotation (Line(points={{ + 172,-6},{180,-6},{180,-70},{92,-70},{92,-102},{98,-102}}, color={0,0, + 127})); + + connect(truDel.y, booRep1.u) annotation (Line(points={{122,0},{126,0},{126,-166}, + {60,-166},{60,-150},{68,-150}}, color={255,0,255})); + + connect(booRep1.y, swi1.u2) annotation (Line(points={{92,-150},{96,-150},{96, + -110},{98,-110}}, color={255,0,255})); + + connect(swi1.y, yHotWatIsoVal) annotation (Line(points={{122,-110},{134,-110}, + {134,-90},{210,-90},{210,-70},{300,-70}}, color={0,0,127})); + + connect(and1.y, truDel1.u) annotation (Line(points={{22,0},{28,0},{28,60},{ + -10,60},{-10,100},{-2,100}}, + color={255,0,255})); + + connect(disHotWatIsoVal1.yEnaHotWatIsoVal, and3.u1) annotation (Line(points={{ + 172,6},{180,6},{180,0},{188,0}}, color={255,0,255})); + + connect(minBypRes.yMinBypRes, booRep.u) annotation (Line(points={{-148,20},{ + -110,20},{-110,-130},{-2,-130}}, color={255,0,255})); + + connect(minBypRes.yMinBypRes, enaHotWatIsoVal.uUpsDevSta) annotation (Line( + points={{-148,20},{-110,20},{-110,-5},{-72,-5}}, color={255,0,255})); + + connect(uHotWatIsoVal, disHotWatIsoVal1.uHotWatIsoVal) annotation (Line( + points={{-260,120},{144,120},{144,5},{148,5}}, color={0,0,127})); + + connect(enaHotWatIsoVal.yEnaHotWatIsoVal, lat1.u) annotation (Line(points={{ + -48,6},{-40,6},{-40,-110},{-34,-110}}, color={255,0,255})); + + connect(lat1.y, and1.u1) annotation (Line(points={{-10,-110},{-6,-110},{-6,0}, + {-2,0}}, color={255,0,255})); + + connect(nexBoi.yOnOff, logSwi.u2) annotation (Line(points={{-148,-66},{34,-66}, + {34,-40},{38,-40}}, color={255,0,255})); + + connect(truDel1.y, logSwi.u1) annotation (Line(points={{22,100},{36,100},{36,-32}, + {38,-32}}, color={255,0,255})); + + connect(lat.y, logSwi.u3) annotation (Line(points={{-200,0},{-196,0},{-196,-48}, + {38,-48}}, color={255,0,255})); + + connect(nexBoi.yEnaSmaBoi, enaHotWatIsoVal.nexChaBoi) annotation (Line(points= + {{-148,-75},{-76,-75},{-76,8},{-72,8}}, color={255,127,0})); + + connect(logSwi.y, disBoi.uUpsDevSta) annotation (Line(points={{62,-40},{70,-40}, + {70,-20},{50,-20},{50,2},{58,2}}, color={255,0,255})); + + connect(lat.y, disBoi.uStaDow) annotation (Line(points={{-200,0},{-196,0},{-196, + -20},{44,-20},{44,6},{58,6}}, color={255,0,255})); + + connect(nexBoi.yEnaSmaBoi, disBoi.nexEnaBoi) annotation (Line(points={{-148,-75}, + {-76,-75},{-76,20},{50,20},{50,9},{58,9}}, color={255,127,0})); + + connect(uBoi, disBoi.uBoi) annotation (Line(points={{-260,80},{54,80},{54,-2}, + {58,-2}}, color={255,0,255})); + + connect(nexBoi.yLasDisBoi, disBoi.nexDisBoi) annotation (Line(points={{-148,-70}, + {26,-70},{26,-5},{58,-5}}, color={255,127,0})); + + connect(nexBoi.yOnOff, disBoi.uOnOff) annotation (Line(points={{-148,-66},{34, + -66},{34,-9},{58,-9}}, color={255,0,255})); + + connect(disBoi.yBoiDisPro, truDel.u) annotation (Line(points={{82,-8},{90,-8}, + {90,0},{98,0}}, color={255,0,255})); + + connect(disBoi.yBoi, yBoi) annotation (Line(points={{82,0},{86,0},{86,110},{300, + 110}}, color={255,0,255})); + + connect(nexBoi.yLasDisBoi, disHotWatIsoVal1.nexChaBoi) annotation (Line( + points={{-148,-70},{60,-70},{60,-60},{140,-60},{140,8},{148,8}}, color={ + 255,127,0})); + + connect(and3.y, edg.u) annotation (Line(points={{212,0},{220,0},{220,50},{228, + 50}}, color={255,0,255})); + + connect(nexBoi.yOnOff, enaHotWatIsoVal.chaPro) annotation (Line(points={{-148, + -66},{-80,-66},{-80,-8},{-72,-8}}, color={255,0,255})); + + connect(nexBoi.yOnOff, minBypRes.chaPro) annotation (Line(points={{-148,-66},{ + -140,-66},{-140,0},{-184,0},{-184,24},{-172,24}}, color={255,0,255})); + + connect(lat.y, disHotWatIsoVal1.chaPro) annotation (Line(points={{-200,0},{ + -196,0},{-196,-20},{44,-20},{44,-18},{146,-18},{146,-8},{148,-8}}, + color={255, + 0,255})); + + connect(lat.y, mulOr.u[1]) annotation (Line(points={{-200,0},{-196,0},{-196,60}, + {-172,60}}, color={255,0,255})); + + connect(mulOr.y, lat5.u) annotation (Line(points={{-148,60},{-110,60},{-110,40}, + {-72,40}}, color={255,0,255})); + + connect(mulOr.y, enaHotWatIsoVal.uUpsDevSta) annotation (Line(points={{-148,60}, + {-110,60},{-110,-5},{-72,-5}}, color={255,0,255})); + + connect(mulOr.y, booRep.u) annotation (Line(points={{-148,60},{-110,60},{-110, + -130},{-2,-130}}, color={255,0,255})); + + connect(nexBoi.yEnaSmaBoi, yNexEnaBoi) annotation (Line(points={{-148,-75},{-76, + -75},{-76,-86},{260,-86},{260,-150},{300,-150}}, color={255,127,0})); + + connect(con.y, and1.u2) annotation (Line(points={{-138,-160},{-48,-160},{-48,-26}, + {-10,-26},{-10,-8},{-2,-8}}, color={255,0,255})); + connect(con.y, and3.u2) annotation (Line(points={{-138,-160},{52,-160},{52,-172}, + {184,-172},{184,-8},{188,-8}}, color={255,0,255})); + connect(nexBoi.yLasDisBoi, yLasDisBoi) annotation (Line(points={{-148,-70},{60, + -70},{60,-60},{140,-60},{140,-116},{254,-116},{254,-190},{300,-190}}, + color={255,127,0})); + connect(uStaChaPro, lat.clr) annotation (Line(points={{-260,-130},{-230,-130}, + {-230,-6},{-224,-6}}, color={255,0,255})); + connect(uStaChaPro, lat5.clr) annotation (Line(points={{-260,-130},{-230,-130}, + {-230,-110},{-90,-110},{-90,34},{-72,34}}, color={255,0,255})); + connect(uStaChaPro, lat1.clr) annotation (Line(points={{-260,-130},{-230,-130}, + {-230,-110},{-90,-110},{-90,-116},{-34,-116}}, color={255,0,255})); + connect(uStaChaPro, lat3.clr) annotation (Line(points={{-260,-130},{-230,-130}, + {-230,-196},{-142,-196}}, color={255,0,255})); + connect(uStaChaPro, lat4.clr) annotation (Line(points={{-260,-130},{-230,-130}, + {-230,-110},{-90,-110},{-90,-180},{110,-180},{110,-214},{156,-214},{156, + -196},{158,-196}}, color={255,0,255})); + connect(uStaChaPro, lat6.clr) annotation (Line(points={{-260,-130},{-230,-130}, + {-230,-110},{-90,-110},{-90,70},{120,70},{120,34},{148,34}}, color={255, + 0,255})); + + connect(and2.y, edg1.u) + annotation (Line(points={{-58,-240},{-42,-240}}, color={255,0,255})); + connect(mulOr.y, and2.u1) annotation (Line(points={{-148,60},{-110,60},{-110,-240}, + {-82,-240}}, color={255,0,255})); + connect(nexBoi.yOnOff, and2.u2) annotation (Line(points={{-148,-66},{-100,-66}, + {-100,-248},{-82,-248}}, color={255,0,255})); +annotation ( + defaultComponentName="dowProCon", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-240,-260},{280,260}})), + 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,260},{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, + rotation=180), + Polygon( + points={{0,160},{-40,120},{0,120},{40,120},{0,160}}, + lineColor={200,200,200}, + fillColor={207,207,207}, + fillPattern=FillPattern.Solid, + rotation=180)}), +Documentation(info=" +

+Block that controls boiler status and isolation valve position, initiates status +change in devices like pumps and minimum flow bypass valve, and resets plant +parameters like minimum flow setpoint when there is a stage-down command. +This development is based on ASHRAE RP-1711, March 2020 draft,sections 5.3.3.11 - 5.3.3.18, +which specify the step-by-step control of devices during boiler staging down process. +

+
    +
  1. +Identify the boiler(s) that should be disabled (and enabled). This is implemented in block nexBoi. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler +for more decriptions. +
  2. +
  3. +If the stage change process involves disabling a larger boiler and enabling a smaller boiler, + +
  4. +
  5. +If the stage down process does not involve turning on a smaller boiler, start the +staging down process immediately by changing yBoi using disBoi. +
  6. +
  7. +Wait for time delBoiEna before closing the isolation valve for the +disabled boiler using disHotWatIsoVal1 and initiating the pump stage +change process. +
  8. +
  9. +End the staging process after the valve has been closed and the pump change process +completion signal has been received. Send rising edge signal through yStaChaPro +to indicate the same. +
  10. +
+", revisions=" + +")); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/DisableBoiler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/DisableBoiler.mo new file mode 100644 index 00000000000..eb4ef4a5a27 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/DisableBoiler.mo @@ -0,0 +1,573 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences; +block DisableBoiler + "Sequence for disabling boiler in stage-down process" + + parameter Integer nBoi = 3 + "Total number of boilers"; + + parameter Real proOnTim( + final unit="s", + final quantity="Time", + displayUnit="s") = 300 + "Enabled boiler operation time to indicate if it is proven on"; + + 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 uUpsDevSta + "Status of upstream device: true=upstream device has completed stage change + process" + annotation (Placement(transformation(extent={{-240,90},{-200,130}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoi[nBoi] + "Boiler proven on status vector" + annotation (Placement(transformation(extent={{-240,40},{-200,80}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOnOff + "Signal indicating if the stage change process requires one boiler 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.IntegerInput nexDisBoi + "Next disabling boiler index" + annotation (Placement(transformation(extent={{-240,-100},{-200,-60}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaBoi + "Index of next enabling boiler when there is any stage down that requires one boiler + on and another off" + annotation (Placement(transformation(extent={{-240,180},{-200,220}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler enabling status vector" + annotation (Placement(transformation(extent={{200,-140},{240,-100}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoiDisPro + "Signal indicating completion of boiler disable process; True: Disable process + has been completed for the stage change process" + annotation (Placement(transformation(extent={{200,-70},{240,-30}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + final parameter Integer boiInd[nBoi]={i for i in 1:nBoi} + "Boiler index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,190},{120,210}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Check for stage change sigal and upstream device status" + annotation (Placement(transformation(extent={{-160,130},{-140,150}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-100,130},{-80,150}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{-40,190},{-20,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nBoi]( + final k=fill(true, nBoi)) + "True constant" + annotation (Placement(transformation(extent={{-40,220},{-20,240}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nBoi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greEquThr[nBoi]( + final t=fill(0.5, nBoi)) + "Convert real input to boolean output" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,0},{120,20}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nBoi]( + final k=fill(false, nBoi)) + "False constant" + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{160,40},{180,60}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nBoi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,190},{-140,210}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nBoi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,190},{-80,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim(t=proOnTim) + "Count the time after new boiler has been enabled" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nBoi] + "Record the old boiler hot water isolation valve status" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge detector" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nBoi) + "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[nBoi]( + final k=boiInd) + "Boiler index array" + annotation (Placement(transformation(extent={{-160,160},{-140,180}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1( + final nout=nBoi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,-90},{-140,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nBoi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-80,-170},{-60,-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[nBoi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-160,-220},{-140,-200}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam1[nBoi] + "Record the old boiler hot water isolation valve status" + annotation (Placement(transformation(extent={{-80,-220},{-60,-200}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep5( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-120,-250},{-100,-230}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greEquThr1[nBoi]( + final t=fill(0.5, nBoi)) + "Convert real input to boolean output" + annotation (Placement(transformation(extent={{40,-220},{60,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{40,-190},{60,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nBoi]( + final k=fill(false, nBoi)) + "False constant" + annotation (Placement(transformation(extent={{40,-160},{60,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-190},{120,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{160,-130},{180,-110}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep6( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{100,-130},{120,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi5[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi6[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-250},{120,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi7 + "Logical switch" + annotation (Placement(transformation(extent={{100,-60},{120,-40}}))); + +equation + connect(nexEnaBoi, 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(uUpsDevSta, 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(uBoi,booToRea. u) + annotation (Line(points={{-220,60},{-170,60},{-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(uBoi,logSwi1. u3) + annotation (Line(points={{-220,60},{-170,60},{-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(nexDisBoi, 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(uBoi, booToRea1.u) + annotation (Line(points={{-220,60},{-170,60},{-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={{-58,-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,yBoi) + 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(uBoi, logSwi5.u3) + annotation (Line(points={{-220,60},{-170,60},{-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={{-58,-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(uBoi, logSwi6.u3) + annotation (Line(points={{-220,60},{-170,60},{-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,-50},{98,-50}}, + color={255,0,255})); + + + connect(and2.y, booRep4.u) annotation (Line(points={{-138,140},{-120,140},{ + -120,-160},{-82,-160}}, color={255,0,255})); + + connect(and2.y, logSwi7.u3) annotation (Line(points={{-138,140},{-120,140},{ + -120,-58},{98,-58}}, color={255,0,255})); + + connect(logSwi7.y, yBoiDisPro) + annotation (Line(points={{122,-50},{220,-50}}, color={255,0,255})); + + connect(tim.passed, booRep2.u) annotation (Line(points={{-78,-8},{-30,-8},{ + -30,0},{-22,0}}, color={255,0,255})); + connect(tim.passed, logSwi7.u1) annotation (Line(points={{-78,-8},{-30,-8},{ + -30,-42},{98,-42}}, color={255,0,255})); + connect(tim.passed, not1.u) annotation (Line(points={{-78,-8},{-30,-8},{-30, + 50},{-22,50}}, color={255,0,255})); +annotation ( + defaultComponentName="disBoi", + 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="nexEnaBoi"), + Text( + extent={{-98,70},{-52,56}}, + textColor={255,0,255}, + textString="uStaDow"), + Text( + extent={{-96,30},{-24,10}}, + textColor={255,0,255}, + textString="uUpsDevSta"), + Text( + extent={{-100,-14},{-78,-24}}, + textColor={255,0,255}, + textString="uBoi"), + Text( + extent={{-98,-82},{-70,-94}}, + textColor={255,0,255}, + textString="uOnOff"), + Text( + extent={{-98,-40},{-44,-56}}, + textColor={255,127,0}, + textString="nexDisBoi"), + Text( + extent={{74,6},{98,-6}}, + textColor={255,0,255}, + textString="yBoi"), + Text( + extent={{44,-72},{96,-84}}, + textColor={255,0,255}, + textString="yBoiDis")}), + 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, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable small boiler"), + Text( + extent={{102,-6},{172,-24}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable large boiler"), + Text( + extent={{-164,-244},{190,-286}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable boiler when the down-process does not require any other boiler being disabled"), + Text( + extent={{-144,278},{166,258}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString= + "Disable boiler when the down-process requires small boiler being enabled")}), +Documentation(info=" +

+Block that controls boiler diabling process when there is stage down command +uStaDow=true. +This implementation is based on RP-1711, March 2020 draft, sections 5.3.3.12, +5.3.3.16, 5.3.3.17 and 5.3.3.18. These sections specify how to start the +smaller boiler and shut off larger boiler when the stage change requires large +boiler off and smaller boiler on. +In other stage change, when it does not require boiler on/off, the boiler will then +be shut off. +

+

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

+ +

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

+", revisions=" + +")); +end DisableBoiler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/EnableBoiler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/EnableBoiler.mo new file mode 100644 index 00000000000..821941f13e4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/EnableBoiler.mo @@ -0,0 +1,497 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences; +block EnableBoiler + "Sequence for enabling boiler" + + parameter Integer nBoi = 3 + "Total number of boilers"; + + parameter Real proOnTim( + final unit="s", + final quantity="Time", + displayUnit="s") = 300 + "Enabled boiler operation time to indicate if it is proven on"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp + "Continuous stage-up command until change process is completed" + annotation (Placement(transformation(extent={{-240,40},{-200,80}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of upstream device: true=upstream device is proved functional" + annotation (Placement(transformation(extent={{-240,10},{-200,50}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoi[nBoi] + "Boiler 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 boiler 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 nexDisBoi + "Next disabling boiler when there is any stage up that need one boiler on and another off" + annotation (Placement(transformation(extent={{-240,-170},{-200,-130}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nexEnaBoi + "Index of next enabling boiler" + annotation (Placement(transformation(extent={{-240,100},{-200,140}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler enabling status" + annotation (Placement(transformation(extent={{200,-70},{240,-30}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoiEnaPro + "True signal when the boiler enabling process has been completed" + annotation (Placement(transformation(extent={{200,-190},{240,-150}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + final parameter Integer boiInd[nBoi]={i for i in 1:nBoi} + "Boiler index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,110},{120,130}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical And" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nBoi]( + final k=fill(true, nBoi)) + "True constant" + annotation (Placement(transformation(extent={{-40,140},{-20,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nBoi] + "Convert boolean input to real output" + annotation (Placement(transformation(extent={{-160,-10},{-140,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greEquThr[nBoi]( + final t=fill(0.5, nBoi)) + "Check boilers that are on" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{100,-120},{120,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{40,-120},{60,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nBoi]( + final k=fill(false, nBoi)) + "False constant" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nBoi] + "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=nBoi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,110},{-140,130}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nBoi] + "Check next enabling boiler" + annotation (Placement(transformation(extent={{-100,110},{-80,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=proOnTim) + "Count the time after new boiler has been enabled" + annotation (Placement(transformation(extent={{-100,-120},{-80,-100}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nBoi] + "Record the old boiler status" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-20,-120},{0,-100}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nBoi) + "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[nBoi]( + final k=boiInd) + "Boiler index array" + annotation (Placement(transformation(extent={{-160,80},{-140,100}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1( + final nout=nBoi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nBoi] + "Check next enabling boiler" + annotation (Placement(transformation(extent={{-100,-160},{-80,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4 + "Logical switch" + annotation (Placement(transformation(extent={{120,-180},{140,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Xor xor[nBoi] + "Boolean Exclusive Or" + annotation (Placement(transformation(extent={{-68,-230},{-48,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3[nBoi] + "Logical Not" + annotation (Placement(transformation(extent={{-20,-230},{0,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=nBoi+1) + "Multi-input Logical And" + annotation (Placement(transformation(extent={{52,-230},{72,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[nBoi] "Logical pre block" + annotation (Placement(transformation(extent={{-160,-240},{-140,-220}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Logical pre block" + annotation (Placement(transformation(extent={{20,-210},{40,-190}}))); + +equation + connect(nexEnaBoi, 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(uUpsDevSta, 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(uBoi,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(uBoi,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,yBoi) + 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(nexDisBoi, 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(uBoi, 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},{118,-170}}, + color={255,0,255})); + + connect(logSwi4.y, yBoiEnaPro) + annotation (Line(points={{142,-170},{220,-170}}, color={255,0,255})); + + connect(tim.passed, booRep2.u) annotation (Line(points={{-78,-118},{-32,-118}, + {-32,-110},{-22,-110}}, color={255,0,255})); + connect(tim.passed, logSwi4.u3) annotation (Line(points={{-78,-118},{-32,-118}, + {-32,-178},{118,-178}}, color={255,0,255})); + connect(tim.passed, not1.u) annotation (Line(points={{-78,-118},{-32,-118},{-32, + -70},{-22,-70}}, color={255,0,255})); + connect(xor.y, not3.u) + annotation (Line(points={{-46,-220},{-22,-220}}, color={255,0,255})); + connect(uBoi, xor.u1) annotation (Line(points={{-220,0},{-180,0},{-180,-200},{ + -130,-200},{-130,-220},{-70,-220}}, + color={255,0,255})); + connect(not3.y, mulAnd.u[1:nBoi]) annotation (Line(points={{2,-220},{50,-220}}, + color={255,0,255})); + connect(mulAnd.y, logSwi4.u1) annotation (Line(points={{74,-220},{100,-220},{100, + -162},{118,-162}}, color={255,0,255})); + connect(logSwi2.y, pre1.u) annotation (Line(points={{182,-50},{190,-50},{190,-250}, + {-180,-250},{-180,-230},{-162,-230}}, color={255,0,255})); + connect(pre1.y, xor.u2) annotation (Line(points={{-138,-230},{-100,-230},{-100, + -228},{-70,-228}}, color={255,0,255})); + connect(and2.y, pre2.u) annotation (Line(points={{-138,60},{-120,60},{-120,-200}, + {18,-200}}, color={255,0,255})); + connect(pre2.y, mulAnd.u[nBoi+1]) annotation (Line(points={{42,-200},{46,-200},{46, + -220},{50,-220}}, color={255,0,255})); +annotation ( + defaultComponentName="enaBoi", + 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={{-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="nexEnaBoi"), + Text( + extent={{-98,-84},{-50,-96}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="nexDisBoi"), + 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="uUpsDevSta"), + Text( + extent={{-100,-14},{-78,-24}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uBoi"), + 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="yBoi"), + Text( + extent={{60,-72},{98,-84}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yNewBoiEna")}), + Diagram( + coordinateSystem(preserveAspectRatio=false, extent={{-200,-260},{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={{20,158},{100,150}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Output new boiler status array:\n1. When the stage change does not require one boiler off and another boiler on.\n2. When the stage change does require one boiler off and another boiler on,\n but the enabled boiler has not yet finished starting."), + Text( + extent={{34,-140},{114,-148}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + lineColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Output new boiler status array:\nWhen the stage change does require one boiler off and another boiler on,\nand the enabled boiler has finished starting.")}), +Documentation(info=" +

+Block that controls boiler when there is staging up command uStaUp=true. +This implementation is based on RP-1711, March 2020 draft, sections 5.3.3.11, +5.3.3.13, 5.3.3.14 and 5.3.3.15. These sections specify when the next boiler should be enabled +and when the running smaller boiler should be diabled. +

+

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

+ +

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

+ +", revisions=" + +")); +end EnableBoiler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/HWIsoVal.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/HWIsoVal.mo new file mode 100644 index 00000000000..e583a39096d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/HWIsoVal.mo @@ -0,0 +1,450 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences; +block HWIsoVal + "Sequence of enable or disable hot water isolation valve" + + parameter Integer nBoi = 3 + "Total number of boiler, which is also the total number of hot water isolation valve"; + + parameter Real chaHotWatIsoTim( + final unit="s", + final quantity="Time", + displayUnit="s") = 60 + "Time to slowly change isolation valve position, should be determined in the field"; + + parameter Real iniValPos + "Initial valve position, if it needs to turn on boiler, the value should be 0"; + + parameter Real endValPos + "Ending valve position, if it needs to turn on boiler, the value should be 1"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUpsDevSta + "Status of device reset 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 chaPro + "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.IntegerInput nexChaBoi + "Index of next boiler that should change status" + annotation (Placement(transformation(extent={{-200,-10},{-160,30}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal[nBoi]( + final unit=fill("1", nBoi), + final min=fill(0, nBoi), + final max=fill(1, nBoi)) + "Hot water isolation valve position" + annotation (Placement(transformation(extent={{-200,-120},{-160,-80}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaHotWatIsoVal + "Status of hot water isolation valve control: true=enabled valve is fully open" + annotation (Placement(transformation(extent={{180,120},{220,160}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal[nBoi]( + final unit=fill("1", nBoi), + final min=fill(0, nBoi), + final max=fill(1, nBoi)) + "Hot water isolation valve position" + annotation (Placement(transformation(extent={{180,-60},{220,-20}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + final parameter Integer boiInd[nBoi]={i for i in 1:nBoi} + "Boiler index, {1,2,...,nBoi}"; + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con7( + final k=chaHotWatIsoTim) + "Time to change hot water isolation valve" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con8( + final k=endValPos) + "Ending valve position" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con6( + final k=iniValPos) + "Initial isolation valve position" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con9( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line lin1 + "Hot water isolation valve setpoint" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=chaHotWatIsoTim) + "Count the time after changing up-stream device status" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nBoi] + "Record the old hot water isolation valve status" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "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={{-80,-180},{-60,-160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{120,-50},{140,-30}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2[nBoi] + "Logical not" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2[nBoi] + "Logical switch" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nBoi] + "Check next enabling isolation valve" + annotation (Placement(transformation(extent={{-20,0},{0,20}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nBoi) + "Replicate integer input" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nBoi) + "Replicate real input" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys3[nBoi]( + final uLow=fill(0.025,nBoi), + final uHigh=fill(0.05, nBoi)) + "Check if isolation valve is enabled" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys4[nBoi]( + final uLow=fill(0.925,nBoi), + final uHigh=fill(0.975, nBoi)) + "Check if isolation valve is open more than 95%" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3[nBoi] + "Logical not" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4[nBoi] + "Logical not" + annotation (Placement(transformation(extent={{-40,150},{-20,170}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{0,180},{20,200}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3[nBoi] + "Logical and" + annotation (Placement(transformation(extent={{0,210},{20,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2[nBoi] + "Logical or" + annotation (Placement(transformation(extent={{40,210},{60,230}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd1( + final nin=nBoi) + "Logical and" + annotation (Placement(transformation(extent={{80,210},{100,230}}))); + + Buildings.Controls.OBC.CDL.Logical.And3 and5 + "Check if the isolation valve has been fully open" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nBoi]( + final k=boiInd) + "Boiler index array" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Edge detector" + annotation (Placement(transformation(extent={{-20,-150},{0,-130}}))); + +equation + connect(uHotWatIsoVal, triSam.u) + annotation (Line(points={{-180,-100},{-82,-100}}, color={0,0,127})); + + connect(con9.y, lin1.x1) + annotation (Line(points={{22,100},{30,100},{30,88},{38,88}}, + color={0,0,127})); + + connect(con6.y, lin1.f1) + annotation (Line(points={{-18,100},{-10,100},{-10,84},{38,84}}, + color={0,0,127})); + + connect(con7.y, lin1.x2) + annotation (Line(points={{-18,50},{-10,50},{-10,76},{38,76}}, + color={0,0,127})); + + connect(con8.y, lin1.f2) + annotation (Line(points={{22,50},{30,50},{30,72},{38,72}}, color={0,0,127})); + + connect(tim.y, lin1.u) + annotation (Line(points={{-78,80},{38,80}}, color={0,0,127})); + + connect(chaPro, and2.u2) + annotation (Line(points={{-180,-178},{-82,-178}}, 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,yHotWatIsoVal) + 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(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},{90,-60},{90,-48},{118,-48}}, + color={0,0,127})); + + connect(uHotWatIsoVal, 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,10},{100,10},{100,-32},{118,-32}}, + color={0,0,127})); + + connect(nexChaBoi, intRep.u) + annotation (Line(points={{-180,10},{-82,10}}, color={255,127,0})); + + connect(intRep.y, intEqu.u1) + annotation (Line(points={{-58,10},{-22,10}}, color={255,127,0})); + + connect(intEqu.y, swi2.u2) + annotation (Line(points={{2,10},{58,10}}, color={255,0,255})); + + connect(lin1.y, reaRep.u) + annotation (Line(points={{62,80},{78,80}}, color={0,0,127})); + + connect(reaRep.y, swi2.u1) + annotation (Line(points={{102,80},{120,80},{120,50},{40,50},{40,18},{58,18}}, + color={0,0,127})); + + connect(triSam.y, swi2.u3) + annotation (Line(points={{-58,-100},{40,-100},{40,2},{58,2}}, + color={0,0,127})); + + connect(uHotWatIsoVal, hys4.u) + annotation (Line(points={{-180,-100},{-140,-100},{-140,160},{-122,160}}, + color={0,0,127})); + + connect(uHotWatIsoVal, 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},{120,220},{120,148},{138,148}}, + color={255,0,255})); + + connect(and5.y,yEnaHotWatIsoVal) + annotation (Line(points={{162,140},{200,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,-20},{-40,-20},{-40,2},{-22,2}}, + color={255,127,0})); + + connect(uUpsDevSta, and5.u2) + annotation (Line(points={{-180,-140},{-130,-140},{-130,140},{138,140}}, + color={255,0,255})); + + + connect(uUpsDevSta, and2.u1) annotation (Line(points={{-180,-140},{-100,-140}, + {-100,-170},{-82,-170}},color={255,0,255})); + + connect(and2.y, booRep1.u) + annotation (Line(points={{-58,-170},{58,-170}}, color={255,0,255})); + + connect(edg.y, booRep.u) + annotation (Line(points={{2,-140},{18,-140}}, color={255,0,255})); + + connect(and2.y, edg.u) annotation (Line(points={{-58,-170},{-40,-170},{-40, + -140},{-22,-140}}, color={255,0,255})); + + connect(tim.u, and2.y) annotation (Line(points={{-102,80},{-120,80},{-120, + -200},{-40,-200},{-40,-170},{-58,-170}}, color={255,0,255})); + + connect(tim.passed, and5.u3) annotation (Line(points={{-78,72},{-60,72},{-60,132}, + {138,132}}, color={255,0,255})); +annotation ( + defaultComponentName="hotWatIsoVal", + 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 HW 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="chaPro"), + 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="nexChaBoi"), + Text( + extent={{-96,58},{-42,46}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="uHotWatIsoVal"), + Text( + extent={{32,70},{96,54}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yEnaHotWatIsoVal"), + 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="yHotWatIsoVal")}), + Documentation(info=" +

+ Block updates boiler hot water isolation valve enabling-disabling status when + there is stage change command (chaPro=true). It will also generate + status to indicate if the valve reset process has finished. + This block is not based on any specific section in RP-1711, but has been designed + to carry out the hot water isolation valve operations in the staging sequences + defined in 5.3.3. +

+ +

+ The valve opens or closes in a time period chaHotWatIsoTim, which + can be defined as per the valve specification. +

+

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

+ ", revisions=" + + ")); +end HWIsoVal; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/NextBoiler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/NextBoiler.mo new file mode 100644 index 00000000000..d27b4bf2bcf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/NextBoiler.mo @@ -0,0 +1,383 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences; +block NextBoiler + "Identify next enable and disable boilers" + + parameter Integer nBoi=3 + "Total number of boilers"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiSet[nBoi] + "Vector of boilers status setpoint" + annotation (Placement(transformation(extent={{-260,-20},{-220,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "True: in the stage change process" + annotation (Placement(transformation(extent={{-260,-180},{-220,-140}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Boiler stage setpoint" + annotation (Placement(transformation(extent={{-260,90},{-220,130}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yOnOff + "True: if the stage change require one boiler to be enabled while another is disabled" + annotation (Placement(transformation(extent={{220,-40},{260,0}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yNexEnaBoi + "Next enabling boiler index" + annotation (Placement(transformation(extent={{220,140},{260,180}}), + iconTransformation(extent={{100,70},{140,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yDisSmaBoi + "Smaller boiler to be disabled in staging-up process" + annotation (Placement(transformation(extent={{220,90},{260,130}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yLasDisBoi + "Disable last boiler when it is in stage-down process" + annotation (Placement(transformation(extent={{220,-120},{260,-80}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yEnaSmaBoi + "Smaller boiler to be enabled in stage-down process" + annotation (Placement(transformation(extent={{220,-180},{260,-140}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + +protected + parameter Integer boiInd[nBoi]={i for i in 1:nBoi} + "Boiler index, {1,2,...,n}"; + + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if it is stage up or stage down" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch enaBoi[nBoi] + "True when the boiler should be enabled" + annotation (Placement(transformation(extent={{-120,30},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch disBoi[nBoi] + "True when the boiler should be disabled" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr anyEnaBoi( + final nin=nBoi) + "Check if there is any enabling boiler" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr anyDisBoi( + final nin=nBoi) + "Check if there is any disabling boiler" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.And enaDis + "Check if enabling and disabling boilers at the same process" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt[nBoi] + "Find out the index of enabling boiler" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt1[nBoi] + "Find out the index of disabling boiler" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum enaBoiInd( + final nin=nBoi) + "Enabling boiler index" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + + Buildings.Controls.OBC.CDL.Integers.MultiSum disBoiInd( + final nin = nBoi) + "Disabling boiler index" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch upPro + "True when it is in stage up process" + annotation (Placement(transformation(extent={{-120,120},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch dowPro + "True when it is in stage down process" + annotation (Placement(transformation(extent={{-120,80},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt2 + "Find out the index of enabling boiler" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt3 + "Staging up process and it requires boiler on and off" + annotation (Placement(transformation(extent={{120,110},{140,130}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt4 + "Disabling boiler during stage up process" + annotation (Placement(transformation(extent={{180,100},{200,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt5 + "Find out the index of disabling boiler" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt6 + "Staging down process and it requires boiler on and off" + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt7 + "Enabling boiler during stage down process" + annotation (Placement(transformation(extent={{180,-170},{200,-150}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nBoi] + "Boolean to integer" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nBoi] + "Boolean to integer" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + 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={{-80,120},{-60,140}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt4 + "Boolean to integer" + annotation (Placement(transformation(extent={{-80,80},{-60,100}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant boiIndVec[nBoi]( + final k=boiInd) + "Vector of boiler index" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-160,-170},{-140,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg[nBoi] + "Detect boilers being turned on" + annotation (Placement(transformation(extent={{-200,30},{-180,50}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg[nBoi] + "Detect boilers being turned off" + annotation (Placement(transformation(extent={{-200,-110},{-180,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-200,-170},{-180,-150}}))); + +equation + connect(booRep.y,enaBoi. clr) annotation (Line(points={{-138,-160},{-130,-160}, + {-130,34},{-122,34}}, color={255,0,255})); + + connect(booRep.y,disBoi. clr) annotation (Line(points={{-138,-160},{-130,-160}, + {-130,-106},{-122,-106}}, color={255,0,255})); + + connect(enaBoi.y,anyEnaBoi. u) annotation (Line(points={{-98,40},{-90,40},{-90, + -20},{-82,-20}},color={255,0,255})); + + connect(anyEnaBoi.y, enaDis.u1) annotation (Line(points={{-58,-20},{-22,-20}}, + color={255,0,255})); + + connect(disBoi.y,anyDisBoi. u) annotation (Line(points={{-98,-100},{-90,-100}, + {-90,-60},{-82,-60}},color={255,0,255})); + + connect(anyDisBoi.y, enaDis.u2) annotation (Line(points={{-58,-60},{-30,-60},{ + -30,-28},{-22,-28}}, color={255,0,255})); + + connect(enaDis.y, yOnOff) annotation (Line(points={{2,-20},{240,-20}}, + color={255,0,255})); + + connect(uStaSet, cha.u) + annotation (Line(points={{-240,110},{-202,110}}, color={255,127,0})); + + connect(disBoi.y, booToInt1.u) + annotation (Line(points={{-98,-100},{-82,-100}}, color={255,0,255})); + + connect(enaBoi.y, booToInt.u) + annotation (Line(points={{-98,40},{-82,40}}, color={255,0,255})); + + connect(booToInt.y, proInt.u1) annotation (Line(points={{-58,40},{-40,40},{-40, + 46},{-22,46}}, color={255,127,0})); + + connect(booToInt1.y, proInt1.u2) annotation (Line(points={{-58,-100},{-40,-100}, + {-40,-106},{-22,-106}}, color={255,127,0})); + + connect(boiIndVec.y, proInt.u2) annotation (Line(points={{-98,0},{-40,0},{-40, + 34},{-22,34}}, color={255,127,0})); + + connect(proInt.y,enaBoiInd. u) + annotation (Line(points={{2,40},{18,40}}, color={255,127,0})); + + connect(boiIndVec.y, proInt1.u1) annotation (Line(points={{-98,0},{-40,0},{-40, + -94},{-22,-94}}, color={255,127,0})); + + connect(proInt1.y,disBoiInd. u) + annotation (Line(points={{2,-100},{18,-100}}, color={255,127,0})); + + connect(enaDis.y, booToInt2.u) annotation (Line(points={{2,-20},{20,-20},{20,-60}, + {38,-60}}, color={255,0,255})); + + connect(upPro.y, booToInt3.u) + annotation (Line(points={{-98,130},{-82,130}}, color={255,0,255})); + + connect(booToInt3.y, proInt2.u1) annotation (Line(points={{-58,130},{-20,130}, + {-20,166},{118,166}}, color={255,127,0})); + + connect(enaBoiInd.y, proInt2.u2) annotation (Line(points={{42,40},{80,40},{80, + 154},{118,154}}, color={255,127,0})); + + connect(proInt2.y,yNexEnaBoi) + annotation (Line(points={{142,160},{240,160}}, color={255,127,0})); + + connect(booToInt3.y, proInt3.u1) annotation (Line(points={{-58,130},{-20,130}, + {-20,126},{118,126}},color={255,127,0})); + + connect(booToInt2.y, proInt3.u2) annotation (Line(points={{62,-60},{70,-60},{70, + 114},{118,114}},color={255,127,0})); + + connect(proInt3.y, proInt4.u1) annotation (Line(points={{142,120},{160,120},{160, + 116},{178,116}}, color={255,127,0})); + + connect(disBoiInd.y, proInt4.u2) annotation (Line(points={{42,-100},{90,-100}, + {90,104},{178,104}}, color={255,127,0})); + + connect(proInt4.y,yDisSmaBoi) + annotation (Line(points={{202,110},{240,110}}, color={255,127,0})); + + connect(dowPro.y, booToInt4.u) + annotation (Line(points={{-98,90},{-82,90}}, color={255,0,255})); + + connect(booToInt4.y, proInt5.u1) annotation (Line(points={{-58,90},{100,90},{ + 100,-94},{118,-94}}, + color={255,127,0})); + + connect(disBoiInd.y, proInt5.u2) annotation (Line(points={{42,-100},{90,-100}, + {90,-106},{118,-106}}, color={255,127,0})); + + connect(proInt5.y,yLasDisBoi) + annotation (Line(points={{142,-100},{240,-100}}, color={255,127,0})); + + connect(booToInt2.y, proInt6.u2) annotation (Line(points={{62,-60},{70,-60},{70, + -146},{118,-146}}, color={255,127,0})); + + connect(booToInt4.y, proInt6.u1) annotation (Line(points={{-58,90},{100,90},{ + 100,-134},{118,-134}}, + color={255,127,0})); + + connect(proInt6.y, proInt7.u1) annotation (Line(points={{142,-140},{160,-140}, + {160,-154},{178,-154}}, color={255,127,0})); + + connect(enaBoiInd.y, proInt7.u2) annotation (Line(points={{42,40},{80,40},{80, + -166},{178,-166}}, color={255,127,0})); + + connect(proInt7.y,yEnaSmaBoi) + annotation (Line(points={{202,-160},{240,-160}}, color={255,127,0})); + + connect(falEdg.u, uBoiSet) annotation (Line(points={{-202,-100},{-212,-100},{ + -212,0},{-240,0}}, color={255,0,255})); + + connect(edg.u, uBoiSet) annotation (Line(points={{-202,40},{-212,40},{-212,0}, + {-240,0}}, color={255,0,255})); + + connect(falEdg.y, disBoi.u) + annotation (Line(points={{-178,-100},{-122,-100}}, color={255,0,255})); + connect(edg.y, enaBoi.u) + annotation (Line(points={{-178,40},{-122,40}}, color={255,0,255})); + connect(cha.up, upPro.u) annotation (Line(points={{-178,116},{-140,116},{-140, + 130},{-122,130}}, color={255,0,255})); + connect(cha.down, dowPro.u) annotation (Line(points={{-178,104},{-140,104},{ + -140,90},{-122,90}}, color={255,0,255})); + connect(chaPro, not1.u) + annotation (Line(points={{-240,-160},{-202,-160}}, color={255,0,255})); + connect(not1.y, booRep.u) + annotation (Line(points={{-178,-160},{-162,-160}}, color={255,0,255})); + connect(not1.y, upPro.clr) annotation (Line(points={{-178,-160},{-170,-160},{-170, + 124},{-122,124}}, color={255,0,255})); + connect(not1.y, dowPro.clr) annotation (Line(points={{-178,-160},{-170,-160},{ + -170,84},{-122,84}}, color={255,0,255})); + +annotation ( + defaultComponentName="nexBoi", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-220,-180},{220,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={{-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="uBoiSet"), + Text( + extent={{50,100},{98,80}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yNexEnaBoi"), + Text( + extent={{-98,-62},{-64,-74}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + Text( + extent={{50,52},{98,32}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yDisSmaBoi"), + Text( + extent={{50,-28},{98,-48}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yDisLasBoi"), + Text( + extent={{44,-78},{98,-100}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yEnaSmaBoi"), + Text( + extent={{54,8},{96,-4}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yOnOff"), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="?")}), +Documentation(info=" +

+This block identifies index of next enabled boiler (yNexEnaBoi and +yEnaSmaBoi) or disabled boiler (yDisSmaBoi and +yLasDisBoi) based on current boiler stage setpoint +uStaSet and the boiler status setpoint uBoiSet. +

+

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

+", revisions=" + +")); +end NextBoiler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/ResetHotWaterSupplyTemperature.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/ResetHotWaterSupplyTemperature.mo new file mode 100644 index 00000000000..c84131d7044 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/ResetHotWaterSupplyTemperature.mo @@ -0,0 +1,260 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences; +block ResetHotWaterSupplyTemperature + "Sequence for hot water supply temperature reset" + + parameter Integer nSta = 5 + "Number of stages in boiler plant"; + + parameter Real delPro( + final unit="s", + final quantity="Time", + displayUnit="s") = 300 + "Process time-out"; + + parameter Real TMinSupNonConBoi( + final min=0, + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 333.2 + "Minimum supply temperature required for non-condensing boilers"; + + parameter Real sigDif( + final min=0, + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 0.1 + "Significant difference based on minimum resolution of temperature sensor" + annotation (Dialog(tab="Advanced")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp + "Stage up command" + annotation (Placement(transformation(extent={{-200,50},{-160,90}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaTyp[nSta] + "Vector of stage-types" + annotation (Placement(transformation(extent={{-200,-40},{-160,0}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Stage setpoint being changed to" + annotation (Placement(transformation(extent={{-200,-100},{-160,-60}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSup( + final min=0, + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-200,10},{-160,50}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yHotWatSupTemRes + "True: Hot water supply temperature has been reset" + annotation (Placement(transformation(extent={{160,10},{200,50}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + parameter Integer boiStaInd[nSta]={i for i in 1:nSta} + "Index vector of boiler plant stages"; + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Ensure stage-completion signal is passed only when the stage-up signal is active" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesThr( + final t=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler) + "Pass True if all preceding stages are condensing boiler type stages" + annotation (Placement(transformation(extent={{80,-70},{100,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nSta]( + final k=boiStaInd) + "Boiler plant stage index generator" + annotation (Placement(transformation(extent={{-156,-70},{-136,-50}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nSta) + "Generate row vector with current stage setpoint" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Less intLes[nSta] + "Identify stage indices below current setpoint" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi[nSta] + "Pass stage-type values for all stage indices lower than current setpoint" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1[nSta]( + final k=fill(0, nSta)) + "Pass zero for stage indices higher than and equal to current setpoint" + annotation (Placement(transformation(extent={{-80,-96},{-60,-76}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta] + "Integer to Real conversion" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMax mulMax( + final nin=nSta) + "Detect maximum from stage-type vector" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nSta) + "Identify stage-type for current stage setpoint" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1[nSta] + "Integer to Real conversion" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr1( + final t=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler) + "Identify if current stage setpoint is a non-condensing boiler stage" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Ensure current stage setpoint is the lead non-condensing boiler stage" + annotation (Placement(transformation(extent={{120,-40},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Pass process completion signal based on whether stage setpoint is lead non-condensing stage" + annotation (Placement(transformation(extent={{120,20},{140,40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=delPro, + final delayOnInit=true) + "Process time-out delay" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Pass process completion signal upon temperature reset or process time-out" + annotation (Placement(transformation(extent={{-100,40},{-80,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=TMinSupNonConBoi, + final uHigh=TMinSupNonConBoi + sigDif) + "Check if measured hot water supply temperature is greater than minimum + required temperature for non-condensing boilers" + annotation (Placement(transformation(extent={{-140,20},{-120,40}}))); + +equation + connect(intRep.u, uStaSet) + annotation (Line(points={{-122,-80},{-180,-80}}, color={255,127,0})); + + connect(uStaTyp, intSwi.u1) annotation (Line(points={{-180,-20},{-150,-20},{ + -150,-40},{-50,-40},{-50,-52},{-42,-52}}, + color={255,127,0})); + + connect(conInt1.y, intSwi.u3) annotation (Line(points={{-58,-86},{-50,-86},{-50, + -68},{-42,-68}}, color={255,127,0})); + + connect(intSwi.y, intToRea.u) + annotation (Line(points={{-18,-60},{-2,-60}}, color={255,127,0})); + + connect(uStaTyp, intToRea1.u) + annotation (Line(points={{-180,-20},{-142,-20}}, color={255,127,0})); + + connect(intToRea1.y, extIndSig.u) + annotation (Line(points={{-118,-20},{-102,-20}}, color={0,0,127})); + + connect(extIndSig.index, uStaSet) annotation (Line(points={{-90,-32},{-90,-34}, + {-130,-34},{-130,-80},{-180,-80}}, color={255,127,0})); + + connect(extIndSig.y, greThr1.u) + annotation (Line(points={{-78,-20},{-62,-20}}, color={0,0,127})); + + connect(greThr1.y, and2.u1) annotation (Line(points={{-38,-20},{110,-20},{110, + -30},{118,-30}}, color={255,0,255})); + + connect(logSwi.y, yHotWatSupTemRes) + annotation (Line(points={{142,30},{180,30}}, color={255,0,255})); + + connect(truDel.u, uStaUp) annotation (Line(points={{-142,70},{-180,70},{-180, + 70}}, color={255,0,255})); + + connect(or2.u1, truDel.y) annotation (Line(points={{-102,50},{-110,50},{-110, + 70},{-118,70}}, color={255,0,255})); + + connect(and2.y, logSwi.u2) annotation (Line(points={{142,-30},{150,-30},{150, + 10},{110,10},{110,30},{118,30}}, color={255,0,255})); + + connect(uStaUp, logSwi.u3) annotation (Line(points={{-180,70},{-150,70},{-150, + 10},{100,10},{100,22},{118,22}}, color={255,0,255})); + + connect(hys.u, THotWatSup) + annotation (Line(points={{-142,30},{-180,30}}, color={0,0,127})); + + connect(hys.y, or2.u2) annotation (Line(points={{-118,30},{-110,30},{-110,42}, + {-102,42}}, color={255,0,255})); + + connect(intRep.y, intLes.u2) annotation (Line(points={{-98,-80},{-90,-80},{-90, + -68},{-82,-68}}, color={255,127,0})); + + connect(conInt.y, intLes.u1) + annotation (Line(points={{-134,-60},{-82,-60}}, color={255,127,0})); + + connect(intLes.y, intSwi.u2) + annotation (Line(points={{-58,-60},{-42,-60}}, color={255,0,255})); + + connect(intToRea.y, mulMax.u[1:nSta]) annotation (Line(points={{22,-60},{30,-60}, + {30,-60},{38,-60}}, color={0,0,127})); + + connect(mulMax.y, lesThr.u) + annotation (Line(points={{62,-60},{78,-60}}, color={0,0,127})); + + connect(lesThr.y, and2.u2) annotation (Line(points={{102,-60},{110,-60},{110,-38}, + {118,-38}}, color={255,0,255})); + + connect(or2.y, and1.u1) + annotation (Line(points={{-78,50},{-42,50}}, color={255,0,255})); + + connect(uStaUp, and1.u2) annotation (Line(points={{-180,70},{-150,70},{-150, + 10},{-50,10},{-50,42},{-42,42}}, color={255,0,255})); + + connect(and1.y, logSwi.u1) annotation (Line(points={{-18,50},{100,50},{100,38}, + {118,38}}, color={255,0,255})); + +annotation ( + defaultComponentName="hotWatSupTemRes", + 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={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-100},{160,100}})), + Documentation(info=" +

+Block that generates hot water supply temperature reset status when there is +stage-change command. +This development is based on RP-1711, March 2020 draft, section 5.3.3.14, item 3. +

+

+When a stage-up command is received (uStaUp = true), +the sequence checks if the hot water supply temperature THotWatSup +has exceeded the minimum supply temperature for non-condensing boilers +TMinSupNonConBoi or if the process time-out delPro has +been exceeded since uStaUp became true. It will then set yHotWatSupTemRes +to true. +

+", +revisions=" + +")); +end ResetHotWaterSupplyTemperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo new file mode 100644 index 00000000000..b6c12c2a620 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo @@ -0,0 +1,236 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences; +block ResetMinBypass + "Sequence for minimum hot water flow setpoint reset" + + parameter Real delEna( + final unit="s", + final quantity="Time", + displayUnit="s") = 60 + "Enable delay after setpoint achieved"; + + parameter Real relFloDif( + final unit="1", + displayUnit="1")=0.05 + "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 + "Reset status of upstream device before resetting minimum flow setpoint" + annotation (Placement(transformation(extent={{-200,60},{-160,100}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "Continuous signal indicating if stage change is in process" + annotation (Placement(transformation(extent={{-200,20},{-160,60}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final min=0, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured hot water flow rate" + annotation (Placement(transformation(extent={{-200,-40},{-160,0}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinHotWatSet_flow( + final min=0, + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Minimum hot water flow setpoint" + annotation (Placement(transformation(extent={{-200,-100},{-160,-60}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yMinBypRes + "True: minimum hot water flow bypass setpoint has been reset successfully" + annotation (Placement(transformation(extent={{160,60},{200,100}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=-relFloDif, + final uHigh=0) + "Check if boiler water flow rate is different from its setpoint" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.And3 and1 + "Logical and" + annotation (Placement(transformation(extent={{120,70},{140,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=delEna) + "Time after achieving setpoint" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical and" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div + "Flow rate error divided by its setpoint" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) + "Add a small positive to avoid zero output" + annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Rising edge" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical and" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg2 + "Rising edge" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Find difference between measured flowrate and minimum flow setpoint" + annotation (Placement(transformation(extent={{-148,-30},{-128,-10}}))); + +equation + connect(uUpsDevSta, and2.u1) + annotation (Line(points={{-180,80},{-82,80}}, color={255,0,255})); + + connect(chaPro, and2.u2) + annotation (Line(points={{-180,40},{-140,40},{-140,72},{-82,72}}, + color={255,0,255})); + + connect(and2.y, and1.u1) + annotation (Line(points={{-58,80},{-10,80},{-10,88},{118,88}}, + color={255,0,255})); + + connect(and1.y,yMinBypRes) + annotation (Line(points={{142,80},{180,80}}, color={255,0,255})); + + connect(chaPro, not1.u) + annotation (Line(points={{-180,40},{-140,40},{-140,20},{-122,20}}, + color={255,0,255})); + + connect(lat.y, and1.u2) + annotation (Line(points={{102,40},{108,40},{108,80},{118,80}}, + color={255,0,255})); + + connect(VMinHotWatSet_flow, addPar.u) + annotation (Line(points={{-180,-80},{-142,-80}}, color={0,0,127})); + + connect(div.y, hys.u) + annotation (Line(points={{-78,-60},{-62,-60}}, color={0,0,127})); + + connect(not1.y, edg1.u) + annotation (Line(points={{-98,20},{-82,20}}, color={255,0,255})); + + connect(edg1.y, lat.clr) + annotation (Line(points={{-58,20},{70,20},{70,34},{78,34}}, + color={255,0,255})); + + connect(and3.y, tim.u) + annotation (Line(points={{22,-20},{38,-20}}, color={255,0,255})); + + connect(addPar.y, div.u2) + annotation (Line(points={{-118,-80},{-110,-80},{-110,-66},{-102,-66}}, + color={0,0,127})); + + connect(and3.y, edg2.u) + annotation (Line(points={{22,-20},{30,-20},{30,40},{38,40}}, + color={255,0,255})); + + connect(edg2.y, lat.u) + annotation (Line(points={{62,40},{78,40}}, color={255,0,255})); + + connect(and2.y, and3.u1) + annotation (Line(points={{-58,80},{-10,80},{-10,-20},{-2,-20}}, + color={255,0,255})); + + connect(sub2.u1, VHotWat_flow) annotation (Line(points={{-150,-14},{-154,-14}, + {-154,-20},{-180,-20}}, color={0,0,127})); + + connect(sub2.u2, VMinHotWatSet_flow) annotation (Line(points={{-150,-26},{-154, + -26},{-154,-80},{-180,-80}}, color={0,0,127})); + + connect(tim.passed, and1.u3) annotation (Line(points={{62,-28},{114,-28},{114, + 72},{118,72}}, color={255,0,255})); + connect(hys.y, and3.u2) annotation (Line(points={{-38,-60},{-10,-60},{-10,-28}, + {-2,-28}}, color={255,0,255})); + connect(sub2.y, div.u1) annotation (Line(points={{-126,-20},{-110,-20},{-110,-54}, + {-102,-54}}, color={0,0,127})); +annotation ( + defaultComponentName="minBypRes", + 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={{50,8},{98,-8}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yMinBypRes"), + Text( + extent={{-98,-32},{-50,-46}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VHotWat_flow"), + Text( + extent={{-98,-72},{-30,-88}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VMinHotWat_setpoint"), + Text( + extent={{-98,46},{-66,36}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-100},{160,100}})), + Documentation(info=" +

+Block that generates minimum bypass flow reset status when there is +stage-change command. +This development is based on RP-1711, March 2020 draft, sections 5.3.3.11 and +5.3.3.12, subsection 1.a. +

+

+When a stage-change command is received (chaPro = true) and the upstream +device has finished its adjustment process (uUpsDevSta = true), +check if the minimum hot water flow rate VHotWat_flow has achieved +its new set point VMinHotWat_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/BoilerPlant/Staging/Processes/Subsequences/Validation/DisableBoiler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/DisableBoiler.mo new file mode 100644 index 00000000000..9eeb1a39928 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/DisableBoiler.mo @@ -0,0 +1,231 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.Validation; +model DisableBoiler + "Validate sequence of disabling boiler during stage-down process" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.DisableBoiler + boiOnOff( + final nBoi=3, + final proOnTim=300) + "Disable a boiler and enable another boiler" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.DisableBoiler + boiOff( + final nBoi=3, + final proOnTim=300) + "Disable boiler" + annotation (Placement(transformation(extent={{102,70},{122,90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol(trueHoldDuration=10) + "Hold boolean pulse signal for easy visualization" + annotation (Placement(transformation(extent={{-10,90},{10,110}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1(trueHoldDuration=10) + "Hold boolean pulse signal for easy visualization" + annotation (Placement(transformation(extent={{170,90},{190,110}}))); + +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 boiOne( + final k=true) + "Operating boiler one" + annotation (Placement(transformation(extent={{-160,-30},{-140,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaBoi( + final k=3) + "Enabling boiler index" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch boiTwo + "Boiler two status" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff( + final k=true) + "Requires one boiler on and another boiler off" + annotation (Placement(transformation(extent={{-160,-110},{-140,-90}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disBoi( + final k=2) + "Disabling boiler index" + annotation (Placement(transformation(extent={{-160,-70},{-140,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaBoi1( + final k=1) + "Enabling boiler index" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant noOnOff( + final k=false) + "Does not requires one boiler on and another boiler off" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch boiTwo1 + "Boiler two status" + annotation (Placement(transformation(extent={{140,-50},{160,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre boiStaRet[2] + "Boiler status return value" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre boiStaRet1[2] + "Boiler 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(enaBoi.y, boiOnOff.nexEnaBoi) annotation (Line(points={{-138,100},{-100, + 100},{-100,89},{-82,89}}, color={255,127,0})); + + connect(staCha.y,boiOnOff. uStaDow) + annotation (Line(points={{-138,60},{-124,60},{-124,86},{-82,86}}, + color={255,0,255})); + + connect(upsDevSta.y,boiOnOff. uUpsDevSta) annotation (Line(points={{-138,20}, + {-116,20},{-116,82},{-82,82}}, color={255,0,255})); + + connect(boiOne.y,boiOnOff. uBoi[1]) annotation (Line(points={{-138,-20},{-108, + -20},{-108,76.6667},{-82,76.6667}}, color={255,0,255})); + + connect(upsDevSta.y,boiTwo. u2) + annotation (Line(points={{-138,20},{-116,20},{-116,-40},{-42,-40}}, + color={255,0,255})); + + connect(boiOne.y,boiTwo. u3) + annotation (Line(points={{-138,-20},{-108,-20},{-108,-48},{-42,-48}}, + color={255,0,255})); + + connect(boiStaRet[1].y,boiTwo. u1) annotation (Line(points={{-18,80},{-10,80}, + {-10,0},{-50,0},{-50,-32},{-42,-32}}, color={255,0,255})); + + connect(boiStaRet[2].y,boiOnOff. uBoi[3]) annotation (Line(points={{-18,80},{ + -10,80},{-10,40},{-112,40},{-112,79.3333},{-82,79.3333}}, color={255, + 0,255})); + + connect(boiTwo.y,boiOnOff. uBoi[2]) annotation (Line(points={{-18,-40},{-10,-40}, + {-10,-70},{-120,-70},{-120,78},{-82,78}}, color={255,0,255})); + + connect(disBoi.y,boiOnOff.nexDisBoi) + annotation (Line(points={{-138,-60},{-104,-60},{-104,75},{-82,75}}, + color={255,127,0})); + + connect(onOff.y,boiOnOff. uOnOff) + annotation (Line(points={{-138,-100},{-100,-100},{-100,71},{-82,71}}, + color={255,0,255})); + + connect(enaBoi1.y,boiOff.nexEnaBoi) + annotation (Line(points={{42,100},{80,100},{80,89},{100,89}}, + color={255,127,0})); + + connect(staCha.y,boiOff. uStaDow) + annotation (Line(points={{-138,60},{56,60},{56,86},{100,86}}, + color={255,0,255})); + + connect(boiOne.y,boiOff. uBoi[1]) annotation (Line(points={{-138,-20},{64,-20}, + {64,76.6667},{100,76.6667}}, color={255,0,255})); + + connect(disBoi.y,boiOff.nexDisBoi) + annotation (Line(points={{-138,-60},{76,-60},{76,75},{100,75}}, + color={255,127,0})); + + connect(noOnOff.y,boiOff. uOnOff) + annotation (Line(points={{42,-100},{80,-100},{80,71},{100,71}}, + color={255,0,255})); + + connect(staCha.y,boiTwo1. u2) + annotation (Line(points={{-138,60},{56,60},{56,-40},{138,-40}}, + color={255,0,255})); + + connect(boiOne.y,boiTwo1. u3) + annotation (Line(points={{-138,-20},{64,-20},{64,-48},{138,-48}}, + color={255,0,255})); + + connect(boiStaRet1[1].y,boiTwo1. u1) annotation (Line(points={{162,80},{170, + 80},{170,-20},{130,-20},{130,-32},{138,-32}}, color={255,0,255})); + + connect(boiTwo1.y,boiOff. uBoi[2]) annotation (Line(points={{162,-40},{170,-40}, + {170,-70},{68,-70},{68,78},{100,78}}, color={255,0,255})); + + connect(boiStaRet1[2].y,boiOff. uBoi[3]) annotation (Line(points={{162,80},{ + 170,80},{170,40},{72,40},{72,79.3333},{100,79.3333}}, color={255,0, + 255})); + + + connect(boiOnOff.yBoi[2], boiStaRet[1].u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + + connect(boiOnOff.yBoi[3], boiStaRet[2].u) annotation (Line(points={{-58, + 81.3333},{-52,81.3333},{-52,80},{-42,80}}, + color={255,0,255})); + + connect(boiOff.yBoi[2], boiStaRet1[1].u) + annotation (Line(points={{124,80},{138,80}}, color={255,0,255})); + + connect(boiOff.yBoi[3], boiStaRet1[2].u) annotation (Line(points={{124, + 81.3333},{130,81.3333},{130,80},{138,80}}, + color={255,0,255})); + + connect(boiOnOff.yBoiDisPro, truFalHol.u) annotation (Line(points={{-58,72},{-48, + 72},{-48,100},{-12,100}}, color={255,0,255})); + + connect(boiOff.yBoiDisPro, truFalHol1.u) annotation (Line(points={{124,72},{134, + 72},{134,100},{168,100}}, color={255,0,255})); + + connect(upsDevSta.y, boiOff.uUpsDevSta) annotation (Line(points={{-138,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/BoilerPlant/Staging/Processes/Subsequences/Validation/DisableBoiler.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.DisableBoiler. +

+", 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 DisableBoiler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/EnableBoiler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/EnableBoiler.mo new file mode 100644 index 00000000000..2223cadc452 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/EnableBoiler.mo @@ -0,0 +1,209 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.Validation; +model EnableBoiler + "Validate sequence of enabling and disabling boiler" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.EnableBoiler + enaDisBoi( + final nBoi=3) + "Enable larger boiler and disable smaller boiler" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.EnableBoiler + enaOneBoi( + final nBoi=3) + "Enable additional boiler" + annotation (Placement(transformation(extent={{100,70},{120,90}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol( + final trueHoldDuration=10) + "Hold pulse signal for visualization" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol1( + final trueHoldDuration=10) + "Hold pulse signal for visualization" + annotation (Placement(transformation(extent={{140,110},{160,130}}))); + +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 boiIsoVal + "Hot water isolation valve resetting status" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant enaBoi( + final k=3) + "Enabling boiler index" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiOne( + final k=true) + "Operating boiler one" + annotation (Placement(transformation(extent={{-160,-30},{-140,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant onOff( + final k=true) + "Requires one boiler on and another boiler off" + annotation (Placement(transformation(extent={{-160,-70},{-140,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disBoi( + final k=2) + "Disabling boiler index" + annotation (Placement(transformation(extent={{-160,-110},{-140,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre boiStaRet[2] + "Boiler status return value" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch boiTwo + "Boiler two status" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre boiStaRet1 + "Boiler 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 boiler on and another boiler off" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant disBoi1( + final k=1) + "Disabling boiler 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,boiIsoVal. u) + annotation (Line(points={{-178,20},{-162,20}}, color={255,0,255})); + + connect(staUp.y,enaDisBoi. uStaUp) + annotation (Line(points={{-138,60},{-120,60},{-120,86},{-82,86}}, + color={255,0,255})); + + connect(boiIsoVal.y,boiTwo. u2) + annotation (Line(points={{-138,20},{-116,20},{-116,-40},{-42,-40}}, + color={255,0,255})); + + connect(boiOne.y,boiTwo. u3) + annotation (Line(points={{-138,-20},{-112,-20},{-112,-48},{-42,-48}}, + color={255,0,255})); + + connect(onOff.y,enaDisBoi. uOnOff) + annotation (Line(points={{-138,-60},{-100,-60},{-100,74},{-82,74}}, + color={255,0,255})); + + connect(staUp.y,enaOneBoi. uStaUp) + annotation (Line(points={{-138,60},{40,60},{40,86},{98,86}}, + color={255,0,255})); + + connect(noOnOff.y,enaOneBoi. uOnOff) + annotation (Line(points={{42,-60},{56,-60},{56,74},{98,74}}, + color={255,0,255})); + + connect(enaBoi.y, enaDisBoi.nexEnaBoi) annotation (Line(points={{-138,100},{-120, + 100},{-120,89},{-82,89}}, color={255,127,0})); + + connect(boiIsoVal.y, enaDisBoi.uUpsDevSta) annotation (Line(points={{-138,20}, + {-116,20},{-116,82},{-82,82}}, color={255,0,255})); + + connect(boiOne.y, enaDisBoi.uBoi[1]) annotation (Line(points={{-138,-20},{ + -112,-20},{-112,76.6667},{-82,76.6667}}, + color={255,0,255})); + + connect(boiTwo.y, enaDisBoi.uBoi[2]) annotation (Line(points={{-18,-40},{-10,-40}, + {-10,40},{-108,40},{-108,78},{-82,78}}, color={255,0,255})); + + connect(enaDisBoi.yBoi[2], boiStaRet[1].u) annotation (Line(points={{-58,88},{ + -56,88},{-56,80},{-42,80}}, color={255,0,255})); + + connect(boiStaRet[1].y, boiTwo.u1) annotation (Line(points={{-18,80},{0,80},{0, + 0},{-60,0},{-60,-32},{-42,-32}}, color={255,0,255})); + + connect(enaDisBoi.yBoi[3], boiStaRet[2].u) annotation (Line(points={{-58, + 89.3333},{-52,89.3333},{-52,80},{-42,80}}, color={255,0,255})); + + connect(boiStaRet[2].y, enaDisBoi.uBoi[3]) annotation (Line(points={{-18,80}, + {0,80},{0,66},{-104,66},{-104,79.3333},{-82,79.3333}},color={255,0,255})); + + connect(disBoi.y, enaDisBoi.nexDisBoi) annotation (Line(points={{-138,-100},{-90, + -100},{-90,71},{-82,71}}, color={255,127,0})); + + connect(enaBoi.y, enaOneBoi.nexEnaBoi) annotation (Line(points={{-138,100},{80, + 100},{80,89},{98,89}}, color={255,127,0})); + + connect(enaOneBoi.yBoi[3], boiStaRet1.u) annotation (Line(points={{122, + 89.3333},{130,89.3333},{130,80},{138,80}}, + color={255,0,255})); + + connect(boiOne.y, enaOneBoi.uBoi[1]) annotation (Line(points={{-138,-20},{50, + -20},{50,76.6667},{98,76.6667}}, + color={255,0,255})); + + connect(boiOne.y, enaOneBoi.uBoi[2]) annotation (Line(points={{-138,-20},{50,-20}, + {50,78},{98,78}}, color={255,0,255})); + + connect(boiStaRet1.y, enaOneBoi.uBoi[3]) annotation (Line(points={{162,80},{ + 180,80},{180,60},{80,60},{80,79.3333},{98,79.3333}}, + color={255,0,255})); + + connect(boiIsoVal.y, enaOneBoi.uUpsDevSta) annotation (Line(points={{-138,20}, + {46,20},{46,82},{98,82}}, color={255,0,255})); + + connect(disBoi1.y, enaOneBoi.nexDisBoi) annotation (Line(points={{42,-100},{60, + -100},{60,71},{98,71}}, color={255,127,0})); + + connect(enaDisBoi.yBoiEnaPro, truFalHol.u) annotation (Line(points={{-58,72}, + {-50,72},{-50,120},{-42,120}}, color={255,0,255})); + + connect(enaOneBoi.yBoiEnaPro, truFalHol1.u) annotation (Line(points={{122,72}, + {132,72},{132,120},{138,120}}, color={255,0,255})); + +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/EnableBoiler.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.EnableBoiler. +

+", 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 EnableBoiler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/HWIsoVal.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/HWIsoVal.mo new file mode 100644 index 00000000000..20598b6e4b8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/HWIsoVal.mo @@ -0,0 +1,145 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.Validation; +model HWIsoVal + "Validate isolation valve enable and disable sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal + enaHotIsoVal( + final nBoi=2, + final chaHotWatIsoTim=300, + final iniValPos=0, + final endValPos=1) + "Enable isolation valve" + annotation (Placement(transformation(extent={{-100,0},{-80,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal + disHotIsoVal( + final nBoi=2, + final chaHotWatIsoTim=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.Continuous.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 enaBoi( + final k=2) + "Enabling boiler index" + annotation (Placement(transformation(extent={{-160,70},{-140,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.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 disBoi( + final k=2) + "Disabling boiler index" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel( + final samplePeriod=1) + "Unit delay" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel1( + final samplePeriod=1, + final y_start=1) + "Unit delay" + annotation (Placement(transformation(extent={{160,-20},{180,0}}))); + +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(enaBoi.y, enaHotIsoVal.nexChaBoi) annotation (Line(points={{-138,80}, + {-120,80},{-120,18},{-102,18}}, color={255,127,0})); + + connect(upsDevSta.y, enaHotIsoVal.uUpsDevSta) annotation (Line(points={{-138, + -30},{-120,-30},{-120,5},{-102,5}}, color={255,0,255})); + + connect(upsDevSta.y, disHotIsoVal.uUpsDevSta) annotation (Line(points={{-138, + -30},{100,-30},{100,-5},{118,-5}}, color={255,0,255})); + + connect(staCha.y, enaHotIsoVal.chaPro) annotation (Line(points={{-138,-70},{ + -110,-70},{-110,2},{-102,2}}, color={255,0,255})); + + connect(staCha.y, disHotIsoVal.chaPro) annotation (Line(points={{-138,-70},{ + 110,-70},{110,-8},{118,-8}}, color={255,0,255})); + + connect(disBoi.y, disHotIsoVal.nexChaBoi) annotation (Line(points={{82,80},{ + 90,80},{90,8},{118,8}}, color={255,127,0})); + + connect(valOne1.y, disHotIsoVal.uHotWatIsoVal[1]) annotation (Line(points={{ + 42,20},{60,20},{60,4},{118,4}}, color={0,0,127})); + + connect(valOne.y, enaHotIsoVal.uHotWatIsoVal[1]) annotation (Line(points={{-178, + 20},{-140,20},{-140,14},{-102,14}}, color={0,0,127})); + connect(enaHotIsoVal.yHotWatIsoVal[2], uniDel.u) annotation (Line(points={{-78, + 5},{-70,5},{-70,0},{-62,0}}, color={0,0,127})); + connect(uniDel.y, enaHotIsoVal.uHotWatIsoVal[2]) annotation (Line(points={{-38, + 0},{-30,0},{-30,40},{-110,40},{-110,16},{-102,16}}, color={0,0,127})); + connect(disHotIsoVal.yHotWatIsoVal[2], uniDel1.u) annotation (Line(points={{142, + -5},{150,-5},{150,-10},{158,-10}}, color={0,0,127})); + connect(uniDel1.y, disHotIsoVal.uHotWatIsoVal[2]) annotation (Line(points={{182, + -10},{190,-10},{190,30},{110,30},{110,6},{118,6}}, color={0,0,127})); + +annotation ( + experiment(StopTime=3600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/HWIsoVal.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal. +

+ ", 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 HWIsoVal; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/NextBoiler.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/NextBoiler.mo new file mode 100644 index 00000000000..ead5542a069 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/NextBoiler.mo @@ -0,0 +1,525 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.Validation; +model NextBoiler + "Validate sequence of identifying next enable or disable boilers" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler + nexBoi( + final nBoi=2) + "Identify next enabling and disabling boiler during the staging up process" + annotation (Placement(transformation(extent={{-60,170},{-40,190}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler + nexBoi1( + final nBoi=2) + "Identify next enabling during the staging up process" + annotation (Placement(transformation(extent={{240,170},{260,190}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler + nexBoi2( + final nBoi=2) + "Identify next enabling and disabling boiler during the staging down process" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler + nexBoi3( + final nBoi=2) + "Identify next disabling boiler during the staging down process" + annotation (Placement(transformation(extent={{240,-150},{260,-130}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Switch boiSet[2] + "Boiler 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 boiSet1[2] + "Boiler 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 boiSet2[2] + "Boiler 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 boiSet3[2] + "Boiler 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 staOneBoi[2]( + final k={true,false}) + "Vector of boilers status setpoint at stage one" + annotation (Placement(transformation(extent={{-260,70},{-240,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-260,230},{-240,250}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-260,190},{-240,210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Logical switch" + annotation (Placement(transformation(extent={{-180,210},{-160,230}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet + "Stage setpoint index" + annotation (Placement(transformation(extent={{-140,210},{-120,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoBoi[2]( + final k={false,true}) + "Vector of boilers 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 notIn( + final k=false) + "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 staOneBoi1[2]( + final k={true,false}) + "Vector of boilers status setpoint at stage one" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta1( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{40,230},{60,250}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta1( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{40,190},{60,210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + "Logical switch" + annotation (Placement(transformation(extent={{120,210},{140,230}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet1 + "Stage setpoint index" + annotation (Placement(transformation(extent={{160,210},{180,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoBoi1[2]( + final k={true,true}) + "Vector of boilers 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 notIn1( + final k=false) + "Not in the process" + 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 staOneBoi2[2]( + final k={true,false}) + "Vector of boilers status setpoint at stage one" + annotation (Placement(transformation(extent={{-260,-210},{-240,-190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta2( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-260,-130},{-240,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta2( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-260,-90},{-240,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 + "Logical switch" + annotation (Placement(transformation(extent={{-180,-110},{-160,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet2 + "Stage setpoint index" + annotation (Placement(transformation(extent={{-140,-110},{-120,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoBoi2[2]( + final k={false,true}) + "Vector of boilers 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 notIn2( + final k=false) + "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 staOneBoi3[2]( + final k={true,false}) + "Vector of boilers status setpoint at stage one" + annotation (Placement(transformation(extent={{40,-210},{60,-190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta3( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta3( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi3 + "Logical switch" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet3 + "Stage setpoint index" + annotation (Placement(transformation(extent={{160,-110},{180,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant staTwoBoi3[2]( + final k={true,true}) + "Vector of boilers 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 notIn3( + final k=false) + "Not in the process" + annotation (Placement(transformation(extent={{80,-310},{100,-290}}))); + +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-238,160},{-222,160}}, color={255,0,255})); + + connect(staUp.y, swi.u2) + annotation (Line(points={{-198,160},{-190,160},{-190,220},{-182,220}}, + color={255,0,255})); + + connect(dowSta.y, swi.u3) + annotation (Line(points={{-238,200},{-220,200},{-220,212},{-182,212}}, + color={0,0,127})); + + connect(upSta.y, swi.u1) + annotation (Line(points={{-238,240},{-220,240},{-220,228},{-182,228}}, + color={0,0,127})); + + connect(swi.y, staSet.u) + annotation (Line(points={{-158,220},{-142,220}}, color={0,0,127})); + + connect(staUp.y, booRep.u) annotation (Line(points={{-198,160},{-190,160},{-190, + 100},{-182,100}}, color={255,0,255})); + + connect(booRep.y,boiSet. 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(booPul4.y, inPro.u1) annotation (Line(points={{-238,40},{-220,40},{-220, + 48},{-142,48}}, color={255,0,255})); + + connect(notIn.y, inPro.u3) annotation (Line(points={{-198,20},{-160,20},{-160, + 32},{-142,32},{-142,32}}, color={255,0,255})); + + connect(booPul1.y, staUp1.u) + annotation (Line(points={{62,160},{78,160}}, color={255,0,255})); + + connect(staUp1.y, swi1.u2) annotation (Line(points={{102,160},{110,160},{110,220}, + {118,220}}, color={255,0,255})); + + connect(dowSta1.y, swi1.u3) annotation (Line(points={{62,200},{80,200},{80,212}, + {118,212}}, color={0,0,127})); + + connect(upSta1.y, swi1.u1) annotation (Line(points={{62,240},{80,240},{80,228}, + {118,228}}, color={0,0,127})); + + connect(swi1.y, staSet1.u) + annotation (Line(points={{142,220},{158,220}}, 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,boiSet1. 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(booPul5.y, inPro1.u1) annotation (Line(points={{62,40},{80,40},{80,48}, + {158,48}}, color={255,0,255})); + + connect(notIn1.y, inPro1.u3) annotation (Line(points={{102,20},{140,20},{140,32}, + {158,32}}, color={255,0,255})); + + connect(booPul2.y, staDow.u) + annotation (Line(points={{-238,-160},{-222,-160}}, color={255,0,255})); + + connect(staDow.y, swi2.u2) annotation (Line(points={{-198,-160},{-190,-160},{-190, + -100},{-182,-100}}, color={255,0,255})); + + connect(swi2.y, staSet2.u) + annotation (Line(points={{-158,-100},{-142,-100}}, color={0,0,127})); + + connect(staDow.y, booRep2.u) annotation (Line(points={{-198,-160},{-190,-160}, + {-190,-220},{-182,-220}}, color={255,0,255})); + + connect(staOneBoi2.y,boiSet2. u1) annotation (Line(points={{-238,-200},{-150,-200}, + {-150,-212},{-142,-212}}, color={255,0,255})); + + connect(booRep2.y,boiSet2. u2) + annotation (Line(points={{-158,-220},{-142,-220}}, color={255,0,255})); + + connect(staTwoBoi2.y,boiSet2. 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(booPul6.y, inPro2.u1) annotation (Line(points={{-238,-280},{-220,-280}, + {-220,-272},{-142,-272}}, color={255,0,255})); + + connect(notIn2.y, inPro2.u3) annotation (Line(points={{-198,-300},{-160,-300}, + {-160,-288},{-142,-288}}, color={255,0,255})); + + connect(dowSta2.y, swi2.u1) annotation (Line(points={{-238,-80},{-200,-80},{-200, + -92},{-182,-92}}, color={0,0,127})); + + connect(upSta2.y, swi2.u3) annotation (Line(points={{-238,-120},{-200,-120},{-200, + -108},{-182,-108}}, color={0,0,127})); + + connect(staTwoBoi.y,boiSet. u1) annotation (Line(points={{-238,120},{-150,120}, + {-150,108},{-142,108}}, color={255,0,255})); + + connect(staOneBoi.y,boiSet. u3) annotation (Line(points={{-238,80},{-150,80},{ + -150,92},{-142,92}}, color={255,0,255})); + + connect(staTwoBoi1.y,boiSet1. u1) annotation (Line(points={{62,120},{150,120}, + {150,108},{158,108}}, color={255,0,255})); + + connect(staOneBoi1.y,boiSet1. 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, swi3.u2) annotation (Line(points={{102,-160},{110,-160},{110, + -100},{118,-100}}, color={255,0,255})); + + connect(swi3.y, staSet3.u) + annotation (Line(points={{142,-100},{158,-100}}, color={0,0,127})); + + connect(staDow1.y, booRep3.u) annotation (Line(points={{102,-160},{110,-160},{ + 110,-220},{118,-220}}, color={255,0,255})); + + connect(staOneBoi3.y,boiSet3. u1) annotation (Line(points={{62,-200},{150,-200}, + {150,-212},{158,-212}}, color={255,0,255})); + + connect(booRep3.y,boiSet3. u2) + annotation (Line(points={{142,-220},{158,-220}}, color={255,0,255})); + + connect(staTwoBoi3.y,boiSet3. u3) annotation (Line(points={{62,-240},{152,-240}, + {152,-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(booPul7.y, inPro3.u1) annotation (Line(points={{62,-280},{80,-280},{80, + -272},{158,-272}}, color={255,0,255})); + + connect(notIn3.y, inPro3.u3) annotation (Line(points={{102,-300},{140,-300},{140, + -288},{158,-288}}, color={255,0,255})); + + connect(dowSta3.y, swi3.u1) annotation (Line(points={{62,-80},{100,-80},{100,-92}, + {118,-92}}, color={0,0,127})); + + connect(upSta3.y, swi3.u3) annotation (Line(points={{62,-120},{100,-120},{100, + -108},{118,-108}}, color={0,0,127})); + + connect(staSet.y, nexBoi.uStaSet) annotation (Line(points={{-118,220},{-80,220}, + {-80,187},{-62,187}}, color={255,127,0})); + + connect(boiSet.y, nexBoi.uBoiSet) annotation (Line(points={{-118,100},{-100,100}, + {-100,180},{-62,180}}, color={255,0,255})); + + connect(inPro.y, nexBoi.chaPro) annotation (Line(points={{-118,40},{-80,40},{-80, + 173},{-62,173}}, color={255,0,255})); + + connect(staSet1.y, nexBoi1.uStaSet) annotation (Line(points={{182,220},{220,220}, + {220,187},{238,187}}, color={255,127,0})); + + connect(boiSet1.y, nexBoi1.uBoiSet) annotation (Line(points={{182,100},{200,100}, + {200,180},{238,180}}, color={255,0,255})); + + connect(inPro1.y, nexBoi1.chaPro) annotation (Line(points={{182,40},{220,40},{ + 220,173},{238,173}}, color={255,0,255})); + + connect(staSet2.y, nexBoi2.uStaSet) annotation (Line(points={{-118,-100},{-80, + -100},{-80,-133},{-62,-133}}, color={255,127,0})); + + connect(boiSet2.y, nexBoi2.uBoiSet) annotation (Line(points={{-118,-220},{-100, + -220},{-100,-140},{-62,-140}}, color={255,0,255})); + + connect(inPro2.y, nexBoi2.chaPro) annotation (Line(points={{-118,-280},{-80,-280}, + {-80,-147},{-62,-147}}, color={255,0,255})); + + connect(staSet3.y, nexBoi3.uStaSet) annotation (Line(points={{182,-100},{220,-100}, + {220,-133},{238,-133}}, color={255,127,0})); + + connect(inPro3.y, nexBoi3.chaPro) annotation (Line(points={{182,-280},{220,-280}, + {220,-147},{238,-147}}, color={255,0,255})); + + connect(boiSet3.y, nexBoi3.uBoiSet) annotation (Line(points={{182,-220},{200,-220}, + {200,-140},{238,-140}}, color={255,0,255})); + +annotation ( + experiment(StopTime=120, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/NextBoiler.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler. +

+", 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 boiler (1) off and large boiler (2) on."), + Text( + extent={{64,278},{228,268}}, + textColor={0,0,127}, + textString="add one more boiler (1) on top of current boiler (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 boiler (2) off and small boiler (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 boiler (2)."), + Text( + extent={{62,-28},{182,-38}}, + textColor={0,0,127}, + textString="In stage down process (stage 2 to 1),")})); +end NextBoiler; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetHotWaterSupplyTemperature.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetHotWaterSupplyTemperature.mo new file mode 100644 index 00000000000..4057e05f7a5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetHotWaterSupplyTemperature.mo @@ -0,0 +1,135 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.Validation; +model ResetHotWaterSupplyTemperature + "Validate sequence of reseting hot water supply temperature" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetHotWaterSupplyTemperature + hotWatSupTemRes( + final nSta=1, + final delPro=300, + final TMinSupNonConBoi=333.2, + final sigDif=0.1) + "Scenario testing reset for condensing boiler stage type" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetHotWaterSupplyTemperature + hotWatSupTemRes1( + final nSta=2, + final delPro=300, + final TMinSupNonConBoi=333.2, + final sigDif=0.1) + "Scenario testing reset for lead non-condensing boiler stage type" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetHotWaterSupplyTemperature + hotWatSupTemRes2( + final nSta=2, + final delPro=300, + final TMinSupNonConBoi=333.2, + final sigDif=0.1) + "Scenario testing reset for lag non-condensing boiler stage type" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=800) + "Stage-up signal" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[1]( + final k={1}) + "Vector of stage types" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=2, + final freqHz=1/3200, + final offset=333.2) + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Current stage setpoint" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3[2]( + final k={2,2}) + "Vector of stage types" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4( + final k=2) + "Current stage setpoint" + annotation (Placement(transformation(extent={{100,-70},{120,-50}}))); + +equation + connect(booPul.y, hotWatSupTemRes.uStaUp) annotation (Line(points={{-58,60},{-46, + 60},{-46,7},{-42,7}}, color={255,0,255})); + + connect(conInt.y, hotWatSupTemRes.uStaTyp) annotation (Line(points={{-58,-20}, + {-50,-20},{-50,-3},{-42,-3}}, color={255,127,0})); + + connect(sin.y, hotWatSupTemRes.THotWatSup) annotation (Line(points={{-58,20},{ + -50,20},{-50,3},{-42,3}}, color={0,0,127})); + + connect(conInt1.y, hotWatSupTemRes.uStaSet) annotation (Line(points={{-58,-60}, + {-46,-60},{-46,-7},{-42,-7}}, color={255,127,0})); + + connect(booPul.y, hotWatSupTemRes1.uStaUp) annotation (Line(points={{-58,60},{ + 54,60},{54,7},{58,7}}, color={255,0,255})); + + connect(sin.y, hotWatSupTemRes1.THotWatSup) annotation (Line(points={{-58,20}, + {50,20},{50,3},{58,3}}, color={0,0,127})); + + connect(booPul.y, hotWatSupTemRes2.uStaUp) annotation (Line(points={{-58,60},{ + 134,60},{134,7},{138,7}}, color={255,0,255})); + + connect(sin.y, hotWatSupTemRes2.THotWatSup) annotation (Line(points={{-58,20}, + {130,20},{130,3},{138,3}}, color={0,0,127})); + + connect(conInt3.y, hotWatSupTemRes2.uStaTyp) annotation (Line(points={{42,-20}, + {130,-20},{130,-3},{138,-3}}, color={255,127,0})); + + connect(conInt4.y, hotWatSupTemRes2.uStaSet) annotation (Line(points={{122,-60}, + {134,-60},{134,-7},{138,-7}}, color={255,127,0})); + + connect(conInt3.y, hotWatSupTemRes1.uStaTyp) annotation (Line(points={{42,-20}, + {50,-20},{50,-3},{58,-3}}, color={255,127,0})); + + connect(conInt1.y, hotWatSupTemRes1.uStaSet) annotation (Line(points={{-58,-60}, + {54,-60},{54,-7},{58,-7}}, color={255,127,0})); + +annotation ( + experiment( + StopTime=3200, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetHotWaterSupplyTemperature.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetHotWaterSupplyTemperature. +

+", 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},{180,100}}))); +end ResetHotWaterSupplyTemperature; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo new file mode 100644 index 00000000000..48e29ddddac --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo @@ -0,0 +1,97 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.Validation; +model ResetMinBypass + "Validate sequence of reseting minimum flow bypass" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetMinBypass + minBypRes + "Check if the setpoint has achieved" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.15, + final period=600) + "Boolean pulse" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Not staUp + "Stage up command" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Not upStrDev + "Upstream device reset status" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.2, + final period=600) + "Boolean pulse" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp minFloSet( + final height=0.5, + final duration=180, + final offset=1, + final startTime=60) + "Minimum boiler water flow setpoint" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp meaFlo( + final height=0.5, + final duration=80, + final offset=1, + final startTime=120) + "Measured boiler water flow" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + +equation + connect(booPul2.y, upStrDev.u) + annotation (Line(points={{-58,60},{-42,60}}, color={255,0,255})); + + connect(booPul1.y, staUp.u) + annotation (Line(points={{-58,20},{-42,20}}, color={255,0,255})); + + connect(upStrDev.y, minBypRes.uUpsDevSta) + annotation (Line(points={{-18,60},{16,60},{16,8},{38,8}}, color={255,0,255})); + + connect(staUp.y, minBypRes.chaPro) + annotation (Line(points={{-18,20},{12,20},{12,4},{38,4}}, color={255,0,255})); + + connect(meaFlo.y,minBypRes.VHotWat_flow) + annotation (Line(points={{-18,-20},{12,-20},{12,-4},{38,-4}}, + color={0,0,127})); + + connect(minFloSet.y, minBypRes.VMinHotWatSet_flow) annotation (Line(points={{-18,-60}, + {16,-60},{16,-8},{38,-8}}, color={0,0,127})); + +annotation ( + experiment(StopTime=600, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mos" + "Simulate and plot"), + Documentation(info=" +

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

+", 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 ResetMinBypass; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..3453fb9058f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Staging/Processes/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/package.order new file mode 100644 index 00000000000..727f15f7b77 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/Validation/package.order @@ -0,0 +1,6 @@ +DisableBoiler +EnableBoiler +HWIsoVal +NextBoiler +ResetHotWaterSupplyTemperature +ResetMinBypass diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/package.mo new file mode 100644 index 00000000000..ddc312242f4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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/BoilerPlant/Staging/Processes/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/package.order new file mode 100644 index 00000000000..cd91253514e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Subsequences/package.order @@ -0,0 +1,7 @@ +DisableBoiler +EnableBoiler +HWIsoVal +NextBoiler +ResetHotWaterSupplyTemperature +ResetMinBypass +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Up.mo new file mode 100644 index 00000000000..fd773844b74 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Up.mo @@ -0,0 +1,679 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes; +block Up + "Sequence for control devices when there is stage-up command" + + parameter Boolean have_priOnl = false + "True: The boiler plant is primary-only" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Boolean have_heaPriPum = true + "True: Headered hot water pumps; + False: Dedicated hot water pumps" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Integer nBoi=3 + "Total number of boilers in the plant" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Integer nSta=5 + "Total number of stages" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Real TMinSupNonConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 333.2 + "Minimum supply temperature required for non-condensing boilers" + annotation (Dialog(group="Boiler plant parameters")); + + parameter Real delProSupTemSet( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Process time-out for hot water supply temperature setpoint reset" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real delEnaMinFloSet( + final unit="s", + displayUnit="s", + final quantity="time") = 60 + "Enable delay after minimum flow setpoint is achieved in bypass valve" + annotation (Evaluate=true, + Dialog(group="Time and delay parameters", + enable=have_priOnl)); + + parameter Real chaIsoValTim( + final unit="s", + displayUnit="s", + final quantity="time") = 60 + "Time to slowly change isolation valve, should be determined in the field" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real delPreBoiEna( + final unit="s", + displayUnit="s", + final quantity="time") = 30 + "Time delay after valve and pump change process has been completed before + starting boiler change process" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real boiChaProOnTim( + final unit="s", + displayUnit="s", + final quantity="time") = 300 + "Enabled boiler operation time to indicate if it is proven on during a staging + process where one boiler is turned on and the other is turned off" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real delBoiEna( + final unit="s", + displayUnit="s", + final quantity="time") = 180 + "Time delay after boiler change process has been completed before turning off + excess valves and pumps" + annotation (Dialog(group="Time and delay parameters")); + + parameter Real sigDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference")=0.1 + "Significant difference based on minimum resolution of temperature sensor" + annotation (Dialog(tab="Advanced")); + + parameter Real relFloDif( + final unit="1", + displayUnit="1")=0.05 + "Relative error to the flow setpoint for checking if it has been achieved" + annotation (Evaluate=true, + Dialog(tab="Advanced", + enable=have_priOnl)); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPlaEna + "Plant enable signal" + annotation (Placement(transformation(extent={{-280,-140},{-240,-100}}), + iconTransformation(extent={{-140,-150},{-100,-110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUpPro + "Pulse indicating start of stage up process" + annotation (Placement(transformation(extent={{-280,-20},{-240,20}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoi[nBoi] + "Boiler status: true=ON" + annotation (Placement(transformation(extent={{-280,60},{-240,100}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPumChaPro if not + have_priOnl + "Pulse indicating all pump change processes have been completed and pumps have been proved on" + annotation (Placement(transformation(extent={{-280,-210},{-240,-170}}), + iconTransformation(extent={{-140,-210},{-100,-170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiSet[nBoi] + "Boiler status setpoint: true=ON" + annotation (Placement(transformation(extent={{-280,20},{-240,60}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaPro + "Signal indicating final completion of stage change processes" + annotation (Placement(transformation(extent={{-280,-170},{-240,-130}}), + iconTransformation(extent={{-140,-180},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaTyp[nSta] + "Boiler plant stage type vector" + annotation (Placement(transformation(extent={{-280,-60},{-240,-20}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uStaSet + "Boiler stage setpoint index" + annotation (Placement(transformation(extent={{-280,-100},{-240,-60}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinHotWatSet_flow( + final quantity="VolumeFlowRate", + final unit="m3/s", + displayUnit="m3/s", + final min=0) if have_priOnl + "Minimum hot water flow rate setpoint" + annotation (Placement(transformation(extent={{-280,180},{-240,220}}), + iconTransformation(extent={{-140,130},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final min=0, + final quantity="VolumeFlowRate", + final unit="m3/s", + displayUnit="m3/s") if have_priOnl + "Measured hot water flow rate through the minimum flow bypass valve" + annotation (Placement(transformation(extent={{-280,220},{-240,260}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSupSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-280,140},{-240,180}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotWatIsoVal[nBoi]( + final min=fill(0, nBoi), + final max=fill(1, nBoi), + final unit=fill("1", nBoi)) if have_heaPriPum + "Hot water isolation valve position" + annotation (Placement(transformation(extent={{-280,100},{-240,140}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler enabling status" + annotation (Placement(transformation(extent={{280,90},{320,130}}), + iconTransformation(extent={{100,100},{140,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaChaPro + "Pulse indicating end of stage change process" + annotation (Placement(transformation(extent={{280,30},{320,70}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPumChaPro if not + have_priOnl + "Pulse indicating start of pump change process" + annotation (Placement(transformation(extent={{280,-260},{320,-220}}), + iconTransformation(extent={{100,-140},{140,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yOnOff + "Signal indicating whether stage change involves simultaneous turning on + and turning off of boilers" + annotation (Placement(transformation(extent={{280,-130},{320,-90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yNexEnaBoi + "Boiler index of next boiler being enabled" + annotation (Placement(transformation(extent={{280,-170},{320,-130}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yLasDisBoi + "Boiler index of last boilerenabled that will be disabled" + annotation (Placement(transformation(extent={{280,-210},{320,-170}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal[nBoi]( + final min=fill(0, nBoi), + final max=fill(1, nBoi), + final unit=fill("1", nBoi)) if have_heaPriPum + "Boiler hot water isolation valve position" + annotation (Placement(transformation(extent={{280,-90},{320,-50}}), + iconTransformation(extent={{100,20},{140,60}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetMinBypass minBypRes( + final delEna=delEnaMinFloSet, + final relFloDif=relFloDif) if have_priOnl + "Reset process for minimum flow bypass valve setpoint" + annotation (Placement(transformation(extent={{-170,10},{-150,30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetHotWaterSupplyTemperature hotWatSupTemRes( + final nSta=nSta, + final delPro=delProSupTemSet, + final TMinSupNonConBoi=TMinSupNonConBoi, + final sigDif=sigDif) if not have_priOnl + "Reset process for hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-170,-30},{-150,-10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler nexBoi( + final nBoi=nBoi) + "Identify boiler indices to be turned on and off during the stage change process" + annotation (Placement(transformation(extent={{-170,-70},{-150,-50}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal enaHotWatIsoVal( + final nBoi=nBoi, + final chaHotWatIsoTim=chaIsoValTim, + final iniValPos=0, + final endValPos=1) if have_heaPriPum + "Open hot water isolation valve for boiler being enabled" + annotation (Placement(transformation(extent={{-70,-10},{-50,10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Check for completion of valve opening process and pump change process" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.EnableBoiler enaBoi( + final nBoi=nBoi, + final proOnTim=boiChaProOnTim) + "Change boiler status as per stage change required" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal disHotWatIsoVal1( + final nBoi=nBoi, + final chaHotWatIsoTim=chaIsoValTim, + final iniValPos=1, + final endValPos=0) if have_heaPriPum + "Close hot water valve for boiler being disabled" + annotation (Placement(transformation(extent={{150,-10},{170,10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Check for completion of valve closing process and pump change process" + annotation (Placement(transformation(extent={{190,-10},{210,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Latch to retain stage-up edge signal till the stage change process is completed" + annotation (Placement(transformation(extent={{-222,-10},{-202,10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=delBoiEna) + "Time delay after boiler status has been changed" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat3 if not have_priOnl + "Hold process completion signal after pump enable process" + annotation (Placement(transformation(extent={{-180,-200},{-160,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat4 if not have_priOnl + "Hold process completion signal after pump disable process" + annotation (Placement(transformation(extent={{160,-200},{180,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4 if not have_priOnl + "Check for pump disable completion after start of pump disable process" + annotation (Placement(transformation(extent={{132,-200},{152,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Detect change in process completion status and send out pulse signal" + annotation (Placement(transformation(extent={{230,40},{250,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 if not have_priOnl + "Generate pulse to signal start of pump change process" + annotation (Placement(transformation(extent={{-90,-250},{-70,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg2 if not have_priOnl + "Generate pulse to signal start of pump change process" + annotation (Placement(transformation(extent={{170,-240},{190,-220}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 if not have_priOnl + "Check for pump change proces start signal" + annotation (Placement(transformation(extent={{210,-250},{230,-230}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat5 if not have_heaPriPum + "Latch to short valve opening process in dedicated pump configuration plants" + annotation (Placement(transformation(extent={{-70,30},{-50,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat6 if not have_heaPriPum + "Latch to short valve closing process in dedicated pump configuration plants" + annotation (Placement(transformation(extent={{150,30},{170,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nBoi] if have_heaPriPum + "Pass valve position signal from valve opening controller once the opening process starts" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) if have_heaPriPum + "Boolean replicator" + annotation (Placement(transformation(extent={{0,-140},{20,-120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nBoi] if have_heaPriPum + "Pass valve position signal from valve closing controller once the closing process starts" + annotation (Placement(transformation(extent={{100,-120},{120,-100}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) if have_heaPriPum + "Boolean replicator" + annotation (Placement(transformation(extent={{70,-160},{90,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=delPreBoiEna) + "Time delay after valve has been opened and pump status has been changed" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Pass process completion signal based on whether stage change involves turning off smaller boiler or not" + annotation (Placement(transformation(extent={{230,-20},{250,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1 if have_heaPriPum + "Hold process completion signal after valve has been opened" + annotation (Placement(transformation(extent={{-32,-120},{-12,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) if have_priOnl + "Boolean True signal" + annotation (Placement(transformation(extent={{-180,-160},{-160,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Pass signal when plant is enabled or when stage-up process is initiated" + annotation (Placement(transformation(extent={{-130,-130},{-110,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Hold status when plant enable is detected" + annotation (Placement(transformation(extent={{-180,-130},{-160,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if not have_priOnl + "Logical And" + annotation (Placement(transformation(extent={{140,-240},{160,-220}}))); + +equation + connect(nexBoi.yNexEnaBoi, enaHotWatIsoVal.nexChaBoi) annotation (Line(points={{-148, + -51},{-90,-51},{-90,8},{-72,8}}, color={255,127,0})); + + connect(lat.y, minBypRes.uUpsDevSta) annotation (Line(points={{-200,0},{-196, + 0},{-196,28},{-172,28}}, + color={255,0,255})); + + connect(lat.y, minBypRes.chaPro) annotation (Line(points={{-200,0},{-196,0},{ + -196,24},{-172,24}}, + color={255,0,255})); + + connect(lat.y, hotWatSupTemRes.uStaUp) annotation (Line(points={{-200,0},{ + -196,0},{-196,-13},{-172,-13}}, + color={255,0,255})); + + connect(lat.y, nexBoi.chaPro) annotation (Line(points={{-200,0},{-196,0},{ + -196,-67},{-172,-67}}, + color={255,0,255})); + + connect(enaBoi.yBoiEnaPro, truDel.u) annotation (Line(points={{82,-8},{90,-8}, + {90,0},{98,0}}, color={255,0,255})); + + connect(truDel.y,disHotWatIsoVal1. uUpsDevSta) annotation (Line(points={{122,0}, + {126,0},{126,-5},{148,-5}}, color={255,0,255})); + + connect(nexBoi.yDisSmaBoi,disHotWatIsoVal1. nexChaBoi) annotation (Line( + points={{-148,-56},{140,-56},{140,8},{148,8}}, color={255,127,0})); + + connect(nexBoi.yOnOff,disHotWatIsoVal1. chaPro) annotation (Line(points={{-148, + -60},{144,-60},{144,-8},{148,-8}}, color={255,0,255})); + + connect(lat.y, enaHotWatIsoVal.chaPro) annotation (Line(points={{-200,0},{-196, + 0},{-196,-34},{-80,-34},{-80,-8},{-72,-8}}, color={255,0,255})); + + connect(lat.y, enaBoi.uStaUp) annotation (Line(points={{-200,0},{-196,0},{ + -196,-34},{52,-34},{52,6},{58,6}}, + color={255,0,255})); + + connect(nexBoi.yOnOff, enaBoi.uOnOff) annotation (Line(points={{-148,-60},{42, + -60},{42,-6},{58,-6}}, color={255,0,255})); + + connect(nexBoi.yDisSmaBoi, enaBoi.nexDisBoi) annotation (Line(points={{-148, + -56},{46,-56},{46,-9},{58,-9}}, + color={255,127,0})); + + connect(nexBoi.yNexEnaBoi, enaBoi.nexEnaBoi) annotation (Line(points={{-148, + -51},{-90,-51},{-90,-40},{38,-40},{38,9},{58,9}}, + color={255,127,0})); + + connect(VHotWat_flow, minBypRes.VHotWat_flow) annotation (Line(points={{-260, + 240},{-176,240},{-176,16},{-172,16}}, + color={0,0,127})); + + connect(VMinHotWatSet_flow, minBypRes.VMinHotWatSet_flow) annotation (Line( + points={{-260,200},{-180,200},{-180,12},{-172,12}}, color={0,0,127})); + + connect(THotWatSupSet, hotWatSupTemRes.THotWatSup) annotation (Line(points={{-260, + 160},{-186,160},{-186,-17},{-172,-17}}, color={0,0,127})); + + connect(uHotWatIsoVal, enaHotWatIsoVal.uHotWatIsoVal) annotation (Line(points={{-260, + 120},{-80,120},{-80,5},{-72,5}}, color={0,0,127})); + + connect(nexBoi.uBoiSet, uBoiSet) annotation (Line(points={{-172,-60},{-190, + -60},{-190,40},{-260,40}}, color={255,0,255})); + + connect(uBoi, enaBoi.uBoi) annotation (Line(points={{-260,80},{46,80},{46,-2}, + {58,-2}}, color={255,0,255})); + + connect(uStaSet, nexBoi.uStaSet) annotation (Line(points={{-260,-80},{-234, + -80},{-234,-53},{-172,-53}}, color={255,127,0})); + + connect(uStaSet, hotWatSupTemRes.uStaSet) annotation (Line(points={{-260,-80}, + {-234,-80},{-234,-27},{-172,-27}}, color={255,127,0})); + + connect(uStaTyp, hotWatSupTemRes.uStaTyp) annotation (Line(points={{-260,-40}, + {-186,-40},{-186,-23},{-172,-23}}, color={255,127,0})); + + connect(uStaUpPro, lat.u) + annotation (Line(points={{-260,0},{-224,0}}, color={255,0,255})); + + connect(lat3.y, and1.u2) annotation (Line(points={{-158,-190},{-48,-190},{-48, + -30},{-10,-30},{-10,-8},{-2,-8}}, color={255,0,255})); + + connect(uPumChaPro, lat3.u) + annotation (Line(points={{-260,-190},{-182,-190}}, color={255,0,255})); + + connect(and4.y, lat4.u) + annotation (Line(points={{154,-190},{158,-190}}, color={255,0,255})); + + connect(truDel.y, and4.u1) annotation (Line(points={{122,0},{126,0},{126,-190}, + {130,-190}}, color={255,0,255})); + + connect(uPumChaPro, and4.u2) annotation (Line(points={{-260,-190},{-200,-190}, + {-200,-210},{120,-210},{120,-198},{130,-198}}, color={255,0,255})); + + connect(lat4.y, and3.u2) annotation (Line(points={{182,-190},{184,-190},{184, + -8},{188,-8}}, color={255,0,255})); + + connect(edg.y, yStaChaPro) + annotation (Line(points={{252,50},{300,50}}, color={255,0,255})); + + connect(edg2.y, or2.u1) annotation (Line(points={{192,-230},{200,-230},{200,-240}, + {208,-240}}, color={255,0,255})); + + connect(edg1.y, or2.u2) annotation (Line(points={{-68,-240},{66,-240},{66,-248}, + {208,-248}}, color={255,0,255})); + + connect(enaBoi.yBoi, yBoi) annotation (Line(points={{82,8},{90,8},{90,110},{300, + 110}}, color={255,0,255})); + + connect(or2.y, yPumChaPro) + annotation (Line(points={{232,-240},{300,-240}}, color={255,0,255})); + + connect(nexBoi.yOnOff, yOnOff) annotation (Line(points={{-148,-60},{144,-60},{ + 144,-110},{300,-110}}, color={255,0,255})); + + connect(nexBoi.yNexEnaBoi, yNexEnaBoi) annotation (Line(points={{-148,-51},{160, + -51},{160,-150},{300,-150}}, color={255,127,0})); + + connect(lat5.y, and1.u1) annotation (Line(points={{-48,40},{-6,40},{-6,0},{-2, + 0}}, color={255,0,255})); + + connect(truDel.y, lat6.u) annotation (Line(points={{122,0},{126,0},{126,40},{148, + 40}}, color={255,0,255})); + + connect(lat6.y, and3.u1) annotation (Line(points={{172,40},{180,40},{180,0},{188, + 0}}, color={255,0,255})); + + connect(enaHotWatIsoVal.yHotWatIsoVal, swi.u1) annotation (Line(points={{-48, + -6},{-30,-6},{-30,-90},{26,-90},{26,-122},{38,-122}}, color={0,0,127})); + + connect(uHotWatIsoVal, swi.u3) annotation (Line(points={{-260,120},{30,120},{ + 30,-138},{38,-138}}, color={0,0,127})); + + connect(booRep.y, swi.u2) + annotation (Line(points={{22,-130},{38,-130}}, color={255,0,255})); + + connect(swi.y, swi1.u3) annotation (Line(points={{62,-130},{92,-130},{92,-118}, + {98,-118}}, color={0,0,127})); + + connect(disHotWatIsoVal1.yHotWatIsoVal, swi1.u1) annotation (Line(points={{ + 172,-6},{180,-6},{180,-70},{92,-70},{92,-102},{98,-102}}, color={0,0, + 127})); + + connect(truDel.y, booRep1.u) annotation (Line(points={{122,0},{126,0},{126, + -170},{60,-170},{60,-150},{68,-150}}, color={255,0,255})); + + connect(booRep1.y, swi1.u2) annotation (Line(points={{92,-150},{96,-150},{96, + -110},{98,-110}}, color={255,0,255})); + + connect(swi1.y, yHotWatIsoVal) annotation (Line(points={{122,-110},{134,-110}, + {134,-90},{210,-90},{210,-70},{300,-70}}, color={0,0,127})); + + connect(and1.y, truDel1.u) annotation (Line(points={{22,0},{28,0},{28,60},{ + -10,60},{-10,100},{-2,100}}, + color={255,0,255})); + + connect(truDel1.y, enaBoi.uUpsDevSta) annotation (Line(points={{22,100},{42,100}, + {42,2},{58,2}}, color={255,0,255})); + + connect(disHotWatIsoVal1.yEnaHotWatIsoVal, and3.u1) annotation (Line(points={{ + 172,6},{180,6},{180,0},{188,0}}, color={255,0,255})); + + connect(and3.y, logSwi.u1) annotation (Line(points={{212,0},{220,0},{220,-2},{ + 228,-2}}, color={255,0,255})); + + connect(enaBoi.yBoiEnaPro, logSwi.u3) annotation (Line(points={{82,-8},{90,-8}, + {90,-18},{228,-18}}, color={255,0,255})); + + connect(nexBoi.yOnOff, logSwi.u2) annotation (Line(points={{-148,-60},{170,-60}, + {170,-24},{220,-24},{220,-10},{228,-10}}, color={255,0,255})); + + connect(logSwi.y, edg.u) annotation (Line(points={{252,-10},{260,-10},{260,20}, + {220,20},{220,50},{228,50}}, color={255,0,255})); + + connect(uHotWatIsoVal, disHotWatIsoVal1.uHotWatIsoVal) annotation (Line( + points={{-260,120},{144,120},{144,5},{148,5}}, color={0,0,127})); + + connect(enaHotWatIsoVal.yEnaHotWatIsoVal, lat1.u) annotation (Line(points={{ + -48,6},{-40,6},{-40,-110},{-34,-110}}, color={255,0,255})); + + connect(lat1.y, and1.u1) annotation (Line(points={{-10,-110},{-6,-110},{-6,0}, + {-2,0}}, color={255,0,255})); + + connect(con.y, and1.u2) annotation (Line(points={{-158,-150},{-48,-150},{-48,-30}, + {-10,-30},{-10,-8},{-2,-8}}, color={255,0,255})); + connect(con.y, and3.u2) annotation (Line(points={{-158,-150},{-30,-150},{-30,-190}, + {110,-190},{110,-160},{184,-160},{184,-8},{188,-8}}, color={255,0,255})); + connect(lat2.y, or1.u1) + annotation (Line(points={{-158,-120},{-132,-120}}, color={255,0,255})); + connect(minBypRes.yMinBypRes, or1.u2) annotation (Line(points={{-148,20},{-146, + 20},{-146,-128},{-132,-128}}, color={255,0,255})); + connect(hotWatSupTemRes.yHotWatSupTemRes, or1.u2) annotation (Line(points={{-148, + -20},{-146,-20},{-146,-128},{-132,-128}}, color={255,0,255})); + connect(or1.y, lat5.u) annotation (Line(points={{-108,-120},{-104,-120},{-104, + 40},{-72,40}}, color={255,0,255})); + connect(or1.y, booRep.u) annotation (Line(points={{-108,-120},{-104,-120},{-104, + -130},{-2,-130}}, color={255,0,255})); + connect(or1.y, enaHotWatIsoVal.uUpsDevSta) annotation (Line(points={{-108,-120}, + {-104,-120},{-104,-5},{-72,-5}}, color={255,0,255})); + connect(nexBoi.yDisSmaBoi, yLasDisBoi) annotation (Line(points={{-148,-56},{156, + -56},{156,-156},{240,-156},{240,-190},{300,-190}}, color={255,127,0})); + connect(uStaChaPro, lat.clr) annotation (Line(points={{-260,-150},{-228,-150}, + {-228,-6},{-224,-6}}, color={255,0,255})); + connect(uStaChaPro, lat2.clr) annotation (Line(points={{-260,-150},{-190,-150}, + {-190,-126},{-182,-126}}, color={255,0,255})); + connect(uStaChaPro, lat3.clr) annotation (Line(points={{-260,-150},{-190,-150}, + {-190,-196},{-182,-196}}, color={255,0,255})); + connect(uStaChaPro, lat5.clr) annotation (Line(points={{-260,-150},{-190,-150}, + {-190,-100},{-98,-100},{-98,34},{-72,34}}, color={255,0,255})); + connect(uStaChaPro, lat6.clr) annotation (Line(points={{-260,-150},{-190,-150}, + {-190,-100},{-98,-100},{-98,70},{132,70},{132,34},{148,34}}, color={ + 255,0,255})); + connect(uStaChaPro, lat1.clr) annotation (Line(points={{-260,-150},{-190,-150}, + {-190,-100},{-98,-100},{-98,-116},{-34,-116}}, color={255,0,255})); + connect(uStaChaPro, lat4.clr) annotation (Line(points={{-260,-150},{-190,-150}, + {-190,-100},{-98,-100},{-98,70},{132,70},{132,-168},{156,-168},{156, + -196},{158,-196}}, color={255,0,255})); + connect(and2.y, edg2.u) + annotation (Line(points={{162,-230},{168,-230}}, color={255,0,255})); + connect(truDel.y, and2.u1) annotation (Line(points={{122,0},{126,0},{126,-230}, + {138,-230}}, color={255,0,255})); + connect(nexBoi.yOnOff, and2.u2) annotation (Line(points={{-148,-60},{-54,-60}, + {-54,-238},{138,-238}}, color={255,0,255})); + connect(or1.y, edg1.u) annotation (Line(points={{-108,-120},{-104,-120},{-104, + -240},{-92,-240}}, color={255,0,255})); + connect(uPlaEna, lat2.u) + annotation (Line(points={{-260,-120},{-182,-120}}, color={255,0,255})); +annotation ( + defaultComponentName="upProCon", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-240,-260},{280,260}})), + 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,260},{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)}), +Documentation(info=" +

+Block that controls boiler status and isolation valve position, initiates status +change in devices like pumps and minimum flow bypass valve, and resets plant +parameters like hot water supply temperature setpoint and minimum flow setpoint +when there is a stage-up command. +This development is based on ASHRAE RP-1711, March 2020 draft,sections 5.3.3.11 - 5.3.3.18, +which specify the step-by-step control of devices during boiler staging up process. +

+
    +
  1. +Identify the boiler(s) that should be enabled (and disabled). This is implemented in block nexBoi. See + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.NextBoiler +for more decriptions. +
  2. +
  3. +Initiate the process to reset the minimum hot water flow setpoint for the minimum +flow bypass valve, + +The minimum flow setpoint is reset in sequence +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.MinimumFlowBypass.Subsequences.FlowSetpoint). +Block minBypRes checks if the new setpoint is achieved +( +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.ResetMinBypass). +
  4. +
  5. +Start the next hot water pump and/or open the hot water isolation valves using the +block enaHotWatIsoVal using sequence implemented in +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.HWIsoVal +for the valves and initiating the pump change process with the pulse signal yPumChaPro. +Once the pumps have been reset, the controller receives a pulse signal on the +input uPumChaPro. +
  6. +
  7. +After waiting for time delPreBoiEna, the boiler status yBoi +is changed using the boiler status controller enaBoi implemented in the sequence + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Subsequences.EnableBoiler. +
  8. +
  9. +If the stage up process does not involve turning off a smaller boiler, end the +staging up process by sending a pulse signal through yStaChaPro. Otherwise, + +
+", revisions=" + +")); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Down.mo new file mode 100644 index 00000000000..c4a5ba932af --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Down.mo @@ -0,0 +1,863 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Validation; +model Down + "Validate sequence of staging down process" + + parameter Integer nBoi=2 + "Total number of boilers in the plant"; + + parameter Integer nSta=3 + "Total number of stages"; + + parameter Real delBoiEna( + final unit="s", + final displayUnit="s", + final quantity="Time") = 180 + "Time delay after boiler change process has been completed before turning off excess valves and pumps"; + + parameter Real delEnaMinFloSet( + final unit="s", + final displayUnit="s", + final quantity="Time")=60 + "Enable delay after minimum flow setpoint is achieved in bypass valve"; + + parameter Real delProSupTemSet( + final unit="s", + final displayUnit="s", + final quantity="Time")=300 + "Process time-out for hot water supply temperature setpoint reset"; + + parameter Real TMinSupNonConBoi( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature")=333.2 + "Minimum supply temperature required for non-condensing boilers"; + + parameter Real sigDif( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature")=0.1 + "Significant difference based on minimum resolution of temperature sensor"; + + parameter Real chaIsoValTim( + final unit="s", + final displayUnit="s", + final quantity="Time")=60 + "Time to slowly change isolation valve, should be determined in the field"; + + parameter Real boiChaProOnTim( + final unit="s", + final displayUnit="s", + final quantity="Time")=300 + "Enabled boiler operation time to indicate if it is proven on during a staging + process where one boiler is turned on and the other is turned off"; + + parameter Real relFloDif( + final unit="1", + final displayUnit="1")=0.05 + "Relative error to the flow setpoint for checking if it has been achieved"; + + parameter Real delPreBoiEna( + final unit="s", + final displayUnit="s", + final quantity="Time")=30 + "Time delay after valve and pump change process has been completed before + starting boiler change process"; + + parameter Real VNom_flow( + final unit="m3/s", + final displayUnit="m3/s", + final quantity="VolumeFlowRate") = 1 + "Nominal minimum flow rate"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Down dowProCon( + final have_priOnl=false, + final have_heaPriPum=true, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage down process for primary-secondary plant with headered pumps" + annotation (Placement(transformation(extent={{-160,166},{-140,206}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Down dowProCon1( + final have_priOnl=false, + final have_heaPriPum=false, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage down process for primary-secondary plant with dedicated pumps" + annotation (Placement(transformation(extent={{210,166},{230,206}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Down dowProCon4( + final have_priOnl=true, + final have_heaPriPum=true, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage down process for primary-only plant with headered pumps" + annotation (Placement(transformation(extent={{-160,-170},{-140,-130}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yPumChaPro( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yPumChaPro1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{250,150},{270,170}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-120,190},{-100,210}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{250,190},{270,210}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro4( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-120,-146},{-100,-126}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{-334,70},{-314,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3[nBoi]( + final pre_u_start={true,true}) + "Logical pre block" + annotation (Placement(transformation(extent={{-260,180},{-240,200}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{-220,100},{-200,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nBoi]( + final k={true,false}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{-260,120},{-240,140}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Falling edge detector" + annotation (Placement(transformation(extent={{-90,150},{-70,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{-220,30},{-200,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{-260,50},{-240,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{-368,0},{-348,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{-130,110},{-110,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nBoi] + "Pass initial valve position and switch to signal from controller" + annotation (Placement(transformation(extent={{-220,270},{-200,290}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{-370,250},{-350,270}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con[nBoi]( + final k={1,1}) + "Initial isolation valve positions" + annotation (Placement(transformation(extent={{-300,280},{-280,300}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[nBoi]( + final samplePeriod=fill(10, nBoi)) + "Zero order hold" + annotation (Placement(transformation(extent={{-60,170},{-40,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{-40,130},{-20,150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Logical pre block" + annotation (Placement(transformation(extent={{-28,190},{-8,210}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg1 + "Falling edge detector" + annotation (Placement(transformation(extent={{-90,190},{-70,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{-300,100},{-280,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con4[nBoi]( + final k={true,true}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{-334,130},{-314,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{-320,20},{-300,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3( + final k=3) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{-370,40},{-350,60}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg2 + "Falling edge detector" + annotation (Placement(transformation(extent={{-164,110},{-144,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{-40,60},{-20,80}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con5[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{36,70},{56,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre4[nBoi]( + final pre_u_start={true,true}) + "Logical pre block" + annotation (Placement(transformation(extent={{110,180},{130,200}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{150,100},{170,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con6[nBoi]( + final k={true,false}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{110,120},{130,140}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg3 + "Falling edge detector" + annotation (Placement(transformation(extent={{280,150},{300,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{150,30},{170,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4( + final k=1) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{110,50},{130,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{240,110},{260,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{0,250},{20,270}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre5 + "Logical pre block" + annotation (Placement(transformation(extent={{330,130},{350,150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre6 + "Logical pre block" + annotation (Placement(transformation(extent={{340,190},{360,210}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg4 + "Falling edge detector" + annotation (Placement(transformation(extent={{280,190},{300,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi5[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{70,100},{90,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con9[nBoi]( + final k={true,true}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{36,130},{56,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi3 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{50,20},{70,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7( + final k=3) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg5 + "Falling edge detector" + annotation (Placement(transformation(extent={{206,110},{226,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat3[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{330,60},{350,80}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{280,60},{300,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con20[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{-334,-266},{-314,-246}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre13[nBoi]( + final pre_u_start={true,true}) + "Logical pre block" + annotation (Placement(transformation(extent={{-260,-160},{-240,-140}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi13[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{-220,-236},{-200,-216}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con21[nBoi]( + final k={true, + false}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{-260,-216},{-240,-196}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi8 + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{-220,-306},{-200,-286}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt16( + final k=1) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{-260,-286},{-240,-266}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt17( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{-370,-336},{-350,-316}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or5 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{-130,-226},{-110,-206}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi4[nBoi] + "Pass initial valve position and switch to signal from controller" + annotation (Placement(transformation(extent={{-220,-66},{-200,-46}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul4[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{-370,-86},{-350,-66}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con22[nBoi]( + final k={1,1}) + "Initial isolation valve positions" + annotation (Placement(transformation(extent={{-300,-56},{-280,-36}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con23( + final k=VNom_flow) + "Calculated minimum flow rate signal" + annotation (Placement(transformation(extent={{-180,-56},{-160,-36}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol4[nBoi]( + final samplePeriod=fill(10, nBoi)) + "Zero order hold" + annotation (Placement(transformation(extent={{-60,-166},{-40,-146}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre15 + "Logical pre block" + annotation (Placement(transformation(extent={{-28,-146},{-8,-126}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg13 + "Falling edge detector" + annotation (Placement(transformation(extent={{-90,-146},{-70,-126}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi14[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{-300,-236},{-280,-216}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con24[nBoi]( + final k={true,true}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{-334,-206},{-314,-186}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi9 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{-320,-316},{-300,-296}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt19( + final k=3) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{-370,-296},{-350,-276}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg14 + "Falling edge detector" + annotation (Placement(transformation(extent={{-164,-226},{-144,-206}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat9[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{-50,-280},{-30,-260}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{-90,-280},{-70,-260}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con12( + final k=1.1*VNom_flow) + "Calculated minimum flow rate signal" + annotation (Placement(transformation(extent={{-90,-26},{-70,-6}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con17( + final k=VNom_flow) + "Calculated minimum flow rate signal" + annotation (Placement(transformation(extent={{-90,-66},{-70,-46}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 + "Pass different instances of measured flow-rate after stage change" + annotation (Placement(transformation(extent={{-50,-46},{-30,-26}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat10 + "Hold true signal after stage change" + annotation (Placement(transformation(extent={{-130,-46},{-110,-26}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre7 + "Logical pre block" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre8 + "Logical pre block" + annotation (Placement(transformation(extent={{240,60},{260,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre9 + "Logical pre block" + annotation (Placement(transformation(extent={{-130,-280},{-110,-260}}))); + +equation + + connect(con2.y, logSwi1.u1) annotation (Line(points={{-238,130},{-230,130},{ + -230,118},{-222,118}}, + color={255,0,255})); + + connect(yPumChaPro.y, falEdg.u) + annotation (Line(points={{-98,160},{-92,160}}, color={255,0,255})); + + connect(conInt.y, intSwi.u1) annotation (Line(points={{-238,60},{-230,60},{ + -230,48},{-222,48}}, + color={255,127,0})); + + connect(booPul.y, swi.u2) annotation (Line(points={{-348,260},{-240,260},{ + -240,280},{-222,280}}, + color={255,0,255})); + + connect(con.y, swi.u1) annotation (Line(points={{-278,290},{-230,290},{-230, + 288},{-222,288}}, + color={0,0,127})); + + connect(zerOrdHol.y, swi.u3) annotation (Line(points={{-38,180},{-34,180},{-34, + 260},{-230,260},{-230,272},{-222,272}}, + color={0,0,127})); + + connect(falEdg.y, pre1.u) annotation (Line(points={{-68,160},{-46,160},{-46, + 140},{-42,140}}, color={255,0,255})); + + connect(yStaChaPro.y, falEdg1.u) + annotation (Line(points={{-98,200},{-92,200}}, color={255,0,255})); + + connect(con1.y, logSwi2.u3) annotation (Line(points={{-312,80},{-306,80},{ + -306,102},{-302,102}}, color={255,0,255})); + + connect(con4.y, logSwi2.u1) annotation (Line(points={{-312,140},{-308,140},{-308, + 118},{-302,118}}, color={255,0,255})); + + connect(booPul.y, logSwi2.u2) annotation (Line(points={{-348,260},{-340,260}, + {-340,110},{-302,110}}, color={255,0,255})); + + connect(logSwi2.y, logSwi1.u3) annotation (Line(points={{-278,110},{-272,110}, + {-272,102},{-222,102}}, color={255,0,255})); + + connect(conInt1.y, intSwi1.u3) annotation (Line(points={{-346,10},{-330,10},{-330, + 22},{-322,22}}, color={255,127,0})); + + connect(conInt3.y, intSwi1.u1) annotation (Line(points={{-348,50},{-330,50},{-330, + 38},{-322,38}}, color={255,127,0})); + + connect(intSwi1.y, intSwi.u3) annotation (Line(points={{-298,30},{-230,30},{-230, + 32},{-222,32}}, color={255,127,0})); + + connect(booPul[1].y, intSwi1.u2) annotation (Line(points={{-348,260},{-340,260}, + {-340,30},{-322,30}}, color={255,0,255})); + + connect(falEdg1.y, pre2.u) + annotation (Line(points={{-68,200},{-30,200}}, color={255,0,255})); + + connect(booPul[1].y, falEdg2.u) annotation (Line(points={{-348,260},{-340,260}, + {-340,96},{-168,96},{-168,120},{-166,120}}, color={255,0,255})); + + connect(falEdg2.y, or2.u1) + annotation (Line(points={{-142,120},{-132,120}}, color={255,0,255})); + + connect(booRep.y, lat1.u) + annotation (Line(points={{-58,70},{-42,70}}, color={255,0,255})); + + connect(lat1.y, logSwi1.u2) annotation (Line(points={{-18,70},{-10,70},{-10, + 50},{-160,50},{-160,74},{-226,74},{-226,110},{-222,110}}, color={255, + 0,255})); + + connect(lat1[1].y, intSwi.u2) annotation (Line(points={{-18,70},{-10,70},{-10, + 50},{-160,50},{-160,74},{-226,74},{-226,40},{-222,40}}, color={255,0, + 255})); + + connect(con1[1].y, lat1[1].clr) annotation (Line(points={{-312,80},{-150,80}, + {-150,54},{-50,54},{-50,64},{-42,64}}, color={255,0,255})); + + connect(con1[1].y, lat1[2].clr) annotation (Line(points={{-312,80},{-150,80}, + {-150,54},{-50,54},{-50,64},{-42,64}}, color={255,0,255})); + + connect(con6.y,logSwi4. u1) annotation (Line(points={{132,130},{140,130},{140, + 118},{148,118}}, color={255,0,255})); + + connect(yPumChaPro1.y, falEdg3.u) + annotation (Line(points={{272,160},{278,160}}, color={255,0,255})); + + connect(conInt4.y, intSwi2.u1) annotation (Line(points={{132,60},{140,60},{140, + 48},{148,48}}, color={255,127,0})); + + connect(falEdg3.y, pre5.u) annotation (Line(points={{302,160},{324,160},{324,140}, + {328,140}}, color={255,0,255})); + + connect(yStaChaPro1.y, falEdg4.u) + annotation (Line(points={{272,200},{278,200}}, color={255,0,255})); + + connect(con5.y,logSwi5. u3) annotation (Line(points={{58,80},{64,80},{64,102}, + {68,102}}, color={255,0,255})); + + connect(con9.y,logSwi5. u1) annotation (Line(points={{58,140},{62,140},{62,118}, + {68,118}}, color={255,0,255})); + + connect(booPul1.y, logSwi5.u2) annotation (Line(points={{22,260},{30,260},{30, + 110},{68,110}}, color={255,0,255})); + + connect(logSwi5.y,logSwi4. u3) annotation (Line(points={{92,110},{98,110},{98, + 102},{148,102}}, color={255,0,255})); + + connect(conInt5.y,intSwi3. u3) annotation (Line(points={{22,10},{40,10},{40,22}, + {48,22}}, color={255,127,0})); + + connect(conInt7.y,intSwi3. u1) annotation (Line(points={{22,50},{40,50},{40,38}, + {48,38}}, color={255,127,0})); + + connect(intSwi3.y, intSwi2.u3) annotation (Line(points={{72,30},{140,30},{140, + 32},{148,32}}, color={255,127,0})); + + connect(booPul1[1].y, intSwi3.u2) annotation (Line(points={{22,260},{30,260},{ + 30,30},{48,30}}, color={255,0,255})); + + connect(falEdg4.y,pre6. u) + annotation (Line(points={{302,200},{338,200}}, color={255,0,255})); + + connect(booPul1[1].y, falEdg5.u) annotation (Line(points={{22,260},{30,260},{30, + 96},{202,96},{202,120},{204,120}}, color={255,0,255})); + + connect(falEdg5.y,or1. u1) + annotation (Line(points={{228,120},{238,120}}, color={255,0,255})); + + connect(booRep1.y, lat3.u) + annotation (Line(points={{302,70},{328,70}}, color={255,0,255})); + + connect(lat3.y,logSwi4. u2) annotation (Line(points={{352,70},{360,70},{360, + 50},{210,50},{210,74},{144,74},{144,110},{148,110}}, color={255, + 0,255})); + connect(lat3[1].y, intSwi2.u2) annotation (Line(points={{352,70},{360,70},{ + 360,50},{210,50},{210,74},{144,74},{144,40},{148,40}}, + color={255,0,255})); + + connect(con5[1].y,lat3 [1].clr) annotation (Line(points={{58,80},{220,80},{ + 220,54},{320,54},{320,64},{328,64}}, color={255,0,255})); + + connect(con5[1].y,lat3 [2].clr) annotation (Line(points={{58,80},{220,80},{ + 220,54},{320,54},{320,64},{328,64}}, color={255,0,255})); + + connect(con21.y, logSwi13.u1) annotation (Line(points={{-238,-206},{-230,-206}, + {-230,-218},{-222,-218}}, + color={255,0,255})); + + connect(conInt16.y, intSwi8.u1) annotation (Line(points={{-238,-276},{-230,-276}, + {-230,-288},{-222,-288}}, + color={255,127,0})); + + connect(booPul4.y, swi4.u2) annotation (Line(points={{-348,-76},{-240,-76},{-240, + -56},{-222,-56}},color={255,0,255})); + + connect(con22.y, swi4.u1) annotation (Line(points={{-278,-46},{-230,-46},{-230, + -48},{-222,-48}}, + color={0,0,127})); + + connect(zerOrdHol4.y, swi4.u3) annotation (Line(points={{-38,-156},{-34,-156}, + {-34,-76},{-230,-76},{-230,-64},{-222,-64}}, + color={0,0,127})); + + connect(yStaChaPro4.y, falEdg13.u) + annotation (Line(points={{-98,-136},{-92,-136}}, + color={255,0,255})); + + connect(con20.y, logSwi14.u3) annotation (Line(points={{-312,-256},{-306,-256}, + {-306,-234},{-302,-234}}, + color={255,0,255})); + + connect(con24.y, logSwi14.u1) annotation (Line(points={{-312,-196},{-310,-196}, + {-310,-218},{-302,-218}}, + color={255,0,255})); + + connect(booPul4.y, logSwi14.u2) annotation (Line(points={{-348,-76},{-340,-76}, + {-340,-226},{-302,-226}}, + color={255,0,255})); + + connect(logSwi14.y, logSwi13.u3) annotation (Line(points={{-278,-226},{-272,-226}, + {-272,-234},{-222,-234}}, + color={255,0,255})); + + connect(conInt17.y, intSwi9.u3) annotation (Line(points={{-348,-326},{-330,-326}, + {-330,-314},{-322,-314}}, + color={255,127,0})); + + connect(conInt19.y, intSwi9.u1) annotation (Line(points={{-348,-286},{-330,-286}, + {-330,-298},{-322,-298}}, + color={255,127,0})); + + connect(intSwi9.y, intSwi8.u3) annotation (Line(points={{-298,-306},{-230,-306}, + {-230,-304},{-222,-304}}, + color={255,127,0})); + + connect(booPul4[1].y, intSwi9.u2) annotation (Line(points={{-348,-76},{-340,-76}, + {-340,-306},{-322,-306}}, + color={255,0,255})); + + connect(falEdg13.y, pre15.u) + annotation (Line(points={{-68,-136},{-30,-136}}, + color={255,0,255})); + + connect(booPul4[1].y, falEdg14.u) annotation (Line(points={{-348,-76},{-340,-76}, + {-340,-240},{-168,-240},{-168,-216},{-166,-216}}, + color={255,0,255})); + + connect(falEdg14.y, or5.u1) + annotation (Line(points={{-142,-216},{-132,-216}}, + color={255,0,255})); + + connect(booRep4.y, lat9.u) + annotation (Line(points={{-68,-270},{-52,-270}}, + color={255,0,255})); + + connect(lat9.y, logSwi13.u2) annotation (Line(points={{-28,-270},{-20,-270},{ + -20,-286},{-160,-286},{-160,-262},{-226,-262},{-226,-226},{-222,-226}}, + color={255,0,255})); + + connect(lat9[1].y, intSwi8.u2) annotation (Line(points={{-28,-270},{-20,-270}, + {-20,-286},{-160,-286},{-160,-262},{-226,-262},{-226,-296},{-222,-296}}, + color={255,0,255})); + + connect(con20[1].y, lat9[1].clr) annotation (Line(points={{-312,-256},{-150, + -256},{-150,-282},{-60,-282},{-60,-276},{-52,-276}}, + color={255,0,255})); + + connect(con20[1].y, lat9[2].clr) annotation (Line(points={{-312,-256},{-150, + -256},{-150,-282},{-60,-282},{-60,-276},{-52,-276}}, + color={255,0,255})); + + connect(con12.y, swi2.u1) annotation (Line(points={{-68,-16},{-60,-16},{-60,-28}, + {-52,-28}}, color={0,0,127})); + + connect(con17.y, swi2.u3) annotation (Line(points={{-68,-56},{-60,-56},{-60,-44}, + {-52,-44}}, color={0,0,127})); + + connect(lat10.y, swi2.u2) + annotation (Line(points={{-108,-36},{-52,-36}},color={255,0,255})); + + connect(pre15.y, lat10.u) annotation (Line(points={{-6,-136},{0,-136},{0,-80}, + {-140,-80},{-140,-36},{-132,-36}}, color={255,0,255})); + + connect(booPul4[1].y, lat10.clr) annotation (Line(points={{-348,-76},{-240,-76}, + {-240,-82},{-136,-82},{-136,-42},{-132,-42}}, + color={255,0,255})); + + connect(swi.y, dowProCon.uHotWatIsoVal) annotation (Line(points={{-198,280},{-170, + 280},{-170,192},{-162,192}}, color={0,0,127})); + + connect(dowProCon.yBoi, pre3.u) annotation (Line(points={{-138,198},{-130,198}, + {-130,250},{-270,250},{-270,190},{-262,190}}, color={255,0,255})); + + connect(logSwi1.y, dowProCon.uBoiSet) annotation (Line(points={{-198,110},{-180, + 110},{-180,184},{-162,184}}, color={255,0,255})); + + connect(or2.y, dowProCon.uStaDowPro) annotation (Line(points={{-108,120},{-100, + 120},{-100,104},{-176,104},{-176,180},{-162,180}}, color={255,0,255})); + + connect(intSwi.y, dowProCon.uStaSet) annotation (Line(points={{-198,40},{-172, + 40},{-172,176},{-162,176}}, color={255,127,0})); + + connect(pre1.y, dowProCon.uPumChaPro) annotation (Line(points={{-18,140},{-10, + 140},{-10,120},{-80,120},{-80,140},{-166,140},{-166,168},{-162,168}}, + color={255,0,255})); + + connect(dowProCon.yStaChaPro, yStaChaPro.u) annotation (Line(points={{-138,194}, + {-126,194},{-126,200},{-122,200}}, color={255,0,255})); + + connect(dowProCon.yHotWatIsoVal, zerOrdHol.u) annotation (Line(points={{-138,190}, + {-130,190},{-130,180},{-62,180}}, color={0,0,127})); + + connect(dowProCon.yPumChaPro, yPumChaPro.u) annotation (Line(points={{-138,174}, + {-130,174},{-130,160},{-122,160}}, color={255,0,255})); + + connect(dowProCon1.yBoi, pre4.u) annotation (Line(points={{232,198},{240,198}, + {240,250},{100,250},{100,190},{108,190}}, color={255,0,255})); + + connect(logSwi4.y, dowProCon1.uBoiSet) annotation (Line(points={{172,110},{190, + 110},{190,184},{208,184}}, color={255,0,255})); + + connect(or1.y, dowProCon1.uStaDowPro) annotation (Line(points={{262,120},{270, + 120},{270,104},{194,104},{194,180},{208,180}}, color={255,0,255})); + + connect(intSwi2.y, dowProCon1.uStaSet) annotation (Line(points={{172,40},{198, + 40},{198,176},{208,176}}, color={255,127,0})); + + connect(pre5.y, dowProCon1.uPumChaPro) annotation (Line(points={{352,140},{360, + 140},{360,120},{310,120},{310,140},{202,140},{202,168},{208,168}}, + color={255,0,255})); + + connect(dowProCon1.yStaChaPro, yStaChaPro1.u) annotation (Line(points={{232,194}, + {244,194},{244,200},{248,200}}, color={255,0,255})); + + connect(con23.y, dowProCon4.VMinHotWatSet_flow) annotation (Line(points={{-158, + -46},{-150,-46},{-150,-66},{-170,-66},{-170,-136},{-162,-136}}, color= + {0,0,127})); + + connect(swi2.y, dowProCon4.VHotWat_flow) annotation (Line(points={{-28,-36},{-20, + -36},{-20,-96},{-166,-96},{-166,-132},{-162,-132}}, color={0,0,127})); + + connect(swi4.y, dowProCon4.uHotWatIsoVal) annotation (Line(points={{-198,-56}, + {-190,-56},{-190,-144},{-162,-144}}, color={0, + 0,127})); + + connect(logSwi13.y, dowProCon4.uBoiSet) annotation (Line(points={{-198,-226},{ + -180,-226},{-180,-152},{-162,-152}}, color={255,0,255})); + + connect(or5.y, dowProCon4.uStaDowPro) annotation (Line(points={{-108,-216},{-104, + -216},{-104,-232},{-176,-232},{-176,-156},{-162,-156}}, color={255,0,255})); + + connect(intSwi8.y, dowProCon4.uStaSet) annotation (Line(points={{-198,-296},{-172, + -296},{-172,-160},{-162,-160}}, color={255,127,0})); + + connect(dowProCon4.yBoi, pre13.u) annotation (Line(points={{-138,-138},{-130, + -138},{-130,-86},{-270,-86},{-270,-150},{-262,-150}}, + color={255,0,255})); + + connect(dowProCon4.yStaChaPro, yStaChaPro4.u) annotation (Line(points={{-138,-142}, + {-126,-142},{-126,-136},{-122,-136}}, color={255,0,255})); + + connect(dowProCon4.yHotWatIsoVal, zerOrdHol4.u) annotation (Line(points={{-138, + -146},{-130,-146},{-130,-156},{-62,-156}}, color={0,0,127})); + + connect(dowProCon1.yPumChaPro, yPumChaPro1.u) annotation (Line(points={{232,174}, + {240,174},{240,160},{248,160}}, color={255,0,255})); + + connect(pre2.y, dowProCon.uStaChaPro) annotation (Line(points={{-6,200},{0,200}, + {0,100},{-184,100},{-184,172},{-162,172}}, color={255,0,255})); + connect(pre6.y, dowProCon1.uStaChaPro) annotation (Line(points={{362,200},{ + 370,200},{370,100},{186,100},{186,172},{208,172}}, + color={255,0,255})); + connect(pre15.y, dowProCon4.uStaChaPro) annotation (Line(points={{-6,-136},{0, + -136},{0,-236},{-184,-236},{-184,-164},{-162,-164}}, color={255,0,255})); + connect(pre3.y, dowProCon.uBoi) annotation (Line(points={{-238,190},{-180,190}, + {-180,188},{-162,188}}, color={255,0,255})); + connect(pre7.y, booRep.u) + annotation (Line(points={{-98,70},{-82,70}}, color={255,0,255})); + connect(pre2.y, pre7.u) annotation (Line(points={{-6,200},{0,200},{0,90},{ + -140,90},{-140,70},{-122,70}}, color={255,0,255})); + connect(pre7.y, or2.u2) annotation (Line(points={{-98,70},{-90,70},{-90,94},{ + -140,94},{-140,112},{-132,112}}, color={255,0,255})); + connect(pre4.y, dowProCon1.uBoi) annotation (Line(points={{132,190},{190,190}, + {190,188},{208,188}}, color={255,0,255})); + connect(pre8.y, booRep1.u) + annotation (Line(points={{262,70},{278,70}}, color={255,0,255})); + connect(pre8.y, or1.u2) annotation (Line(points={{262,70},{270,70},{270,90},{ + 232,90},{232,112},{238,112}}, color={255,0,255})); + connect(pre6.y, pre8.u) annotation (Line(points={{362,200},{370,200},{370,100}, + {226,100},{226,70},{238,70}}, color={255,0,255})); + connect(pre13.y, dowProCon4.uBoi) annotation (Line(points={{-238,-150},{-200, + -150},{-200,-148},{-162,-148}}, color={255,0,255})); + connect(booRep4.u, pre9.y) + annotation (Line(points={{-92,-270},{-108,-270}}, color={255,0,255})); + connect(pre15.y, pre9.u) annotation (Line(points={{-6,-136},{0,-136},{0,-236}, + {-140,-236},{-140,-270},{-132,-270}}, color={255,0,255})); + connect(pre9.y, or5.u2) annotation (Line(points={{-108,-270},{-100,-270},{ + -100,-240},{-136,-240},{-136,-224},{-132,-224}}, color={255,0,255})); +annotation ( + experiment( + StopTime=900, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Down.mos" + "Simulate and plot"), + Documentation(info=" +

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

+", 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={{-380,-340},{380,340}}))); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Up.mo new file mode 100644 index 00000000000..71e9b0a10f3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Up.mo @@ -0,0 +1,1321 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Validation; +model Up + "Validate sequence of staging up process" + + parameter Integer nBoi=2 + "Total number of boilers in the plant"; + + parameter Integer nSta=3 + "Total number of stages"; + + parameter Real delBoiEna( + final unit="s", + final displayUnit="s", + final quantity="Time") = 180 + "Time delay after boiler change process has been completed before turning off excess valves and pumps"; + + parameter Real delEnaMinFloSet( + final unit="s", + final displayUnit="s", + final quantity="Time")=60 + "Enable delay after minimum flow setpoint is achieved in bypass valve"; + + parameter Real delProSupTemSet( + final unit="s", + final displayUnit="s", + final quantity="Time")=300 + "Process time-out for hot water supply temperature setpoint reset"; + + parameter Real TMinSupNonConBoi( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature")=333.2 + "Minimum supply temperature required for non-condensing boilers"; + + parameter Real sigDif( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature")=0.1 + "Significant difference based on minimum resolution of temperature sensor"; + + parameter Real chaIsoValTim( + final unit="s", + final displayUnit="s", + final quantity="Time")=60 + "Time to slowly change isolation valve, should be determined in the field"; + + parameter Real boiChaProOnTim( + final unit="s", + final displayUnit="s", + final quantity="Time")=300 + "Enabled boiler operation time to indicate if it is proven on during a staging + process where one boiler is turned on and the other is turned off"; + + parameter Real relFloDif( + final unit="1", + final displayUnit="1")=0.05 + "Relative error to the flow setpoint for checking if it has been achieved"; + + parameter Real delPreBoiEna( + final unit="s", + final displayUnit="s", + final quantity="Time")=30 + "Time delay after valve and pump change process has been completed before + starting boiler change process"; + + parameter Real VNom_flow( + final unit="m3/s", + final displayUnit="m3/s", + final quantity="VolumeFlowRate") = 1 + "Nominal minimum flow rate"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Up upProCon( + final have_priOnl=false, + final have_heaPriPum=true, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final delProSupTemSet=delProSupTemSet, + final TMinSupNonConBoi=TMinSupNonConBoi, + final sigDif=sigDif, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage up process where temperature reset condition is met with headered pumps" + annotation (Placement(transformation(extent={{-160,170},{-140,210}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Up upProCon1( + final have_priOnl=false, + final have_heaPriPum=true, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final delProSupTemSet=delProSupTemSet, + final TMinSupNonConBoi=TMinSupNonConBoi, + final sigDif=sigDif, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage up process where temperature reset condition is not met with headered pumps" + annotation (Placement(transformation(extent={{210,170},{230,210}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Up upProCon2( + final have_priOnl=false, + final have_heaPriPum=false, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final delProSupTemSet=delProSupTemSet, + final TMinSupNonConBoi=TMinSupNonConBoi, + final sigDif=sigDif, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage up process where temperature reset condition is met with dedicated pumps" + annotation (Placement(transformation(extent={{-170,-170},{-150,-130}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Up upProCon3( + final have_priOnl=false, + final have_heaPriPum=false, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final delProSupTemSet=delProSupTemSet, + final TMinSupNonConBoi=TMinSupNonConBoi, + final sigDif=sigDif, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage up process where temperature reset condition is not met with dedicated pumps" + annotation (Placement(transformation(extent={{410,-172},{430,-132}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.Processes.Up upProCon4( + final have_priOnl=true, + final have_heaPriPum=true, + final nBoi=nBoi, + final nSta=nSta, + final delBoiEna=delBoiEna, + final delPreBoiEna=delPreBoiEna, + final delEnaMinFloSet=delEnaMinFloSet, + final delProSupTemSet=delProSupTemSet, + final TMinSupNonConBoi=TMinSupNonConBoi, + final sigDif=sigDif, + final chaIsoValTim=chaIsoValTim, + final boiChaProOnTim=boiChaProOnTim, + final relFloDif=relFloDif) + "Stage up process for primary-only, condensing boiler plants with headered pumps" + annotation (Placement(transformation(extent={{600,168},{620,208}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{250,190},{270,210}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-130,-140},{-110,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro3( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{450,-140},{470,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yStaChaPro4( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{640,190},{660,210}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yPumChaPro( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yPumChaPro1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{250,150},{270,170}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yPumChaPro2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{-130,-180},{-110,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold yPumChaPro3( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Hold true pulse signal for visualization" + annotation (Placement(transformation(extent={{450,-180},{470,-160}}))); + +protected + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel[nBoi]( + final samplePeriod=fill(1, nBoi), + final y_start={1,0}) + "Unit delay" + annotation (Placement(transformation(extent={{-60,170},{-40,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{-330,70},{-310,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3[nBoi]( + final pre_u_start={true,false}) + "Logical pre block" + annotation (Placement(transformation(extent={{-300,200},{-280,220}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{-220,100},{-200,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nBoi]( + final k={true,true}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{-260,120},{-240,140}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Falling edge detector" + annotation (Placement(transformation(extent={{-90,150},{-70,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{-220,30},{-200,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=3) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{-260,50},{-240,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{-368,0},{-348,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2[nSta]( + final k={1,2,2}) + "Stage typer vector" + annotation (Placement(transformation(extent={{-220,140},{-200,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{-110,110},{-90,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi), + final shift=fill(1, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{-370,250},{-350,270}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=TMinSupNonConBoi + 1) + "Measured hot water supply temperature signal" + annotation (Placement(transformation(extent={{-180,280},{-160,300}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{-30,150},{-10,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Logical pre block" + annotation (Placement(transformation(extent={{-60,210},{-40,230}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{-290,100},{-270,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con4[nBoi]( + final k={true,false}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{-330,130},{-310,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi1 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{-320,20},{-300,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3( + final k=1) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{-370,40},{-350,60}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg2 + "Falling edge detector" + annotation (Placement(transformation(extent={{-140,110},{-120,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{-70,60},{-50,80}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{-110,60},{-90,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con5[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{36,70},{56,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre4[nBoi]( + final pre_u_start={true,false}) + "Logical pre block" + annotation (Placement(transformation(extent={{70,200},{90,220}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{150,100},{170,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con6[nBoi]( + final k={true,true}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{110,120},{130,140}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg3 + "Falling edge detector" + annotation (Placement(transformation(extent={{280,150},{300,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{150,30},{170,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4( + final k=3) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{110,50},{130,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt6[nSta]( + final k={1,2,2}) + "Stage typer vector" + annotation (Placement(transformation(extent={{150,140},{170,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{270,110},{290,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi), + final shift=fill(1, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{0,250},{20,270}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con8( + final k=TMinSupNonConBoi - 1) + "Measured hot water supply temperature signal" + annotation (Placement(transformation(extent={{190,280},{210,300}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre5 + "Logical pre block" + annotation (Placement(transformation(extent={{340,150},{360,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre6 + "Logical pre block" + annotation (Placement(transformation(extent={{310,210},{330,230}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg4 + "Falling edge detector" + annotation (Placement(transformation(extent={{280,190},{300,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi5[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{70,100},{90,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con9[nBoi]( + final k={true,false}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{36,130},{56,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi3 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{50,20},{70,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7( + final k=1) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg5 + "Falling edge detector" + annotation (Placement(transformation(extent={{230,110},{250,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat3[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{310,60},{330,80}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{270,60},{290,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con10[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{-344,-260},{-324,-240}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre7[nBoi]( + final pre_u_start={true,false}) + "Logical pre block" + annotation (Placement(transformation(extent={{-320,-140},{-300,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi7[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{-230,-230},{-210,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con11[nBoi]( + final k={true,true}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{-270,-210},{-250,-190}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg6 + "Falling edge detector" + annotation (Placement(transformation(extent={{-100,-180},{-80,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi4 + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{-230,-300},{-210,-280}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt8( + final k=3) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{-270,-280},{-250,-260}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt9( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{-380,-330},{-360,-310}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt10[nSta]( + final k={1,2,2}) + "Stage typer vector" + annotation (Placement(transformation(extent={{-230,-190},{-210,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or3 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{-100,-220},{-80,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi), + final shift=fill(1, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{-380,-80},{-360,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con13( + final k=TMinSupNonConBoi + 1) + "Measured hot water supply temperature signal" + annotation (Placement(transformation(extent={{-340,-60},{-320,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre8 + "Logical pre block" + annotation (Placement(transformation(extent={{-50,-200},{-30,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre9 + "Logical pre block" + annotation (Placement(transformation(extent={{-38,-140},{-18,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg7 + "Falling edge detector" + annotation (Placement(transformation(extent={{-100,-140},{-80,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi8[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{-310,-230},{-290,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con14[nBoi]( + final k={true,false}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{-344,-200},{-324,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi5 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{-330,-310},{-310,-290}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt11( + final k=1) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{-380,-290},{-360,-270}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg8 + "Falling edge detector" + annotation (Placement(transformation(extent={{-174,-220},{-154,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat5[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{-70,-270},{-50,-250}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{-110,-270},{-90,-250}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con15[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{236,-260},{256,-240}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre10[nBoi]( + final pre_u_start={true,false}) + "Logical pre block" + annotation (Placement(transformation(extent={{260,-110},{280,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi10[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{350,-230},{370,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con16[nBoi]( + final k={true,true}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{310,-210},{330,-190}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg9 + "Falling edge detector" + annotation (Placement(transformation(extent={{480,-180},{500,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi6 + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{350,-300},{370,-280}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt12( + final k=3) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{310,-280},{330,-260}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt13( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{200,-330},{220,-310}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt14[nSta]( + final k={1,2,2}) + "Stage typer vector" + annotation (Placement(transformation(extent={{350,-190},{370,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or4 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{470,-220},{490,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi), + final shift=fill(1, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{200,-80},{220,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con18( + final k=TMinSupNonConBoi - 1) + "Measured hot water supply temperature signal" + annotation (Placement(transformation(extent={{240,-60},{260,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre11 + "Logical pre block" + annotation (Placement(transformation(extent={{530,-200},{550,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre12 + "Logical pre block" + annotation (Placement(transformation(extent={{542,-140},{562,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg10 + "Falling edge detector" + annotation (Placement(transformation(extent={{480,-140},{500,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi11[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{270,-230},{290,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con19[nBoi]( + final k={true,false}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{236,-200},{256,-180}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi7 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{250,-310},{270,-290}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt15( + final k=1) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{200,-290},{220,-270}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg11 + "Falling edge detector" + annotation (Placement(transformation(extent={{406,-220},{426,-200}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat7[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{510,-270},{530,-250}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{470,-270},{490,-250}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con20[nBoi]( + final k={false,true}) + "Boiler setpoints for stage 2" + annotation (Placement(transformation(extent={{426,70},{446,90}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre13[nBoi]( + final pre_u_start={true,false}) + "Logical pre block" + annotation (Placement(transformation(extent={{460,200},{480,220}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi13[nBoi] + "Pass boiler setpoints for stage 3 after one stage change" + annotation (Placement(transformation(extent={{540,100},{560,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con21[nBoi]( + final k={true,true}) + "Boiler setpoints for stage 3" + annotation (Placement(transformation(extent={{500,120},{520,140}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi8 + "Switch between stage 2 and stage 3 setpoints" + annotation (Placement(transformation(extent={{540,30},{560,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt16( + final k=3) + "Stage 3 setpoint" + annotation (Placement(transformation(extent={{500,50},{520,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt17( + final k=2) + "Stage 2 setpoint" + annotation (Placement(transformation(extent={{390,0},{410,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt18[nSta]( + final k={1,1,1}) + "Stage typer vector" + annotation (Placement(transformation(extent={{540,140},{560,160}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or5 + "Detect first triggering pulse and subsequent stage change completion signals" + annotation (Placement(transformation(extent={{650,110},{670,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul4[nBoi]( + final width=fill(0.1/1800, nBoi), + final period=fill(1800, nBoi), + final shift=fill(1, nBoi)) + "Boolean pulse to start initial stage change" + annotation (Placement(transformation(extent={{390,250},{410,270}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con23( + final k=VNom_flow) + "Calculated minimum flow rate signal" + annotation (Placement(transformation(extent={{580,280},{600,300}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre15 + "Logical pre block" + annotation (Placement(transformation(extent={{700,210},{720,230}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg13 + "Falling edge detector" + annotation (Placement(transformation(extent={{670,190},{690,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi14[nBoi] + "Pass boiler setpoints for stage 1 and switch to setpoints for stage 2" + annotation (Placement(transformation(extent={{460,100},{480,120}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con24[nBoi]( + final k={true,false}) + "Initial boiler setpoints for stage 1" + annotation (Placement(transformation(extent={{426,130},{446,150}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi9 + "Switch between stage 1 and stage 2 setpoints" + annotation (Placement(transformation(extent={{440,20},{460,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt19( + final k=1) + "Stage 1 setpoint" + annotation (Placement(transformation(extent={{390,40},{410,60}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg14 + "Falling edge detector" + annotation (Placement(transformation(extent={{596,110},{616,130}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat9[nBoi] + "Hold true signal once first stage change is completed" + annotation (Placement(transformation(extent={{700,60},{720,80}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nBoi) + "Boolean replicator" + annotation (Placement(transformation(extent={{650,60},{670,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con17( + final k=1.1*VNom_flow) + "Calculated minimum flow rate signal" + annotation (Placement(transformation(extent={{540,260},{560,280}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre14 + "Logical pre block" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel1[nBoi]( + final samplePeriod=fill(1, nBoi), + final y_start={1,0}) + "Unit delay" + annotation (Placement(transformation(extent={{310,170},{330,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre16 + "Logical pre block" + annotation (Placement(transformation(extent={{240,60},{260,80}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel2[nBoi]( + final samplePeriod=fill(1, nBoi), + final y_start={1,0}) + "Unit delay" + annotation (Placement(transformation(extent={{700,170},{720,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre17 + "Logical pre block" + annotation (Placement(transformation(extent={{620,60},{640,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre18 + "Logical pre block" + annotation (Placement(transformation(extent={{-150,-270},{-130,-250}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre19 + "Logical pre block" + annotation (Placement(transformation(extent={{440,-270},{460,-250}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg1 + "Falling edge detector" + annotation (Placement(transformation(extent={{-90,210},{-70,230}}))); + +equation + connect(con2.y, logSwi1.u1) annotation (Line(points={{-238,130},{-230,130},{ + -230,118},{-222,118}}, + color={255,0,255})); + + connect(logSwi1.y, upProCon.uBoiSet) annotation (Line(points={{-198,110},{-180, + 110},{-180,189},{-162,189}}, color={255,0,255})); + + connect(upProCon.yPumChaPro, yPumChaPro.u) annotation (Line(points={{-138,178}, + {-130,178},{-130,160},{-122,160}}, color={255,0,255})); + + connect(yPumChaPro.y, falEdg.u) + annotation (Line(points={{-98,160},{-92,160}}, color={255,0,255})); + + connect(intSwi.y, upProCon.uStaSet) annotation (Line(points={{-198,40},{-172,40}, + {-172,180},{-162,180}}, color={255,127,0})); + + connect(conInt.y, intSwi.u1) annotation (Line(points={{-238,60},{-230,60},{ + -230,48},{-222,48}}, + color={255,127,0})); + + connect(conInt2.y, upProCon.uStaTyp) annotation (Line(points={{-198,150},{-190, + 150},{-190,183},{-162,183}}, color={255,127,0})); + + connect(con3.y, upProCon.THotWatSupSet) annotation (Line(points={{-158,290},{ + -150,290},{-150,270},{-170,270},{-170,201},{-162,201}}, color={0,0, + 127})); + + connect(falEdg.y, pre1.u) annotation (Line(points={{-68,160},{-32,160}}, + color={255,0,255})); + + connect(pre1.y, upProCon.uPumChaPro) annotation (Line(points={{-8,160},{-6,160}, + {-6,140},{-168,140},{-168,171},{-162,171}}, + color={255,0,255})); + + connect(upProCon.yStaChaPro,yStaChaPro. u) annotation (Line(points={{-138,198}, + {-126,198},{-126,220},{-122,220}}, color={255,0,255})); + + connect(con1.y, logSwi2.u3) annotation (Line(points={{-308,80},{-300,80},{-300, + 102},{-292,102}}, color={255,0,255})); + + connect(con4.y, logSwi2.u1) annotation (Line(points={{-308,140},{-300,140},{-300, + 118},{-292,118}}, color={255,0,255})); + + connect(booPul.y, logSwi2.u2) annotation (Line(points={{-348,260},{-340,260},{ + -340,110},{-292,110}}, color={255,0,255})); + + connect(logSwi2.y, logSwi1.u3) annotation (Line(points={{-268,110},{-260,110}, + {-260,102},{-222,102}}, color={255,0,255})); + + connect(conInt1.y, intSwi1.u3) annotation (Line(points={{-346,10},{-330,10},{-330, + 22},{-322,22}}, color={255,127,0})); + + connect(conInt3.y, intSwi1.u1) annotation (Line(points={{-348,50},{-330,50},{-330, + 38},{-322,38}}, color={255,127,0})); + + connect(intSwi1.y, intSwi.u3) annotation (Line(points={{-298,30},{-230,30},{-230, + 32},{-222,32}}, color={255,127,0})); + + connect(booPul[1].y, intSwi1.u2) annotation (Line(points={{-348,260},{-340,260}, + {-340,30},{-322,30}}, color={255,0,255})); + + connect(upProCon.yBoi, pre3.u) annotation (Line(points={{-138,202},{-130,202}, + {-130,250},{-314,250},{-314,210},{-302,210}}, color={255,0,255})); + + connect(booPul[1].y, falEdg2.u) annotation (Line(points={{-348,260},{-340,260}, + {-340,98},{-168,98},{-168,120},{-142,120}}, color={255,0,255})); + + connect(falEdg2.y, or2.u1) + annotation (Line(points={{-118,120},{-112,120}}, color={255,0,255})); + + connect(booRep.y, lat1.u) + annotation (Line(points={{-88,70},{-72,70}}, color={255,0,255})); + + connect(lat1.y, logSwi1.u2) annotation (Line(points={{-48,70},{-40,70},{-40,50}, + {-160,50},{-160,74},{-226,74},{-226,110},{-222,110}}, color={255, + 0,255})); + + connect(lat1[1].y, intSwi.u2) annotation (Line(points={{-48,70},{-40,70},{-40, + 50},{-160,50},{-160,74},{-226,74},{-226,40},{-222,40}}, color={255,0, + 255})); + + connect(con1[1].y, lat1[1].clr) annotation (Line(points={{-308,80},{-150,80},{ + -150,54},{-80,54},{-80,64},{-72,64}}, color={255,0,255})); + + connect(con1[1].y, lat1[2].clr) annotation (Line(points={{-308,80},{-150,80},{ + -150,54},{-80,54},{-80,64},{-72,64}}, color={255,0,255})); + + connect(con6.y,logSwi4. u1) annotation (Line(points={{132,130},{140,130},{140, + 118},{148,118}}, color={255,0,255})); + + connect(logSwi4.y, upProCon1.uBoiSet) annotation (Line(points={{172,110},{190, + 110},{190,189},{208,189}}, color={255,0,255})); + + connect(upProCon1.yPumChaPro, yPumChaPro1.u) annotation (Line(points={{232,178}, + {240,178},{240,160},{248,160}}, color={255,0,255})); + + connect(yPumChaPro1.y, falEdg3.u) + annotation (Line(points={{272,160},{278,160}}, color={255,0,255})); + + connect(intSwi2.y, upProCon1.uStaSet) annotation (Line(points={{172,40},{198,40}, + {198,180},{208,180}}, color={255,127,0})); + + connect(conInt4.y, intSwi2.u1) annotation (Line(points={{132,60},{140,60},{140, + 48},{148,48}}, color={255,127,0})); + + connect(conInt6.y, upProCon1.uStaTyp) annotation (Line(points={{172,150},{180, + 150},{180,183},{208,183}}, color={255,127,0})); + + connect(or1.y, upProCon1.uStaUpPro) annotation (Line(points={{292,120},{310,120}, + {310,104},{194,104},{194,186},{208,186}}, color={255,0,255})); + + connect(con8.y, upProCon1.THotWatSupSet) annotation (Line(points={{212,290},{ + 220,290},{220,270},{200,270},{200,201},{208,201}}, color={0,0,127})); + + connect(falEdg3.y, pre5.u) annotation (Line(points={{302,160},{338,160}}, + color={255,0,255})); + + connect(pre5.y, upProCon1.uPumChaPro) annotation (Line(points={{362,160},{364, + 160},{364,120},{320,120},{320,140},{202,140},{202,171},{208,171}}, + color={255,0,255})); + connect(upProCon1.yStaChaPro, yStaChaPro1.u) annotation (Line(points={{232,198}, + {244,198},{244,200},{248,200}}, color={255,0,255})); + + connect(yStaChaPro1.y, falEdg4.u) + annotation (Line(points={{272,200},{278,200}}, color={255,0,255})); + + connect(con5.y,logSwi5. u3) annotation (Line(points={{58,80},{64,80},{64,102}, + {68,102}}, color={255,0,255})); + + connect(con9.y,logSwi5. u1) annotation (Line(points={{58,140},{64,140},{64,118}, + {68,118}}, color={255,0,255})); + + connect(booPul1.y, logSwi5.u2) annotation (Line(points={{22,260},{30,260},{30, + 110},{68,110}}, color={255,0,255})); + + connect(logSwi5.y,logSwi4. u3) annotation (Line(points={{92,110},{98,110},{98, + 102},{148,102}}, color={255,0,255})); + + connect(conInt5.y,intSwi3. u3) annotation (Line(points={{22,10},{40,10},{40,22}, + {48,22}}, color={255,127,0})); + + connect(conInt7.y,intSwi3. u1) annotation (Line(points={{22,50},{40,50},{40,38}, + {48,38}}, color={255,127,0})); + + connect(intSwi3.y, intSwi2.u3) annotation (Line(points={{72,30},{140,30},{140, + 32},{148,32}}, color={255,127,0})); + + connect(booPul1[1].y, intSwi3.u2) annotation (Line(points={{22,260},{30,260},{ + 30,30},{48,30}}, color={255,0,255})); + + connect(upProCon1.yBoi, pre4.u) annotation (Line(points={{232,202},{240,202},{ + 240,230},{60,230},{60,210},{68,210}}, color={255,0,255})); + + connect(falEdg4.y,pre6. u) + annotation (Line(points={{302,200},{306,200},{306,220},{308,220}}, + color={255,0,255})); + + connect(booPul1[1].y, falEdg5.u) annotation (Line(points={{22,260},{30,260},{30, + 96},{202,96},{202,120},{228,120}}, color={255,0,255})); + + connect(falEdg5.y,or1. u1) + annotation (Line(points={{252,120},{268,120}}, color={255,0,255})); + + connect(booRep1.y, lat3.u) + annotation (Line(points={{292,70},{308,70}}, color={255,0,255})); + + connect(lat3.y,logSwi4. u2) annotation (Line(points={{332,70},{340,70},{340,50}, + {210,50},{210,74},{144,74},{144,110},{148,110}}, color={255, + 0,255})); + connect(lat3[1].y, intSwi2.u2) annotation (Line(points={{332,70},{340,70},{340, + 50},{210,50},{210,74},{144,74},{144,40},{148,40}}, color={255,0,255})); + + connect(con5[1].y,lat3 [1].clr) annotation (Line(points={{58,80},{220,80},{220, + 54},{300,54},{300,64},{308,64}}, color={255,0,255})); + + connect(con5[1].y,lat3 [2].clr) annotation (Line(points={{58,80},{220,80},{220, + 54},{300,54},{300,64},{308,64}}, color={255,0,255})); + + connect(con11.y, logSwi7.u1) annotation (Line(points={{-248,-200},{-240,-200}, + {-240,-212},{-232,-212}}, color={255,0,255})); + + connect(logSwi7.y, upProCon2.uBoiSet) annotation (Line(points={{-208,-220},{-190, + -220},{-190,-151},{-172,-151}}, color={255,0,255})); + + connect(upProCon2.yPumChaPro, yPumChaPro2.u) annotation (Line(points={{-148,-162}, + {-140,-162},{-140,-170},{-132,-170}}, color={255,0,255})); + + connect(yPumChaPro2.y, falEdg6.u) + annotation (Line(points={{-108,-170},{-102,-170}}, color={255,0,255})); + + connect(intSwi4.y, upProCon2.uStaSet) annotation (Line(points={{-208,-290},{-182, + -290},{-182,-160},{-172,-160}}, color={255,127,0})); + + connect(conInt8.y, intSwi4.u1) annotation (Line(points={{-248,-270},{-240,-270}, + {-240,-282},{-232,-282}}, color={255,127,0})); + + connect(conInt10.y, upProCon2.uStaTyp) annotation (Line(points={{-208,-180},{-200, + -180},{-200,-157},{-172,-157}}, color={255,127,0})); + + connect(or3.y, upProCon2.uStaUpPro) annotation (Line(points={{-78,-210},{-70,-210}, + {-70,-226},{-186,-226},{-186,-154},{-172,-154}}, color={255,0,255})); + + connect(con13.y, upProCon2.THotWatSupSet) annotation (Line(points={{-318,-50}, + {-180,-50},{-180,-139},{-172,-139}}, color={0,0,127})); + + connect(falEdg6.y, pre8.u) annotation (Line(points={{-78,-170},{-56,-170},{-56, + -190},{-52,-190}}, color={255,0,255})); + + connect(pre8.y, upProCon2.uPumChaPro) annotation (Line(points={{-28,-190},{-16, + -190},{-16,-210},{-60,-210},{-60,-188},{-178,-188},{-178,-169},{-172,-169}}, + color={255,0,255})); + + connect(upProCon2.yStaChaPro, yStaChaPro2.u) annotation (Line(points={{-148,-142}, + {-136,-142},{-136,-130},{-132,-130}}, color={255,0,255})); + + connect(yStaChaPro2.y, falEdg7.u) + annotation (Line(points={{-108,-130},{-102,-130}}, color={255,0,255})); + + connect(con10.y, logSwi8.u3) annotation (Line(points={{-322,-250},{-316,-250}, + {-316,-228},{-312,-228}}, color={255,0,255})); + + connect(con14.y, logSwi8.u1) annotation (Line(points={{-322,-190},{-316,-190}, + {-316,-212},{-312,-212}}, color={255,0,255})); + + connect(booPul2.y, logSwi8.u2) annotation (Line(points={{-358,-70},{-350,-70}, + {-350,-220},{-312,-220}}, color={255,0,255})); + + connect(logSwi8.y,logSwi7. u3) annotation (Line(points={{-288,-220},{-282,-220}, + {-282,-228},{-232,-228}}, + color={255,0,255})); + connect(conInt9.y,intSwi5. u3) annotation (Line(points={{-358,-320},{-340,-320}, + {-340,-308},{-332,-308}}, + color={255,127,0})); + + connect(conInt11.y, intSwi5.u1) annotation (Line(points={{-358,-280},{-340,-280}, + {-340,-292},{-332,-292}}, color={255,127,0})); + + connect(intSwi5.y, intSwi4.u3) annotation (Line(points={{-308,-300},{-240,-300}, + {-240,-298},{-232,-298}}, color={255,127,0})); + + connect(booPul2[1].y, intSwi5.u2) annotation (Line(points={{-358,-70},{-350,-70}, + {-350,-300},{-332,-300}}, color={255,0,255})); + + connect(upProCon2.yBoi, pre7.u) annotation (Line(points={{-148,-138},{-140,-138}, + {-140,-110},{-332,-110},{-332,-130},{-322,-130}}, + color={255,0,255})); + + connect(falEdg7.y,pre9. u) + annotation (Line(points={{-78,-130},{-40,-130}}, + color={255,0,255})); + + connect(booPul2[1].y, falEdg8.u) annotation (Line(points={{-358,-70},{-350,-70}, + {-350,-234},{-178,-234},{-178,-210},{-176,-210}}, color={255,0,255})); + + connect(falEdg8.y,or3. u1) + annotation (Line(points={{-152,-210},{-102,-210}}, + color={255,0,255})); + + connect(booRep2.y, lat5.u) + annotation (Line(points={{-88,-260},{-72,-260}}, color={255,0,255})); + + connect(lat5.y,logSwi7. u2) annotation (Line(points={{-48,-260},{-30,-260},{-30, + -280},{-170,-280},{-170,-256},{-236,-256},{-236,-220},{-232,-220}}, + color={255, + 0,255})); + connect(lat5[1].y, intSwi4.u2) annotation (Line(points={{-48,-260},{-30,-260}, + {-30,-280},{-170,-280},{-170,-256},{-236,-256},{-236,-290},{-232,-290}}, + color={255,0,255})); + connect(con10[1].y, lat5[1].clr) annotation (Line(points={{-322,-250},{-160,-250}, + {-160,-276},{-80,-276},{-80,-266},{-72,-266}}, color={255,0,255})); + + connect(con10[1].y, lat5[2].clr) annotation (Line(points={{-322,-250},{-160,-250}, + {-160,-276},{-80,-276},{-80,-266},{-72,-266}}, color={255,0,255})); + + connect(con16.y, logSwi10.u1) annotation (Line(points={{332,-200},{340,-200},{ + 340,-212},{348,-212}}, color={255,0,255})); + + connect(logSwi10.y, upProCon3.uBoiSet) annotation (Line(points={{372,-220},{390, + -220},{390,-153},{408,-153}}, color={255,0,255})); + + connect(upProCon3.yPumChaPro, yPumChaPro3.u) annotation (Line(points={{432,-164}, + {440,-164},{440,-170},{448,-170}}, color={255,0,255})); + + connect(yPumChaPro3.y, falEdg9.u) + annotation (Line(points={{472,-170},{478,-170}}, color={255,0,255})); + + connect(intSwi6.y, upProCon3.uStaSet) annotation (Line(points={{372,-290},{398, + -290},{398,-162},{408,-162}}, color={255,127,0})); + + connect(conInt12.y, intSwi6.u1) annotation (Line(points={{332,-270},{340,-270}, + {340,-282},{348,-282}}, color={255,127,0})); + + connect(conInt14.y, upProCon3.uStaTyp) annotation (Line(points={{372,-180},{380, + -180},{380,-159},{408,-159}}, color={255,127,0})); + + connect(or4.y, upProCon3.uStaUpPro) annotation (Line(points={{492,-210},{500,-210}, + {500,-226},{394,-226},{394,-156},{408,-156}}, color={255,0,255})); + + connect(con18.y, upProCon3.THotWatSupSet) annotation (Line(points={{262,-50}, + {400,-50},{400,-141},{408,-141}}, color={0,0,127})); + + connect(falEdg9.y, pre11.u) annotation (Line(points={{502,-170},{524,-170},{524, + -190},{528,-190}}, color={255,0,255})); + + connect(pre11.y, upProCon3.uPumChaPro) annotation (Line(points={{552,-190},{564, + -190},{564,-210},{510,-210},{510,-188},{402,-188},{402,-171},{408,-171}}, + color={255,0,255})); + connect(upProCon3.yStaChaPro, yStaChaPro3.u) annotation (Line(points={{432,-144}, + {441,-144},{441,-130},{448,-130}}, color={255,0,255})); + + connect(yStaChaPro3.y, falEdg10.u) + annotation (Line(points={{472,-130},{478,-130}}, color={255,0,255})); + + connect(con15.y, logSwi11.u3) annotation (Line(points={{258,-250},{264,-250},{ + 264,-228},{268,-228}}, + color={255,0,255})); + + connect(con19.y, logSwi11.u1) annotation (Line(points={{258,-190},{264,-190},{ + 264,-212},{268,-212}}, + color={255,0,255})); + + connect(booPul3.y, logSwi11.u2) annotation (Line(points={{222,-70},{230,-70},{ + 230,-220},{268,-220}}, + color={255,0,255})); + + connect(logSwi11.y, logSwi10.u3) annotation (Line(points={{292,-220},{298,-220}, + {298,-228},{348,-228}},color={255,0,255})); + + connect(conInt13.y, intSwi7.u3) annotation (Line(points={{222,-320},{240,-320}, + {240,-308},{248,-308}}, + color={255,127,0})); + + connect(conInt15.y, intSwi7.u1) annotation (Line(points={{222,-280},{240,-280}, + {240,-292},{248,-292}}, + color={255,127,0})); + + connect(intSwi7.y, intSwi6.u3) annotation (Line(points={{272,-300},{340,-300}, + {340,-298},{348,-298}},color={255,127,0})); + + connect(booPul3[1].y, intSwi7.u2) annotation (Line(points={{222,-70},{230,-70}, + {230,-300},{248,-300}}, + color={255,0,255})); + + connect(upProCon3.yBoi, pre10.u) annotation (Line(points={{432,-140},{440,-140}, + {440,-80},{250,-80},{250,-100},{258,-100}}, color={255,0,255})); + + connect(falEdg10.y, pre12.u) + annotation (Line(points={{502,-130},{540,-130}}, color={255,0,255})); + + connect(booPul3[1].y, falEdg11.u) annotation (Line(points={{222,-70},{230,-70}, + {230,-234},{402,-234},{402,-210},{404,-210}}, + color={255,0,255})); + + connect(falEdg11.y, or4.u1) + annotation (Line(points={{428,-210},{468,-210}}, color={255,0,255})); + + connect(booRep3.y, lat7.u) + annotation (Line(points={{492,-260},{508,-260}}, color={255,0,255})); + + connect(lat7.y, logSwi10.u2) annotation (Line(points={{532,-260},{540,-260},{540, + -280},{410,-280},{410,-256},{344,-256},{344,-220},{348,-220}}, color={ + 255,0,255})); + + connect(lat7[1].y, intSwi6.u2) annotation (Line(points={{532,-260},{540,-260}, + {540,-280},{410,-280},{410,-256},{344,-256},{344,-290},{348,-290}}, + color={255,0,255})); + connect(con15[1].y, lat7[1].clr) annotation (Line(points={{258,-250},{420,-250}, + {420,-276},{500,-276},{500,-266},{508,-266}}, color={255,0,255})); + + connect(con15[1].y, lat7[2].clr) annotation (Line(points={{258,-250},{420,-250}, + {420,-276},{500,-276},{500,-266},{508,-266}}, color={255,0,255})); + + connect(con21.y, logSwi13.u1) annotation (Line(points={{522,130},{530,130},{530, + 118},{538,118}}, color={255,0,255})); + + connect(logSwi13.y, upProCon4.uBoiSet) annotation (Line(points={{562,110},{580, + 110},{580,187},{598,187}}, color={255,0,255})); + + connect(intSwi8.y, upProCon4.uStaSet) annotation (Line(points={{562,40},{588,40}, + {588,178},{598,178}}, color={255,127,0})); + + connect(conInt16.y, intSwi8.u1) annotation (Line(points={{522,60},{530,60},{530, + 48},{538,48}}, color={255,127,0})); + + connect(conInt18.y, upProCon4.uStaTyp) annotation (Line(points={{562,150},{570, + 150},{570,181},{598,181}}, color={255,127,0})); + + connect(or5.y, upProCon4.uStaUpPro) annotation (Line(points={{672,120},{680,120}, + {680,104},{584,104},{584,184},{598,184}}, color={255,0,255})); + + connect(upProCon4.yStaChaPro, yStaChaPro4.u) annotation (Line(points={{622,196}, + {632,196},{632,200},{638,200}}, color={255,0,255})); + + connect(yStaChaPro4.y, falEdg13.u) + annotation (Line(points={{662,200},{668,200}}, color={255,0,255})); + + connect(con20.y, logSwi14.u3) annotation (Line(points={{448,80},{454,80},{454, + 102},{458,102}}, color={255,0,255})); + + connect(con24.y, logSwi14.u1) annotation (Line(points={{448,140},{454,140},{454, + 118},{458,118}}, color={255,0,255})); + + connect(booPul4.y, logSwi14.u2) annotation (Line(points={{412,260},{420,260},{ + 420,110},{458,110}}, color={255,0,255})); + + connect(logSwi14.y, logSwi13.u3) annotation (Line(points={{482,110},{488,110}, + {488,102},{538,102}}, color={255,0,255})); + + connect(conInt17.y, intSwi9.u3) annotation (Line(points={{412,10},{430,10},{430, + 22},{438,22}}, color={255,127,0})); + + connect(conInt19.y, intSwi9.u1) annotation (Line(points={{412,50},{430,50},{430, + 38},{438,38}}, color={255,127,0})); + + connect(intSwi9.y, intSwi8.u3) annotation (Line(points={{462,30},{530,30},{530, + 32},{538,32}}, color={255,127,0})); + + connect(booPul4[1].y, intSwi9.u2) annotation (Line(points={{412,260},{420,260}, + {420,30},{438,30}}, color={255,0,255})); + + connect(upProCon4.yBoi, pre13.u) annotation (Line(points={{622,200},{630,200}, + {630,230},{450,230},{450,210},{458,210}}, color={255,0,255})); + + connect(falEdg13.y, pre15.u) + annotation (Line(points={{692,200},{696,200},{696,220},{698,220}}, + color={255,0,255})); + + connect(booPul4[1].y, falEdg14.u) annotation (Line(points={{412,260},{420,260}, + {420,96},{592,96},{592,120},{594,120}}, color={255,0,255})); + + connect(falEdg14.y, or5.u1) + annotation (Line(points={{618,120},{648,120}}, color={255,0,255})); + + connect(booRep4.y, lat9.u) + annotation (Line(points={{672,70},{698,70}}, color={255,0,255})); + + connect(lat9.y, logSwi13.u2) annotation (Line(points={{722,70},{740,70},{740,50}, + {600,50},{600,74},{534,74},{534,110},{538,110}}, color={255,0,255})); + + connect(lat9[1].y, intSwi8.u2) annotation (Line(points={{722,70},{740,70},{740, + 50},{600,50},{600,74},{534,74},{534,40},{538,40}}, color={255,0,255})); + + connect(con20[1].y, lat9[1].clr) annotation (Line(points={{448,80},{610,80},{610, + 54},{680,54},{680,64},{698,64}}, color={255,0,255})); + + connect(con20[1].y, lat9[2].clr) annotation (Line(points={{448,80},{610,80},{610, + 54},{680,54},{680,64},{698,64}}, color={255,0,255})); + + connect(con23.y, upProCon4.VMinHotWatSet_flow) annotation (Line(points={{602,290}, + {610,290},{610,268},{590,268},{590,203},{598,203}}, color={0,0, + 127})); + + connect(booPul[1].y, upProCon.uPlaEna) annotation (Line(points={{-348,260},{-234, + 260},{-234,240},{-184,240},{-184,177},{-162,177}}, color={255,0, + 255})); + connect(booPul1[1].y, upProCon1.uPlaEna) annotation (Line(points={{22,260},{186, + 260},{186,177},{208,177}}, color={255,0,255})); + connect(booPul4[1].y, upProCon4.uPlaEna) annotation (Line(points={{412,260},{520, + 260},{520,254},{574,254},{574,175},{598,175}}, color={255,0,255})); + connect(booPul2[1].y, upProCon2.uPlaEna) annotation (Line(points={{-358,-70},{ + -350,-70},{-350,-174},{-236,-174},{-236,-163},{-172,-163}}, color={ + 255,0,255})); + connect(booPul3[1].y, upProCon3.uPlaEna) annotation (Line(points={{222,-70},{230, + -70},{230,-165},{408,-165}}, color={255,0,255})); + connect(pre3.y, upProCon.uBoi) annotation (Line(points={{-278,210},{-180,210}, + {-180,193},{-162,193}}, color={255,0,255})); + connect(upProCon.yHotWatIsoVal, uniDel.u) annotation (Line(points={{-138,194}, + {-126,194},{-126,180},{-62,180}}, color={0,0,127})); + connect(uniDel.y, upProCon.uHotWatIsoVal) annotation (Line(points={{-38,180},{ + -30,180},{-30,240},{-176,240},{-176,197},{-162,197}}, color={0,0,127})); + connect(pre2.y, upProCon.uStaChaPro) annotation (Line(points={{-38,220},{0,220}, + {0,100},{-184,100},{-184,174},{-162,174}}, color={255,0,255})); + connect(booRep.u, pre14.y) + annotation (Line(points={{-112,70},{-118,70}}, color={255,0,255})); + connect(pre2.y, pre14.u) annotation (Line(points={{-38,220},{0,220},{0,100},{-146, + 100},{-146,70},{-142,70}}, color={255,0,255})); + connect(pre14.y, or2.u2) annotation (Line(points={{-118,70},{-116,70},{-116,112}, + {-112,112}}, color={255,0,255})); + connect(pre4.y, upProCon1.uBoi) annotation (Line(points={{92,210},{204,210},{204, + 193},{208,193}}, color={255,0,255})); + connect(upProCon1.yHotWatIsoVal, uniDel1.u) annotation (Line(points={{232,194}, + {240,194},{240,180},{308,180}}, color={0,0,127})); + connect(uniDel1.y, upProCon1.uHotWatIsoVal) annotation (Line(points={{332,180}, + {340,180},{340,240},{194,240},{194,197},{208,197}}, color={0,0,127})); + connect(pre6.y, upProCon1.uStaChaPro) annotation (Line(points={{332,220},{370, + 220},{370,100},{186,100},{186,174},{208,174}}, color={255,0,255})); + connect(pre16.y, booRep1.u) + annotation (Line(points={{262,70},{268,70}}, color={255,0,255})); + connect(pre16.y, or1.u2) annotation (Line(points={{262,70},{264,70},{264,112}, + {268,112}}, color={255,0,255})); + connect(pre6.y, pre16.u) annotation (Line(points={{332,220},{370,220},{370,100}, + {230,100},{230,70},{238,70}}, color={255,0,255})); + connect(pre13.y, upProCon4.uBoi) annotation (Line(points={{482,210},{588,210}, + {588,191},{598,191}}, color={255,0,255})); + connect(upProCon4.yHotWatIsoVal, uniDel2.u) annotation (Line(points={{622,192}, + {632,192},{632,180},{698,180}}, color={0,0,127})); + connect(uniDel2.y, upProCon4.uHotWatIsoVal) annotation (Line(points={{722,180}, + {730,180},{730,160},{590,160},{590,195},{598,195}}, color={0,0,127})); + connect(pre15.y, upProCon4.uStaChaPro) annotation (Line(points={{722,220},{760, + 220},{760,100},{574,100},{574,172},{598,172}}, color={255,0,255})); + connect(booRep4.u, pre17.y) + annotation (Line(points={{648,70},{642,70}}, color={255,0,255})); + connect(pre15.y, pre17.u) annotation (Line(points={{722,220},{760,220},{760,100}, + {614,100},{614,70},{618,70}}, color={255,0,255})); + connect(pre17.y, or5.u2) annotation (Line(points={{642,70},{644,70},{644,112}, + {648,112}}, color={255,0,255})); + connect(pre7.y, upProCon2.uBoi) annotation (Line(points={{-298,-130},{-186,-130}, + {-186,-147},{-172,-147}}, color={255,0,255})); + connect(pre9.y, upProCon2.uStaChaPro) annotation (Line(points={{-16,-130},{-10, + -130},{-10,-230},{-196,-230},{-196,-166},{-172,-166}}, color={255,0,255})); + connect(pre18.y, booRep2.u) + annotation (Line(points={{-128,-260},{-112,-260}}, color={255,0,255})); + connect(pre9.y, pre18.u) annotation (Line(points={{-16,-130},{-10,-130},{-10,-230}, + {-156,-230},{-156,-260},{-152,-260}}, color={255,0,255})); + connect(pre18.y, or3.u2) annotation (Line(points={{-128,-260},{-120,-260},{-120, + -218},{-102,-218}}, color={255,0,255})); + connect(pre10.y, upProCon3.uBoi) annotation (Line(points={{282,-100},{396,-100}, + {396,-149},{408,-149}}, color={255,0,255})); + connect(pre12.y, upProCon3.uStaChaPro) annotation (Line(points={{564,-130},{570, + -130},{570,-230},{386,-230},{386,-168},{408,-168}}, color={255,0,255})); + connect(pre19.y, booRep3.u) + annotation (Line(points={{462,-260},{468,-260}}, color={255,0,255})); + connect(pre19.y, or4.u2) annotation (Line(points={{462,-260},{466,-260},{466,-218}, + {468,-218}}, color={255,0,255})); + connect(pre12.y, pre19.u) annotation (Line(points={{564,-130},{570,-130},{570, + -230},{430,-230},{430,-260},{438,-260}}, color={255,0,255})); + + connect(falEdg1.y, pre2.u) + annotation (Line(points={{-68,220},{-62,220}}, color={255,0,255})); + connect(yStaChaPro.y, falEdg1.u) + annotation (Line(points={{-98,220},{-92,220}}, color={255,0,255})); + connect(or2.y, upProCon.uStaUpPro) annotation (Line(points={{-88,120},{-80,120}, + {-80,104},{-176,104},{-176,186},{-162,186}}, color={255,0,255})); + connect(con17.y, upProCon4.VHotWat_flow) annotation (Line(points={{562,270},{ + 580,270},{580,207},{598,207}}, color={0,0,127})); +annotation ( + experiment( + StopTime=900, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/Up.mos" + "Simulate and plot"), + Documentation(info=" +

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

+", 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={{-380,-340},{780,340}}))); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/package.mo new file mode 100644 index 00000000000..b24d6702592 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/package.mo @@ -0,0 +1,38 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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/BoilerPlant/Staging/Processes/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/package.order new file mode 100644 index 00000000000..c33e6f176dc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/Validation/package.order @@ -0,0 +1,2 @@ +Down +Up diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/package.mo new file mode 100644 index 00000000000..b85eaa4a53c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/package.mo @@ -0,0 +1,45 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging; +package Processes "Package of sequences for controlling devices when there is a boiler 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/BoilerPlant/Staging/Processes/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/package.order new file mode 100644 index 00000000000..95417cff338 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/Processes/package.order @@ -0,0 +1,4 @@ +Down +Up +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/SetpointController.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/SetpointController.mo new file mode 100644 index 00000000000..1ca758de4f4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/SetpointController.mo @@ -0,0 +1,598 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints; +block SetpointController + "Calculates the boiler stage status setpoint signal" + + parameter Boolean have_priOnl = false + "Is the boiler plant a primary-only, condensing boiler plant?" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer nBoi = 2 + "Number of boilers" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer boiTyp[nBoi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler} + "Boiler type" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer nSta = 3 + "Number of boiler plant stages" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Integer staMat[nSta, nBoi] = {{1,0},{0,1},{1,1}} + "Staging matrix with stage as row index and boiler as column index" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real boiDesCap[nBoi]( + final unit=fill("W",nBoi), + displayUnit=fill("W",nBoi), + final quantity=fill("Power",nBoi)) + "Design boiler capacities vector" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real boiFirMin[nBoi]( + final unit=fill("1",nBoi), + displayUnit=fill("1",nBoi)) + "Boiler minimum firing ratio" + annotation(Dialog(tab="General", group="Boiler plant configuration parameters")); + + parameter Real boiMinPriPumSpeSta[nSta]( + final unit=fill("1",nSta), + displayUnit=fill("1",nSta), + final max=fill(1,nSta), + final min=fill(0,nSta)) = {0,0,0} + "Minimum primary pump speed for the boiler plant stage" + annotation(Evaluate=true, + Dialog(enable=not + (have_priOnl), + tab="General", + group="Boiler plant configuration parameters")); + + parameter Real delStaCha( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Hold period for each stage change" + annotation(Dialog(tab="Staging parameters", group="General parameters")); + + parameter Real avePer( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Time period for the capacity requirement rolling average" + annotation(Dialog(tab="Staging parameters", group="Capacity requirement calculation parameters")); + + parameter Real fraNonConBoi( + final unit="1", + displayUnit="1") = 0.9 + "Fraction of current stage design capacity at which efficiency condition is + satisfied for non-condensing boilers" + annotation(Dialog(tab="Staging parameters", group="Efficiency condition parameters")); + + parameter Real fraConBoi( + final unit="1", + displayUnit="1") = 1.5 + "Fraction of higher stage design capacity at which efficiency condition is + satisfied for condensing boilers" + annotation(Dialog(tab="Staging parameters", group="Efficiency condition parameters")); + + parameter Real delEffCon( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Enable delay for heating capacity requirement condition" + annotation(Dialog(tab="Staging parameters", group="Efficiency condition parameters")); + + parameter Real TDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 10 + "Required temperature difference between setpoint and measured temperature" + annotation(Dialog(tab="Staging parameters", group="Failsafe condition parameters")); + + parameter Real delFaiCon( + final unit="s", + displayUnit="s", + final quantity="Time") = 900 + "Enable delay for temperature condition" + annotation(Dialog(tab="Staging parameters", group="Failsafe condition parameters")); + + parameter Real sigDif( + final unit="1", + displayUnit="1") = 0.1 + "Signal hysteresis deadband" + annotation (Dialog(tab="Advanced", group="Efficiency condition parameters")); + + parameter Real TDifHys( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1 + "Temperature deadband for hysteresis loop" + annotation(Dialog(tab="Advanced", group="Failsafe condition parameters")); + + parameter Real fraMinFir( + final unit="1", + displayUnit="1") = 1.1 + "Fraction of boiler minimum firing rate that required capacity needs to be + to initiate stage-down process" + annotation(Dialog(tab="Staging parameters", group="Staging down parameters")); + + parameter Real delMinFir( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Delay for staging based on minimum firing rate of current stage" + annotation(Dialog(tab="Staging parameters", group="Staging down parameters")); + + parameter Real fraDesCap( + final unit="1", + displayUnit="1") = 0.8 + "Fraction of design capacity of next lower stage that heating capacity needs + to be for staging down" + annotation(Dialog(tab="Staging parameters", group="Staging down parameters")); + + parameter Real delDesCapNonConBoi( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Enable delay for capacity requirement condition for non-condensing boilers" + annotation(Dialog(tab="Staging parameters", group="Staging down parameters")); + + parameter Real delDesCapConBoi( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for capacity requirement condition for condensing boilers" + annotation(Dialog(tab="Staging parameters", group="Staging down parameters")); + + parameter Real delBypVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for bypass valve condition for primary-only plants" + annotation ( + Evaluate=true, + Dialog( + enable=have_priOnl, + tab="Staging parameters", + group="Staging down parameters")); + + parameter Real TCirDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 3 + "Required return water temperature difference between primary and secondary + circuits for staging down" + annotation ( + Evaluate=true, + Dialog( + enable=not + (have_priOnl), + tab="Staging parameters", + group="Staging down parameters")); + + parameter Real delTRetDif( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for measured hot water return temperature difference condition" + annotation ( + Evaluate=true, + Dialog( + enable=not + (have_priOnl), + tab="Staging parameters", + group="Staging down parameters")); + + parameter Real bypValClo( + final unit="1", + displayUnit="1") = 0 + "Adjustment for signal received when bypass valve is closed" + annotation ( + Evaluate=true, + Dialog( + enable=have_priOnl, + tab="Advanced", + group="Staging down parameters")); + + parameter Real dTemp( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 0.1 + "Hysteresis deadband for measured temperatures" + annotation (Dialog(tab="Advanced", group="Failsafe condition parameters")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal indicating end of stage change process" + annotation (Placement(transformation(extent={{-440,-280},{-400,-240}}), + iconTransformation(extent={{-140,150},{-100,190}}, + rotation=90, + origin={80,-80}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiAva[nBoi] + "Boiler availability status vector" + annotation (Placement(transformation(extent={{-440,-190},{-400,-150}}), + iconTransformation(extent={{-140,-180},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-440,-100},{-400,-60}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta) + "Boiler stage" + annotation (Placement(transformation(extent={{-440,-130},{-400,-90}}), + iconTransformation(extent={{-140,-150},{-100,-110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatRetPri( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl + "Measured temperature of return hot water in primary circuit" + annotation (Placement(transformation(extent={{-440,30},{-400,70}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatRetSec( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl + "Measured temperature of return hot water in secondary circuit" + annotation (Placement(transformation(extent={{-440,-10},{-400,30}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSupSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-440,270},{-400,310}}), + iconTransformation(extent={{-140,150},{-100,190}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSup( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-440,150},{-400,190}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatRet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Hot water return temperature" + annotation (Placement(transformation(extent={{-440,230},{-400,270}}), + iconTransformation(extent={{-140,120},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s", + displayUnit="m3/s") + "Measured hot water flow rate" + annotation (Placement(transformation(extent={{-440,190},{-400,230}}), + iconTransformation(extent={{-140,90},{-100,130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinSet_flow[nSta]( + final unit=fill("m3/s",nSta), + displayUnit=fill("m3/s",nSta), + final quantity=fill("VolumeFlowRate",nSta)) + "Vector with primary circuit minimum flow setpoint for all stages" + annotation (Placement(transformation(extent={{-440,110},{-400,150}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uBypValPos( + final unit="1", + displayUnit="1") if have_priOnl + "Bypass valve position" + annotation (Placement(transformation(extent={{-440,70},{-400,110}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uPumSpe( + final unit="1", + displayUnit="1") if not have_priOnl + "Pump speed signal" + annotation (Placement(transformation(extent={{-440,-50},{-400,-10}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaUpEdg + "Boiler stage change higher edge signal" + annotation (Placement(transformation(extent={{120,-90},{160,-50}}), + iconTransformation(extent={{100,0},{140,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaDowEdg + "Boiler stage change lower edge signal" + annotation (Placement(transformation(extent={{120,-210},{160,-170}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler status setpoint vector for the current boiler stage setpoint" + annotation (Placement(transformation(extent={{120,-280},{160,-240}}), + iconTransformation(extent={{100,-120},{140,-80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaEdg + "Boiler stage change edge signal" + annotation (Placement(transformation(extent={{120,-150},{160,-110}}), + iconTransformation(extent={{100,-40},{140,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput ySta( + final min=0, + final max=nSta) "Boiler stage integer setpoint" + annotation (Placement(transformation(extent={{120,-20},{160,20}}), + iconTransformation(extent={{100,40},{140,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yStaTyp[nSta] + "Boiler stage type vector" + annotation (Placement(transformation(extent={{120,40},{160,80}}), + iconTransformation(extent={{100,80},{140,120}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.CapacityRequirement capReq1( + final avePer=avePer) + "Capacity requirement calculator" + annotation (Placement(transformation(extent={{-360,240},{-340,260}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Capacities cap( + final nSta=nSta) + "Stage capacity calculator to to find design and minimum capacities for staging calculations" + annotation (Placement(transformation(extent={{-270,-180},{-250,-160}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Change cha( + final nSta=nSta, + final delStaCha=delStaCha) + "Stage change assignment" + annotation (Placement(transformation(extent={{-20,-180},{0,-160}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices boiInd( + final nSta=nSta, + final nBoi=nBoi, + final staMat=staMat) + "Boiler index generator" + annotation (Placement(transformation(extent={{40,-210},{60,-190}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator conf( + final nSta=nSta, + final nBoi=nBoi, + final boiTyp=boiTyp, + final staMat=staMat, + final boiDesCap=boiDesCap, + final boiFirMin=boiFirMin) + "Configurator to decide stage availability based on boiler availability" + annotation (Placement(transformation(extent={{-360,-180},{-340,-160}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta( + final nSta=nSta, + final nBoi=nBoi, + final staMat=staMat) + "Status calculator to find next higher and lower available stages" + annotation (Placement(transformation(extent={{-310,-220},{-290,-200}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Up staUp( + final nSta=nSta, + final fraNonConBoi=fraNonConBoi, + final fraConBoi=fraConBoi, + final sigDif=sigDif, + final delEffCon=delEffCon, + final TDif=TDif, + final TDifHys=TDifHys, + final delFaiCon=delFaiCon) + "Staging up calculator" + annotation (Placement(transformation(extent={{-140,-120},{-120,-88}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Down staDow( + final have_priOnl=have_priOnl, + final nSta=nSta, + final fraMinFir=fraMinFir, + final delMinFir=delMinFir, + final fraDesCap=fraDesCap, + final delDesCapNonConBoi=delDesCapNonConBoi, + final delDesCapConBoi=delDesCapConBoi, + final sigDif=sigDif, + final delBypVal=delBypVal, + final bypValClo=bypValClo, + final TCirDif=TCirDif, + final delTRetDif=delTRetDif, + final dTemp=dTemp, + final TDif=TDif, + final delFaiCon=delFaiCon, + final boiMinPriPumSpeSta=boiMinPriPumSpeSta) + "Staging down calculator" + annotation (Placement(transformation(extent={{-140,-256},{-120,-221}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nSta) + "Identify minimum flow rate for the next higher available stage" + annotation (Placement(transformation(extent={{-240,-120},{-220,-100}}))); + +equation + connect(uPla, cha.uPla) annotation (Line(points={{-420,-80},{-280,-80},{-280,-140}, + {-60,-140},{-60,-165},{-22,-165}}, color={255,0,255})); + connect(cha.ySta, ySta) annotation (Line(points={{2,-164},{20,-164},{20,0},{ + 140,0}}, color={255,127,0})); + connect(boiInd.yBoi,yBoi) + annotation (Line(points={{62,-200},{80,-200},{80,-260},{140,-260}}, + color={255,0,255})); + connect(cha.ySta,boiInd. u) annotation (Line(points={{2,-164},{20,-164},{20, + -200},{38,-200}}, color={255,127,0})); + connect(capReq1.TSupSet, THotWatSupSet) annotation (Line(points={{-362,257},{ + -380,257},{-380,290},{-420,290}}, + color={0,0,127})); + connect(capReq1.TRet, THotWatRet) + annotation (Line(points={{-362,250},{-420,250}}, color={0,0,127})); + connect(capReq1.VHotWat_flow, VHotWat_flow) annotation (Line(points={{-362, + 243},{-380,243},{-380,210},{-420,210}}, + color={0,0,127})); + connect(conf.uBoiAva,uBoiAva) annotation (Line(points={{-362,-170},{-420,-170}}, + color={255,0,255})); + connect(sta.uAva, conf.yAva) annotation (Line(points={{-312,-216},{-332,-216}, + {-332,-178},{-338,-178}}, color={255,0,255})); + connect(sta.u, u) annotation (Line(points={{-312,-204},{-328,-204},{-328,-110}, + {-420,-110}},color={255,127,0})); + connect(conf.yCapDes, cap.uDesCap) annotation (Line(points={{-338,-162},{-310, + -162},{-310,-161},{-272,-161}}, color={0,0,127})); + connect(conf.yCapMin, cap.uMinCap) annotation (Line(points={{-338,-166},{-310, + -166},{-310,-164},{-272,-164}}, color={0,0,127})); + connect(cap.u, u) annotation (Line(points={{-272,-167},{-308,-167},{-308,-168}, + {-328,-168},{-328,-110},{-420,-110}}, + color={255,127,0})); + connect(sta.yAvaUp, cap.uUp) annotation (Line(points={{-288,-203},{-280,-203}, + {-280,-170},{-272,-170}}, color={255,127,0})); + connect(sta.yAvaDow, cap.uDown) annotation (Line(points={{-288,-206},{-278,-206}, + {-278,-173},{-272,-173}}, color={255,127,0})); + connect(sta.yHig, cap.uHig) annotation (Line(points={{-288,-211},{-276,-211},{ + -276,-176},{-272,-176}}, color={255,0,255})); + connect(sta.yLow, cap.uLow) annotation (Line(points={{-288,-214},{-274,-214},{ + -274,-179},{-272,-179}}, color={255,0,255})); + connect(cap.yDes, staUp.uCapDes) annotation (Line(points={{-248,-162},{-210,-162}, + {-210,-92},{-142,-92}}, color={0,0,127})); + connect(cap.yUpMin, staUp.uCapUpMin) annotation (Line(points={{-248,-178},{-208, + -178},{-208,-95},{-142,-95}}, color={0,0,127})); + connect(conf.yTyp, staUp.uTyp) annotation (Line(points={{-338,-174},{-336,-174}, + {-336,-226},{-206,-226},{-206,-104},{-142,-104}}, color={255,127,0})); + connect(sta.yAvaCur, staUp.uAvaCur) annotation (Line(points={{-288,-217},{-154, + -217},{-154,-116},{-142,-116}}, color={255,0,255})); + connect(THotWatSup, staUp.THotWatSup) annotation (Line(points={{-420,170},{-188, + 170},{-188,-113},{-142,-113}}, color={0,0,127})); + connect(THotWatSupSet, staUp.THotWatSupSet) annotation (Line(points={{-420,290}, + {-184,290},{-184,-110},{-142,-110}}, color={0,0,127})); + connect(VHotWat_flow, staUp.VHotWat_flow) annotation (Line(points={{-420,210}, + {-194,210},{-194,-98},{-142,-98}}, color={0,0,127})); + connect(staDow.THotWatSupSet, THotWatSupSet) annotation (Line(points={{-142,-231}, + {-184,-231},{-184,290},{-420,290}}, color={0,0,127})); + connect(staDow.THotWatSup, THotWatSup) annotation (Line(points={{-142,-234},{-188, + -234},{-188,170},{-420,170}}, color={0,0,127})); + connect(staDow.uCapReq, capReq1.y) annotation (Line(points={{-142,-237},{-180, + -237},{-180,250},{-338,250}}, color={0,0,127})); + connect(extIndSig.y, staUp.VUpMinSet_flow) annotation (Line(points={{-218,-110}, + {-216,-110},{-216,-101},{-142,-101}}, color={0,0,127})); + connect(extIndSig.u, VMinSet_flow) annotation (Line(points={{-242,-110},{-250, + -110},{-250,130},{-420,130}}, color={0,0,127})); + connect(extIndSig.index, sta.yAvaUp) annotation (Line(points={{-230,-122},{-230, + -154},{-280,-154},{-280,-203},{-288,-203}}, color={255,127,0})); + connect(cap.yMin, staDow.uCapMin) annotation (Line(points={{-248,-174},{-190,-174}, + {-190,-240},{-142,-240}}, color={0,0,127})); + connect(cap.yDowDes, staDow.uCapDowDes) annotation (Line(points={{-248,-170},{ + -192,-170},{-192,-243},{-142,-243}}, color={0,0,127})); + connect(staDow.uBypValPos, uBypValPos) annotation (Line(points={{-142,-246},{-172, + -246},{-172,90},{-420,90}}, color={0,0,127})); + connect(THotWatRetPri, staDow.TPriHotWatRet) annotation (Line(points={{-420,50}, + {-170,50},{-170,-252},{-142,-252}}, color={0,0,127})); + connect(THotWatRetSec, staDow.TSecHotWatRet) annotation (Line(points={{-420,10}, + {-168,10},{-168,-255},{-142,-255}}, color={0,0,127})); + connect(capReq1.y, staUp.uCapReq) annotation (Line(points={{-338,250},{-180,250}, + {-180,-89},{-142,-89}}, color={0,0,127})); + connect(sta.yAvaUp, staUp.uAvaUp) annotation (Line(points={{-288,-203},{-280,-203}, + {-280,-154},{-202,-154},{-202,-107},{-142,-107}}, color={255,127,0})); + connect(u, staDow.uCur) annotation (Line(points={{-420,-110},{-328,-110},{-328, + -228},{-142,-228}}, color={255,127,0})); + connect(cha.uAvaUp, sta.yAvaUp) annotation (Line(points={{-22,-168},{-60,-168}, + {-60,-203},{-288,-203}}, color={255,127,0})); + connect(cha.uAvaDow, sta.yAvaDow) annotation (Line(points={{-22,-172},{-56,-172}, + {-56,-206},{-288,-206}}, color={255,127,0})); + connect(staUp.yStaUp, cha.uUp) annotation (Line(points={{-118,-104},{-64,-104}, + {-64,-175},{-22,-175}}, color={255,0,255})); + connect(staDow.yStaDow, cha.uDow) annotation (Line(points={{-118,-240},{-64,-240}, + {-64,-178},{-22,-178}}, color={255,0,255})); + connect(uPumSpe, staDow.uPumSpe) annotation (Line(points={{-420,-30},{-198, + -30},{-198,-249},{-142,-249}}, + color={0,0,127})); + connect(conf.yTyp, staDow.uTyp) annotation (Line(points={{-338,-174},{-336,-174}, + {-336,-226},{-142,-226},{-142,-225}}, color={255,127,0})); + connect(uStaChaProEnd, staDow.uStaChaProEnd) annotation (Line(points={{-420,-260}, + {-150,-260},{-150,-222},{-142,-222}}, color={255,0,255})); + connect(uStaChaProEnd, cha.uStaChaProEnd) annotation (Line(points={{-420,-260}, + {-19,-260},{-19,-182}}, color={255,0,255})); + connect(cha.yChaEdg, yChaEdg) annotation (Line(points={{2,-172},{110,-172},{ + 110,-130},{140,-130}}, color={255,0,255})); + connect(cha.yChaUpEdg, yChaUpEdg) annotation (Line(points={{2,-168},{100,-168}, + {100,-70},{140,-70}}, color={255,0,255})); + connect(cha.yChaDowEdg, yChaDowEdg) annotation (Line(points={{2,-176},{100, + -176},{100,-190},{140,-190}}, color={255,0,255})); + connect(uStaChaProEnd, staUp.uStaChaProEnd) annotation (Line(points={{-420,-260}, + {-150,-260},{-150,-119},{-142,-119}}, color={255,0,255})); + connect(conf.yAva, cha.uStaAva) annotation (Line(points={{-338,-178},{-332, + -178},{-332,-280},{-30,-280},{-30,-162},{-22,-162}}, color={255,0,255})); + connect(conf.yTyp, yStaTyp) annotation (Line(points={{-338,-174},{-336,-174}, + {-336,60},{140,60}}, color={255,127,0})); + annotation (defaultComponentName = "staSetCon", + Icon(coordinateSystem(extent={{-100,-180},{100,180}}), + graphics={ + Rectangle( + extent={{-100,-180},{100,180}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-110,210},{110,172}}, + textColor={0,0,255}, + textString="%name")}), Diagram( + coordinateSystem(preserveAspectRatio=false, + extent={{-400,-300},{120,320}})), +Documentation(info=" +

+The sequence is a boiler stage status setpoint controller that outputs the +boiler stage integer index ySta, boiler stage change trigger signals +yChaEdg, yChaUpEdg, yChaDowEdg, and a boiler +status vector for the current stage yBoi. +

+

+Implemented according to ASHRAE RP-1711 March 2020 Draft, section 5.3.3.10. +

+

+The controller contains the following subsequences: +

+ +", +revisions=" + +")); +end SetpointController; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/BoilerIndices.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/BoilerIndices.mo new file mode 100644 index 00000000000..1636ffe00e8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/BoilerIndices.mo @@ -0,0 +1,145 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block BoilerIndices + "Returns boiler indices for the current stage" + + parameter Integer nSta = 5 + "Number of stages"; + + parameter Integer nBoi = 3 + "Number of boilers"; + + parameter Integer staMat[nSta, nBoi] = {{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}} + "Staging matrix with stages in rows and boilers in columns"; + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta, + final start=0) + "Current boiler stage" + annotation (Placement(transformation(extent={{-240,0},{-200,40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoi[nBoi] + "Boiler status setpoint vector for the current stage" + annotation (Placement(transformation(extent={{200,-20},{240,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, nBoi] = {j for i in 1:nBoi, 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={{-180,10},{-160,30}}))); + + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep1[nSta]( + final nout=fill(nBoi, nSta)) + "Replicates signal to dimensions of the staging matrix" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staIndMatr[nSta,nBoi]( + final k=staIndMat) + "Matrix with stage index in each column" + annotation (Placement(transformation(extent={{-140,-40},{-120,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nSta,nBoi] + "Outputs a zero matrix populated with ones in the current stage index row" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant boiStaMatr[nSta,nBoi]( + final k=staMat) + "Staging matrix" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixMax matMax( + final nRow=nSta, + final nCol=nBoi, + final rowMax=false) + "Column-wise matrix maximum" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold boiInSta[nBoi]( + final t=fill(0.5, nBoi)) + "Identifies boilers designated to operate in a given stage" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt[nSta,nBoi] + "Outputs a zero matrix populated with ones for any available boiler in the current stage" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nSta,nBoi]( + final integerTrue=fill(1,nSta,nBoi), + final integerFalse=fill(0,nSta,nBoi)) + "Type converter" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta,nBoi] + "Type converter" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + +equation + connect(intRep.y, intRep1.u) + annotation (Line(points={{-158,20},{-142,20}}, color={255,127,0})); + connect(intRep1.y, intEqu1.u1) + annotation (Line(points={{-118,20},{-82,20}}, color={255,127,0})); + connect(matMax.y,boiInSta. u) + annotation (Line(points={{122,0},{138,0}}, color={0,0,127})); + connect(staIndMatr.y, intEqu1.u2) annotation (Line(points={{-118,-30},{-100,-30}, + {-100,12},{-82,12}}, color={255,127,0})); + connect(boiInSta.y, yBoi) + annotation (Line(points={{162,0},{220,0}}, + color={255,0,255})); + connect(proInt.y, intToRea.u) + annotation (Line(points={{42,0},{58,0}}, color={255,127,0})); + connect(intToRea.y, matMax.u) + annotation (Line(points={{82,0},{98,0}}, color={0,0,127})); + connect(booToInt.y, proInt.u1) annotation (Line(points={{-18,20},{0,20},{0,6}, + {18,6}}, color={255,127,0})); + connect(intEqu1.y, booToInt.u) + annotation (Line(points={{-58,20},{-42,20}}, color={255,0,255})); + connect(boiStaMatr.y, proInt.u2) annotation (Line(points={{-38,-30},{0,-30},{0, + -6},{18,-6}}, color={255,127,0})); + connect(u, intRep.u) annotation (Line(points={{-220,20},{-182,20}}, + color={255,127,0})); + + annotation (defaultComponentName = "boiInd", + 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,-60},{200,60}})), +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 boilers and stages provided by the +user. +

+

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

+", +revisions=" + +")); +end BoilerIndices; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Capacities.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Capacities.mo new file mode 100644 index 00000000000..090ff09856b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Capacities.mo @@ -0,0 +1,276 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block Capacities + "Returns design and minimal stage capacities for current and next available higher and lower stage" + + parameter Integer nSta = 5 + "Total number of stages"; + + 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,-140},{-200,-100}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput u( + final min=0, + final max=nSta) + "Boiler plant 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,-20},{-200,20}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uDesCap[nSta]( + final quantity=fill("Power", 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("Power", 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="Power") + "Design capacity of the current stage" + annotation (Placement(transformation(extent={{200,130},{240,170}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDowDes( + final unit="W", + final quantity="Power") + "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="Power") + "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="Power") + "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="Power") + "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={{-100,140},{-80,160}}))); + + 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={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor upCapMin( + final nin=nSta) + "Extracts minimal capacity of the next higher stage" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor upCap( + final nin=nSta) + "Extracts the design capacity of the next stage" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor capMin( + final nin=nSta) + "Extracts the minimum capacity of the current stage" + annotation (Placement(transformation(extent={{0,-80},{20,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 + "Switch" + annotation (Placement(transformation(extent={{160,50},{180,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi4 + "Switch" + annotation (Placement(transformation(extent={{160,-100},{180,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + "Outputs minimum current stage capacity as design stage down capacity if + operating in the lowest available stage" + annotation (Placement(transformation(extent={{100,10},{120,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.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={{-60,110},{-40,130}}))); + +equation + connect(swi2.y, yUpDes) annotation (Line(points={{182,60},{220,60}}, color={0,0,127})); + connect(upCap.y, swi2.u3) annotation ( + Line(points={{22,80},{80,80},{80,52},{158,52}}, color={0,0,127})); + connect(yMin, yMin) + annotation (Line(points={{220,-20},{220,-20}}, color={0,0,127})); + connect(upCapMin.y, swi4.u3) annotation (Line(points={{22,-30},{40,-30},{40,-98}, + {158,-98}}, color={0,0,127})); + connect(swi4.y, yUpMin) annotation (Line(points={{182,-90},{220,-90}}, color={0,0,127})); + connect(capMin.y, yMin) annotation (Line(points={{22,-70},{80,-70},{80,-20},{220, + -20}}, color={0,0,127})); + connect(dowCap.y, swi1.u3) annotation (Line(points={{-78,80},{-40,80},{-40,12}, + {98,12}}, color={0,0,127})); + connect(uMinCap, upCapMin.u) annotation (Line(points={{-220,-180},{-120,-180}, + {-120,-30},{-2,-30}}, color={0,0,127})); + connect(uMinCap, capMin.u) annotation (Line(points={{-220,-180},{-120,-180},{-120, + -70},{-2,-70}}, color={0,0,127})); + connect(uDesCap, cap.u) annotation (Line(points={{-220,180},{-120,180},{-120,150}, + {-102,150}}, color={0,0,127})); + connect(uDesCap, dowCap.u) annotation (Line(points={{-220,180},{-140,180},{-140, + 80},{-102,80}}, color={0,0,127})); + connect(uDesCap, upCap.u) annotation (Line(points={{-220,180},{-20,180},{-20,80}, + {-2,80}}, color={0,0,127})); + connect(uLow, swi1.u2) annotation (Line(points={{-220,-60},{-140,-60},{-140,20}, + {98,20}}, color={255,0,255})); + connect(uHig, swi2.u2) annotation (Line(points={{-220,-120},{140,-120},{140,60}, + {158,60}}, color={255,0,255})); + connect(uHig, swi4.u2) annotation (Line(points={{-220,-120},{140,-120},{140,-90}, + {158,-90}}, color={255,0,255})); + connect(cap.y, gai.u) annotation (Line(points={{-78,150},{-70,150},{-70,120},{ + -62,120}}, color={0,0,127})); + connect(gai.y, swi2.u1) annotation (Line(points={{-38,120},{100,120},{100,68}, + {158,68}}, color={0,0,127})); + connect(gai.y, swi4.u1) annotation (Line(points={{-38,120},{60,120},{60,-82},{ + 158,-82}}, color={0,0,127})); + connect(swi1.y, yDowDes) annotation (Line(points={{122,20},{220,20}}, color={0,0,127})); + connect(u, cap.index) annotation (Line(points={{-220,120},{-90,120},{-90,138}}, + color={255,127,0})); + connect(uDown, dowCap.index) annotation (Line(points={{-220,0},{-90,0},{-90,68}}, + color={255,127,0})); + connect(uUp, upCap.index) annotation (Line(points={{-220,60},{10,60},{10,68}}, + color={255,127,0})); + connect(uUp, upCapMin.index) annotation (Line(points={{-220,60},{-60,60},{-60, + -50},{10,-50},{10,-42}}, color={255,127,0})); + connect(cap.y, yDes) annotation (Line(points={{-78,150},{220,150}}, + color={0,0,127})); + connect(capMin.y, swi1.u1) annotation (Line(points={{22,-70},{80,-70},{80,28}, + {98,28}},color={0,0,127})); + connect(u, capMin.index) annotation (Line(points={{-220,120},{-160,120},{-160, + -90},{10,-90},{10,-82}}, color={255,127,0})); + connect(yUpMin, yUpMin) + annotation (Line(points={{220,-90},{220,-90}}, color={0,0,127})); + +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 1711 as it provides +a side calculation pertaining to generalization of the staging +sequences for any number of boilers 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 calculations involved in staging the plant up and down. +

+

+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/BoilerPlant/Staging/SetPoints/Subsequences/CapacityRequirement.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/CapacityRequirement.mo new file mode 100644 index 00000000000..d0fde9fb7ce --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/CapacityRequirement.mo @@ -0,0 +1,171 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block CapacityRequirement + "Heating capacity requirement" + + parameter Real avePer( + final unit="s", + final displayUnit="s", + final quantity="Time") = 300 + "Time period for the rolling average"; + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupSet( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-160,50},{-120,90}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TRet( + final unit="K", + final displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water return temperature" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final quantity="VolumeFlowRate", + final unit="m3/s", + final displayUnit="m3/s") + "Measured hot water flow rate" + annotation (Placement(transformation(extent={{-160,-90},{-120,-50}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput y( + final quantity="Power", + final unit="W", + final displayUnit="W") + "Hot water heating capacity requirement" + annotation (Placement(transformation(extent={{120,-20},{160,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + constant Real rhoWat( + final unit="kg/m3", + final quantity="Density") = 1000 + "Water density"; + + constant Real cpWat( + final unit="J/(kg.K)", + final quantity="SpecificHeatCapacity") = 4184 + "Specific heat capacity of water"; + + Buildings.Controls.OBC.CDL.Continuous.Max max + "Ensure negative heating requirement calculation is not passed downstream" + annotation (Placement(transformation(extent={{90,-10},{110,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=0) + "Lowest allowed heating requirement" + annotation (Placement(transformation(extent={{60,24},{80,44}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant density( + final k=rhoWat) + "Water density" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant speHeaCap( + final k=cpWat) + "Specific heat capacity of water" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Difference between supply temperature setpoint and return temperature" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.MovingAverage movMea( + final delta=avePer) + "Moving average" + annotation (Placement(transformation(extent={{60,-16},{80,4}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro + "Product" + annotation (Placement(transformation(extent={{20,-16},{40,4}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1 + "Product" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro2 + "Product" + annotation (Placement(transformation(extent={{-20,-22},{0,-2}}))); + +equation + connect(TRet,sub2. u2) + annotation (Line(points={{-140,0},{-110,0},{-110,34},{-102,34}}, + color={0,0,127})); + connect(sub2.u1, TSupSet) + annotation (Line(points={{-102,46},{-110,46},{-110,70},{-140,70}}, + color={0,0,127})); + connect(sub2.y, pro.u1) + annotation (Line(points={{-78,40},{10,40},{10,0},{18,0}}, + color={0,0,127})); + connect(pro.y, movMea.u) + annotation (Line(points={{42,-6},{58,-6}}, + color={0,0,127})); + connect(speHeaCap.y, pro1.u2) + annotation (Line(points={{-78,-70},{-70,-70},{-70,-56},{-62,-56}}, + color={0,0,127})); + connect(pro1.y, pro2.u2) + annotation (Line(points={{-38,-50},{-30,-50},{-30,-18},{-22,-18}}, + color={0,0,127})); + connect(pro.u2, pro2.y) + annotation (Line(points={{18,-12},{2,-12}}, + color={0,0,127})); + connect(pro1.u1, density.y) + annotation (Line(points={{-62,-44},{-70,-44},{-70,-30},{-78,-30}}, + color={0,0,127})); + connect(VHotWat_flow, pro2.u1) + annotation (Line(points={{-140,-70},{-110,-70},{-110,-6},{-22,-6}}, + color={0,0,127})); + connect(movMea.y, max.u2) + annotation (Line(points={{82,-6},{88,-6}}, + color={0,0,127})); + connect(con.y, max.u1) + annotation (Line(points={{82,34},{86,34},{86,6},{88,6}}, + color={0,0,127})); + connect(max.y, y) + annotation (Line(points={{112,0},{140,0}}, + color={0,0,127})); + + annotation (defaultComponentName = "capReq", + 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={{-62,88},{60,-76}}, + textColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + textString="Load")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-120,-100},{120,100}})), + Documentation(info=" +

+ Calculates heating capacity requirement based on the measured hot water return + temperature, TRet, calculated hot water supply temperature + setpoint TSupSet, and the measured hot water flow rate, + VHotWat_flow. +
+ The calculation is according to section 5.3.3.5 and 5.3.3.6. in RP-1711, March + 2020 draft. +

+ ", + revisions=" + + ")); +end CapacityRequirement; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Change.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Change.mo new file mode 100644 index 00000000000..d45a910c913 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Change.mo @@ -0,0 +1,443 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block Change + "Calculates the boiler stage signal" + + parameter Integer nSta = 5 + "Number of boiler stages"; + + parameter Real delStaCha( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Hold period for each stage change"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaAva[nSta] + "Stage availability vector" + annotation (Placement(transformation(extent={{-480,250},{-440,290}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal indicating end of stage change process" + annotation (Placement(transformation(extent={{-480,-260},{-440,-220}}), + iconTransformation(extent={{-140,70},{-100,110}}, + rotation=90))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-480,140},{-440,180}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uUp + "Stage up signal" + annotation (Placement(transformation(extent={{-480,-60},{-440,-20}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uDow + "Stage down signal" + annotation (Placement(transformation(extent={{-480,-160},{-440,-120}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAvaUp( + final min=0, + final max=nSta) + "Next available stage up" + annotation (Placement(transformation(extent={{-480,80},{-440,120}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAvaDow( + final min=0, + final max=nSta) + "Next available stage down" + annotation (Placement(transformation(extent={{-480,0},{-440,40}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaEdg + "Boiler stage change edge signal" + annotation (Placement(transformation(extent={{440,-20},{480,20}}), + iconTransformation(extent={{100,-40},{140,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaDowEdg + "Boiler stage change lower edge signal" + annotation (Placement(transformation(extent={{440,-90},{480,-50}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChaUpEdg + "Boiler stage change higher edge signal" + annotation (Placement(transformation(extent={{440,70},{480,110}}), + iconTransformation(extent={{100,0},{140,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput ySta( + final min=0, + final max=nSta) + "Boiler stage integer setpoint" + annotation (Placement(transformation(extent={{440,130},{480,170}}), + iconTransformation(extent={{100,40},{140,80}}))); + +protected + parameter Integer staInd[nSta]={i for i in 1:nSta} + "Stage index vector"; + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con(final k=0) + "Zero boiler stage" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 + "Logical or" + annotation (Placement(transformation(extent={{-380,-90},{-360,-70}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam( + final y_start=0) + "Triggered sampler" + annotation (Placement(transformation(extent={{130,140},{150,160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch switch1 + "Switch" + annotation (Placement(transformation(extent={{-200,50},{-180,70}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Type converter" + annotation (Placement(transformation(extent={{-320,10},{-300,30}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Type converter" + annotation (Placement(transformation(extent={{360,140},{380,160}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Type converter" + annotation (Placement(transformation(extent={{-320,90},{-300,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Latch" + annotation (Placement(transformation(extent={{-320,50},{-300,70}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold holIniSta( + final trueHoldDuration=delStaCha, + final falseHoldDuration=0) + "Holds stage switched to initial upon plant start" + annotation (Placement(transformation(extent={{-320,150},{-300,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch switch2 + "Switch" + annotation (Placement(transformation(extent={{40,140},{60,160}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam1 + "Triggered sampler" + annotation (Placement(transformation(extent={{240,0},{260,20}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea + "Boolean to Real conversion" + annotation (Placement(transformation(extent={{200,0},{220,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr1( + final t=0.5) + "Check if plant is still enabled" + annotation (Placement(transformation(extent={{280,0},{300,20}}))); + + 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={{-80,140},{-60,160}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Logical And" + annotation (Placement(transformation(extent={{280,60},{300,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Detects plant start" + annotation (Placement(transformation(extent={{-380,150},{-360,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical not" + annotation (Placement(transformation(extent={{-280,150},{-260,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or3 + "Logical or" + annotation (Placement(transformation(extent={{220,-60},{240,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Detects plant disable" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staChaHol3( + final trueHoldDuration=delStaCha, + final falseHoldDuration=0) + "Stage change hold" + annotation (Placement(transformation(extent={{360,-120},{380,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{400,-120},{420,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Previous value" + annotation (Placement(transformation(extent={{320,-120},{340,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd( + final nin=4) + "Ensure all conditions for stage change are satisfied" + annotation (Placement(transformation(extent={{-160,-90},{-140,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Latch" + annotation (Placement(transformation(extent={{-280,-190},{-260,-170}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha + "Integer change" + annotation (Placement(transformation(extent={{340,-10},{360,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 + "Trigger stage number sampler when plant is turned on or when staging conditions are met" + annotation (Placement(transformation(extent={{100,100},{120,120}}))); + + Buildings.Controls.OBC.CDL.Logical.And and5 + "Ensure stage change signal is passed through only when the plant is enabled" + annotation (Placement(transformation(extent={{-320,-90},{-300,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Change cha1 + "Detect change in boiler plant enable status" + annotation (Placement(transformation(extent={{-120,120},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Logical pre block" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Edge detector" + annotation (Placement(transformation(extent={{60,-90},{80,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch switch3 + "Switch" + annotation (Placement(transformation(extent={{-40,100},{-20,120}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nSta] + "Boolean to Integer conversion" + annotation (Placement(transformation(extent={{-420,260},{-400,280}}))); + + Buildings.Controls.OBC.CDL.Integers.Multiply proInt[nSta] + "Element-wise products" + annotation (Placement(transformation(extent={{-360,240},{-340,260}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nSta]( + final k=staInd) + "Vector of stage indices" + annotation (Placement(transformation(extent={{-420,220},{-400,240}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea2[nSta] + "Integer to Real conversion" + annotation (Placement(transformation(extent={{-320,240},{-300,260}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMin mulMin( + final nin=nSta) + "Find lowest available stage" + annotation (Placement(transformation(extent={{-280,240},{-260,260}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or4 + "Logical Or" + annotation (Placement(transformation(extent={{-340,-190},{-320,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Logical Not" + annotation (Placement(transformation(extent={{-380,-190},{-360,-170}}))); + +equation + connect(reaToInt.y,ySta) + annotation (Line(points={{382,150},{460,150}}, color={255,127,0})); + connect(intToRea1.y,switch1. u1) annotation (Line(points={{-298,100},{-220,100}, + {-220,68},{-202,68}}, color={0,0,127})); + connect(intToRea.y,switch1. u3) annotation (Line(points={{-298,20},{-220,20},{ + -220,52},{-202,52}}, color={0,0,127})); + connect(edg.y,holIniSta. u) + annotation (Line(points={{-358,160},{-322,160}}, + color={255,0,255})); + connect(triSam1.u,booToRea. y) + annotation (Line(points={{238,10},{222,10}}, color={0,0,127})); + connect(triSam1.y,greThr1. u) + annotation (Line(points={{262,10},{278,10}}, color={0,0,127})); + connect(greThr1.y,and3. u2) annotation (Line(points={{302,10},{320,10},{320,40}, + {260,40},{260,62},{278,62}}, color={255,0,255})); + connect(uUp, lat.u) annotation (Line(points={{-460,-40},{-380,-40},{-380,60},{ + -322,60}}, color={255,0,255})); + connect(uDow, lat.clr) annotation (Line(points={{-460,-140},{-340,-140},{-340, + 54},{-322,54}}, color={255,0,255})); + connect(uUp, or2.u1) annotation (Line(points={{-460,-40},{-400,-40},{-400,-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,100},{-322,100}}, color={255,127,0})); + connect(uAvaDow, intToRea.u) + annotation (Line(points={{-460,20},{-322,20}}, color={255,127,0})); + connect(holIniSta.y, not3.u) annotation (Line(points={{-298,160},{-282,160}}, + color={255,0,255})); + connect(uPla, booToRea.u) annotation (Line(points={{-460,160},{-388,160},{-388, + 130},{-160,130},{-160,10},{198,10}}, color={255,0,255})); + connect(or3.y, triSam1.trigger) annotation (Line(points={{242,-50},{250,-50},{ + 250,-2}}, color={255,0,255})); + connect(uPla, falEdg.u) annotation (Line(points={{-460,160},{-388,160},{-388,130}, + {-160,130},{-160,-30},{-62,-30}}, + color={255,0,255})); + connect(falEdg.y, or3.u1) annotation (Line(points={{-38,-30},{210,-30},{210,-50}, + {218,-50}}, color={255,0,255})); + connect(uPla, edg.u) + annotation (Line(points={{-460,160},{-382,160}}, color={255,0,255})); + connect(lat.y, switch1.u2) + annotation (Line(points={{-298,60},{-202,60}}, color={255,0,255})); + connect(staChaHol3.y, not1.u) + annotation (Line(points={{382,-110},{398,-110}}, color={255,0,255})); + connect(lat1.y, switch2.u2) + annotation (Line(points={{-58,150},{38,150}}, color={255,0,255})); + connect(switch2.y, triSam.u) + annotation (Line(points={{62,150},{128,150}}, color={0,0,127})); + connect(triSam.y, reaToInt.u) + annotation (Line(points={{152,150},{358,150}}, color={0,0,127})); + connect(switch1.y, switch2.u1) annotation (Line(points={{-178,60},{-140,60},{-140, + 180},{0,180},{0,158},{38,158}}, color={0,0,127})); + connect(and3.y, lat1.u) annotation (Line(points={{302,70},{320,70},{320,220},{ + -120,220},{-120,150},{-82,150}}, color={255,0,255})); + connect(not3.y, mulAnd.u[1]) annotation (Line(points={{-258,160},{-240,160},{ + -240,-74.75},{-162,-74.75}}, + color={255,0,255})); + connect(mulAnd.y, and3.u1) annotation (Line(points={{-138,-80},{40,-80},{40, + 70},{278,70}}, color={255,0,255})); + connect(pre1.y, staChaHol3.u) + annotation (Line(points={{342,-110},{358,-110}}, color={255,0,255})); + connect(not1.y, mulAnd.u[2]) annotation (Line(points={{422,-110},{430,-110},{ + 430,-140},{-200,-140},{-200,-78.25},{-162,-78.25}}, + color={255,0,255})); + connect(lat2.y, mulAnd.u[3]) annotation (Line(points={{-258,-180},{-166,-180}, + {-166,-81.75},{-162,-81.75}}, color={255,0,255})); + connect(pre1.y, lat2.clr) annotation (Line(points={{342,-110},{350,-110},{350, + -200},{-290,-200},{-290,-186},{-282,-186}}, color={255,0,255})); + connect(reaToInt.y, cha.u) annotation (Line(points={{382,150},{400,150},{400,130}, + {330,130},{330,0},{338,0}}, color={255,127,0})); + connect(or1.y, triSam.trigger) annotation (Line(points={{122,110},{140,110},{140, + 138}}, color={255,0,255})); + connect(or2.y, and5.u1) + annotation (Line(points={{-358,-80},{-322,-80}}, color={255,0,255})); + connect(and5.y, mulAnd.u[4]) annotation (Line(points={{-298,-80},{-230,-80},{ + -230,-85.25},{-162,-85.25}}, color={255,0,255})); + connect(uPla, and5.u2) annotation (Line(points={{-460,160},{-388,160},{-388, + -20},{-328,-20},{-328,-88},{-322,-88}}, color={255,0,255})); + connect(uPla, cha1.u) annotation (Line(points={{-460,160},{-388,160},{-388,130}, + {-122,130}}, color={255,0,255})); + connect(cha1.y, lat1.clr) annotation (Line(points={{-98,130},{-90,130},{-90,144}, + {-82,144}}, color={255,0,255})); + connect(cha1.y, pre2.u) annotation (Line(points={{-98,130},{-90,130},{-90,30}, + {-82,30}}, color={255,0,255})); + connect(pre2.y, or1.u1) annotation (Line(points={{-58,30},{20,30},{20,110},{ + 98,110}}, color={255,0,255})); + connect(mulAnd.y, edg1.u) + annotation (Line(points={{-138,-80},{58,-80}}, color={255,0,255})); + connect(edg1.y, or1.u2) annotation (Line(points={{82,-80},{92,-80},{92,102},{ + 98,102}}, color={255,0,255})); + connect(edg1.y, or3.u2) annotation (Line(points={{82,-80},{120,-80},{120,-58}, + {218,-58}}, color={255,0,255})); + connect(con.y, switch3.u3) annotation (Line(points={{-58,70},{-50,70},{-50, + 102},{-42,102}}, color={0,0,127})); + connect(switch3.y, switch2.u3) annotation (Line(points={{-18,110},{0,110},{0, + 142},{38,142}}, color={0,0,127})); + connect(uStaAva, booToInt.u) + annotation (Line(points={{-460,270},{-422,270}}, color={255,0,255})); + connect(booToInt.y, proInt.u1) annotation (Line(points={{-398,270},{-380,270}, + {-380,256},{-362,256}}, color={255,127,0})); + connect(conInt.y, proInt.u2) annotation (Line(points={{-398,230},{-380,230},{-380, + 244},{-362,244}}, color={255,127,0})); + connect(proInt.y, intToRea2.u) + annotation (Line(points={{-338,250},{-322,250}}, color={255,127,0})); + connect(mulMin.u[1:nSta], intToRea2.y) annotation (Line(points={{-282,250},{-290, + 250},{-290,250},{-298,250}}, color={0,0,127})); + connect(mulMin.y, switch3.u1) annotation (Line(points={{-258,250},{-150,250},{ + -150,100},{-68,100},{-68,118},{-42,118}}, color={0,0,127})); + connect(uPla, switch3.u2) annotation (Line(points={{-460,160},{-388,160},{-388, + 130},{-160,130},{-160,110},{-42,110}}, color={255,0,255})); + connect(cha.up, yChaUpEdg) annotation (Line(points={{362,6},{380,6},{380,92}, + {460,92},{460,90}}, color={255,0,255})); + connect(cha.y, yChaEdg) annotation (Line(points={{362,0},{404,0},{404,0},{460, + 0}}, color={255,0,255})); + connect(cha.down, yChaDowEdg) annotation (Line(points={{362,-6},{380,-6},{380, + -70},{460,-70}}, color={255,0,255})); + connect(cha.y, pre1.u) annotation (Line(points={{362,0},{370,0},{370,-80},{ + 310,-80},{310,-110},{318,-110}}, color={255,0,255})); + connect(or4.y, lat2.u) + annotation (Line(points={{-318,-180},{-282,-180}}, color={255,0,255})); + connect(not2.y, or4.u1) + annotation (Line(points={{-358,-180},{-342,-180}}, color={255,0,255})); + connect(uPla, not2.u) annotation (Line(points={{-460,160},{-388,160},{-388,-180}, + {-382,-180}}, color={255,0,255})); + connect(uStaChaProEnd, or4.u2) annotation (Line(points={{-460,-240},{-350,-240}, + {-350,-188},{-342,-188}}, 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 1711 as it provides a side + calculation pertaining to generalization of the staging sequences for any + number of boilers and stages provided by the user. +

+

This subsequence is used to generate the boiler stage setpoint + ySta and a boolean vector of + boiler 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 delStaCha + multiple consecutive stage change signals are issued. +

+

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

+

+ Per 1711 March 2020 Draft 5.3.3.10.1, each stage shall have a minimum + runtime of delStaCha. +

+ ", + revisions=" + + ")); +end Change; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Configurator.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Configurator.mo new file mode 100644 index 00000000000..ad152f238af --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Configurator.mo @@ -0,0 +1,370 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block Configurator "Configures boiler staging" + + parameter Integer nSta = 5 + "Number of boiler stages"; + + parameter Integer nBoi = 3 + "Number of boilers"; + + parameter Integer boiTyp[nBoi]={ + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler} + "Boiler type. Recommended staging order: 1. condensing boilers, 2. non-codensing boilers"; + + parameter Integer staMat[nSta, nBoi] = {{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}} + "Staging matrix with stage as row index and boiler as column index"; + + parameter Real boiDesCap[nBoi]( + final unit="W", + displayUnit="W", + final quantity="Power") + "Design boiler capacities vector"; + + parameter Real boiFirMin[nBoi]( + final unit="1", + displayUnit="1") + "Boiler minimum firing ratios vector"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiAva[nBoi] + "Boiler availability status vector" + 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)) + "Boiler stage types vector" + annotation (Placement(transformation(extent={{220,-140},{260,-100}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCapDes[nSta]( + final unit=fill("W", nSta), + final quantity=fill("Power", 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 yCapMin[nSta]( + final unit=fill("W", nSta), + final quantity=fill("Power", nSta)) + "Minimum stage capacities vector" + annotation (Placement(transformation(extent={{220,-40},{260,0}}), + iconTransformation(extent={{100,20},{140,60}}))); + + Buildings.Controls.OBC.CDL.Utilities.Assert assMes1( + final message="The boilers must be tagged in order of design capacity if unequally sized") + "Asserts whether boilers are tagged in ascending order with regards to capacity" + annotation (Placement(transformation(extent={{60,150},{80,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1[nBoi] + "Subtracts signals" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMax multiMax( + nin=nBoi) + "Maximum value in a vector input" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Abs abs + "Absolute values" + annotation (Placement(transformation(extent={{-20,150},{0,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesThr1( + final t=0.5) + "Less threshold" + annotation (Placement(transformation(extent={{20,150},{40,170}}))); + +protected + final parameter Integer boiTypMat[nSta, nBoi] = {boiTyp[i] for i in 1:nBoi, j in 1:nSta} + "Boiler type array expanded to allow for element-wise multiplication with the + staging matrix"; + + final parameter Real boiFirMinVal[nSta, nBoi] = {boiFirMin[i] for i in 1:nBoi, j in 1:nSta} + "Boiler minimum firing ratio array expanded for element-wise multiplication + with the staging matrix"; + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant boiDesCaps[nBoi]( + final k=boiDesCap) + "Design boiler capacities vector" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant boiFirMinMat[nSta,nBoi]( + final k=boiFirMinVal) + "Boiler minimum firing ratios matrix" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixGain staDesCaps( + final K=staMat) + "Matrix gain for design capacities" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixGain sumNumBoi( + final K=staMat) + "Outputs the total boiler count per stage vector" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixGain sumNumAvaBoi( + final K=staMat) + "Outputs the available boiler count per stage vector" + annotation (Placement(transformation(extent={{-140,-50},{-120,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant oneVec[nBoi]( + final k=fill(1, nBoi)) + "Mocks a case with all boilers available" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nBoi] + "Type converter" + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2[nSta] + "Subtracts count of available boilers from the design count, at each stage" + annotation (Placement(transformation(extent={{-80,-20},{-60,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesThr[nSta]( + final t=fill(0.5, nSta)) + "Checks if the count of available boilers in each stage equals the design count" + annotation (Placement(transformation(extent={{-40,-20},{-20,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant boiStaMat[nSta,nBoi]( + final k=staMat) + "Staging matrix" + annotation (Placement(transformation(extent={{-200,-100},{-180,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staType[nSta,nBoi]( + final k=boiTypMat) + "Boiler stage type matrix" + annotation (Placement(transformation(extent={{-200,-160},{-180,-140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[nSta,nBoi] + "Element-wise product" + annotation (Placement(transformation(extent={{-140,-130},{-120,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixMax matMax( + final nRow=nSta, + final nCol=nBoi) + "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.Continuous.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="The boilers are not being staged in an order + recommended by ASHRAE RP1711 or Guideline 36. + Please make sure to follow the recommendation that is: + any condensing boilers first, any non-condensing boilers last.") + "Asserts warning if boilers are not staged in recommended order by type" + 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}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[nSta,nBoi] + "Element-wise product" + annotation (Placement(transformation(extent={{-160,60},{-140,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixMax matMax1( + final rowMax=true, + final nRow=nSta, + final nCol=nBoi) + "Find highest BFirMin in each stage" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro2[nSta] + "Product" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sort sort1( + final nin=nBoi) + "Sort values" + annotation (Placement(transformation(extent={{-140,160},{-120,180}}))); + +equation + connect(boiDesCaps.y, staDesCaps.u) + annotation (Line(points={{-178,110},{-142,110}}, + color={0,0,127})); + connect(uBoiAva, booToRea.u) + annotation (Line(points={{-240,-40},{-202,-40}}, + color={255,0,255})); + connect(booToRea.y,sumNumAvaBoi. u) + annotation (Line(points={{-178,-40},{-142,-40}}, + color={0,0,127})); + connect(sumNumBoi.y,sub2. u1) + annotation (Line(points={{-118,20},{-100,20},{-100,-4},{-82,-4}}, + color={0,0,127})); + connect(sumNumAvaBoi.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(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(staDesCaps.y,yCapDes) + annotation (Line(points={{-118,110},{100,110},{100,20},{240,20}}, + color={0,0,127})); + connect(oneVec.y,sumNumBoi. u) + annotation (Line(points={{-178,20},{-142,20}}, + color={0,0,127})); + connect(boiStaMat.y, pro.u1) + annotation (Line(points={{-178,-90},{-160,-90},{-160,-114},{-142,-114}}, + color={0,0,127})); + connect(staType.y, pro.u2) + annotation (Line(points={{-178,-150},{-160,-150},{-160,-126},{-142,-126}}, + color={0,0,127})); + connect(boiFirMinMat.y, pro1.u1) + annotation (Line(points={{-178,70},{-170,70},{-170,76},{-162,76}}, + color={0,0,127})); + connect(pro1.u2, boiStaMat.y) + annotation (Line(points={{-162,64},{-170,64},{-170,-90},{-178,-90}}, + color={0,0,127})); + connect(pro1.y, matMax1.u) + annotation (Line(points={{-138,70},{-122,70}}, + color={0,0,127})); + connect(matMax1.y, pro2.u2) + annotation (Line(points={{-98,70},{-90,70},{-90,64},{-82,64}}, + color={0,0,127})); + connect(staDesCaps.y, pro2.u1) + annotation (Line(points={{-118,110},{-90,110},{-90,76},{-82,76}}, + color={0,0,127})); + connect(pro2.y,yCapMin) + annotation (Line(points={{-58,70},{80,70},{80,-20},{240,-20}}, + color={0,0,127})); + + connect(boiDesCaps.y,sub1. u2) annotation (Line(points={{-178,110},{-160,110}, + {-160,154},{-102,154}}, color={0,0,127})); + connect(sort1.y,sub1. u1) annotation (Line(points={{-118,170},{-110,170}, + {-110,166},{-102,166}}, color={0,0,127})); + connect(sub1.y, multiMax.u) annotation (Line(points={{-78,160},{-70,160}, + {-70,160},{-62,160}}, color={0,0,127})); + connect(multiMax.y, abs.u) + annotation (Line(points={{-38,160},{-22,160}}, color={0,0,127})); + connect(abs.y, lesThr1.u) + annotation (Line(points={{2,160},{18,160}}, color={0,0,127})); + connect(lesThr1.y, assMes1.u) + annotation (Line(points={{42,160},{58,160}}, color={255,0,255})); + connect(sort1.u, boiDesCaps.y) annotation (Line(points={{-142,170},{-160, + 170},{-160,110},{-178,110}}, color={0,0,127})); + 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 1711 as it provides + a side calculation pertaining to generalization of the staging + sequences for any number of boilers 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/BoilerPlant/Staging/SetPoints/Subsequences/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Down.mo new file mode 100644 index 00000000000..4e02a279727 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Down.mo @@ -0,0 +1,672 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block Down + "Generates a stage down signal" + + parameter Boolean have_priOnl = false + "Is the boiler plant a primary-only, condensing boiler plant?"; + + parameter Integer nSta = 5 + "Number of stages"; + + parameter Real fraMinFir( + final unit="1", + displayUnit="1", + final min=0) = 1.10 + "Fraction of boiler minimum firing ratio that required capacity needs to be + for minimum firing ratio condition" + annotation(Dialog(group="Minimum firing rate condition parameters")); + + parameter Real delMinFir( + final unit="s", + displayUnit="s", + final quantity="Time")= 300 + "Delay for staging based on minimum firing rate of current stage" + annotation(Dialog(group="Minimum firing rate condition parameters")); + + parameter Real fraDesCap( + final unit="1", + displayUnit="1", + final min=0, + final max=1) = 0.80 + "Fraction of design capacity of next lower stage that heating capacity needs + to be for lower design capacity ratio condition" + annotation(Dialog(group="Stage design capacity condition parameters")); + + parameter Real delDesCapNonConBoi( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Enable delay for lower stage design capacity ratio condition for non-condensing boilers" + annotation(Evaluate=true,Dialog(enable=not + (have_priOnl), group="Stage design capacity condition parameters")); + + parameter Real delDesCapConBoi( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for lower stage design capacity ratio condition for condensing boilers" + annotation(Dialog(group="Stage design capacity condition parameters")); + + parameter Real sigDif( + final unit="1", + displayUnit="1", + final min=0) = 0.01 + "Hysteresis deadband normalized signals" + annotation(Dialog(tab="Advanced")); + + parameter Real delBypVal( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for bypass valve position condition" + annotation ( + Evaluate=true, + Dialog( + enable=have_priOnl, + group="Bypass valve condition parameters")); + + parameter Real bypValClo = 0 + "Adjustment for signal received when bypass valve is closed" + annotation ( + Evaluate=true, + Dialog( + enable=have_priOnl, + tab="Advanced")); + + parameter Real TCirDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 3 + "Required return water temperature difference between the primary and + secondary circuits for staging down" + annotation ( + Evaluate=true, + Dialog( + enable=not + (have_priOnl), + group="Return temperature condition parameters")); + + parameter Real delTRetDif( + final unit="s", + displayUnit="s", + final quantity="Time") = 300 + "Enable delay for measured hot water return temperature difference condition" + annotation ( + Evaluate=true, + Dialog( + enable=not + (have_priOnl), + group="Return temperature condition parameters")); + + parameter Real dTemp( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 0.1 + "Hysteresis deadband for measured temperatures" + annotation(Dialog(tab="Advanced")); + + parameter Real TDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 10 + "Temperature difference for failsafe condition" + annotation(Dialog(group="Failsafe condition parameters")); + + parameter Real delFaiCon( + final unit="s", + displayUnit="s", + final quantity="Time") = 900 + "Enable delay for the failsafe condition" + annotation(Dialog(group="Failsafe condition parameters")); + + parameter Real boiMinPriPumSpeSta[nSta]( + final unit=fill("1",nSta), + displayUnit=fill("1",nSta), + final min=fill(0,nSta), + final max=fill(1,nSta)) = {0,0,0,0,0} + "Minimum primary pump speed for the boiler plant stage"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal indicating end of stage change process" + annotation (Placement(transformation(extent={{-220,70},{-180,110}}), + iconTransformation(extent={{-140,160},{-100,200}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uTyp[nSta] + "Type vector to identify boiler types in each stage" + annotation (Placement(transformation( + extent={{-220,130},{-180,170}}, + rotation=90, + origin={80,-20}), + iconTransformation(extent={{-140,130},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uCur + "Current stage index" + annotation (Placement(transformation( + extent={{-220,90},{-180,130}}, + rotation=90, + origin={80,-20}), + iconTransformation(extent={{-140,100},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSupSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-220,130},{-180,170}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSup( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-220,100},{-180,140}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapReq( + final unit="W", + displayUnit="W", + final quantity="Power") + "Heating capacity required" + annotation (Placement(transformation(extent={{-220,40},{-180,80}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapMin( + final unit="W", + displayUnit="W", + final quantity="Power") + "Minimum firing capacity of current stage" + annotation (Placement(transformation(extent={{-220,10},{-180,50}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapDowDes( + final unit="W", + displayUnit="W", + final quantity="Power") + "Design capacity of the next lower available stage" + annotation (Placement(transformation(extent={{-220,-50},{-180,-10}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uPumSpe( + final unit="1", + displayUnit="1", + final min=0, + final max=1) if not have_priOnl + "Pump speed signal" + annotation (Placement(transformation(extent={{-220,-80},{-180,-40}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uBypValPos( + final unit="1", + displayUnit="1", + final min=0, + final max=1) if have_priOnl + "Bypass valve position" + annotation (Placement(transformation(extent={{-220,-20},{-180,20}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TPriHotWatRet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl + "Measured primary hot water return temperature" + annotation (Placement(transformation(extent={{-220,-180},{-180,-140}}), + iconTransformation(extent={{-140,-140},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSecHotWatRet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") if not have_priOnl + "Measured secondary hot water return temperature" + annotation (Placement(transformation(extent={{-220,-210},{-180,-170}}), + iconTransformation(extent={{-140,-170},{-100,-130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaDow + "Stage down signal" + annotation (Placement(transformation(extent={{220,-20},{260,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition faiSafCon( + final delEna=delFaiCon, + final TDif=TDif, + final TDifHys=dTemp) + "Failsafe condition" + annotation (Placement(transformation(extent={{-160,120},{-140,140}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-120,120},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div + "Thermal capacity ratio" + annotation (Placement(transformation(extent={{-150,34},{-130,54}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=fraMinFir, + final uHigh=fraMinFir + sigDif) + "Hysteresis loop" + annotation (Placement(transformation(extent={{-120,34},{-100,54}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or2 if have_priOnl + "Logical Or" + annotation (Placement(transformation(extent={{60,8},{80,28}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div1 + "Thermal capacity ratio" + annotation (Placement(transformation(extent={{-160,-50},{-140,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=fraDesCap, + final uHigh=fraDesCap + sigDif) + "Hysteresis loop" + annotation (Placement(transformation(extent={{-130,-50},{-110,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And3 and3 + "Logical And" + annotation (Placement(transformation(extent={{180,-10},{200,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub4 if not have_priOnl + "Compare primary and secondary circuit return temperature" + annotation (Placement(transformation(extent={{-162,-190},{-142,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys3( + final uLow=TCirDif - dTemp, + final uHigh=TCirDif) if not have_priOnl + "Hysteresis loop" + annotation (Placement(transformation(extent={{-132,-190},{-112,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 if not have_priOnl + "Logical And" + annotation (Placement(transformation(extent={{-90,-110},{-70,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Or or1 if not have_priOnl + "Logical Or" + annotation (Placement(transformation(extent={{60,-108},{80,-88}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Logical switch" + annotation (Placement(transformation(extent={{100,-50},{120,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=true) if not have_priOnl + "Constant Boolean True source" + annotation (Placement(transformation(extent={{100,-80},{120,-60}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nSta) + "Identify stage type of current stage" + annotation (Placement(transformation(extent={{-20,-180},{0,-160}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta] + "Integer to Real conversion" + annotation (Placement(transformation(extent={{-60,-180},{-40,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 if not have_priOnl + "Logical switch" + annotation (Placement(transformation(extent={{140,-100},{160,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Logical Not" + annotation (Placement(transformation(extent={{-90,34},{-70,54}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Logical Not" + annotation (Placement(transformation(extent={{-90,-50},{-70,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys4( + final uLow=bypValClo, + final uHigh=bypValClo + sigDif) if have_priOnl + "Hysteresis loop" + annotation (Placement(transformation(extent={{-158,-10},{-138,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys2( + final uLow=sigDif, + final uHigh=2*sigDif) if not have_priOnl + "Hysteresis loop" + annotation (Placement(transformation(extent={{-146,-90},{-126,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not4 if not have_priOnl + "Logical Not" + annotation (Placement(transformation(extent={{-120,-90},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer conversion" + annotation (Placement(transformation(extent={{20,-180},{40,-160}}))); + + Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr( + final t=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler) + "Check for non-condensing boilers in stage" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=delDesCapNonConBoi) + "Time since condition has been met" + annotation (Placement(transformation(extent={{50,-30},{70,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim1( + final t=delBypVal) if have_priOnl + "Time since condition has been met" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim2( + final t=delTRetDif) if not have_priOnl + "Time since condition has been met" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim3( + final t=delMinFir) + "Time since condition has been met" + annotation (Placement(transformation(extent={{-20,34},{0,54}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig1( + final nin=nSta) if not have_priOnl + "Identify stage type of current stage" + annotation (Placement(transformation(extent={{-140,-140},{-120,-120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2[nSta]( + final k=boiMinPriPumSpeSta) if not have_priOnl + "Signal source for minimum primary pump speed for boiler plant stage" + annotation (Placement(transformation(extent={{-170,-140},{-150,-120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 if not have_priOnl + "Compare pump speed signal and minimum pump speed for stage" + annotation (Placement(transformation(extent={{-174,-90},{-154,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{-50,34},{-30,54}}))); + + Buildings.Controls.OBC.CDL.Logical.And and4 if have_priOnl + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{-50,-10},{-30,10}}))); + + Buildings.Controls.OBC.CDL.Logical.And and5 + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{-50,-50},{-30,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And and6 if not have_priOnl + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{-50,-110},{-30,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not5 + "Logical Not" + annotation (Placement(transformation(extent={{-120,80},{-100,100}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim4( + final t=delDesCapConBoi) + "Time since condition has been met" + annotation (Placement(transformation(extent={{50,-70},{70,-50}}))); + +equation + connect(faiSafCon.TSupSet, THotWatSupSet) annotation (Line(points={{-162,135}, + {-170,135},{-170,150},{-200,150}}, color={0,0,127})); + connect(faiSafCon.TSup, THotWatSup) + annotation (Line(points={{-162,130},{-170,130},{-170,120},{-200,120}}, + color={0,0,127})); + connect(div.u2, uCapMin) annotation (Line(points={{-152,38},{-160,38},{-160,30}, + {-200,30}}, color={0,0,127})); + connect(hys.u, div.y) + annotation (Line(points={{-122,44},{-128,44}}, + color={0,0,127})); + connect(div1.u2, uCapDowDes) annotation (Line(points={{-162,-46},{-172,-46},{-172, + -30},{-200,-30}}, color={0,0,127})); + connect(hys1.u, div1.y) + annotation (Line(points={{-132,-40},{-138,-40}}, + color={0,0,127})); + connect(and3.y, yStaDow) + annotation (Line(points={{202,0},{240,0}}, color={255,0,255})); + connect(and3.u1, not1.y) annotation (Line(points={{178,8},{150,8},{150,130},{-98, + 130}}, color={255,0,255})); + connect(and3.u2, or2.y) annotation (Line(points={{178,0},{134,0},{134,18},{82, + 18}}, color={255,0,255})); + connect(sub4.u1, TPriHotWatRet) annotation (Line(points={{-164,-174},{-170, + -174},{-170,-160},{-200,-160}}, color={0,0,127})); + connect(sub4.u2, TSecHotWatRet) annotation (Line(points={{-164,-186},{-170, + -186},{-170,-190},{-200,-190}}, color={0,0,127})); + connect(hys3.u,sub4. y) + annotation (Line(points={{-134,-180},{-140,-180}}, color={0,0,127})); + connect(logSwi.y, and3.u3) annotation (Line(points={{122,-40},{150,-40},{150,-8}, + {178,-8}}, color={255,0,255})); + connect(intToRea.u, uTyp) annotation (Line(points={{-62,-170},{-70,-170},{-70, + -220}}, color={255,127,0})); + connect(intToRea.y, extIndSig.u) + annotation (Line(points={{-38,-170},{-22,-170}}, color={0,0,127})); + connect(uCur, extIndSig.index) annotation (Line(points={{-30,-220},{-30,-190}, + {-10,-190},{-10,-182}}, color={255,127,0})); + connect(con1.y, logSwi1.u1) annotation (Line(points={{122,-70},{132,-70},{132, + -82},{138,-82}}, color={255,0,255})); + connect(or1.y, logSwi1.u3) annotation (Line(points={{82,-98},{138,-98}}, + color={255,0,255})); + connect(and3.u2, logSwi1.y) annotation (Line(points={{178,0},{134,0},{134,-20}, + {170,-20},{170,-90},{162,-90}}, color={255,0,255})); + connect(div.u1, uCapReq) annotation (Line(points={{-152,50},{-160,50},{-160,60}, + {-200,60}}, color={0,0,127})); + connect(div1.u1, uCapReq) annotation (Line(points={{-162,-34},{-166,-34},{-166, + 60},{-200,60}}, color={0,0,127})); + connect(not2.u, hys.y) + annotation (Line(points={{-92,44},{-98,44}}, color={255,0,255})); + connect(hys1.y, not3.u) + annotation (Line(points={{-108,-40},{-92,-40}},color={255,0,255})); + connect(hys4.u, uBypValPos) + annotation (Line(points={{-160,0},{-200,0}}, color={0,0,127})); + connect(hys2.y, not4.u) + annotation (Line(points={{-124,-80},{-122,-80}}, + color={255,0,255})); + connect(extIndSig.y, reaToInt.u) + annotation (Line(points={{2,-170},{18,-170}}, color={0,0,127})); + connect(intGreThr.u, reaToInt.y) + annotation (Line(points={{58,-170},{42,-170}}, color={255,127,0})); + connect(intGreThr.y, logSwi.u2) annotation (Line(points={{82,-170},{94,-170},{ + 94,-40},{98,-40}}, + color={255,0,255})); + connect(intGreThr.y, logSwi1.u2) annotation (Line(points={{82,-170},{94,-170}, + {94,-90},{138,-90}},color={255,0,255})); + connect(faiSafCon.yFaiCon, not1.u) + annotation (Line(points={{-138,130},{-130,130},{-130,130},{-122,130}}, + color={255,0,255})); + connect(not4.y, and2.u1) annotation (Line(points={{-98,-80},{-96,-80},{-96,-100}, + {-92,-100}}, color={255,0,255})); + connect(hys3.y, and2.u2) annotation (Line(points={{-110,-180},{-98,-180},{-98, + -108},{-92,-108}}, + color={255,0,255})); + connect(uStaChaProEnd, faiSafCon.uStaChaProEnd) annotation (Line(points={{-200, + 90},{-166,90},{-166,125},{-162,125}}, color={255,0,255})); + connect(con2.y, extIndSig1.u) + annotation (Line(points={{-148,-130},{-142,-130}}, color={0,0,127})); + connect(uCur, extIndSig1.index) annotation (Line(points={{-30,-220},{-30,-190}, + {-80,-190},{-80,-160},{-130,-160},{-130,-142}}, color={255,127,0})); + connect(hys2.u,sub2. y) + annotation (Line(points={{-148,-80},{-152,-80}}, color={0,0,127})); + connect(uPumSpe,sub2. u1) annotation (Line(points={{-200,-60},{-176,-60},{ + -176,-74}}, color={0,0,127})); + connect(extIndSig1.y,sub2. u2) annotation (Line(points={{-118,-130},{-112,-130}, + {-112,-110},{-178,-110},{-178,-86},{-176,-86}}, color={0,0,127})); + connect(tim3.u, and1.y) + annotation (Line(points={{-22,44},{-28,44}}, color={255,0,255})); + connect(and1.u1, not2.y) + annotation (Line(points={{-52,44},{-68,44}}, color={255,0,255})); + connect(tim1.u, and4.y) + annotation (Line(points={{-22,0},{-28,0}}, color={255,0,255})); + connect(and5.y, tim.u) + annotation (Line(points={{-28,-40},{30,-40},{30,-20},{48,-20}}, + color={255,0,255})); + connect(tim2.u, and6.y) + annotation (Line(points={{-22,-100},{-28,-100}}, color={255,0,255})); + connect(hys4.y, and4.u1) + annotation (Line(points={{-136,0},{-52,0}}, color={255,0,255})); + connect(not3.y, and5.u1) + annotation (Line(points={{-68,-40},{-52,-40}}, color={255,0,255})); + connect(and2.y, and6.u1) + annotation (Line(points={{-68,-100},{-52,-100}}, color={255,0,255})); + connect(not5.u, uStaChaProEnd) + annotation (Line(points={{-122,90},{-200,90}}, color={255,0,255})); + connect(not5.y, and1.u2) annotation (Line(points={{-98,90},{-60,90},{-60,36},{ + -52,36}}, color={255,0,255})); + connect(not5.y, and4.u2) annotation (Line(points={{-98,90},{-60,90},{-60,-8},{ + -52,-8}}, color={255,0,255})); + connect(not5.y, and5.u2) annotation (Line(points={{-98,90},{-60,90},{-60,-48}, + {-52,-48}}, color={255,0,255})); + connect(not5.y, and6.u2) annotation (Line(points={{-98,90},{-60,90},{-60,-108}, + {-52,-108}}, color={255,0,255})); + + connect(tim3.passed, or2.u1) annotation (Line(points={{2,36},{40,36},{40,18},{ + 58,18}}, color={255,0,255})); + connect(tim3.passed, or1.u1) annotation (Line(points={{2,36},{40,36},{40,-98}, + {58,-98}}, color={255,0,255})); + connect(tim1.passed, or2.u2) annotation (Line(points={{2,-8},{50,-8},{50,10},{ + 58,10}}, color={255,0,255})); + connect(and5.y, tim4.u) annotation (Line(points={{-28,-40},{30,-40},{30,-60},{ + 48,-60}}, color={255,0,255})); + connect(tim.passed, logSwi.u1) annotation (Line(points={{72,-28},{90,-28},{90, + -32},{98,-32}}, color={255,0,255})); + connect(tim4.passed, logSwi.u3) annotation (Line(points={{72,-68},{90,-68},{90, + -48},{98,-48}}, color={255,0,255})); + connect(tim2.passed, or1.u2) annotation (Line(points={{2,-108},{40,-108},{40,-106}, + {58,-106}}, color={255,0,255})); +annotation(defaultComponentName = "staDow", + Icon(coordinateSystem(extent={{-100,-160},{100,190}}), + graphics={ + Rectangle( + extent={{-100,-160},{100,190}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,244},{100,206}}, + 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},{220,180}})), + Documentation(info=" +
    +
  1. +If the current stage uCur has only condensing boilers, the +block outputs a boolean stage down signal yStaDow when all +the following are true: + +
  2. +
  3. +If the current stage uCur has a non-condensing boiler, the +block outputs a boolean stage down signal yStaDow when all +the following are true: + +
  4. +
  5. +If the plant is a primary-only, condensing type boiler plant, +have_priOnl is set to true and the block +outputs a boolean stage down signal yStaDow +when all the following are true: + +
  6. +
+

+The implementation is according to ASHRAE RP1711 March 2020 draft, section 5.3.3.10. +Timer reset has been implemented according to 5.3.3.10.2. +

+", +revisions=" + +")); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo new file mode 100644 index 00000000000..e697a0c036e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo @@ -0,0 +1,318 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block EfficiencyCondition + "Efficiency condition used in staging up and down" + + parameter Integer nSta = 5 + "Number of stages in the boiler plant"; + + parameter Real fraNonConBoi( + final min=0, + final unit="1", + displayUnit="1") = 0.9 + "Fraction of design capacity of current stage at which the efficiency condition + is satisfied for non-condensing boilers"; + + parameter Real fraConBoi( + final min=0, + final unit="1", + displayUnit="1") = 1.5 + "Fraction of B-Stage minimum of next higher stage at which the efficiency + condition is satisfied for condensing boilers"; + + parameter Real sigDif( + final min=0, + final unit="1", + final max=1, + displayUnit="1") = 0.1 + "Signal hysteresis deadband" + annotation (Dialog(tab="Advanced")); + + parameter Real delCapReq( + final unit="s", + displayUnit="s", + final quantity="Time") = 600 + "Enable delay for heating requirement condition"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal indicating end of stage change process" + annotation (Placement(transformation(extent={{-160,-200},{-120,-160}}), + iconTransformation(extent={{-140,70},{-100,110}}, + rotation=90))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uTyp[nSta] + "Vector of boiler types for all stages" + annotation (Placement(transformation(extent={{-160,-120},{-120,-80}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAvaUp + "Stage number of next available higher stage" + annotation (Placement(transformation(extent={{-160,-160},{-120,-120}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapReq( + final unit="W", + displayUnit="W", + final quantity="Power") + "Heating capacity required" + annotation (Placement(transformation(extent={{-160,40},{-120,80}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapDes( + final unit="W", + displayUnit="W", + final quantity="Power") + "Design heating capacity of current stage" + annotation (Placement(transformation(extent={{-160,80},{-120,120}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapUpMin( + final unit="W", + displayUnit="W", + final quantity="Power") + "Minimum capacity of the next available higher stage" + annotation (Placement(transformation(extent={{-160,0},{-120,40}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured hot-water flow-rate" + annotation (Placement(transformation(extent={{-160,-40},{-120,0}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VUpMinSet_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Minimum flow setpoint for the next available higher stage" + annotation (Placement(transformation(extent={{-160,-80},{-120,-40}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEffCon + "Efficiency condition for boiler staging" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Divide div + "Divider to get relative value of required heating capacity" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div1 + "Divider to get relative value of required heating capacity" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div2 + "Divider to get relative value of flow-rate" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=-sigDif, + final uHigh=0) + "Hysteresis loop for flow-rate condition" + annotation (Placement(transformation(extent={{30,-60},{50,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=true) + "Constant boolean source" + annotation (Placement(transformation(extent={{30,-20},{50,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=fraNonConBoi - sigDif, + final uHigh=fraNonConBoi) + "Hysteresis loop for heating capacity condition of non-condensing boilers" + annotation (Placement(transformation(extent={{-40,60},{-20,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys2( + final uLow=fraConBoi - sigDif, + final uHigh=fraConBoi) + "Hysteresis loop for heating capacity condition of condensing boilers" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta] + "Convert integers in stage-type vector to real data-type" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig( + final nin=nSta) + "Pick out stage-type for next stage from vector" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr( + final t=1) + "Check for non-condensing boilers" + annotation (Placement(transformation(extent={{30,-110},{50,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Switch for heating capacity condition based on stage type" + annotation (Placement(transformation(extent={{100,40},{120,60}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Logical And" + annotation (Placement(transformation(extent={{130,-10},{150,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 + "Switch for flow-rate condition" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + "Find difference between measurted flowrate and minimum flow setpoint for next higher stage" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim(t=delCapReq) + "Time since condition has been met" + annotation (Placement(transformation(extent={{20,60},{40,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim1(t=delCapReq) + "Time since condition has been met" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1 + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{-10,60},{10,80}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{-10,20},{10,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-40,-190},{-20,-170}}))); + +equation + connect(div.u2,uCapUpMin) + annotation (Line(points={{-82,24},{-110,24},{-110,20},{-140,20}}, + color={0,0,127})); + connect(div1.u2, uCapDes) annotation (Line(points={{-82,64},{-90,64},{-90,70}, + {-114,70},{-114,100},{-140,100}}, color={0,0,127})); + connect(sub1.u1, VHotWat_flow) annotation (Line(points={{-82,-34},{-110,-34},{ + -110,-20},{-140,-20}}, color={0,0,127})); + connect(sub1.u2, VUpMinSet_flow) annotation (Line(points={{-82,-46},{-110,-46}, + {-110,-60},{-140,-60}}, color={0,0,127})); + connect(sub1.y, div2.u1) + annotation (Line(points={{-58,-40},{-50,-40},{-50,-44},{-42,-44}}, + color={0,0,127})); + connect(div2.y, hys.u) + annotation (Line(points={{-18,-50},{28,-50}}, + color={0,0,127})); + connect(div1.y, hys1.u) + annotation (Line(points={{-58,70},{-42,70}}, + color={0,0,127})); + connect(div.y, hys2.u) + annotation (Line(points={{-58,30},{-42,30}}, + color={0,0,127})); + connect(intToRea.u, uTyp) + annotation (Line(points={{-82,-100},{-140,-100}}, + color={255,127,0})); + connect(extIndSig.u, intToRea.y) + annotation (Line(points={{-42,-100},{-58,-100}}, + color={0,0,127})); + connect(extIndSig.index, uAvaUp) + annotation (Line(points={{-30,-112},{-30,-140},{-140,-140}}, + color={255,127,0})); + connect(greThr.u, extIndSig.y) + annotation (Line(points={{28,-100},{-18,-100}}, + color={0,0,127})); + connect(greThr.y, logSwi.u2) + annotation (Line(points={{52,-100},{92,-100},{92,50},{98,50}}, + color={255,0,255})); + connect(and2.y, yEffCon) + annotation (Line(points={{152,0},{180,0}}, + color={255,0,255})); + connect(logSwi.y, and2.u1) + annotation (Line(points={{122,50},{126,50},{126,0},{128,0}}, + color={255,0,255})); + connect(logSwi1.y, and2.u2) + annotation (Line(points={{122,-30},{126,-30},{126,-8},{128,-8}}, + color={255,0,255})); + connect(con1.y, logSwi1.u1) + annotation (Line(points={{52,-10},{80,-10},{80,-22},{98,-22}}, + color={255,0,255})); + connect(hys.y, logSwi1.u3) + annotation (Line(points={{52,-50},{80,-50},{80,-38},{98,-38}}, + color={255,0,255})); + connect(logSwi1.u2, greThr.y) + annotation (Line(points={{98,-30},{92,-30},{92,-100},{52,-100}}, + color={255,0,255})); + connect(div.u1, uCapReq) annotation (Line(points={{-82,36},{-100,36},{-100,60}, + {-140,60}}, color={0,0,127})); + connect(div1.u1, uCapReq) annotation (Line(points={{-82,76},{-100,76},{-100,60}, + {-140,60}}, color={0,0,127})); + connect(hys1.y, and1.u1) + annotation (Line(points={{-18,70},{-12,70}}, color={255,0,255})); + connect(and1.y, tim.u) + annotation (Line(points={{12,70},{18,70}}, color={255,0,255})); + connect(and3.y, tim1.u) + annotation (Line(points={{12,30},{18,30}}, color={255,0,255})); + connect(and3.u1, hys2.y) + annotation (Line(points={{-12,30},{-18,30}}, color={255,0,255})); + connect(not1.u, uStaChaProEnd) + annotation (Line(points={{-42,-180},{-140,-180}}, color={255,0,255})); + connect(not1.y, and3.u2) annotation (Line(points={{-18,-180},{-16,-180},{-16,22}, + {-12,22}}, color={255,0,255})); + connect(not1.y, and1.u2) annotation (Line(points={{-18,-180},{-16,-180},{-16,62}, + {-12,62}}, color={255,0,255})); + + connect(tim.passed, logSwi.u1) annotation (Line(points={{42,62},{80,62},{80,58}, + {98,58}}, color={255,0,255})); + connect(tim1.passed, logSwi.u3) annotation (Line(points={{42,22},{80,22},{80,42}, + {98,42}}, color={255,0,255})); + connect(VUpMinSet_flow, addPar.u) annotation (Line(points={{-140,-60},{-110,-60}, + {-110,-70},{-82,-70}}, color={0,0,127})); + connect(addPar.y, div2.u2) annotation (Line(points={{-58,-70},{-50,-70},{-50,-56}, + {-42,-56}}, color={0,0,127})); +annotation ( + defaultComponentName = "effCon", + 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={{-120,-200},{160,120}})), + Documentation( + info=" +

+ Efficiency condition used in staging up and down for boiler plants with both + condensing and non-condensing boilers. Implemented according to the + specification provided in 5.3.3.10, subsections 6.b, 8.b, 10.b and 12.b in + RP-1711, March 2020 Draft. Timer reset has been implemented according to + 5.3.3.10.2. +

+

+ \"State-machine +
+ State-machine chart for the sequence for condensing boilers defined in RP-1711 +

+

+ \"State-machine +
+ State-machine chart for the sequence for non-condensing boilers defined in RP-1711 +

+ ", + revisions=" + + ")); +end EfficiencyCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo new file mode 100644 index 00000000000..b0707b9b356 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo @@ -0,0 +1,134 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block FailsafeCondition + "Failsafe condition used in staging up and down" + + parameter Real TDif( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 10 + "Required temperature difference between setpoint and measured temperature + for failsafe condition"; + + parameter Real TDifHys( + final unit="K", + displayUnit="K", + final quantity="TemperatureDifference") = 1 + "Temperature deadband for hysteresis loop" + annotation (Dialog(tab="Advanced")); + + parameter Real delEna( + final unit="s", + displayUnit="s", + final quantity="Time") = 900 + "Enable delay"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal indicating end of stage change process" + annotation (Placement(transformation(extent={{-160,-70},{-120,-30}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupSet( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-160,30},{-120,70}}), + iconTransformation(extent={{-140,30},{-100,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSup( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-160,-20},{-120,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yFaiCon + "Failsafe condition for boiler staging" + annotation (Placement(transformation(extent={{120,-20},{160,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Difference between setpoint and measured temperature" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=TDif - TDifHys, + final uHigh=TDif) + "Hysteresis deadband to prevent cycling" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=delEna) + "Time since condition has been met" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical Not" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.And and2 + "Turn on timer when hysteresis turns on and reset it when hysteresis turns + off or stage change process is completed" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + +equation + connect(sub2.u2, TSup) + annotation (Line(points={{-82,-6},{-90,-6},{-90,0},{-140,0}}, + color={0,0,127})); + connect(sub2.u1, TSupSet) + annotation (Line(points={{-82,6},{-90,6},{-90,50},{-140,50}}, + color={0,0,127})); + connect(sub2.y, hys.u) + annotation (Line(points={{-58,0},{-42,0}}, + color={0,0,127})); + connect(not1.u, uStaChaProEnd) + annotation (Line(points={{-42,-50},{-140,-50}}, color={255,0,255})); + connect(hys.y, and2.u1) + annotation (Line(points={{-18,0},{-2,0}}, color={255,0,255})); + connect(not1.y, and2.u2) annotation (Line(points={{-18,-50},{-12,-50},{-12,-8}, + {-2,-8}}, color={255,0,255})); + connect(and2.y, tim.u) + annotation (Line(points={{22,0},{38,0}}, color={255,0,255})); + + connect(tim.passed, yFaiCon) annotation (Line(points={{62,-8},{70,-8},{70,0},{ + 140,0}}, color={255,0,255})); +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={{-120,-120},{120,120}})), + Documentation(info=" +

+ Failsafe condition used in staging up and down, implemented according to + the specification provided in section 5.3.3.10, subsections 6.c, 8.c, 10.c + and 12.c in RP-1711, March 2020 Draft. Timer reset has been implemented + according to 5.3.3.10.2. +

+

+ \"State-machine +
+ State-machine chart for the sequence defined in RP-1711 +

+ ", + revisions=" + + ")); +end FailsafeCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Status.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Status.mo new file mode 100644 index 00000000000..682c70ddde3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Status.mo @@ -0,0 +1,403 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block Status + "Outputs current stage boiler index vector, current, next available lower and + higher stage index and whether current stage is the lowest and/or the highest + available stage" + + parameter Integer nSta = 5 + "Number of stages"; + + parameter Integer nBoi = 3 + "Number of boilers"; + + parameter Integer staMat[nSta, nBoi] = {{1,0,0},{0,1,1},{1,1,0},{0,1,1},{1,1,1}} + "Staging matrix with stages in rows and boilers 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 boiler 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,-100},{480,-60}}), + 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, nBoi] = {j for i in 1:nBoi, 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 available" + annotation (Placement(transformation(extent={{-60,-160},{-40,-140}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi2 + "Switch" + annotation (Placement(transformation(extent={{100,-220},{120,-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.Continuous.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,-70},{-160,-50}}))); + + 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]( + final integerTrue=fill(1, nSta), + final 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.Continuous.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}}))); + + CDL.Routing.BooleanExtractor extStaAva( + final nin=nSta) + "Extracts stage availability for the current stage" + annotation (Placement(transformation(extent={{-200,-160},{-180,-140}}))); + + Buildings.Controls.OBC.CDL.Utilities.Assert cheStaAva1( + final message="There are no available boiler 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=1) + "Lowest allowed stage" + 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,-130},{-360,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr1( + final t=nSta) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-380,-210},{-360,-190}}))); + + Buildings.Controls.OBC.CDL.Logical.And and3 + "Check if index is in the range" + annotation (Placement(transformation(extent={{-320,-130},{-300,-110}}))); + + 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,-210},{-300,-190}}))); + + Buildings.Controls.OBC.CDL.Integers.Switch intSwi4 "Valid index" + annotation (Placement(transformation(extent={{-260,-180},{-240,-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, + -68},{-182,-68}}, color={255,127,0})); + connect(staIndx.y, intLes.u1) annotation (Line(points={{-218,130},{-200,130},{ + -200,-60},{-182,-60}}, 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,-60},{-150,-60},{-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,-30},{-70,-30},{-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},{340,-90},{340,-80},{460,-80}}, 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(yAvaUp, yAvaUp) + annotation (Line(points={{460,80},{460,80}}, color={255,127,0})); + 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},{-320,80},{-320,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, + -160},{80,-160},{80,-202},{98,-202}}, color={255,127,0})); + connect(intSwi2.y, intSwi3.u1) annotation (Line(points={{122,-210},{350,-210}, + {350,88},{358,88}}, color={255,127,0})); + connect(u, intSwi2.u3) annotation (Line(points={{-440,80},{-400,80},{-400,-218}, + {98,-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},{-300,80},{-300,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(intSwi3.y, yAvaUp) + annotation (Line(points={{382,80},{460,80}}, color={255,127,0})); + connect(conInt1.y, intSwi4.u3) annotation (Line(points={{-298,-200},{-280,-200}, + {-280,-178},{-262,-178}}, color={255,127,0})); + connect(and3.y, intSwi4.u2) annotation (Line(points={{-298,-120},{-280,-120},{ + -280,-170},{-262,-170}}, color={255,0,255})); + connect(intGreEquThr.y, and3.u1) + annotation (Line(points={{-358,-120},{-322,-120}}, color={255,0,255})); + connect(intLesEquThr1.y, and3.u2) annotation (Line(points={{-358,-200},{-340,-200}, + {-340,-128},{-322,-128}}, color={255,0,255})); + connect(u, intGreEquThr.u) annotation (Line(points={{-440,80},{-400,80},{-400, + -120},{-382,-120}}, color={255,127,0})); + connect(u, intLesEquThr1.u) annotation (Line(points={{-440,80},{-400,80},{-400, + -200},{-382,-200}}, color={255,127,0})); + connect(u, intSwi4.u1) annotation (Line(points={{-440,80},{-400,80},{-400,-162}, + {-262,-162}}, color={255,127,0})); + connect(intSwi4.y, extStaAva.index) annotation (Line(points={{-238,-170},{-190, + -170},{-190,-162}}, color={255,127,0})); + connect(uAva, extStaAva.u) annotation (Line(points={{-440,-80},{-220,-80},{-220, + -150},{-202,-150}}, color={255,0,255})); + connect(extStaAva.y, not1.u) + annotation (Line(points={{-178,-150},{-62,-150}}, color={255,0,255})); + connect(not1.y, intSwi2.u2) annotation (Line(points={{-38,-150},{-20,-150},{-20, + -210},{98,-210}}, color={255,0,255})); + connect(not1.y, and4.u2) annotation (Line(points={{-38,-150},{210,-150},{210,72}, + {218,72}}, color={255,0,255})); + connect(reaToInt1.y, intSwi1.u3) annotation (Line(points={{82,-70},{90,-70},{90, + -100},{160,-100},{160,-78},{178,-78}}, color={255,127,0})); + connect(extStaAva.y, yAvaCur) annotation (Line(points={{-178,-150},{-140,-150}, + {-140,-240},{460,-240}}, 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 1711 as it provides a side + calculation pertaining to generalization of the staging sequences for any number + of boilers 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: +

+ +

+ The sequences are implemented according to 1711 March 2020 Draft, section 5.3.3.9. +

+ ", + revisions=" + + ")); +end Status; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Up.mo new file mode 100644 index 00000000000..1d706498f8f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Up.mo @@ -0,0 +1,265 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +block Up + "Generates a stage up signal" + + parameter Integer nSta = 5 + "Number of stages in the boiler plant"; + + parameter Real fraNonConBoi( + final unit="1", + displayUnit="1", + final min=0, + final max=1) = 0.9 + "Fraction of stage design capacity at which the efficiency condition + is satisfied for non-condensing boilers" + annotation(Dialog(group="Efficiency condition")); + + parameter Real fraConBoi( + final unit="1", + displayUnit="1", + final min=0) = 1.5 + "Fraction of stage minimum capacity at which the efficiency condition is + satisfied for condensing boilers" + annotation(Dialog(group="Efficiency condition")); + + parameter Real sigDif( + final unit="1", + displayUnit="1", + final min=0) = 0.1 + "Signal hysteresis deadband" + annotation (Dialog(tab="Advanced", + group="Efficiency condition")); + + parameter Real delEffCon( + final unit="s", + displayUnit="s") = 600 + "Enable delay for heating capacity and heating requirement" + annotation(Dialog(group="Efficiency condition")); + + parameter Real TDif( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 10 + "Required temperature difference between setpoint and measured temperature + for failsafe condition" + annotation(Dialog(group="Failsafe condition")); + + parameter Real TDifHys( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 1 + "Temperature deadband for hysteresis loop in failsafe condition" + annotation (Dialog(tab="Advanced", + group="Failsafe condition")); + + parameter Real delFaiCon( + final unit="s", + displayUnit="s") = 900 + "Enable delay for temperature" + annotation(Dialog(group="Failsafe condition")); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaChaProEnd + "Signal indicating end of stage change process" + annotation (Placement(transformation(extent={{-140,-190},{-100,-150}}), + iconTransformation(extent={{-140,-170},{-100,-130}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uAvaCur + "Current stage availability status" + annotation (Placement(transformation(extent={{-140,-160},{-100,-120}}), + iconTransformation(extent={{-140,-140},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uTyp[nSta] + "Boiler-type vector specifying boiler-type in each stage" + annotation (Placement(transformation(extent={{-140,-40},{-100,0}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAvaUp + "Index of next available higher stage" + annotation (Placement(transformation(extent={{-140,-70},{-100,-30}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSupSet( + final unit="K", + final quantity="ThermodynamicTemperature") + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-140,-100},{-100,-60}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSup( + final unit="K", + final quantity="ThermodynamicTemperature") + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-140,-130},{-100,-90}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapUpMin( + final unit="W", + displayUnit="W", + final quantity="Power") + "Minimum heating capacity of next available stage" + annotation (Placement(transformation(extent={{-140,50},{-100,90}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapDes( + final unit="W", + displayUnit="W", + final quantity="Power") + "Design heating capacity of the current stage" + annotation (Placement(transformation(extent={{-140,80},{-100,120}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uCapReq( + final unit="W", + displayUnit="W", + final quantity="Power") + "Calculated heating capacity requirement" + annotation (Placement(transformation(extent={{-140,110},{-100,150}}), + iconTransformation(extent={{-140,130},{-100,170}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured hot water flow rate" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput VUpMinSet_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Minimum flow setpoint for next available higher stage" + annotation (Placement(transformation(extent={{-140,-10},{-100,30}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yStaUp + "Stage up signal" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition effCon( + final nSta=nSta, + final fraNonConBoi=fraNonConBoi, + final fraConBoi=fraConBoi, + final delCapReq=delEffCon, + final sigDif=sigDif) + "Efficiency condition for staging up" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition faiSafCon( + final delEna=delFaiCon, + final TDif=TDif, + final TDifHys=TDifHys) + "Failsafe condition for staging up and down" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=3) + "Logical Or" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +equation + connect(effCon.uTyp, uTyp) + annotation (Line(points={{-62,34},{-72,34},{-72,-20},{-120,-20}}, + color={255,127,0})); + connect(effCon.uAvaUp, uAvaUp) + annotation (Line(points={{-62,31},{-64,31},{-64,-50},{-120,-50}}, + color={255,127,0})); + connect(faiSafCon.TSupSet, THotWatSupSet) + annotation (Line(points={{-62,-85},{-80,-85},{-80,-80},{-120,-80}}, + color={0,0,127})); + connect(faiSafCon.TSup, THotWatSup) + annotation (Line(points={{-62,-90},{-80,-90},{-80,-110},{-120,-110}}, + color={0,0,127})); + connect(mulOr.y, yStaUp) + annotation (Line(points={{62,0},{120,0}}, + color={255,0,255})); + connect(effCon.yEffCon, mulOr.u[1]) + annotation (Line(points={{-38,40},{10,40},{10,4.66667},{38,4.66667}}, + color={255,0,255})); + connect(not1.u, uAvaCur) + annotation (Line(points={{-62,-140},{-120,-140}}, + color={255,0,255})); + connect(faiSafCon.yFaiCon, mulOr.u[2]) annotation (Line(points={{-38,-90},{0,-90}, + {0,0},{38,0}}, color={255,0,255})); + connect(not1.y, mulOr.u[3]) annotation (Line(points={{-38,-140},{10,-140},{10, + -4.66667},{38,-4.66667}}, color={255,0,255})); + connect(effCon.uCapReq, uCapReq) annotation (Line(points={{-62,49},{-64,49},{-64, + 130},{-120,130}}, color={0,0,127})); + connect(effCon.uCapDes, uCapDes) annotation (Line(points={{-62,46},{-72,46},{-72, + 100},{-120,100}}, color={0,0,127})); + connect(effCon.uCapUpMin, uCapUpMin) annotation (Line(points={{-62,43},{-80,43}, + {-80,70},{-120,70}}, color={0,0,127})); + connect(effCon.VHotWat_flow, VHotWat_flow) + annotation (Line(points={{-62,40},{-120,40}}, color={0,0,127})); + connect(effCon.VUpMinSet_flow, VUpMinSet_flow) annotation (Line(points={{-62,37}, + {-80,37},{-80,10},{-120,10}}, color={0,0,127})); + connect(uStaChaProEnd, faiSafCon.uStaChaProEnd) annotation (Line(points={{-120, + -170},{-70,-170},{-70,-95},{-62,-95}}, color={255,0,255})); + connect(uStaChaProEnd, effCon.uStaChaProEnd) annotation (Line(points={{-120,-170}, + {-70,-170},{-70,-70},{-59,-70},{-59,28}}, color={255,0,255})); + + annotation (defaultComponentName = "staUp", + Icon(coordinateSystem(extent={{-100,-160},{100,160}}), + graphics={ + Rectangle( + extent={{-100,-160},{100,160}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-120,206},{100,168}}, + 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={{-100,-180},{100,140}})), + Documentation(info=" +

+ Outputs a boolean stage up signal yStaUp based on the + various plant operation conditions that get provided as input signals. + Implemented according to 1711 March 2020 Draft, section 5.3.3.10. + and applies to all boiler plants defined in RP-1711. Timer reset has been + implemented according to 5.3.3.10.2. +

+

+ The stage up signal yStaUp becomes true when: +

+ + ", + revisions=" + + ")); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/BoilerIndices.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/BoilerIndices.mo new file mode 100644 index 00000000000..603e0b48dfd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/BoilerIndices.mo @@ -0,0 +1,143 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model BoilerIndices + "Validates extraction of boiler indices in a given stage" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd( + final nSta=3, + final nBoi=2, + final staMat={{1,0},{0,1},{1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{0,80},{20,100}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd1( + final nSta=3, + final nBoi=2, + final staMat={{1,0},{0,1},{1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd2( + final nSta=3, + final nBoi=2, + final staMat={{1,0},{0,1},{1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd3( + final nSta=3, + final nBoi=2, + final staMat={{1,0},{0,1},{1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd4( + final nSta=5, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd5( + final nSta=5, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd6( + final nSta=5, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices + boiInd7( + final nSta=5, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}) + "Boiler index generator" + annotation (Placement(transformation(extent={{40,-100},{60,-80}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u( + final k=0) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u1( + final k=1) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,40},{-40,60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u2( + final k=2) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,0},{-40,20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u3( + final k=3) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u4( + final k=5) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + +equation + connect(u.y, boiInd.u) + annotation (Line(points={{-38,90},{-2,90}}, color={255,127,0})); + connect(u1.y, boiInd1.u) + annotation (Line(points={{-38,50},{-2,50}}, color={255,127,0})); + connect(u2.y, boiInd2.u) + annotation (Line(points={{-38,10},{-2,10}}, color={255,127,0})); + connect(u3.y, boiInd3.u) + annotation (Line(points={{-38,-30},{-2,-30}}, color={255,127,0})); + connect(boiInd4.u, u.y) annotation (Line(points={{38,70},{-20,70},{-20,90},{-38, + 90}}, color={255,127,0})); + connect(boiInd5.u, u1.y) annotation (Line(points={{38,30},{-20,30},{-20,50},{-38, + 50}}, color={255,127,0})); + connect(boiInd6.u, u3.y) annotation (Line(points={{38,-50},{-20,-50},{-20,-30}, + {-38,-30}}, color={255,127,0})); + connect(boiInd7.u, u4.y) annotation (Line(points={{38,-90},{-20,-90},{-20,-70}, + {-38,-70}}, color={255,127,0})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/BoilerIndices.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.BoilerIndices. +

+ ", + 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 BoilerIndices; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Capacities.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Capacities.mo new file mode 100644 index 00000000000..eb07c310468 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Capacities.mo @@ -0,0 +1,181 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model Capacities + "Validate stage capacities subsequence for boiler stage inputs" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.BoilerPlant.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.Continuous.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.Continuous.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) + "Boiler stage" + annotation (Placement(transformation(extent={{-140,20},{-120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage1( + final k=1) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage2( + final k=2) + "Boiler 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) + "Boiler stage" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage4( + final k=3) + "Boiler stage" + annotation (Placement(transformation(extent={{100,-20},{120,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage5( + final k=3) + "Boiler stage" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage6( + final k=3) + "Boiler stage" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant stage7( + final k=1) + "Boiler 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/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Capacities.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mo new file mode 100644 index 00000000000..c3b692a7e6b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mo @@ -0,0 +1,171 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +block CapacityRequirement + "Validation model for CapacityRequirement" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq( + final avePer=300) + "Scenario with sine input for return temperature" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq1( + final avePer=300) + "Scenario with sine input for supply setpoint temperature" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq2( + final avePer=300) + "Scenario with sine input for flow-rate" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.CapacityRequirement + capReq3( + final avePer=300) + "Scenario with sine input for all inputs" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=333.15) + "Constant input" + annotation (Placement(transformation(extent={{-90,70},{-70,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=333.15 - 322.04, + final freqHz=1/3600, + final offset=322.04) + "Sine input" + annotation (Placement(transformation(extent={{-90,40},{-70,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=1) + "Constant input" + annotation (Placement(transformation(extent={{-90,10},{-70,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=322.04) + "Constant input" + annotation (Placement(transformation(extent={{10,40},{30,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final amplitude=333.15 - 322.04, + final freqHz=1/3600, + final offset=333.15) + "Sine input" + annotation (Placement(transformation(extent={{10,70},{30,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=1) + "Constant input" + annotation (Placement(transformation(extent={{10,10},{30,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con4( + final k=333.15) + "Constant input" + annotation (Placement(transformation(extent={{-90,-30},{-70,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin2( + final amplitude=1, + final freqHz=1/3600, + final offset=1) + "Sine input" + annotation (Placement(transformation(extent={{-90,-90},{-70,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con5( + final k=322.04) + "Constant input" + annotation (Placement(transformation(extent={{-90,-60},{-70,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin3( + final amplitude=333.15 - 322.04, + final freqHz=2/3600, + final offset=322.04) + "Sine input" + annotation (Placement(transformation(extent={{10,-60},{30,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin4( + final amplitude=333.15 - 322.04, + final freqHz=1/3600, + final offset=333.15) + "Sine input" + annotation (Placement(transformation(extent={{10,-30},{30,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin5( + final amplitude=1, + final freqHz=3/3600, + final offset=1) + "Sine input" + annotation (Placement(transformation(extent={{10,-90},{30,-70}}))); + +equation + connect(con.y, capReq.TSupSet) + annotation (Line(points={{-68,80},{-50,80},{-50,57},{-42,57}}, + color={0,0,127})); + connect(sin.y, capReq.TRet) + annotation (Line(points={{-68,50},{-42,50}}, + color={0,0,127})); + connect(con1.y, capReq.VHotWat_flow) + annotation (Line(points={{-68,20},{-50,20},{-50,43},{-42,43}}, + color={0,0,127})); + connect(con3.y, capReq1.VHotWat_flow) + annotation (Line(points={{32,20},{50,20},{50,43},{58,43}}, + color={0,0,127})); + connect(con4.y, capReq2.TSupSet) + annotation (Line(points={{-68,-20},{-50,-20},{-50,-43},{-42,-43}}, + color={0,0,127})); + connect(sin3.y, capReq3.TRet) + annotation (Line(points={{32,-50},{58,-50}}, + color={0,0,127})); + connect(con2.y, capReq1.TRet) + annotation (Line(points={{32,50},{58,50}}, + color={0,0,127})); + connect(sin1.y, capReq1.TSupSet) + annotation (Line(points={{32,80},{50,80},{50,57},{58,57}}, + color={0,0,127})); + connect(con5.y, capReq2.TRet) + annotation (Line(points={{-68,-50},{-42,-50}}, + color={0,0,127})); + connect(sin2.y, capReq2.VHotWat_flow) + annotation (Line(points={{-68,-80},{-50,-80},{-50,-57},{-42,-57}}, + color={0,0,127})); + connect(sin5.y, capReq3.VHotWat_flow) + annotation (Line(points={{32,-80},{50,-80},{50,-57},{58,-57}}, + color={0,0,127})); + connect(sin4.y, capReq3.TSupSet) + annotation (Line(points={{32,-20},{50,-20},{50,-43},{58,-43}}, + color={0,0,127})); + + annotation(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)), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/CapacityRequirement.mos" + "Simulate and plot"), + experiment( + StopTime=7200, + Interval=1, + Tolerance=1e-6), + Documentation(info=" +

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

+ ", revisions=" + + ")); +end CapacityRequirement; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo new file mode 100644 index 00000000000..c07029e17ae --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo @@ -0,0 +1,434 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model Change + "Validates boiler stage status setpoint signal generation for boiler plants" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Change + cha( + final nSta=10, + final delStaCha=600) + "Controls for stage up signal variations" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Change + cha1( + final nSta=10, + final delStaCha=600) + "Controls for stage down signal variations" + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Change + cha2( + final nSta=10, + final delStaCha=600) + "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}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol6( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{0,220},{20,240}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol9( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol10( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{0,-140},{20,-120}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol11( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Short true hold to have stage change edge signals be better visible" + annotation (Placement(transformation(extent={{40,-140},{60,-120}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.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 example and stage down signal for the second + example from the top" + annotation (Placement(transformation(extent={{-160,220},{-140,240}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[10]( + final k=fill(true, 10)) + "Constant Boolean source" + annotation (Placement(transformation(extent={{-120,260},{-100,280}}))); + + Buildings.Controls.OBC.CDL.Continuous.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 + "Find next higher stage" + annotation (Placement(transformation(extent={{140,200},{160,220}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract subInt1 + "Find next lower stage" + 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 + "Find next higher stage" + annotation (Placement(transformation(extent={{140,20},{160,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract subInt3 + "Find next lower stage" + annotation (Placement(transformation(extent={{140,-20},{160,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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 + "Find next higher stage" + annotation (Placement(transformation(extent={{140,-160},{160,-140}}))); + + Buildings.Controls.OBC.CDL.Integers.Subtract subInt5 + "Find next lower stage" + annotation (Placement(transformation(extent={{140,-200},{160,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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 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 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 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=1) + "Boiler stage" + annotation (Placement(transformation(extent={{140,120},{160,140}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u4( + final k=1) + "Boiler stage" + annotation (Placement(transformation(extent={{140,-60},{160,-40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u5( + final k=1) + "Boiler stage" + annotation (Placement(transformation(extent={{140,-240},{160,-220}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.GreaterThreshold greThr1( + final t=0.5) + "Greater than threshold" + annotation (Placement(transformation(extent={{-160,20},{-140,40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=120) + "True delay to represent staging process" + annotation (Placement(transformation(extent={{70,-240},{90,-220}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol3( + final trueHoldDuration=121, + final falseHoldDuration=0) + "True hold to represent staging process delay" + annotation (Placement(transformation(extent={{40,-240},{60,-220}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol4( + final trueHoldDuration=121, + final falseHoldDuration=0) + "True hold to represent staging process delay" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=120) + "True delay to represent staging process" + annotation (Placement(transformation(extent={{70,-60},{90,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol5( + final trueHoldDuration=121, + final falseHoldDuration=0) + "True hold to represent staging process delay" + annotation (Placement(transformation(extent={{40,120},{60,140}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2( + final delayTime=120) + "True delay to represent staging process" + annotation (Placement(transformation(extent={{70,120},{90,140}}))); + +equation + 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,196},{0,196},{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,subInt1. 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,subInt1. 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,192},{-42,192}}, color={255,127,0})); + connect(cha1.ySta, intToRea1.u) annotation (Line(points={{-18,16},{0,16},{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,subInt3. 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,subInt3. 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,12},{-42,12}}, color={255,127,0})); + connect(timeTable2.y[1], greThr2.u) + annotation (Line(points={{-138,-130},{-122,-130}}, color={0,0,127})); + connect(cha2.ySta, intToRea2.u) annotation (Line(points={{-18,-164},{0,-164},{ + 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,subInt5. 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,subInt5. 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,-168},{-42,-168}}, color={255,127,0})); + connect(noStaChaSig.y, cha.uDow) annotation (Line(points={{-178,110},{-170,110}, + {-170,182},{-42,182}}, color={255,0,255})); + connect(noStaChaSig.y, cha1.uUp) annotation (Line(points={{-178,110},{-170,110}, + {-170,60},{-80,60},{-80,5},{-42,5}}, color={255,0,255})); + connect(greThr.y, cha.uUp) annotation (Line(points={{-98,230},{-64,230},{-64,185}, + {-42,185}}, color={255,0,255})); + connect(greThr2.y, cha2.uUp) annotation (Line(points={{-98,-130},{-80,-130},{-80, + -175},{-42,-175}}, color={255,0,255})); + connect(greThr3.y, cha2.uDow) annotation (Line(points={{-98,-170},{-90,-170}, + {-90,-178},{-42,-178}},color={255,0,255})); + connect(greThr.y, cha1.uDow) annotation (Line(points={{-98,230},{-64,230},{-64, + 2},{-42,2}}, 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,188},{-10,188}, + {-10,130},{-2,130}}, color={255,0,255})); + connect(cha1.yChaEdg, truFalHol1.u) annotation (Line(points={{-18,8},{-10,8},{ + -10,-50},{-2,-50}}, color={255,0,255})); + connect(cha2.yChaEdg, truFalHol2.u) annotation (Line(points={{-18,-172},{-10,-172}, + {-10,-230},{-2,-230}}, color={255,0,255})); + connect(subInt1.y, maxInt.u1) annotation (Line(points={{162,170},{170,170},{ + 170,156},{178,156}}, color={255,127,0})); + 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,188},{-42,188}}, color={255,127,0})); + connect(subInt3.y, maxInt1.u1) annotation (Line(points={{162,-10},{170,-10},{ + 170,-24},{178,-24}}, 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,8},{-42,8}}, color={255,127,0})); + connect(subInt5.y, maxInt2.u1) annotation (Line(points={{162,-190},{170,-190}, + {170,-204},{178,-204}}, 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,-172},{-42,-172}}, 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, + 195},{-42,195}}, color={255,0,255})); + connect(greThr1.y, cha1.uPla) annotation (Line(points={{-138,30},{-130,30},{-130, + 15},{-42,15}}, color={255,0,255})); + connect(greThr1.y, cha2.uPla) annotation (Line(points={{-138,30},{-88,30},{-88, + -165},{-42,-165}}, color={255,0,255})); + + connect(truDel.y, cha2.uStaChaProEnd) annotation (Line(points={{92,-230},{100, + -230},{100,-260},{-39,-260},{-39,-182}}, color={255,0,255})); + connect(truFalHol2.y, truFalHol3.u) + annotation (Line(points={{22,-230},{38,-230}}, color={255,0,255})); + connect(truDel.u, truFalHol3.y) + annotation (Line(points={{68,-230},{62,-230}}, color={255,0,255})); + connect(truFalHol1.y, truFalHol4.u) + annotation (Line(points={{22,-50},{38,-50}}, color={255,0,255})); + connect(truFalHol4.y, truDel1.u) + annotation (Line(points={{62,-50},{68,-50}}, color={255,0,255})); + connect(truDel1.y, cha1.uStaChaProEnd) annotation (Line(points={{92,-50},{100, + -50},{100,-80},{-39,-80},{-39,-2}}, color={255,0,255})); + connect(truFalHol.y, truFalHol5.u) + annotation (Line(points={{22,130},{38,130}}, color={255,0,255})); + connect(truFalHol5.y, truDel2.u) + annotation (Line(points={{62,130},{68,130}}, color={255,0,255})); + connect(truDel2.y, cha.uStaChaProEnd) annotation (Line(points={{92,130},{100,130}, + {100,100},{-39,100},{-39,178}}, color={255,0,255})); + connect(cha.yChaUpEdg, truFalHol6.u) annotation (Line(points={{-18,192},{-10,192}, + {-10,230},{-2,230}}, color={255,0,255})); + connect(truFalHol9.u, cha1.yChaDowEdg) annotation (Line(points={{38,50},{30,50}, + {30,28},{12,28},{12,4},{-18,4}}, color={255,0,255})); + connect(truFalHol10.u, cha2.yChaUpEdg) annotation (Line(points={{-2,-130},{-10, + -130},{-10,-168},{-18,-168}}, color={255,0,255})); + connect(truFalHol11.u, cha2.yChaDowEdg) annotation (Line(points={{38,-130},{30, + -130},{30,-148},{10,-148},{10,-176},{-18,-176}}, color={255,0,255})); + connect(con.y, cha.uStaAva) annotation (Line(points={{-98,270},{-56,270},{-56, + 198},{-42,198}}, color={255,0,255})); + connect(con.y, cha1.uStaAva) annotation (Line(points={{-98,270},{-56,270},{-56, + 18},{-42,18}}, color={255,0,255})); + connect(con.y, cha2.uStaAva) annotation (Line(points={{-98,270},{-56,270},{-56, + -162},{-42,-162}}, color={255,0,255})); +annotation ( + experiment(StopTime=14000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Change.mos" + "Simulate and plot"), + Documentation(info=" +

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

+", 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,-280},{220,300}}))); +end Change; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Configurator.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Configurator.mo new file mode 100644 index 00000000000..b9add4c4fbf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Configurator.mo @@ -0,0 +1,156 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model Configurator "Validate boiler staging configurator subsequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator + conf( + final nSta=5, + final nBoi=3, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final staMat={{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}}, + final boiDesCap={100,150,250}, + final boiFirMin={0.4,0.2,0.3}) + "Validation scenario-1" + annotation (Placement(transformation(extent={{20,90},{40,110}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator + conf1( + final nSta=5, + final nBoi=3, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final staMat={{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}}, + final boiDesCap={100,150,250}, + final boiFirMin={0.4,0.2,0.3}) + "Validation scenario-2" + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator + conf2( + final nSta=5, + final nBoi=3, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final staMat={{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}}, + final boiDesCap={100,150,250}, + final boiFirMin={0.4,0.2,0.3}) + "Validation scenario-3" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator + conf3( + final nSta=5, + final nBoi=3, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final staMat={{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}}, + final boiDesCap={100,150,250}, + final boiFirMin={0.4,0.2,0.3}) + "Validation scenario-4" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator + conf4( + final nSta=5, + final nBoi=3, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final staMat={{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}}, + final boiDesCap={100,150,250}, + final boiFirMin={0.4,0.2,0.3}) + "Validation scenario-5" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Configurator + conf5( + final nSta=5, + final nBoi=3, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final staMat={{1,0,0},{0,1,0},{1,1,0},{0,1,1},{1,1,1}}, + final boiDesCap={100,150,250}, + final boiFirMin={0.4,0.2,0.3}) + "Validation scenario-6" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva[3]( + final k={true,true,true}) + "Boiler availability array" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva1[3]( + final k={false,true,true}) + "Boiler availability array" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva3[3]( + final k={true,true,false}) + "Boiler availability array" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva4[3]( + final k={true,false,false}) + "Boiler availability array" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva5[3]( + final k={false,false,false}) + "Boiler availability array" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva2[3]( + final k={false,false,true}) + "Boiler availability array" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + +equation + connect(boiAva.y, conf.uBoiAva) + annotation (Line(points={{-18,100},{18,100}}, color={255,0,255})); + connect(boiAva1.y, conf1.uBoiAva) + annotation (Line(points={{-18,60},{18,60}}, color={255,0,255})); + connect(boiAva2.y, conf2.uBoiAva) + annotation (Line(points={{-18,20},{18,20}}, color={255,0,255})); + connect(boiAva3.y, conf3.uBoiAva) + annotation (Line(points={{-18,-20},{18,-20}}, color={255,0,255})); + connect(boiAva4.y, conf4.uBoiAva) + annotation (Line(points={{-18,-60},{18,-60}}, color={255,0,255})); + connect(boiAva5.y, conf5.uBoiAva) + annotation (Line(points={{-18,-100},{18,-100}}, color={255,0,255})); +annotation ( + experiment(StopTime=10.0, Tolerance=1e-06), + __Dymola_Commands(file= + "modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Configurator.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Down.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Down.mo new file mode 100644 index 00000000000..33bf80cd22f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Down.mo @@ -0,0 +1,453 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model Down + "Validate model for stage down conditions sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Down + staDow( + final have_priOnl=false, + final nSta=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapNonConBoi=600, + final delDesCapConBoi=300, + final sigDif=0.01, + final bypValClo=0, + final TCirDif=3, + final delTRetDif=300, + final dTemp=0.1, + final TDif=10, + final delFaiCon=900, + final boiMinPriPumSpeSta={0}) + "Scenario testing sequence for condensing-type stage" + annotation (Placement(transformation(extent={{-120,-16},{-100,19}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Down + staDow1( + final have_priOnl=false, + final nSta=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapNonConBoi=600, + final delDesCapConBoi=300, + final sigDif=0.01, + final bypValClo=0, + final TCirDif=3, + final delTRetDif=300, + final dTemp=0.1, + final TDif=10, + final delFaiCon=900, + final boiMinPriPumSpeSta={0}) + "Scenario testing sequence for non-condensing-type stage" + annotation (Placement(transformation(extent={{20,-16},{40,19}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Down + staDow2( + final have_priOnl=true, + final nSta=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapConBoi=300, + final sigDif=0.01, + final delBypVal=300, + final bypValClo=0, + final TCirDif=3, + final dTemp=0.1, + final TDif=10, + final delFaiCon=900, + final boiMinPriPumSpeSta={0}) + "Scenario testing primary-only, condensing-type boiler plant" + annotation (Placement(transformation(extent={{160,-16},{180,19}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Down + staDow3( + final have_priOnl=true, + final nSta=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapConBoi=300, + final sigDif=0.01, + final delBypVal=300, + final bypValClo=0, + final TCirDif=3, + final dTemp=0.1, + final TDif=10, + final delFaiCon=900, + final boiMinPriPumSpeSta={0}) + "Scenario testing primary-only, condensing-type boiler plant" + annotation (Placement(transformation(extent={{270,-16},{290,19}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{-170,90},{-150,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final amplitude=12, + final period=2000, + final offset=69) + "Pulse source" + annotation (Placement(transformation(extent={{-170,50},{-150,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[1]( + final k={1}) + "Stage-type vector" + annotation (Placement(transformation(extent={{-170,160},{-150,180}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Constant integer source" + annotation (Placement(transformation(extent={{-170,120},{-150,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul1( + final amplitude=0.3, + final period=4000, + final offset=1.05) + "Pulse source" + annotation (Placement(transformation(extent={{-170,10},{-150,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul2( + final amplitude=4, + final period=16000, + final offset=79.8) + "Pulse source" + annotation (Placement(transformation(extent={{-170,-150},{-150,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{-172,-190},{-152,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=1) + "Constant real source" + annotation (Placement(transformation(extent={{-168,-30},{-148,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul3( + final amplitude=0.3, + final period=8000, + final offset=0) + "Pulse source" + annotation (Placement(transformation(extent={{-170,-110},{-150,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con5( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{-30,90},{-10,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul4( + final amplitude=12, + final period=2000, + final offset=69) + "Pulse source" + annotation (Placement(transformation(extent={{-30,50},{-10,70}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2[1]( + final k={2}) + "Stage-type vector" + annotation (Placement(transformation(extent={{-30,160},{-10,180}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3( + final k=1) + "Constant integer source" + annotation (Placement(transformation(extent={{-30,120},{-10,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul5( + final amplitude=0.3, + final period=4000, + final offset=1.05) + "Pulse source" + annotation (Placement(transformation(extent={{-30,10},{-10,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul6( + final amplitude=4, + final period=16000, + final offset=79.8) + "Pulse source" + annotation (Placement(transformation(extent={{-30,-150},{-10,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con6( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{-30,-190},{-10,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con7( + final k=1) + "Constant real source" + annotation (Placement(transformation(extent={{-32,-30},{-12,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul7( + final amplitude=0.3, + final period=8000, + final offset=0) + "Pulse source" + annotation (Placement(transformation(extent={{-30,-110},{-10,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con10( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{110,70},{130,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul8( + final amplitude=12, + final period=2000, + final offset=69) + "Pulse source" + annotation (Placement(transformation(extent={{110,30},{130,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4[1]( + final k={1}) + "Stage-type vector" + annotation (Placement(transformation(extent={{110,150},{130,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5( + final k=1) + "Constant integer source" + annotation (Placement(transformation(extent={{110,110},{130,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul9( + final amplitude=0.3, + final period=4000, + final offset=1.05) + "Pulse source" + annotation (Placement(transformation(extent={{110,-70},{130,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con13( + final k=1) + "Constant real source" + annotation (Placement(transformation(extent={{110,-110},{130,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul11( + final amplitude=0.3, + final period=8000, + final offset=-0.1) + "Pulse source" + annotation (Placement(transformation(extent={{110,-190},{130,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul10( + final amplitude=0.6, + final period=16000, + final offset=1.4) + "Pulse source" + annotation (Placement(transformation(extent={{-168,-70},{-148,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul12( + final amplitude=0.6, + final period=16000, + final offset=1.4) + "Pulse source" + annotation (Placement(transformation(extent={{-30,-70},{-10,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul13( + final amplitude=0.6, + final period=16000, + final offset=1.4) + "Pulse source" + annotation (Placement(transformation(extent={{110,-150},{130,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con11( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{220,70},{240,90}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt6[1]( + final k={1}) + "Stage-type vector" + annotation (Placement(transformation(extent={{220,150},{240,170}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7( + final k=1) + "Constant integer source" + annotation (Placement(transformation(extent={{220,110},{240,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con12( + final k=1) + "Constant real source" + annotation (Placement(transformation(extent={{220,-110},{240,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.05, + final period=1000, + final shift=960) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{190,190},{210,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge detector" + annotation (Placement(transformation(extent={{220,190},{240,210}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con9( + final k=80) + "Constant real source" + annotation (Placement(transformation(extent={{220,30},{240,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con14( + final k=1.05) + "Constant real source" + annotation (Placement(transformation(extent={{220,-70},{240,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con15( + final k=1.5) + "Constant real source" + annotation (Placement(transformation(extent={{220,-150},{240,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con16( + final k=0.5) + "Constant real source" + annotation (Placement(transformation(extent={{220,-190},{240,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3( + final k=false) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{-170,190},{-150,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con4( + final k=false) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{-30,190},{-10,210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con8( + final k=false) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{110,190},{130,210}}))); + +equation + connect(con.y, staDow.THotWatSupSet) annotation (Line(points={{-148,100},{-130, + 100},{-130,9},{-122,9}}, color={0,0,127})); + connect(pul.y, staDow.THotWatSup) annotation (Line(points={{-148,60},{-134,60}, + {-134,6},{-122,6}}, color={0,0,127})); + connect(pul1.y, staDow.uCapReq) annotation (Line(points={{-148,20},{-138,20},{ + -138,3},{-122,3}}, color={0,0,127})); + connect(con2.y, staDow.uCapMin) annotation (Line(points={{-146,-20},{-142,-20}, + {-142,0},{-122,0}},color={0,0,127})); + connect(pul3.y, staDow.uPumSpe) annotation (Line(points={{-148,-100},{-138,-100}, + {-138,-9},{-122,-9}}, + color={0,0,127})); + connect(pul2.y, staDow.TPriHotWatRet) annotation (Line(points={{-148,-140},{-134, + -140},{-134,-12},{-122,-12}}, + color={0,0,127})); + connect(con1.y, staDow.TSecHotWatRet) annotation (Line(points={{-150,-180},{-128, + -180},{-128,-15},{-122,-15}}, + color={0,0,127})); + connect(con5.y, staDow1.THotWatSupSet) annotation (Line(points={{-8,100},{8,100}, + {8,9},{18,9}}, color={0,0,127})); + connect(pul4.y, staDow1.THotWatSup) annotation (Line(points={{-8,60},{4,60},{4, + 6},{18,6}}, color={0,0,127})); + connect(pul5.y, staDow1.uCapReq) annotation (Line(points={{-8,20},{0,20},{0,3}, + {18,3}}, color={0,0,127})); + connect(con7.y, staDow1.uCapMin) + annotation (Line(points={{-10,-20},{0,-20},{0,0},{18,0}}, + color={0,0,127})); + connect(pul7.y, staDow1.uPumSpe) + annotation (Line(points={{-8,-100},{8,-100},{8,-9},{18,-9}}, + color={0,0,127})); + connect(pul6.y, staDow1.TPriHotWatRet) annotation (Line(points={{-8,-140},{12, + -140},{12,-12},{18,-12}}, + color={0,0,127})); + connect(con6.y, staDow1.TSecHotWatRet) annotation (Line(points={{-8,-180},{16, + -180},{16,-15},{18,-15}}, + color={0,0,127})); + connect(con10.y, staDow2.THotWatSupSet) annotation (Line(points={{132,80},{144, + 80},{144,9},{158,9}}, color={0,0,127})); + connect(pul8.y, staDow2.THotWatSup) annotation (Line(points={{132,40},{140,40}, + {140,6},{158,6}}, color={0,0,127})); + connect(pul9.y, staDow2.uCapReq) annotation (Line(points={{132,-60},{140,-60}, + {140,3},{158,3}}, color={0,0,127})); + connect(pul11.y, staDow2.uBypValPos) annotation (Line(points={{132,-180},{154, + -180},{154,-6},{158,-6}}, + color={0,0,127})); + connect(pul10.y, staDow.uCapDowDes) annotation (Line(points={{-146,-60},{-140, + -60},{-140,-3},{-122,-3}}, + color={0,0,127})); + connect(pul12.y, staDow1.uCapDowDes) + annotation (Line(points={{-8,-60},{4,-60},{4,-3},{18,-3}}, + color={0,0,127})); + connect(pul13.y, staDow2.uCapDowDes) annotation (Line(points={{132,-140},{150, + -140},{150,-3},{158,-3}}, + color={0,0,127})); + connect(con13.y, staDow2.uCapMin) annotation (Line(points={{132,-100},{146,-100}, + {146,0},{158,0}},color={0,0,127})); + connect(conInt1.y, staDow.uCur) annotation (Line(points={{-148,130},{-126,130}, + {-126,12},{-122,12}}, + color={255,127,0})); + connect(conInt2.y, staDow1.uTyp) annotation (Line(points={{-8,170},{14,170},{14, + 14},{18,14},{18,15}}, + color={255,127,0})); + connect(conInt3.y, staDow1.uCur) annotation (Line(points={{-8,130},{12,130},{12, + 12},{18,12}}, + color={255,127,0})); + connect(conInt4.y, staDow2.uTyp) annotation (Line(points={{132,160},{152,160}, + {152,14},{158,14},{158,15}}, + color={255,127,0})); + connect(conInt5.y, staDow2.uCur) annotation (Line(points={{132,120},{148,120}, + {148,12},{158,12}}, + color={255,127,0})); + connect(conInt.y, staDow.uTyp) annotation (Line(points={{-148,170},{-124,170}, + {-124,15},{-122,15}}, color={255,127,0})); + connect(con3.y, staDow.uStaChaProEnd) annotation (Line(points={{-148,200},{-122, + 200},{-122,18}}, color={255,0,255})); + connect(con4.y, staDow1.uStaChaProEnd) + annotation (Line(points={{-8,200},{18,200},{18,18}}, color={255,0,255})); + connect(con8.y, staDow2.uStaChaProEnd) annotation (Line(points={{132,200},{154, + 200},{154,18},{158,18}}, color={255,0,255})); + connect(con11.y,staDow3. THotWatSupSet) annotation (Line(points={{242,80},{254, + 80},{254,9},{268,9}}, color={0,0,127})); + connect(con12.y,staDow3. uCapMin) annotation (Line(points={{242,-100},{256,-100}, + {256,0},{268,0}},color={0,0,127})); + connect(conInt6.y,staDow3. uTyp) annotation (Line(points={{242,160},{262,160}, + {262,14},{268,14},{268,15}}, + color={255,127,0})); + connect(conInt7.y,staDow3. uCur) annotation (Line(points={{242,120},{258,120}, + {258,12},{268,12}}, + color={255,127,0})); + connect(booPul.y, edg.u) + annotation (Line(points={{212,200},{218,200}}, color={255,0,255})); + connect(edg.y, staDow3.uStaChaProEnd) annotation (Line(points={{242,200},{264, + 200},{264,18},{268,18}}, color={255,0,255})); + connect(con9.y, staDow3.THotWatSup) annotation (Line(points={{242,40},{248,40}, + {248,6},{268,6}}, color={0,0,127})); + connect(con14.y, staDow3.uCapReq) annotation (Line(points={{242,-60},{248,-60}, + {248,3},{268,3}}, color={0,0,127})); + connect(con15.y, staDow3.uCapDowDes) annotation (Line(points={{242,-140},{260, + -140},{260,-3},{268,-3}}, color={0,0,127})); + connect(con16.y, staDow3.uBypValPos) annotation (Line(points={{242,-180},{264, + -180},{264,-6},{268,-6}}, color={0,0,127})); +annotation ( + experiment( + StopTime=16000, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Down.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Down. +

+ ", 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,-200},{300,220}}))); +end Down; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mo new file mode 100644 index 00000000000..37f6d3e5e6f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mo @@ -0,0 +1,274 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +block EfficiencyCondition + "Validation model for EfficiencyCondition" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition + effCon( + final nSta=1, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final sigDif=0.1, + final delCapReq=600) + "Testing efficiency condition for condensing boiler stage type" + annotation (Placement(transformation(extent={{-30,-10},{-10,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition + effCon1( + final nSta=1, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final sigDif=0.1, + final delCapReq=600) + "Testing efficiency condition for non-condensing boiler stage type" + annotation (Placement(transformation(extent={{110,-10},{130,10}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition + effCon2( + final nSta=1, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final sigDif=0.1, + final delCapReq=600) + "Testing efficiency condition for non-condensing boiler stage type with timer reset" + annotation (Placement(transformation(extent={{250,-10},{270,10}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final amplitude=1.2*0.1, + final period=2.5*600, + final offset=1.5 - 1.1*0.1) + "Pulse source" + annotation (Placement(transformation(extent={{-130,110},{-110,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul3( + final amplitude=1.2*0.1, + final period=5*600, + final offset=1 - 1.1*0.1) + "Pulse source" + annotation (Placement(transformation(extent={{-130,-10},{-110,10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conIntp[1]( + final k={1}) + "Constant source" + annotation (Placement(transformation(extent={{-130,-90},{-110,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-130,70},{-110,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-130,30},{-110,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul1( + final amplitude=1.2*0.1, + final period=2.5*600, + final offset=0.9 - 1.1*0.1) + "Pulse source" + annotation (Placement(transformation(extent={{10,110},{30,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul2( + final amplitude=1.2*0.1, + final period=5*600, + final offset=1 - 1.1*0.1) + "Pulse source" + annotation (Placement(transformation(extent={{10,-10},{30,10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conIntp1[1]( + final k={2}) + "Constant source" + annotation (Placement(transformation(extent={{10,-90},{30,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{10,70},{30,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{10,30},{30,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-130,-130},{-110,-110}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{10,-130},{30,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con4( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-130,-50},{-110,-30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con5( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{10,-50},{30,-30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conIntp2[1]( + final k={2}) + "Constant source" + annotation (Placement(transformation(extent={{150,-90},{170,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con6( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{150,70},{170,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con7( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{150,30},{170,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{150,-130},{170,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con8( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{150,-50},{170,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con9( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{-130,-170},{-110,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con10( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{10,-170},{30,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.05, + final period=1000, + final shift=960) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{150,-170},{170,-150}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Edge detector" + annotation (Placement(transformation(extent={{180,-170},{200,-150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con11( + final k=1.6) + "Constant source" + annotation (Placement(transformation(extent={{150,110},{170,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con12( + final k=1.1) + "Constant source" + annotation (Placement(transformation(extent={{150,-10},{170,10}}))); + +equation + connect(conIntp.y, effCon.uTyp) + annotation (Line(points={{-108,-80},{-50,-80},{-50,-6},{-32,-6}}, + color={255,127,0})); + connect(pul3.y, effCon.VHotWat_flow) + annotation (Line(points={{-108,0},{-70,0},{-70,0},{-32,0}}, + color={0,0,127})); + connect(pul.y, effCon.uCapReq) + annotation (Line(points={{-108,120},{-40,120},{-40,9},{-32,9}}, + color={0,0,127})); + connect(con.y, effCon.uCapDes) + annotation (Line(points={{-108,80},{-50,80},{-50,6},{-32,6}}, + color={0,0,127})); + connect(con1.y, effCon.uCapUpMin) + annotation (Line(points={{-108,40},{-60,40},{-60,3},{-32,3}}, + color={0,0,127})); + connect(conIntp1.y, effCon1.uTyp) + annotation (Line(points={{32,-80},{90,-80},{90,-6},{108,-6}}, + color={255,127,0})); + connect(pul2.y, effCon1.VHotWat_flow) + annotation (Line(points={{32,0},{72,0},{72,0},{108,0}}, + color={0,0,127})); + connect(pul1.y, effCon1.uCapReq) + annotation (Line(points={{32,120},{100,120},{100,9},{108,9}}, + color={0,0,127})); + connect(con2.y, effCon1.uCapDes) + annotation (Line(points={{32,80},{90,80},{90,6},{108,6}}, + color={0,0,127})); + connect(con3.y, effCon1.uCapUpMin) + annotation (Line(points={{32,40},{80,40},{80,3},{108,3}}, + color={0,0,127})); + connect(conInt.y, effCon.uAvaUp) + annotation (Line(points={{-108,-120},{-40,-120},{-40,-9},{-32,-9}}, + color={255,127,0})); + connect(conInt1.y, effCon1.uAvaUp) + annotation (Line(points={{32,-120},{100,-120},{100,-9},{108,-9}}, + color={255,127,0})); + connect(con4.y, effCon.VUpMinSet_flow) + annotation (Line(points={{-108,-40},{-60,-40},{-60,-3},{-32,-3}}, + color={0,0,127})); + connect(con5.y, effCon1.VUpMinSet_flow) + annotation (Line(points={{32,-40},{80,-40},{80,-3},{108,-3}}, + color={0,0,127})); + connect(conIntp2.y,effCon2. uTyp) + annotation (Line(points={{172,-80},{230,-80},{230,-6},{248,-6}}, + color={255,127,0})); + connect(con6.y,effCon2. uCapDes) + annotation (Line(points={{172,80},{230,80},{230,6},{248,6}}, + color={0,0,127})); + connect(con7.y,effCon2. uCapUpMin) + annotation (Line(points={{172,40},{220,40},{220,3},{248,3}}, + color={0,0,127})); + connect(conInt2.y,effCon2. uAvaUp) + annotation (Line(points={{172,-120},{240,-120},{240,-9},{248,-9}}, + color={255,127,0})); + connect(con8.y,effCon2. VUpMinSet_flow) + annotation (Line(points={{172,-40},{220,-40},{220,-3},{248,-3}}, + color={0,0,127})); + connect(con9.y, effCon.uStaChaProEnd) annotation (Line(points={{-108,-160},{-29, + -160},{-29,-12}}, color={255,0,255})); + connect(con10.y, effCon1.uStaChaProEnd) annotation (Line(points={{32,-160},{111, + -160},{111,-12}}, color={255,0,255})); + connect(booPul.y, edg.u) + annotation (Line(points={{172,-160},{178,-160}}, color={255,0,255})); + connect(edg.y, effCon2.uStaChaProEnd) annotation (Line(points={{202,-160},{251, + -160},{251,-12}}, color={255,0,255})); + connect(con11.y, effCon2.uCapReq) annotation (Line(points={{172,120},{240,120}, + {240,9},{248,9}}, color={0,0,127})); + connect(con12.y, effCon2.VHotWat_flow) + annotation (Line(points={{172,0},{248,0}}, color={0,0,127})); + annotation(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,-180},{280,140}})), + experiment( + StopTime=7200, + Interval=1, + Tolerance=1e-6), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/EfficiencyCondition.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.EfficiencyCondition +

+ ", + revisions=" + + ")); +end EfficiencyCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mo new file mode 100644 index 00000000000..41cbb1bf1e1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mo @@ -0,0 +1,223 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +block FailsafeCondition + "Validation model for FailsafeCondition" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon( + final delEna=900, + final TDif=10, + final TDifHys=1) + "Testing scenario with FailsafeCondition unmet" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon1( + final delEna=900, + final TDif=10, + final TDifHys=1) + "Testing scenario with FailsafeCondition met" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon2( + final delEna=900, + final TDif=10, + final TDifHys=1) + "Testing scenario exhibiting lower limit of hysteresis loop in sequence being + unmet" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon3( + final delEna=900, + final TDif=10, + final TDifHys=1) + "Testing scenario exhibitng lower limit of hysteresis loop in sequence being + met" + annotation (Placement(transformation(extent={{60,-60},{80,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition + faiSafCon4( + final delEna=900, + final TDif=10, + final TDifHys=1) + "Testing scenario with timer reset" + annotation (Placement(transformation(extent={{140,40},{160,60}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final amplitude=-10 + 1, + final period=2.5*900, + final offset=80) + "Pulse input" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul1( + final amplitude=-10 - 1, + final period=2.5*900, + final offset=80) + "Pulse input" + annotation (Placement(transformation(extent={{20,40},{40,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul2( + final amplitude=-1, + final period=2.5*900, + final offset=80 - 10) + "Pulse input" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul3( + final amplitude=-2*1 - 1/10, + final period=2.5*900, + final offset=80 - 10 + 1 + 1/10) + "Pulse input" + annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con4( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{100,70},{120,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con5( + final k=69) + "Constant input" + annotation (Placement(transformation(extent={{100,40},{120,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.05, + final period=1000, + final shift=960) + "Boolean pulse signal" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con6( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con7( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con8( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con9( + final k=false) + "Constant Boolean false" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Rising edge detector" + annotation (Placement(transformation(extent={{110,10},{130,30}}))); + +equation + connect(con.y, faiSafCon.TSupSet) + annotation (Line(points={{-58,80},{-50,80},{-50,55},{-42,55}}, + color={0,0,127})); + connect(pul.y, faiSafCon.TSup) + annotation (Line(points={{-58,50},{-50,50},{-50,50},{-42,50}}, + color={0,0,127})); + connect(con1.y, faiSafCon1.TSupSet) + annotation (Line(points={{42,80},{50,80},{50,55},{58,55}}, + color={0,0,127})); + connect(pul1.y, faiSafCon1.TSup) + annotation (Line(points={{42,50},{50,50},{50,50},{58,50}}, + color={0,0,127})); + connect(con2.y,faiSafCon2.TSupSet) + annotation (Line(points={{-58,-20},{-50,-20},{-50,-45},{-42,-45}}, + color={0,0,127})); + connect(pul2.y,faiSafCon2.TSup) + annotation (Line(points={{-58,-50},{-50,-50},{-50,-50},{-42,-50}}, + color={0,0,127})); + connect(con3.y,faiSafCon3.TSupSet) + annotation (Line(points={{42,-20},{50,-20},{50,-45},{58,-45}}, + color={0,0,127})); + connect(pul3.y,faiSafCon3.TSup) + annotation (Line(points={{42,-50},{50,-50},{50,-50},{58,-50}}, + color={0,0,127})); + connect(con4.y,faiSafCon4. TSupSet) + annotation (Line(points={{122,80},{130,80},{130,55},{138,55}}, + color={0,0,127})); + connect(con5.y, faiSafCon4.TSup) + annotation (Line(points={{122,50},{130,50},{130,50},{138,50}}, + color={0,0,127})); + connect(con6.y, faiSafCon.uStaChaProEnd) + annotation (Line(points={{-58,20},{-50,20},{-50,45},{-42,45}}, + color={255,0,255})); + connect(con7.y, faiSafCon2.uStaChaProEnd) + annotation (Line(points={{-58,-80},{-50,-80},{-50,-55},{-42,-55}}, + color={255,0,255})); + connect(con8.y, faiSafCon1.uStaChaProEnd) + annotation (Line(points={{42,20},{50,20},{50,45},{58,45}}, + color={255,0,255})); + connect(con9.y, faiSafCon3.uStaChaProEnd) + annotation (Line(points={{42,-80},{50,-80},{50,-55},{58,-55}}, + color={255,0,255})); + connect(booPul.y, edg.u) + annotation (Line(points={{102,20},{108,20}}, + color={255,0,255})); + connect(edg.y, faiSafCon4.uStaChaProEnd) + annotation (Line(points={{132,20},{134,20},{134,45},{138,45}}, + color={255,0,255})); + annotation ( + 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},{180,100}})), + experiment( + StopTime=7200, + Interval=1, + Tolerance=1e-6), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.FailsafeCondition +

+ ", + revisions=" + + "), + __Dymola_Commands(file= + "./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/FailsafeCondition.mos" + "Simulate and plot")); +end FailsafeCondition; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Status.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Status.mo new file mode 100644 index 00000000000..709ea3de18f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Status.mo @@ -0,0 +1,227 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model Status + "Validates boiler stage status subsequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta( + final nSta=4, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests boiler stage status" + annotation (Placement(transformation(extent={{-40,120},{-20,140}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta1( + final nSta=4, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests boiler stage status at the first stage" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta2( + final nSta=4, + final nBoi=3, + final staMat={{0,1,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests boiler stage status with no higher stages available" + annotation (Placement(transformation(extent={{120,120},{140,140}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta3( + final nSta=4, + final nBoi=3, + final staMat={{0,1,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests boiler stage status with no lower stages available" + annotation (Placement(transformation(extent={{120,40},{140,60}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta4( + final nSta=4, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests boiler stage status at the highest stage" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Status sta6( + final nSta=4, + final nBoi=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.BoilerPlant.Staging.SetPoints.Subsequences.Status sta7( + final nSta=4, + final nBoi=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.BoilerPlant.Staging.SetPoints.Subsequences.Status sta5( + final nSta=4, + final nBoi=3, + final staMat={{1,0,0},{1,1,0},{0,1,1},{1,1,1}}) + "Tests boiler 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) + "Boiler stage" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u1( + final k=2) + "Boiler stage" + annotation (Placement(transformation(extent={{-140,20},{-120,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u2( + final k=3) + "Boiler stage" + annotation (Placement(transformation(extent={{20,100},{40,120}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u3( + final k=1) + "Boiler stage" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u4( + final k=4) + "Boiler stage" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u5( + final k=2) + "Boiler stage" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant u7( + final k=0) + "Boiler 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) + "Logical value 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/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Status.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Up.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Up.mo new file mode 100644 index 00000000000..7ffe58191b2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Up.mo @@ -0,0 +1,319 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Validation; +model Up + "Validate model for stage up conditions sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Up + staUp( + final nSta=2, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final delEffCon=600, + final delFaiCon=900, + final sigDif=0.1, + final TDif=10, + final TDifHys=1) + "Scenario testing activation by efficiency condition" + annotation (Placement(transformation(extent={{-100,-16},{-80,16}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Up + staUp1( + final nSta=2, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final delEffCon=600, + final delFaiCon=900, + final sigDif=0.1, + final TDif=10, + final TDifHys=1) + "Scenario testing activation by failsafe condition" + annotation (Placement(transformation(extent={{30,-16},{50,16}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences.Up + staUp2( + final nSta=2, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final delEffCon=600, + final delFaiCon=900, + final sigDif=0.1, + final TDif=10, + final TDifHys=1) + "Scenario testing activation due to current stage unavailability" + annotation (Placement(transformation(extent={{160,-16},{180,16}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con6( + final k=true) "Constant Boolean True signal" + annotation (Placement(transformation(extent={{-180,-190},{-160,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con7( + final k=true) "Constant Boolean True signal" + annotation (Placement(transformation(extent={{-50,-190},{-30,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=600) "Boolean pulse signal" + annotation (Placement(transformation(extent={{80,-190},{100,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-180,130},{-160,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-180,90},{-160,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul3( + final amplitude=1.2*0.1, + final period=5*10*60, + final offset=1 - 1.1*0.1) + "Pulse source" + annotation (Placement(transformation(extent={{-180,50},{-160,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con4( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-180,10},{-160,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conIntp[2]( + final k={1,1}) + "Constant source" + annotation (Placement(transformation(extent={{-180,-30},{-160,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=2) + "Constant source" + annotation (Placement(transformation(extent={{-180,-70},{-160,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{-180,-110},{-160,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=1.6) + "Constant source" + annotation (Placement(transformation(extent={{-180,170},{-160,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con5( + final k=82) + "Constant input" + annotation (Placement(transformation(extent={{-180,-150},{-160,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con8( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-50,130},{-30,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con9( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-50,90},{-30,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con10( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{-50,10},{-30,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conIntp1[2]( + final k={1,1}) + "Constant source" + annotation (Placement(transformation(extent={{-50,-30},{-30,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1( + final k=2) + "Constant source" + annotation (Placement(transformation(extent={{-50,-70},{-30,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con12( + final k=1.3) + "Constant source" + annotation (Placement(transformation(extent={{-50,170},{-30,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con15( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con16( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{80,90},{100,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con17( + final k=1) + "Constant source" + annotation (Placement(transformation(extent={{80,10},{100,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conIntp2[2]( + final k={1,1}) + "Constant source" + annotation (Placement(transformation(extent={{80,-30},{100,-10}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2( + final k=2) + "Constant source" + annotation (Placement(transformation(extent={{80,-70},{100,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con18( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{80,-110},{100,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con19( + final k=1.3) + "Constant source" + annotation (Placement(transformation(extent={{80,170},{100,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con20( + final k=82) + "Constant input" + annotation (Placement(transformation(extent={{80,-150},{100,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con21( + final k=1.1) + "Constant source" + annotation (Placement(transformation(extent={{-50,50},{-30,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con13( + final k=80) + "Constant input" + annotation (Placement(transformation(extent={{-50,-110},{-30,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse pul( + final amplitude=-11.2, + final period=2.5*900, + final offset=81.1) + "Pulse input" + annotation (Placement(transformation(extent={{-50,-150},{-30,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con11( + final k=1.1) + "Constant source" + annotation (Placement(transformation(extent={{80,50},{100,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con14( + final k=false) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{-180,-230},{-160,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con22( + final k=false) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{-50,-230},{-30,-210}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con23( + final k=false) + "Constant Boolean False signal" + annotation (Placement(transformation(extent={{80,-230},{100,-210}}))); + +equation + connect(staUp.uCapDes, con.y) annotation (Line(points={{-102,12},{-114,12},{-114, + 140},{-158,140}}, color={0,0,127})); + connect(con1.y, staUp.uCapUpMin) annotation (Line(points={{-158,100},{-120,100}, + {-120,9},{-102,9}}, color={0,0,127})); + connect(pul3.y, staUp.VHotWat_flow) annotation (Line(points={{-158,60},{-126,60}, + {-126,6},{-102,6}}, color={0,0,127})); + connect(con4.y, staUp.VUpMinSet_flow) annotation (Line(points={{-158,20},{-132, + 20},{-132,3},{-102,3}}, color={0,0,127})); + connect(conIntp.y, staUp.uTyp) annotation (Line(points={{-158,-20},{-132,-20}, + {-132,0},{-102,0}}, color={255,127,0})); + connect(conInt.y, staUp.uAvaUp) annotation (Line(points={{-158,-60},{-126,-60}, + {-126,-3},{-102,-3}}, color={255,127,0})); + connect(con2.y, staUp.THotWatSupSet) annotation (Line(points={{-158,-100},{-120, + -100},{-120,-6},{-102,-6}}, color={0,0,127})); + connect(con3.y, staUp.uCapReq) annotation (Line(points={{-158,180},{-110,180}, + {-110,15},{-102,15}}, + color={0,0,127})); + connect(con5.y, staUp.THotWatSup) annotation (Line(points={{-158,-140},{-114,-140}, + {-114,-9},{-102,-9}}, color={0,0,127})); + connect(con6.y, staUp.uAvaCur) annotation (Line(points={{-158,-180},{-110,-180}, + {-110,-12},{-102,-12}}, + color={255,0,255})); + connect(staUp1.uCapDes, con8.y) annotation (Line(points={{28,12},{16,12},{16,140}, + {-28,140}}, color={0,0,127})); + connect(con9.y, staUp1.uCapUpMin) annotation (Line(points={{-28,100},{10,100}, + {10,9},{28,9}}, color={0,0,127})); + connect(con10.y, staUp1.VUpMinSet_flow) annotation (Line(points={{-28,20},{-2, + 20},{-2,3},{28,3}}, color={0,0,127})); + connect(conIntp1.y, staUp1.uTyp) annotation (Line(points={{-28,-20},{-2,-20},{ + -2,0},{28,0}}, color={255,127,0})); + connect(conInt1.y, staUp1.uAvaUp) annotation (Line(points={{-28,-60},{4,-60},{ + 4,-3},{28,-3}}, color={255,127,0})); + connect(con12.y, staUp1.uCapReq) annotation (Line(points={{-28,180},{20,180},{ + 20,15},{28,15}}, + color={0,0,127})); + connect(con7.y, staUp1.uAvaCur) annotation (Line(points={{-28,-180},{20,-180}, + {20,-12},{28,-12}}, + color={255,0,255})); + connect(staUp2.uCapDes, con15.y) annotation (Line(points={{158,12},{146,12},{146, + 140},{102,140}}, color={0,0,127})); + connect(con16.y, staUp2.uCapUpMin) annotation (Line(points={{102,100},{140,100}, + {140,9},{158,9}}, color={0,0,127})); + connect(con17.y, staUp2.VUpMinSet_flow) annotation (Line(points={{102,20},{128, + 20},{128,3},{158,3}}, color={0,0,127})); + connect(conIntp2.y, staUp2.uTyp) annotation (Line(points={{102,-20},{128,-20}, + {128,0},{158,0}}, color={255,127,0})); + connect(conInt2.y, staUp2.uAvaUp) annotation (Line(points={{102,-60},{134,-60}, + {134,-3},{158,-3}}, color={255,127,0})); + connect(con18.y, staUp2.THotWatSupSet) annotation (Line(points={{102,-100},{140, + -100},{140,-6},{158,-6}}, color={0,0,127})); + connect(con19.y, staUp2.uCapReq) annotation (Line(points={{102,180},{150,180}, + {150,15},{158,15}}, + color={0,0,127})); + connect(con20.y, staUp2.THotWatSup) annotation (Line(points={{102,-140},{146,-140}, + {146,-9},{158,-9}}, color={0,0,127})); + connect(con21.y, staUp1.VHotWat_flow) + annotation (Line(points={{-28,60},{4,60},{4,6},{28,6}}, color={0,0,127})); + connect(con13.y, staUp1.THotWatSupSet) annotation (Line(points={{-28,-100},{10, + -100},{10,-6},{28,-6}}, color={0,0,127})); + connect(pul.y, staUp1.THotWatSup) annotation (Line(points={{-28,-140},{16,-140}, + {16,-9},{28,-9}}, color={0,0,127})); + connect(con11.y, staUp2.VHotWat_flow) annotation (Line(points={{102,60},{134,60}, + {134,6},{158,6}}, color={0,0,127})); + connect(booPul.y, staUp2.uAvaCur) annotation (Line(points={{102,-180},{150,-180}, + {150,-12},{158,-12}}, + color={255,0,255})); + connect(con14.y, staUp.uStaChaProEnd) annotation (Line(points={{-158,-220},{-106, + -220},{-106,-15},{-102,-15}}, color={255,0,255})); + connect(con22.y, staUp1.uStaChaProEnd) annotation (Line(points={{-28,-220},{24, + -220},{24,-15},{28,-15}}, color={255,0,255})); + connect(con23.y, staUp2.uStaChaProEnd) annotation (Line(points={{102,-220},{154, + -220},{154,-15},{158,-15}}, color={255,0,255})); + +annotation ( + experiment( + StopTime=7200, + Interval=1, + Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/Up.mos" + "Simulate and plot"), + Documentation(info=" +

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

+ ", 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,-240},{200,200}}))); +end Up; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/package.mo new file mode 100644 index 00000000000..bb879253a48 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/package.mo @@ -0,0 +1,36 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Subsequences; +package Validation "Collection of validation models" +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

+ This package contains validation models for the classes in + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.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. +

+ ")); +end Validation; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/package.order new file mode 100644 index 00000000000..369181c67db --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/Validation/package.order @@ -0,0 +1,10 @@ +BoilerIndices +Capacities +CapacityRequirement +Change +Configurator +Down +EfficiencyCondition +FailsafeCondition +Status +Up diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/package.mo new file mode 100644 index 00000000000..11417c8b6ed --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/package.mo @@ -0,0 +1,43 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints; +package Subsequences "Boiler staging setpoint subsequences" + + annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Ellipse( + origin={10,10}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10,10}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10,10}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10,10}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})}), + Documentation(info=" +

+ This package contains subsequences used in boiler staging setpoint control. +

+ ")); +end Subsequences; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/package.order new file mode 100644 index 00000000000..d1db2c14227 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Subsequences/package.order @@ -0,0 +1,11 @@ +BoilerIndices +Capacities +CapacityRequirement +Change +Configurator +Down +EfficiencyCondition +FailsafeCondition +Status +Up +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/SetpointController.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/SetpointController.mo new file mode 100644 index 00000000000..279485de299 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/SetpointController.mo @@ -0,0 +1,554 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.Validation; +model SetpointController + "Validates boiler stage status setpoint signal generation for boiler plants" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.SetpointController staSetCon( + final have_priOnl=false, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final boiDesCap={1000000,1500000}, + final boiFirMin={0.2,0.3}, + final boiMinPriPumSpeSta={0,0,0}, + final delStaCha=600, + final avePer=300, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final delEffCon=600, + final TDif=10, + final delFaiCon=900, + final sigDif=0.01, + final TDifHys=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapNonConBoi=600, + final delDesCapConBoi=300, + final TCirDif=3, + final delTRetDif=300, + final dTemp=0.1) + "Testing staging setpoint controller for condensing boiler plant that is not primary-only" + annotation (Placement(transformation(extent={{60,140},{80,176}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.SetpointController staSetCon1( + final have_priOnl=false, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.nonCondensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final boiDesCap={1000000,1500000}, + final boiFirMin={0.2,0.3}, + final boiMinPriPumSpeSta={0,0,0}, + final delStaCha=600, + final avePer=300, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final delEffCon=600, + final TDif=10, + final delFaiCon=900, + final sigDif=0.01, + final TDifHys=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapNonConBoi=600, + final delDesCapConBoi=300, + final TCirDif=3, + final delTRetDif=300, + final dTemp=0.1) + "Testing staging setpoint controller for non-condensing boiler plant" + annotation (Placement(transformation(extent={{60,-100},{80,-64}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints.SetpointController staSetCon2( + final have_priOnl=true, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final boiDesCap={1000000,1500000}, + final boiFirMin={0.2,0.3}, + final boiMinPriPumSpeSta={0,0,0}, + final delStaCha=600, + final avePer=300, + final fraNonConBoi=0.9, + final fraConBoi=1.5, + final delEffCon=600, + final TDif=10, + final delFaiCon=900, + final sigDif=0.01, + final TDifHys=1, + final fraMinFir=1.1, + final delMinFir=300, + final fraDesCap=0.8, + final delDesCapNonConBoi=600, + final delDesCapConBoi=300, + final TCirDif=3, + final delTRetDif=300, + final dTemp=0.1) + "Testing staging setpoint controller for primary-only, condensing boiler plant" + annotation (Placement(transformation(extent={{460,140},{480,176}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staCha( + final trueHoldDuration=900, + final falseHoldDuration=0) + "Detect stage change signal" + annotation (Placement(transformation(extent={{100,60},{120,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staCha1( + final trueHoldDuration=900, + final falseHoldDuration=0) + "Detect stage change signal" + annotation (Placement(transformation(extent={{100,-180},{120,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staCha2( + final trueHoldDuration=900, + final falseHoldDuration=0) + "Detect stage change signal" + annotation (Placement(transformation(extent={{500,60},{520,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staUp( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Detect stage up signal" + annotation (Placement(transformation(extent={{100,180},{120,200}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staUp1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Detect stage up signal" + annotation (Placement(transformation(extent={{100,-60},{120,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staUp2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Detect stage up signal" + annotation (Placement(transformation(extent={{500,180},{520,200}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staDow( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Detect stage down signal" + annotation (Placement(transformation(extent={{100,120},{120,140}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staDow1( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Detect stage down signal" + annotation (Placement(transformation(extent={{100,-120},{120,-100}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueFalseHold staDow2( + final trueHoldDuration=10, + final falseHoldDuration=0) + "Detect stage down signal" + annotation (Placement(transformation(extent={{500,120},{520,140}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine THotWatRet( + final amplitude=7, + final phase=0, + final offset=273.15 + 22, + final freqHz=1/21600) + "Hot water return temeprature" + annotation (Placement(transformation(extent={{-80,178},{-60,198}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva[2]( + final k={true,true}) + "Boiler availability vector" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=10) "Hold stage setpoint for signal feedback" + annotation (Placement(transformation(extent={{140,148},{160,168}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Integer to Real converter" + annotation (Placement(transformation(extent={{100,148},{120,168}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer converter" + annotation (Placement(transformation(extent={{180,148},{200,168}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3 + "Logical pre block" + annotation (Placement(transformation(extent={{130,60},{150,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta( + final k=true) + "Plant status" + annotation (Placement(transformation(extent={{-160,40},{-140,60}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=10, + final delayOnInit=true) + "Delay plant enable signal" + annotation (Placement(transformation(extent={{-120,40},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatSupSet( + final k=273.15 + 30) + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-80,210},{-60,230}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zero( + final k=10^(-10)) + "Constant" + annotation (Placement(transformation(extent={{-160,110},{-140,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatSup( + final k=273.15 + 30) + "Hot water supply temperature" + annotation (Placement(transformation(extent={{-80,130},{-60,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWat_flow( + final k=0.037) + "Hot water flow rate" + annotation (Placement(transformation(extent={{-160,170},{-140,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatRetSec( + final k=273.15 + 26) + "Hot water secondary loop return temperature" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine uPumSpe( + final amplitude=1, + final offset=0, + final freqHz=1/21600) + "Pump speed signal" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg1 + "Falling edge detector" + annotation (Placement(transformation(extent={{160,-180},{180,-160}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1( + final nout=3) + "Convert input into array" + annotation (Placement(transformation(extent={{-120,-130},{-100,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine THotWatRet1( + final amplitude=7, + final phase=0, + final offset=273.15 + 22, + final freqHz=1/21600) + "Hot water return temeprature" + annotation (Placement(transformation(extent={{-80,-62},{-60,-42}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva1[2]( + final k={true,true}) + "Boiler availability vector" + annotation (Placement(transformation(extent={{-160,-230},{-140,-210}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1( + final samplePeriod=10) + "Hold stage setpoint for signal feedback" + annotation (Placement(transformation(extent={{140,-92},{160,-72}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Integer to Real converter" + annotation (Placement(transformation(extent={{100,-92},{120,-72}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to Integer converter" + annotation (Placement(transformation(extent={{180,-92},{200,-72}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1 + "Logical pre block" + annotation (Placement(transformation(extent={{130,-180},{150,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta1( + final k=true) + "Plant status" + annotation (Placement(transformation(extent={{-160,-200},{-140,-180}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=10, + final delayOnInit=true) + "Delay plant enable signal" + annotation (Placement(transformation(extent={{-120,-200},{-100,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatSupSet1( + final k=273.15 + 30) + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zero1( + final k=10^(-10)) + "Constant" + annotation (Placement(transformation(extent={{-160,-130},{-140,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatSup1( + final k=273.15 + 30) + "Hot water supply temperature" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWat_flow1( + final k=0.037) + "Hot water flow rate" + annotation (Placement(transformation(extent={{-160,-70},{-140,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatRetSec1( + final k=273.15 + 26) + "Hot water secondary loop return temperature" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine uPumSpe1( + final amplitude=1, + final offset=0, + final freqHz=1/21600) "Pump speed signal" + annotation (Placement(transformation(extent={{-80,-180},{-60,-160}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg2 + "Falling edge detector" + annotation (Placement(transformation(extent={{560,60},{580,80}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep2( + final nout=3) + "Convert input into array" + annotation (Placement(transformation(extent={{280,110},{300,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine THotWatRet2( + final amplitude=7, + final phase=0, + final offset=273.15 + 22, + final freqHz=1/21600) + "Hot water return temeprature" + annotation (Placement(transformation(extent={{320,170},{340,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant boiAva2[2]( + final k={true,true}) + "Boiler availability vector" + annotation (Placement(transformation(extent={{240,10},{260,30}}))); + + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2( + final samplePeriod=10) + "Hold stage setpoint for signal feedback" + annotation (Placement(transformation(extent={{540,148},{560,168}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea2 + "Integer to Real converter" + annotation (Placement(transformation(extent={{500,148},{520,168}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Real to Integer converter" + annotation (Placement(transformation(extent={{580,148},{600,168}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2 + "Logical pre block" + annotation (Placement(transformation(extent={{530,60},{550,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaSta2( + final k=true) + "Plant status" + annotation (Placement(transformation(extent={{240,40},{260,60}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2( + final delayTime=10, + final delayOnInit=true) + "Delay plant enable signal" + annotation (Placement(transformation(extent={{280,40},{300,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatSupSet2( + final k=273.15 + 30) + "Hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{320,202},{340,222}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zero2( + final k=10^(-10)) + "Constant" + annotation (Placement(transformation(extent={{240,110},{260,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant THotWatSup2( + final k=273.15 + 30) + "Hot water supply temperature" + annotation (Placement(transformation(extent={{320,130},{340,150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWat_flow2( + final k=0.037) + "Hot water flow rate" + annotation (Placement(transformation(extent={{240,170},{260,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine uPumSpe2( + final amplitude=1, + final offset=0, + final freqHz=1/21600) "Pump speed signal" + annotation (Placement(transformation(extent={{320,80},{340,100}}))); + + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Falling edge detector" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=3) + "Convert input into array" + annotation (Placement(transformation(extent={{-120,110},{-100,130}}))); + +equation + connect(staSetCon.ySta,intToRea. u) + annotation (Line(points={{82,166},{94,166},{94,158},{98,158}}, + color={255,127,0})); + connect(intToRea.y,zerOrdHol. u) + annotation (Line(points={{122,158},{138,158}}, + color={0,0,127})); + connect(zerOrdHol.y,reaToInt. u) + annotation (Line(points={{162,158},{178,158}}, + color={0,0,127})); + connect(reaToInt.y,staSetCon. u) annotation (Line(points={{202,158},{210,158}, + {210,100},{48,100},{48,145},{58,145}}, + color={255,127,0})); + connect(staSetCon.yChaEdg, staCha.u) annotation (Line(points={{82,158},{90,158}, + {90,70},{98,70}}, color={255,0,255})); + connect(staCha.y, pre3.u) + annotation (Line(points={{122,70},{128,70}}, color={255,0,255})); + connect(truDel.y,staSetCon. uPla) annotation (Line(points={{-98,50},{32,50},{32, + 148},{58,148}}, + color={255,0,255})); + connect(plaSta.y, truDel.u) annotation (Line(points={{-138,50},{-122,50}}, + color={255,0,255})); + connect(pre3.y, falEdg.u) + annotation (Line(points={{152,70},{158,70}}, color={255,0,255})); + connect(falEdg.y, staSetCon.uStaChaProEnd) annotation (Line(points={{182,70},{ + 190,70},{190,50},{61,50},{61,138}}, color={255,0,255})); + connect(THotWatSupSet.y, staSetCon.THotWatSupSet) annotation (Line(points={{-58,220}, + {-30,220},{-30,175},{58,175}}, color={0,0,127})); + connect(THotWatRet.y, staSetCon.THotWatRet) annotation (Line(points={{-58,188}, + {-48,188},{-48,172},{58,172}}, color={0,0,127})); + connect(THotWatSup.y, staSetCon.THotWatSup) annotation (Line(points={{-58,140}, + {-40,140},{-40,166},{58,166}}, color={0,0,127})); + connect(zero.y, reaRep.u) annotation (Line(points={{-138,120},{-122,120}}, + color={0,0,127})); + connect(reaRep.y, staSetCon.VMinSet_flow) annotation (Line(points={{-98,120},{ + -30,120},{-30,163},{58,163}}, color={0,0,127})); + connect(boiAva.y, staSetCon.uBoiAva) annotation (Line(points={{-138,20},{40,20}, + {40,142},{58,142}}, color={255,0,255})); + connect(VHotWat_flow.y, staSetCon.VHotWat_flow) annotation (Line(points={{-138, + 180},{-100,180},{-100,169},{58,169}}, color={0,0,127})); + connect(THotWatRet.y, staSetCon.THotWatRetPri) annotation (Line(points={{-58,188}, + {-48,188},{-48,157},{58,157}}, color={0,0,127})); + connect(THotWatRetSec.y, staSetCon.THotWatRetSec) annotation (Line(points={{-58,100}, + {-24,100},{-24,154},{58,154}}, color={0,0,127})); + connect(uPumSpe.y, staSetCon.uPumSpe) annotation (Line(points={{-58,70},{-16,70}, + {-16,151},{58,151}}, color={0,0,127})); + connect(staUp.u, staSetCon.yChaUpEdg) annotation (Line(points={{98,190},{90,190}, + {90,162},{82,162}}, color={255,0,255})); + connect(staDow.u, staSetCon.yChaDowEdg) annotation (Line(points={{98,130},{94, + 130},{94,154},{82,154}}, color={255,0,255})); + connect(staSetCon1.ySta, intToRea1.u) + annotation (Line(points={{82,-74},{94,-74},{94,-82},{98,-82}}, + color={255,127,0})); + connect(intToRea1.y, zerOrdHol1.u) + annotation (Line(points={{122,-82},{138,-82}}, color={0,0,127})); + connect(zerOrdHol1.y, reaToInt1.u) + annotation (Line(points={{162,-82},{178,-82}}, color={0,0,127})); + connect(reaToInt1.y, staSetCon1.u) annotation (Line(points={{202,-82},{210,-82}, + {210,-140},{48,-140},{48,-95},{58,-95}}, color={255,127,0})); + connect(staSetCon1.yChaEdg, staCha1.u) annotation (Line(points={{82,-82},{90,-82}, + {90,-170},{98,-170}}, color={255,0,255})); + connect(staCha1.y, pre1.u) + annotation (Line(points={{122,-170},{128,-170}}, color={255,0,255})); + connect(truDel1.y, staSetCon1.uPla) annotation (Line(points={{-98,-190},{32,-190}, + {32,-92},{58,-92}}, color={255,0,255})); + connect(plaSta1.y, truDel1.u) + annotation (Line(points={{-138,-190},{-122,-190}}, color={255,0,255})); + connect(pre1.y, falEdg1.u) + annotation (Line(points={{152,-170},{158,-170}}, color={255,0,255})); + connect(falEdg1.y, staSetCon1.uStaChaProEnd) annotation (Line(points={{182,-170}, + {190,-170},{190,-190},{61,-190},{61,-102}}, color={255,0,255})); + connect(THotWatSupSet1.y, staSetCon1.THotWatSupSet) annotation (Line(points={{-58,-20}, + {-30,-20},{-30,-65},{58,-65}}, color={0,0,127})); + connect(THotWatRet1.y, staSetCon1.THotWatRet) annotation (Line(points={{-58,-52}, + {-48,-52},{-48,-68},{58,-68}}, color={0,0,127})); + connect(THotWatSup1.y, staSetCon1.THotWatSup) annotation (Line(points={{-58,-100}, + {-40,-100},{-40,-74},{58,-74}}, color={0,0,127})); + connect(zero1.y, reaRep1.u) + annotation (Line(points={{-138,-120},{-122,-120}}, color={0,0,127})); + connect(reaRep1.y, staSetCon1.VMinSet_flow) annotation (Line(points={{-98,-120}, + {-30,-120},{-30,-77},{58,-77}}, color={0,0,127})); + connect(boiAva1.y, staSetCon1.uBoiAva) annotation (Line(points={{-138,-220},{40, + -220},{40,-98},{58,-98}}, color={255,0,255})); + connect(VHotWat_flow1.y, staSetCon1.VHotWat_flow) annotation (Line(points={{-138, + -60},{-100,-60},{-100,-71},{58,-71}}, color={0,0,127})); + connect(THotWatRet1.y, staSetCon1.THotWatRetPri) annotation (Line(points={{-58,-52}, + {-48,-52},{-48,-83},{58,-83}}, color={0,0,127})); + connect(THotWatRetSec1.y, staSetCon1.THotWatRetSec) annotation (Line(points={{-58, + -140},{-24,-140},{-24,-86},{58,-86}}, color={0,0,127})); + connect(uPumSpe1.y, staSetCon1.uPumSpe) annotation (Line(points={{-58,-170},{-16, + -170},{-16,-89},{58,-89}}, color={0,0,127})); + connect(staUp1.u, staSetCon1.yChaUpEdg) annotation (Line(points={{98,-50},{90, + -50},{90,-78},{82,-78}}, color={255,0,255})); + connect(staDow1.u, staSetCon1.yChaDowEdg) annotation (Line(points={{98,-110},{ + 94,-110},{94,-86},{82,-86}}, color={255,0,255})); + connect(staSetCon2.ySta, intToRea2.u) + annotation (Line(points={{482,166},{494,166},{494,158},{498,158}}, + color={255,127,0})); + connect(intToRea2.y, zerOrdHol2.u) + annotation (Line(points={{522,158},{538,158}}, color={0,0,127})); + connect(zerOrdHol2.y, reaToInt2.u) + annotation (Line(points={{562,158},{578,158}}, color={0,0,127})); + connect(reaToInt2.y, staSetCon2.u) annotation (Line(points={{602,158},{610,158}, + {610,100},{448,100},{448,145},{458,145}}, color={255,127,0})); + connect(staSetCon2.yChaEdg, staCha2.u) annotation (Line(points={{482,158},{490, + 158},{490,70},{498,70}}, color={255,0,255})); + connect(staCha2.y, pre2.u) + annotation (Line(points={{522,70},{528,70}}, color={255,0,255})); + connect(truDel2.y, staSetCon2.uPla) annotation (Line(points={{302,50},{432,50}, + {432,148},{458,148}}, color={255,0,255})); + connect(plaSta2.y, truDel2.u) + annotation (Line(points={{262,50},{278,50}}, color={255,0,255})); + connect(pre2.y, falEdg2.u) + annotation (Line(points={{552,70},{558,70}}, color={255,0,255})); + connect(falEdg2.y, staSetCon2.uStaChaProEnd) annotation (Line(points={{582,70}, + {590,70},{590,50},{461,50},{461,138}}, color={255,0,255})); + connect(THotWatSupSet2.y, staSetCon2.THotWatSupSet) annotation (Line(points={{342,212}, + {370,212},{370,175},{458,175}}, color={0,0,127})); + connect(THotWatRet2.y, staSetCon2.THotWatRet) annotation (Line(points={{342,180}, + {352,180},{352,172},{458,172}}, color={0,0,127})); + connect(THotWatSup2.y, staSetCon2.THotWatSup) annotation (Line(points={{342,140}, + {360,140},{360,166},{458,166}}, color={0,0,127})); + connect(zero2.y, reaRep2.u) + annotation (Line(points={{262,120},{278,120}}, color={0,0,127})); + connect(reaRep2.y, staSetCon2.VMinSet_flow) annotation (Line(points={{302,120}, + {370,120},{370,163},{458,163}}, color={0,0,127})); + connect(boiAva2.y, staSetCon2.uBoiAva) annotation (Line(points={{262,20},{440, + 20},{440,142},{458,142}}, color={255,0,255})); + connect(VHotWat_flow2.y, staSetCon2.VHotWat_flow) annotation (Line(points={{262,180}, + {300,180},{300,169},{458,169}}, color={0,0,127})); + connect(staUp2.u, staSetCon2.yChaUpEdg) annotation (Line(points={{498,190},{490, + 190},{490,162},{482,162}}, color={255,0,255})); + connect(staDow2.u, staSetCon2.yChaDowEdg) annotation (Line(points={{498,130},{ + 494,130},{494,154},{482,154}}, color={255,0,255})); + connect(uPumSpe2.y, staSetCon2.uBypValPos) annotation (Line(points={{342,90},{ + 380,90},{380,160},{458,160}}, color={0,0,127})); +annotation ( + experiment(StopTime=14000.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/SetpointController.mos" + "Simulate and plot"), + Documentation(info=" +

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

+", 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,-240},{620,240}}))); +end SetpointController; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/package.mo new file mode 100644 index 00000000000..bddc39431e4 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.SetPoints; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

+ This package contains validation models for the classes in + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging.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/BoilerPlant/Staging/SetPoints/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/package.order new file mode 100644 index 00000000000..704eb1c7289 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/Validation/package.order @@ -0,0 +1 @@ +SetpointController diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/package.mo new file mode 100644 index 00000000000..c4c2eab088f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/package.mo @@ -0,0 +1,24 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Staging; +package SetPoints "Package for boiler plant staging setpoint control sequences" + + annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S")}), + Documentation(info=" +

+ This package contains boiler stage setpoint control sequences. The implementation + is based on section 5.3.3 in ASHRAE RP-1711, Draft on March 23, 2020.

+")); +end SetPoints; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/package.order new file mode 100644 index 00000000000..45752c2fcd2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/SetPoints/package.order @@ -0,0 +1,3 @@ +SetpointController +Subsequences +Validation diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/package.mo new file mode 100644 index 00000000000..b3876514905 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/package.mo @@ -0,0 +1,42 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package Staging "Boiler staging sequences" + annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Ellipse( + origin={10,10}, + fillColor={76,76,76}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{-80.0,-80.0},{-20.0,-20.0}}), + Ellipse( + origin={10,10}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,-80.0},{60.0,-20.0}}), + Ellipse( + origin={10,10}, + fillColor={128,128,128}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + extent={{0.0,0.0},{60.0,60.0}}), + Ellipse( + origin={10,10}, + lineColor={128,128,128}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + extent={{-80.0,0.0},{-20.0,60.0}})}), + Documentation(info=" +

+ This package contains the boiler staging sequences. +

+ ")); +end Staging; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/package.order new file mode 100644 index 00000000000..0aa2322c4dc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Staging/package.order @@ -0,0 +1,2 @@ +Processes +SetPoints diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/BoilerTypes.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/BoilerTypes.mo new file mode 100644 index 00000000000..047306d5093 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/BoilerTypes.mo @@ -0,0 +1,39 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types; +package BoilerTypes + "Definitions for boiler types" + + constant Integer condensingBoiler = 1 + "Condensing boiler"; + + constant Integer nonCondensingBoiler = 2 + "Non-condensing boiler"; + +annotation ( + Documentation(info=" +

+ This package provides constants that indicate the boiler type based on the + presence of flue gas heat recovery. + The boiler types are enumerated in an order that enables identification of stage + type as condensing or non-condensing. +

+ ", + 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 BoilerTypes; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/PrimaryPumpSpeedControlTypes.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/PrimaryPumpSpeedControlTypes.mo new file mode 100644 index 00000000000..7442e243c5a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/PrimaryPumpSpeedControlTypes.mo @@ -0,0 +1,20 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types; +type PrimaryPumpSpeedControlTypes = enumeration( + localDP "Pump speed regulated to maintain local differential pressure setpoint", + remoteDP "Pump speed regulated to maintain remote differential pressure setpoint", + flowrate "Pump speed regulated to maintain flowrate through decoupler", + temperature "Pump speed regulated to maintain temperature difference between + primary and secondary loops") + "Definitions for primary pump speed control types" annotation (Documentation( + info=" +

+Enumeration to define the choice of primary pump speed control types: +

+ + + + + + +
EnumerationDescription
localDPPump speed regulated to maintain local differential pressure setpoint.
remoteDPPump speed regulated to maintain remote differential pressure setpoint.
flowratePump speed regulated to maintain flowrate through decoupler.
temperaturePump speed regulated to maintain temperature difference between primary and secondary loops.
+")); diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/SecondaryPumpSpeedControlTypes.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/SecondaryPumpSpeedControlTypes.mo new file mode 100644 index 00000000000..78102e38577 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/SecondaryPumpSpeedControlTypes.mo @@ -0,0 +1,15 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types; +type SecondaryPumpSpeedControlTypes = enumeration( + localDP "Pump speed regulated to maintain local differential pressure setpoint", + remoteDP "Pump speed regulated to maintain remote differential pressure setpoint") + "Definitions for secondary pump speed control types" annotation ( + Documentation(info=" +

+Enumeration to define the choice of secondary pump speed control types: +

+ + + + +
EnumerationDescription
localDPPump speed regulated to maintain local differential pressure setpoint.
remoteDPPump speed regulated to maintain remote differential pressure setpoint.
+")); diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/package.mo new file mode 100644 index 00000000000..848584bd0e1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/package.mo @@ -0,0 +1,46 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package Types "Package with type definitions for boiler plants" +annotation (Documentation(info=" +

+ This package provides type definitions used in boiler 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/BoilerPlant/Types/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/package.order new file mode 100644 index 00000000000..55dd25fb332 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Types/package.order @@ -0,0 +1,3 @@ +BoilerTypes +PrimaryPumpSpeedControlTypes +SecondaryPumpSpeedControlTypes diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/Controller.mo new file mode 100644 index 00000000000..c70da3b199e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/Controller.mo @@ -0,0 +1,554 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Validation; +model Controller + "Validation model for boiler plant control sequence" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller controller( + final have_priOnl=true, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final nSenPri=1, + final nPumPri_nominal=2, + final nPumSec=0, + final nSenSec=0, + final nPumSec_nominal=0, + final VHotWatPri_flow_nominal=0.0006, + final maxLocDpPri=4100, + final minLocDpPri=3900, + final VHotWatSec_flow_nominal=0, + final speConTypPri=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP, + final boiDesCap={15000*0.8,15000*0.8}, + final boiFirMin={0.2,0.3}, + final minFloSet={0.2*0.0003,0.3*0.0003}, + final maxFloSet={0.0003,0.0003}, + final bypSetRat=0.00001, + final nPumPri=2, + final have_heaPriPum=true, + final TMinSupNonConBoi = 333.2, + final have_varPriPum=true, + final boiDesFlo={0.0003,0.0003}, + final minPriPumSpeSta={0,0,0}) + "Test scenario for primary-only boiler plants with headered variable speed primary pumps" + annotation (Placement(transformation(extent={{-260,40},{-240,108}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller controller1( + final have_priOnl=false, + final have_secFloSen=true, + final have_varSecPum=true, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final nSenPri=1, + final nPumPri_nominal=2, + final nPumSec=2, + final nSenSec=1, + final nPumSec_nominal=2, + final VHotWatPri_flow_nominal=0.0006, + final maxLocDpPri=4100, + final minLocDpPri=3900, + final VHotWatSec_flow_nominal=0.0004, + final maxLocDpSec=4100, + final minLocDpSec=3900, + final speConTypPri=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate, + final boiDesCap={15000*0.8,15000*0.8}, + final boiFirMin={0.2,0.3}, + final minFloSet={0.2*0.0003,0.3*0.0003}, + final maxFloSet={0.0003,0.0003}, + final bypSetRat=0.00001, + final nPumPri=2, + final have_heaPriPum=true, + final TMinSupNonConBoi=333.2, + final have_varPriPum=true, + final boiDesFlo={0.0003,0.0003}, + final minPriPumSpeSta={0,0,0}, + final speConTypSec=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP) + "Test scenario for primary-secondary boiler plants with headered variable speed primary pumps" + annotation (Placement(transformation(extent={{0,40},{20,108}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller controller2( + final have_priOnl=false, + final have_secFloSen=true, + final have_varSecPum=true, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final nSenPri=1, + final nPumPri_nominal=2, + final nPumSec=2, + final nSenSec=1, + final nPumSec_nominal=2, + final VHotWatPri_flow_nominal=0.0006, + final maxLocDpPri=4100, + final minLocDpPri=3900, + final VHotWatSec_flow_nominal=0.0004, + final maxLocDpSec=4100, + final minLocDpSec=3900, + final speConTypPri=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.flowrate, + final boiDesCap={15000*0.8,15000*0.8}, + final boiFirMin={0.2,0.3}, + final minFloSet={0.2*0.0003,0.3*0.0003}, + final maxFloSet={0.0003,0.0003}, + final bypSetRat=0.00001, + final nPumPri=2, + final have_heaPriPum=false, + final TMinSupNonConBoi=333.2, + final have_varPriPum=true, + final boiDesFlo={0.0003,0.0003}, + final minPriPumSpeSta={0,0,0}, + final speConTypSec=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.SecondaryPumpSpeedControlTypes.remoteDP) + "Test scenario for primary-secondary boiler plants with dedicated variable speed primary pumps" + annotation (Placement(transformation(extent={{220,40},{240,108}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel[2]( + final delayTime=fill(10, 2)) + "True delay for simulating boiler proven on process" + annotation (Placement(transformation(extent={{-220,130},{-200,150}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1[2]( + final delayTime=fill(20, 2)) + "True delay for simulating pump proven on process" + annotation (Placement(transformation(extent={{-220,40},{-200,60}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel( + final samplePeriod=1) + "Unit delay to simulate change of bypass valve position" + annotation (Placement(transformation(extent={{-220,70},{-200,90}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel1[2]( + final samplePeriod=fill(1, 2)) + "Unit delay to simulate change of isolation valve position" + annotation (Placement(transformation(extent={{-220,100},{-200,120}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel2[2]( + final delayTime=fill(15, 2)) + "True delay for simulating boiler proven on process" + annotation (Placement(transformation(extent={{40,130},{60,150}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel2[2]( + final samplePeriod=fill(1, 2)) + "Unit delay to simulate change of isolation valve position" + annotation (Placement(transformation(extent={{40,100},{60,120}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel3[2]( + final delayTime=fill(20, 2)) + "True delay for simulating pump proven on process" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel4[2]( + final samplePeriod=fill(1, 2)) + "Unit delay to simulate change of pump speed" + annotation (Placement(transformation(extent={{70,30},{90,50}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel4[2]( + final delayTime=fill(20, 2)) + "True delay for simulating pump proven on process" + annotation (Placement(transformation(extent={{40,0},{60,20}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=2) + "Replicate pump speed to all pumps in system" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel5[2]( + final delayTime=fill(20, 2)) + "True delay for simulating boiler proven on process" + annotation (Placement(transformation(extent={{260,120},{280,140}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel6[2]( + final delayTime=fill(20, 2)) + "True delay for simulating pump proven on process" + annotation (Placement(transformation(extent={{260,90},{280,110}}))); + + Buildings.Controls.OBC.CDL.Discrete.UnitDelay uniDel3[2]( + final samplePeriod=fill(1, 2)) + "Unit delay to simulate change of pump speed" + annotation (Placement(transformation(extent={{290,60},{310,80}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1( + final nout=2) + "Replicate pump speed to all pumps in system" + annotation (Placement(transformation(extent={{260,60},{280,80}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel7[2]( + final delayTime=fill(20, 2)) + "True delay for simulating pump proven on process" + annotation (Placement(transformation(extent={{260,30},{280,50}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) + "Number of temperature reset requests" + annotation (Placement(transformation(extent={{-340,150},{-320,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] + "Logical pre block" + annotation (Placement(transformation(extent={{-190,130},{-170,150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2[2] + "Logical pre block" + annotation (Placement(transformation(extent={{-190,40},{-170,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3[2] + "Logical pre block" + annotation (Placement(transformation(extent={{70,130},{90,150}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre4[2] + "Logical pre block" + annotation (Placement(transformation(extent={{70,60},{90,80}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre5[2] + "Logical pre block" + annotation (Placement(transformation(extent={{70,0},{90,20}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre6[2] + "Logical pre block" + annotation (Placement(transformation(extent={{290,120},{310,140}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre7[2] + "Logical pre block" + annotation (Placement(transformation(extent={{290,90},{310,110}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre8[2] + "Logical pre block" + annotation (Placement(transformation(extent={{290,30},{310,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TOut( + final k=290) + "Measured outdoor air drybulb temperature" + annotation (Placement(transformation(extent={{-340,90},{-320,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TSup( + final k=340) + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-340,60},{-320,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TRet( + final k=335) + "Measured hot water return temperature" + annotation (Placement(transformation(extent={{-340,30},{-320,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWat_flow[4]( + final k={6e-5,9e-5,20e-5,0.0004}) + "Measured hot water volume flowrate in primary loop" + annotation (Placement(transformation(extent={{-340,0},{-320,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dPHotWat[1]( + final k={4000}) + "Measured differential pressure between hot water supply and return in primary loop" + annotation (Placement(transformation(extent={{-340,-30},{-320,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uBoiAva[2]( + final k={true,true}) + "Boiler availability status vector" + annotation (Placement(transformation(extent={{-340,-60},{-320,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=2, + final freqHz=1/14400) + "Sine input" + annotation (Placement(transformation(extent={{-340,120},{-320,140}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-300,120},{-280,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TOut1( + final k=290) + "Measured outdoor air drybulb temperature" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TSup1( + final k=340) + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{-80,60},{-60,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TRet1( + final k=335) + "Measured hot water return temperature" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWat_flow1[4]( + final k={6e-5,9e-5,20e-5,0.00029}) + "Measured hot water volume flowrate in primary loop" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dPHotWat1[1]( + final k={4000}) + "Measured differential pressure between hot water supply and return in secondary loop" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uBoiAva1[2]( + final k={true,true}) + "Boiler availability status vector" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final amplitude=2, final freqHz=1/14400) + "Sine input" + annotation (Placement(transformation(extent={{-80,120},{-60,140}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{-40,120},{-20,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWatSec_flow( + final k=0.0003) + "Measured hot water volume flowrate in secondary loop" + annotation (Placement(transformation(extent={{-80,-100},{-60,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TOut2( + final k=290) + "Measured outdoor air drybulb temperature" + annotation (Placement(transformation(extent={{140,90},{160,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TSup2( + final k=340) + "Measured hot water supply temperature" + annotation (Placement(transformation(extent={{140,60},{160,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TRet2( + final k=335) + "Measured hot water return temperature" + annotation (Placement(transformation(extent={{140,30},{160,50}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWat_flow2[4]( + final k={6e-5,9e-5,20e-5,0.00029}) + "Measured hot water volume flowrate in primary loop" + annotation (Placement(transformation(extent={{140,0},{160,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dPHotWat2[1]( + final k={4000}) + "Measured differential pressure between hot water supply and return in secondary loop" + annotation (Placement(transformation(extent={{140,-30},{160,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uBoiAva2[2]( + final k={true,true}) + "Boiler availability status vector" + annotation (Placement(transformation(extent={{140,-60},{160,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin2( + final amplitude=2, + final freqHz=1/14400) + "Sine input" + annotation (Placement(transformation(extent={{140,120},{160,140}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 + "Real to Integer conversion" + annotation (Placement(transformation(extent={{180,120},{200,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant VHotWatSec_flow1( + final k=0.0003) + "Measured hot water volume flowrate in secondary loop" + annotation (Placement(transformation(extent={{140,-100},{160,-80}}))); + +equation + connect(TOut.y, controller.TOut) annotation (Line(points={{-318,100},{-262,100}}, + color={0,0,127})); + + connect(uBoiAva.y, controller.uBoiAva) annotation (Line(points={{-318,-50},{-288, + -50},{-288,82},{-262,82}}, color={255,0,255})); + + connect(TSup.y, controller.TSupPri) annotation (Line(points={{-318,70},{-310,70}, + {-310,97},{-262,97}}, color={0,0,127})); + + connect(TRet.y, controller.TRetPri) annotation (Line(points={{-318,40},{-300,40}, + {-300,94},{-262,94}}, color={0,0,127})); + + connect(dPHotWat.y, controller.dpHotWatPri_rem) annotation (Line(points={{-318, + -20},{-294,-20},{-294,85},{-262,85}}, color={0,0,127})); + + connect(VHotWat_flow[4].y, controller.VHotWatPri_flow) annotation (Line( + points={{-318,10},{-298,10},{-298,91},{-262,91}}, color={0,0,127})); + + connect(sin.y, reaToInt.u) + annotation (Line(points={{-318,130},{-302,130}}, color={0,0,127})); + + connect(TOut1.y, controller1.TOut) annotation (Line(points={{-58,100},{-2,100}}, + color={0,0,127})); + + connect(uBoiAva1.y, controller1.uBoiAva) annotation (Line(points={{-58,-50},{-34, + -50},{-34,82},{-2,82}}, color={255,0,255})); + + connect(TSup1.y, controller1.TSupPri) annotation (Line(points={{-58,70},{-50,70}, + {-50,97},{-2,97}}, color={0,0,127})); + + connect(TRet1.y, controller1.TRetPri) annotation (Line(points={{-58,40},{-40,40}, + {-40,94},{-2,94}}, color={0,0,127})); + + connect(VHotWat_flow1[4].y, controller1.VHotWatPri_flow) annotation (Line( + points={{-58,10},{-38,10},{-38,91},{-2,91}}, color={0,0,127})); + + connect(sin1.y, reaToInt1.u) + annotation (Line(points={{-58,130},{-42,130}}, color={0,0,127})); + + connect(VHotWatSec_flow.y, controller1.VHotWatSec_flow) annotation (Line( + points={{-58,-90},{-30,-90},{-30,79},{-2,79}}, + color={0,0,127})); + + connect(dPHotWat1.y, controller1.dpHotWatSec_rem) annotation (Line(points={{-58,-20}, + {-26,-20},{-26,66},{-2,66}}, color={0,0,127})); + + connect(TRet1.y, controller1.TRetSec) annotation (Line(points={{-58,40},{-40,40}, + {-40,88},{-2,88}}, color={0,0,127})); + + connect(TOut2.y,controller2. TOut) annotation (Line(points={{162,100},{218,100}}, + color={0,0,127})); + + connect(uBoiAva2.y,controller2. uBoiAva) annotation (Line(points={{162,-50},{192, + -50},{192,82},{218,82}},color={255,0,255})); + + connect(TSup2.y,controller2. TSupPri) annotation (Line(points={{162,70},{170,70}, + {170,97},{218,97}}, color={0,0,127})); + + connect(TRet2.y,controller2. TRetPri) annotation (Line(points={{162,40},{180,40}, + {180,94},{218,94}}, color={0,0,127})); + + connect(VHotWat_flow2[4].y,controller2. VHotWatPri_flow) annotation (Line( + points={{162,10},{182,10},{182,91},{218,91}}, color={0,0,127})); + + connect(sin2.y,reaToInt2. u) + annotation (Line(points={{162,130},{178,130}}, color={0,0,127})); + + connect(VHotWatSec_flow1.y, controller2.VHotWatSec_flow) annotation (Line( + points={{162,-90},{196,-90},{196,79},{218,79}}, color={0,0,127})); + + connect(dPHotWat2.y,controller2. dpHotWatSec_rem) annotation (Line(points={{162,-20}, + {200,-20},{200,66},{218,66}}, color={0,0,127})); + + connect(TRet2.y,controller2. TRetSec) annotation (Line(points={{162,40},{180,40}, + {180,88},{218,88}}, color={0,0,127})); + + connect(controller.yBoi, truDel.u) annotation (Line(points={{-238,84},{-230, + 84},{-230,140},{-222,140}}, + color={255,0,255})); + connect(controller.yPriPum, truDel1.u) annotation (Line(points={{-238,68},{ + -230,68},{-230,50},{-222,50}}, + color={255,0,255})); + connect(controller.yBypValPos, uniDel.u) annotation (Line(points={{-238,72},{ + -224,72},{-224,80},{-222,80}}, + color={0,0,127})); + connect(uniDel.y, controller.uBypValPos) annotation (Line(points={{-198,80},{-150, + 80},{-150,20},{-272,20},{-272,45},{-262,45}}, color={0,0,127})); + connect(controller.yHotWatIsoVal, uniDel1.u) annotation (Line(points={{-238,76}, + {-226,76},{-226,110},{-222,110}}, color={0,0,127})); + connect(uniDel1.y, controller.uHotWatIsoVal) annotation (Line(points={{-198,110}, + {-144,110},{-144,-16},{-278,-16},{-278,48},{-262,48}}, color={0,0,127})); + connect(controller1.yBoi, truDel2.u) annotation (Line(points={{22,84},{26,84}, + {26,140},{38,140}}, color={255,0,255})); + connect(controller1.yHotWatIsoVal, uniDel2.u) annotation (Line(points={{22,76}, + {28,76},{28,110},{38,110}}, color={0,0,127})); + connect(controller1.yPriPum, truDel3.u) annotation (Line(points={{22,68},{34, + 68},{34,70},{38,70}}, + color={255,0,255})); + connect(uniDel2.y, controller1.uHotWatIsoVal) annotation (Line(points={{62,110}, + {106,110},{106,-16},{-18,-16},{-18,48},{-2,48}}, color={0,0,127})); + connect(controller1.ySecPum, truDel4.u) annotation (Line(points={{22,60},{30, + 60},{30,10},{38,10}}, + color={255,0,255})); + connect(reaRep.y, uniDel4.u) + annotation (Line(points={{62,40},{68,40}}, color={0,0,127})); + connect(controller1.yPriPumSpe, reaRep.u) annotation (Line(points={{22,64},{ + 32,64},{32,40},{38,40}}, + color={0,0,127})); + connect(uniDel4.y, controller1.uPriPumSpe) annotation (Line(points={{92,40},{96, + 40},{96,-10},{-6,-10},{-6,42},{-2,42}}, color={0,0,127})); + connect(controller2.yBoi, truDel5.u) annotation (Line(points={{242,84},{250, + 84},{250,130},{258,130}}, + color={255,0,255})); + connect(truDel6.u, controller2.yPriPum) annotation (Line(points={{258,100},{ + 254,100},{254,68},{242,68}}, + color={255,0,255})); + connect(reaRep1.y, uniDel3.u) + annotation (Line(points={{282,70},{288,70}}, color={0,0,127})); + connect(controller2.yPriPumSpe, reaRep1.u) annotation (Line(points={{242,64}, + {254,64},{254,70},{258,70}},color={0,0,127})); + connect(uniDel3.y, controller2.uPriPumSpe) annotation (Line(points={{312,70},{ + 320,70},{320,10},{216,10},{216,42},{218,42}}, color={0,0,127})); + connect(controller2.ySecPum, truDel7.u) annotation (Line(points={{242,60},{ + 252,60},{252,40},{258,40}}, + color={255,0,255})); + connect(conInt.y, controller.TSupResReq) annotation (Line(points={{-318,160},{ + -266,160},{-266,106},{-262,106}}, color={255,127,0})); + connect(conInt.y, controller1.TSupResReq) annotation (Line(points={{-318,160}, + {-6,160},{-6,106},{-2,106}}, color={255,127,0})); + connect(conInt.y, controller2.TSupResReq) annotation (Line(points={{-318,160}, + {212,160},{212,106},{218,106}}, color={255,127,0})); + connect(truDel.y, pre1.u) + annotation (Line(points={{-198,140},{-192,140}}, color={255,0,255})); + connect(pre1.y, controller.uBoi) annotation (Line(points={{-168,140},{-130,140}, + {-130,-30},{-284,-30},{-284,57},{-262,57}}, color={255,0,255})); + connect(pre2.u, truDel1.y) + annotation (Line(points={{-192,50},{-198,50}}, color={255,0,255})); + connect(pre2.y, controller.uPriPum) annotation (Line(points={{-168,50},{-154,50}, + {-154,8},{-274,8},{-274,54},{-262,54}}, color={255,0,255})); + connect(truDel2.y, pre3.u) + annotation (Line(points={{62,140},{68,140}}, color={255,0,255})); + connect(truDel3.y, pre4.u) + annotation (Line(points={{62,70},{68,70}}, color={255,0,255})); + connect(truDel4.y, pre5.u) + annotation (Line(points={{62,10},{68,10}}, color={255,0,255})); + connect(pre5.y, controller1.uSecPum) annotation (Line(points={{92,10},{100,10}, + {100,-12},{-14,-12},{-14,51},{-2,51}}, color={255,0,255})); + connect(pre4.y, controller1.uPriPum) annotation (Line(points={{92,70},{108,70}, + {108,-20},{-10,-20},{-10,54},{-2,54}}, color={255,0,255})); + connect(pre3.y, controller1.uBoi) annotation (Line(points={{92,140},{110,140}, + {110,-22},{-20,-22},{-20,57},{-2,57}}, color={255,0,255})); + connect(pre6.u, truDel5.y) + annotation (Line(points={{288,130},{282,130}}, color={255,0,255})); + connect(pre6.y, controller2.uBoi) annotation (Line(points={{312,130},{340,130}, + {340,0},{202,0},{202,57},{218,57}}, color={255,0,255})); + connect(pre7.u, truDel6.y) + annotation (Line(points={{288,100},{282,100}}, color={255,0,255})); + connect(pre7.y, controller2.uPriPum) annotation (Line(points={{312,100},{338,100}, + {338,2},{204,2},{204,54},{218,54}}, color={255,0,255})); + connect(truDel7.y, pre8.u) + annotation (Line(points={{282,40},{288,40}}, color={255,0,255})); + connect(pre8.y, controller2.uSecPum) annotation (Line(points={{312,40},{336,40}, + {336,4},{206,4},{206,51},{218,51}}, color={255,0,255})); + connect(reaToInt.y, controller.plaReq) annotation (Line(points={{-278,130},{ + -272,130},{-272,103},{-262,103}}, color={255,127,0})); + connect(reaToInt1.y, controller1.plaReq) annotation (Line(points={{-18,130},{ + -12,130},{-12,103},{-2,103}}, color={255,127,0})); + connect(reaToInt2.y, controller2.plaReq) annotation (Line(points={{202,130},{ + 208,130},{208,103},{218,103}}, color={255,127,0})); + annotation ( + 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={{-360,-240},{360,240}})), + experiment( + StopTime=7500, + Tolerance=1e-06), + __Dymola_Commands(file="./Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+ This example validates + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller. +

+ ", revisions=" + + ")); +end Controller; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/package.mo new file mode 100644 index 00000000000..e6fca1d71f2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/package.mo @@ -0,0 +1,37 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant; +package Validation "Collection of validation models" + +annotation (Icon(graphics={ + Rectangle( + lineColor={200,200,200}, + fillColor={248,248,248}, + fillPattern=FillPattern.HorizontalCylinder, + extent={{-100,-100},{100,100}}, + radius=25.0), + Rectangle( + lineColor={128,128,128}, + extent={{-100,-100},{100,100}}, + radius=25.0), + Polygon( + origin={8,14}, + 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}})}), + Documentation(info=" +

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

+

+ 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/BoilerPlant/Validation/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/package.order new file mode 100644 index 00000000000..8cba75e31a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/Validation/package.order @@ -0,0 +1 @@ +Controller diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/package.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/package.mo new file mode 100644 index 00000000000..7980bff1d48 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/package.mo @@ -0,0 +1,23 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem; +package BoilerPlant "Boiler plant control sequences" + +annotation (preferredView="info", + 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)}), + Documentation(info=" +

+ This package contains control sequences for a boiler plant comprising a single boiler or multiple boilers, + hot water pumps and flow-control devices.
+ The control sequences are implemented based on ASHRAE RP-1711, Draft 4 and Draft 5. +

+ ")); +end BoilerPlant; diff --git a/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/package.order b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/package.order new file mode 100644 index 00000000000..0dc8706a7c3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/BoilerPlant/package.order @@ -0,0 +1,8 @@ +Controller +BypassValve +Generic +Pumps +SetPoints +Staging +Types +Validation 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..64b2a023eab --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Controller.mo @@ -0,0 +1,2499 @@ +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="W") + "Design chiller capacities vector" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real chiMinCap[nChi](unit="W") + "Chiller minimum cycling loads vector" + annotation (Dialog(tab="General", group="Chillers configuration")); + + parameter Real TChiWatSupMin[nChi]( + unit="K", + displayUnit="degC")={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=true + "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]( + final min=fill(0, totSta), + final max=fill(1, 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")); + + // ---- 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 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 == CDL.Types.SimpleController.PI or ecoValCon == 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 == CDL.Types.SimpleController.PD or ecoValCon == 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=1 + "Gain of controller" + annotation(Dialog(tab="Head pressure", group="Loop signal", enable=not have_heaPreConSig)); + + parameter Real TiHeaPreCon(unit="s")=0.5 + "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="m3/s")={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="m3/s")={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=1 + "Gain of controller" + annotation (Dialog(tab="Minimum flow bypass", group="Controller")); + + parameter Real TiMinFloBypCon(unit="s")=0.5 + "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( + final max=nChiWatPum, + final 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=1 "Gain of controller" + annotation (Dialog(tab="Chilled water pumps", group="Speed controller")); + + parameter Real TiChiWatPum(unit="s")=0.5 + "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="Pa", displayUnit="Pa") + "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( + final min=0, + final max=1) = 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=1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", + enable=have_WSE)); + + parameter Real TiIntOpeTowFan(unit="s")=0.5 + "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=1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed controller with WSE enabled", enable=have_WSE)); + + parameter Real TiWSETowFan(unit="s")=0.5 + "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="K")={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="K", + displayUnit="degC")={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="K", + displayUnit="degC")={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=1 "Gain of controller" + annotation (Dialog(tab="Cooling Towers", group="Fan speed: Return temperature control", + enable=not closeCoupledPlant)); + + parameter Real TiSupCon(unit="s")=0.5 + "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=0, + final max=1, + final unit="1") "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}}))); + + Generic.PlantEnable.Enable plaEna( + final have_WSE=have_WSE, + 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 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.Continuous.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.Discrete.TriggeredSampler staSam + "Samples stage index after each staging process is finished" + annotation(Placement(transformation(extent={{-20,-20},{0,0}}))); + + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Real to integer" + annotation(Placement(transformation(extent={{20,-20},{40,0}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Integer to real" + annotation(Placement(transformation(extent={{-100,-20},{-80,0}}))); + + 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.Continuous.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.Continuous.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 repDesConTem( + final nout=nChi) + if not have_fixSpeConWatPum + "Replicate design condenser water temperature" + annotation (Placement(transformation(extent={{540,190},{560,210}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMin mulMin( + final nin=nChi) + if not have_fixSpeConWatPum + annotation (Placement(transformation(extent={{-460,150},{-440,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.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={{80,-450},{100,-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.Continuous.Switch chiIsoVal[nChi] + "Chiller isolation valve position setpoint" + annotation (Placement(transformation(extent={{540,-10},{560,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Discrete.ZeroOrderHold zerOrdHol( + final samplePeriod=1) + "Zero order hold" + annotation (Placement(transformation(extent={{-60,-20},{-40,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Multiply pro[nChiWatPum] + "Chilled water pump speed setpoint" + annotation (Placement(transformation(extent={{640,470},{660,490}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[nChiWatPum] + "Chilled 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.Continuous.Multiply pro4[nChi] + "Head pressure control valve position" + annotation (Placement(transformation(extent={{660,230},{680,250}}))); + + Buildings.Controls.OBC.CDL.Continuous.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) + "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 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={{820,-670},{840,-650}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator enaTowCel( + final nout=nTowCel) + "False: disable all tower cells" + annotation (Placement(transformation(extent={{780,-590},{800,-570}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nTowCel] + "Tower cell isolation valve position setpoint" + annotation (Placement(transformation(extent={{880,-630},{900,-610}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1[nTowCel]( + final k=fill(0, nTowCel)) + "Constant zero" + annotation (Placement(transformation(extent={{700,-590},{720,-570}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nTowCel] + "Tower cell fan speed setpoint" + annotation (Placement(transformation(extent={{880,-710},{900,-690}}))); + +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(staSam.y, reaToInt1.u) + annotation(Line(points={{2,-10},{18,-10}}, color={0,0,127})); + connect(staSetCon.ySta, intToRea.u) annotation(Line(points={{-172,-24},{-140,-24}, + {-140,-10},{-102,-10}}, color={255,127,0})); + connect(reaToInt1.y, dowProCon.uChiSta) annotation(Line(points={{42,-10},{60,-10}, + {60,-204},{172,-204}}, color={255,127,0})); + connect(reaToInt1.y, staSetCon.uSta) annotation(Line(points={{42,-10},{60,-10}, + {60,-208},{-460,-208},{-460,60},{-268,60}}, color={255,127,0})); + 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,-164},{172,-164}}, 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(uChiIsoVal, chiWatPumCon.uChiIsoVal) annotation(Line(points={{-920,540}, + {-630,540},{-630,507},{434,507}}, color={255,0,255})); + 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,-172},{-830,-172}, + {-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(reaToInt1.y, upProCon.uChiSta) annotation (Line(points={{42,-10},{60,-10}, + {60,372},{172,372}}, color={255,127,0})); + connect(reaToInt1.y, towCon.uChiSta) annotation (Line(points={{42,-10},{60,-10}, + {60,-208},{-340,-208},{-340,-676},{-268,-676}}, color={255,127,0})); + 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},{-550,250}, + {-550,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(falEdg.y, staSam.trigger) annotation (Line(points={{502,-80},{590,-80}, + {590,-40},{-10,-40},{-10,-22}}, color={255,0,255})); + 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(repDesConTem.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, mulMin.u) annotation (Line(points={{-476,188}, + {-470,188},{-470,160},{-462,160}}, color={0,0,127})); + connect(mulMin.y, dowProCon.uConWatPumSpeSet) annotation (Line(points={{-438,160}, + {-400,160},{-400,-280},{172,-280}}, color={0,0,127})); + connect(mulMin.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, + -296},{350,-296},{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,284},{300, + 284},{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(preConPumLeaSta.y, towCon.uLeaConWatPum) annotation (Line(points={{502, + -250},{560,-250},{560,-520},{-310,-520},{-310,-700},{-268,-700}}, + color={255,0,255})); + 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={{102,-440},{120,-440}, + {120,-510},{-320,-510},{-320,-692},{-268,-692}}, color={255,0,255})); + connect(staCooTow.y, pre2.u) annotation (Line(points={{502,-120},{590,-120},{590, + -400},{60,-400},{60,-440},{78,-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, + -280},{370,-280},{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, repDesConTem.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(staSam.u, zerOrdHol.y) + annotation (Line(points={{-22,-10},{-38,-10}}, color={0,0,127})); + connect(zerOrdHol.u, intToRea.y) + annotation (Line(points={{-62,-10},{-78,-10}}, color={0,0,127})); + 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, heaPreCon.uChiHeaCon) annotation (Line(points={{-920,-80}, + {-560,-80},{-560,220},{-524,220}}, 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(staSetCon.ySta, wseSta.uChiSta) annotation (Line(points={{-172,-24},{-140, + -24},{-140,280},{-740,280},{-740,312},{-704,312}},color={255,127,0})); + 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(enaDev.yEnaPlaPro, chiWatPumCon.uEnaPla) annotation (Line(points={{-518, + -421},{-410,-421},{-410,501},{434,501}}, 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(plaEna.yPla, disChi.uPla) annotation (Line(points={{-658,-520},{-580,-520}, + {-580,-463},{738,-463}}, color={255,0,255})); + 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,-468},{738,-468}}, color={0,0,127})); + connect(uChiWatReq, disChi.uChiWatReq) annotation (Line(points={{-920,634},{-810, + 634},{-810,-466},{738,-466}}, color={255,0,255})); + connect(disChi.yChi, yChi) annotation (Line(points={{762,-461},{800,-461},{800, + 350},{940,350}}, 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,-472},{738,-472}}, color={255,0,255})); + connect(pro4.y, disChi.uConWatIsoVal) annotation (Line(points={{682,240},{700, + 240},{700,-474},{738,-474}}, 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,-477},{738,-477}}, color={0,0,127})); + connect(pro1.y, disChi.uConWatPumSpe) annotation (Line(points={{682,150},{730, + 150},{730,-479},{738,-479}}, color={0,0,127})); + connect(disChi.yConWatPumSpe, yConWatPumSpe) annotation (Line(points={{762,-475}, + {840,-475},{840,150},{940,150}}, color={0,0,127})); + connect(disChi.yTow, enaTowCel.u) annotation (Line(points={{762,-479},{770,-479}, + {770,-580},{778,-580}}, color={255,0,255})); + connect(enaTowCel.y, celCom.u2) annotation (Line(points={{802,-580},{810,-580}, + {810,-668},{818,-668}}, color={255,0,255})); + connect(towCon.yTowSta, celCom.u1) + annotation (Line(points={{-172,-660},{818,-660}}, color={255,0,255})); + connect(celCom.y, yTowCel) + annotation (Line(points={{842,-660},{940,-660}}, color={255,0,255})); + connect(swi.y, yTowCelIsoVal) + annotation (Line(points={{902,-620},{940,-620}}, color={0,0,127})); + connect(celCom.y, swi.u2) annotation (Line(points={{842,-660},{860,-660},{860, + -620},{878,-620}}, color={255,0,255})); + 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(celCom.y, swi1.u2) annotation (Line(points={{842,-660},{860,-660},{860, + -700},{878,-700}}, color={255,0,255})); + 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})); +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 RP-1711 Advanced +Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). It is +assembled by following subsequences: +

+

1. Plant reset

+

+The sequences + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterPlantReset +and + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterSupply +are for resetting chilled water temperature setpoint and differential pressure setpoint. +They are applicable for the primary-only plants or for the primary-secondary systems +serving differential pressure controlled pumps. +

+ + + + + + + + + +
Applicable
Primary-only systems
Primay-secondary systems serving differential pressure controlled pumps
Not applicable
Primary-only systems serving a single large load, e.g. large AHU
Primay-secondary systems where there are any coil pumps
Plants with multiple reset loops
Plants with series chiller
+ +

2. Head pressure control

+

+The sequence + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Controller +generates control signals for chiller head pressure control. +

+ + + + + + +
Applicable
Plants with headered condenser water pump, fixed or variable speed
Plants with or without waterside economizer
Not applicable
Plants with air-cooling chillers
+

+Note the sequence assumes: +

+ + +

3. Minimum flow bypass valve control

+

+The sequence + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Controller +and + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint +control chilled water minimum flow bypass valve. +

+ + + + + +
Applicable
Primary-only plants, with parallel or series chillers
Not applicable
Primary-secondary plants
+ +

4. Chilled water pump control

+

+The sequence + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Pumps.ChilledWater.Controller +controls chilled water pump. It is applicable for primary-only plants with parallel +chillers. +

+ + + + + + +
Applicable
Primary-only plants with parallel chillers
Not applicable
Primary-only plants with series chillers
Primary-secondary plants
+ +

5. Chiller staging control

+

+The sequences + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Up +and + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Down +controls chiller staging up and down process. They are applicable for following plants: +

+ + + + + + + + +
Applicable
water-cooled, primary-only, parallel chiller plants with headered chilled water pumps and headered condenser water pumps
air-cooled primary-only, parallel chiller plants with headered chilled water pumps
Not applicable
Primary-only plants with parallel chillers, dedicated chilled water or condenser water pumps
Primary-only plants with series chillers
Primary-secondary plants
+ +

6. Tower control

+

+The sequence + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller +controls cooling tower staging and the fans speed. It is appliable for plants with +dynamic load profiles, i.e. those for which PLR may change by more than approximately +25% in any hour, for controlling condenser water return temperature. It is not +applicable for the plants where 2-position tower bypass control valves are needed +to prevent tower freezing. +Note that the sequence assumes that the cells are enabled in order as it is labelled, meaning +that it enabled the cells as cell 1, 2, 3, etc. +

+ +

7. Equipment rotation

+

+The sequence + +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..f256378e6c9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Controller.mo @@ -0,0 +1,565 @@ +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 == CDL.Types.SimpleController.PI or valCon == 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 == CDL.Types.SimpleController.PD or valCon == 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,-10},{-180,30}}), + 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,10},{220,50}}), + 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.Continuous.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.Continuous.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,20},{-120,40}}))); + + 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.Continuous.Subtract sub2 "Subtract" + annotation (Placement(transformation(extent={{-20,156},{0,176}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre "Logical pre" + annotation (Placement(transformation(extent={{120,-70},{140,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.TrueHoldWithReset truHol( + final duration=holdPeriod) + "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.Edge edg + "Plant enable edge" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + 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.Edge edg1 + "Becoming not initial stage" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + + Buildings.Controls.OBC.CDL.Logical.Or enaEco "Economizer enabled" + annotation (Placement(transformation(extent={{80,-30},{100,-10}}))); + +equation + connect(uTowFanSpeMax, wseTun.uTowFanSpeMax) annotation (Line(points={{-200,10}, + {-150,10},{-150,25},{-142,25}}, 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(pre.y,wseTun.uWseSta) + annotation (Line(points={{142,-60},{150,-60},{150,-120},{-160,-120},{-160,35}, + {-142,35}}, color={255,0,255})); + 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={{-119,30},{-110,30}, + {-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={{-119,30},{200,30}}, 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(pre.y, falEdg.u) annotation (Line(points={{142,-60},{150,-60},{150,-120}, + {-160,-120},{-160,60},{-102,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(uPla, edg.u) + annotation (Line(points={{-200,-20},{-142,-20}}, color={255,0,255})); + connect(edg.y, and1.u1) + annotation (Line(points={{-118,-20},{-62,-20}}, 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(not1.y, edg1.u) + annotation (Line(points={{-38,-100},{-22,-100}}, color={255,0,255})); + connect(and1.y, lat.u) + annotation (Line(points={{-38,-20},{18,-20}}, color={255,0,255})); + connect(edg1.y, lat.clr) annotation (Line(points={{2,-100},{10,-100},{10,-26}, + {18,-26}}, color={255,0,255})); + connect(lat.y, enaEco.u2) annotation (Line(points={{42,-20},{60,-20},{60,-28}, + {78,-28}}, color={255,0,255})); + connect(truFalHol.y, enaEco.u1) annotation (Line(points={{162,166},{170,166},{ + 170,70},{70,70},{70,-20},{78,-20}}, color={255,0,255})); + connect(enaEco.y, y) + annotation (Line(points={{102,-20},{200,-20}}, color={255,0,255})); + connect(enaEco.y, pre.u) annotation (Line(points={{102,-20},{110,-20},{110,-60}, + {118,-60}}, color={255,0,255})); + connect(enaEco.y, wseVal.uWSE) annotation (Line(points={{102,-20},{110,-20},{ + 110,-140},{118,-140}}, + color={255,0,255})); + connect(enaEco.y, wsePum.uWSE) annotation (Line(points={{102,-20},{110,-20},{ + 110,-176},{118,-176}}, + 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})); + 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 RP-1711, March 2020, section 5.2.3. +It implements the enable/disable conditions as provided in sections 5.2.3.1. and 5.2.3.2. +

+

+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 control sequence uses the following subsequences: +

+ +", +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..da8b0d79afa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/BypassValve.mo @@ -0,0 +1,155 @@ +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 booToRea + annotation (Placement(transformation(extent={{60,30},{80,50}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant con( + final k=1) "Constant one" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Divide div1 + annotation (Placement(transformation(extent={{-40,-56},{-20,-36}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi + 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(booToRea.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, booToRea.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 RP-1711, March 2020, section 5.2.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..9537971d024 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/HeatExchangerPump.mo @@ -0,0 +1,219 @@ +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 booToRea + annotation (Placement(transformation(extent={{40,100},{60,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub "Temperature difference" + annotation (Placement(transformation(extent={{-140,-20},{-120,0}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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(booToRea.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(booToRea.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, booToRea.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=" +

+Waterside economizer valves control when the chilled water flow through the economizer +is controlled by variable speed heat exchanger pump. It is implemented +according to ASHRAE RP-1711, March 2020, section 5.2.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 +unit 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..cfbc1f3728f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/PredictedOutletTemperature.mo @@ -0,0 +1,191 @@ +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.Continuous.Divide heaExcPlr + "Heat exchanger flow part load ratio" + annotation (Placement(transformation(extent={{-90,60},{-70,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant heaExcDes_flow( + final k= VHeaExcDes_flow) "Heat exchanger design flow" + annotation (Placement(transformation(extent={{-130,40},{-110,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant heaAppDes( + final k=heaExcAppDes) + "Heat exchanger design approach" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro "Product" + annotation (Placement(transformation(extent={{-20,44},{0,64}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 "Subtraction" + annotation (Placement(transformation(extent={{-60,-60},{-40,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TWetDes( + final k=TOutWetDes) + "Design outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1 "Product" + annotation (Placement(transformation(extent={{-20,-60},{0,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant towAppDes( + final k=cooTowAppDes) + "Cooling tower design approach" + annotation (Placement(transformation(extent={{20,-100},{40,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum( + final nin=4) + "Sum of multiple inputs" + annotation (Placement(transformation(extent={{80,-10},{100,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Limiter lim( + final uMax=1, + final uMin=0) "Limiter" + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + +equation + connect(heaExcPlr.u2, heaExcDes_flow.y) annotation (Line(points={{-92,64},{ + -100,64},{-100,50},{-108,50}}, color={0,0,127})); + connect(VChiWat_flow, heaExcPlr.u1) annotation (Line(points={{-180,0},{-140,0}, + {-140,76},{-92,76}}, color={0,0,127})); + connect(heaAppDes.y, pro.u2) annotation (Line(points={{-38,30},{-30,30},{-30, + 48},{-22,48}}, color={0,0,127})); + connect(sub1.y, pro1.u1) annotation (Line(points={{-38,-50},{-30,-50},{-30, + -44},{-22,-44}}, color={0,0,127})); + connect(uTunPar, pro1.u2) annotation (Line(points={{-180,-140},{-30,-140},{-30, + -56},{-22,-56}}, color={0,0,127})); + connect(TOutWet, mulSum.u[1]) annotation (Line(points={{-180,140},{60,140},{60, + -0.75},{78,-0.75}}, + color={0,0,127})); + connect(pro.y, mulSum.u[2]) annotation (Line(points={{2,54},{20,54},{20,-0.25}, + {78,-0.25}},color={0,0,127})); + connect(pro1.y, mulSum.u[3]) annotation (Line(points={{2,-50},{20,-50},{20,0.25}, + {78,0.25}}, color={0,0,127})); + connect(towAppDes.y, mulSum.u[4]) annotation (Line(points={{42,-90},{60,-90},{ + 60,-2},{78,-2},{78,0.75}}, color={0,0,127})); + connect(mulSum.y, y) + annotation (Line(points={{102,0},{180,0}}, color={0,0,127})); + connect(heaExcPlr.y, lim.u) + annotation (Line(points={{-68,70},{-62,70}}, color={0,0,127})); + connect(pro.u1, lim.y) + annotation (Line(points={{-22,60},{-30,60},{-30,70},{-38,70}}, + 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})); + 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 RP-1711, March 2020, section 5.2.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..19fc45c8180 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Tuning.mo @@ -0,0 +1,321 @@ +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,-10},{340,10}}), + iconTransformation(extent={{100,-10},{120,10}}))); + +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.Continuous.Sources.Constant resVal( + final k=0) "Reset value" + annotation (Placement(transformation(extent={{120,0},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.And3 and1 "And" + annotation (Placement(transformation(extent={{-140,0},{-120,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesThr( + final t=wseOnTimInc) "Less than" + annotation (Placement(transformation(extent={{-220,40},{-200,60}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre truHol1 + "Logical pre to capture true signal just before the WSE gets disabled" + annotation (Placement(transformation(extent={{-180,40},{-160,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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={{-160,-140},{-140,-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={{-100,0},{-80,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={{60,0},{80,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.Logical.Pre truHol + "Holds true signal for a short period of time to catch the falling edge" + annotation (Placement(transformation(extent={{-180,140},{-160,160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Limiter lim( + final uMax=maxTunPar, + final uMin=minTunPar) "Limiter" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.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}}))); + +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(lesThr.y, truHol1.u) + annotation (Line(points={{-198,50},{-182,50}}, color={255,0,255})); + connect(and1.u1, truHol1.y) annotation (Line(points={{-142,18},{-150,18},{-150, + 50},{-158,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,10},{-160,10},{-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},{-162,-130}}, color={255,0,255})); + connect(lat.y, and4.u2) annotation (Line(points={{-138,-130},{-90,-130},{-90,-118}, + {-82,-118}}, color={255,0,255})); + connect(greThr.y, and1.u3) annotation (Line(points={{2,-80},{10,-80},{10,-50}, + {-150,-50},{-150,2},{-142,2}},color={255,0,255})); + connect(not1.y, lat.clr) annotation (Line(points={{-238,-20},{-168,-20},{-168, + -136},{-162,-136}}, color={255,0,255})); + connect(tim1.y, lesThr.u) + annotation (Line(points={{-238,50},{-222,50}}, color={0,0,127})); + connect(and1.y, disCou1.trigger) + annotation (Line(points={{-118,10},{-102,10}}, color={255,0,255})); + 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(y, y) annotation (Line(points={{330,0},{330,0}}, color={0,0,127})); + connect(disCou1.y, intToRea1.u) + annotation (Line(points={{-78,10},{58,10}}, color={255,127,0})); + connect(truHol.y, and2.u1) + annotation (Line(points={{-158,150},{-142,150}}, color={255,0,255})); + connect(lim.y, y) + annotation (Line(points={{182,70},{300,70},{300,0},{330,0}}, 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},{-60,150},{-60, + 86},{-42,86}}, color={255,127,0})); + connect(disCou1.y, maxInt.u2) annotation (Line(points={{-78,10},{-60,10},{-60, + 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={{82,10},{100,10},{100, + 70},{118,70}}, color={0,0,127})); + connect(intWitRes.y, mulSum.u[3]) annotation (Line(points={{262,10},{280,10}, + {280,-40},{100,-40},{100,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},{-90,-10},{-90,-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(tim.passed, truHol.u) annotation (Line(points={{-238,142},{-200,142}, + {-200,150},{-182,150}}, 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 RP-1711, March 2020, section 5.2.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..4cea9e28cdd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/BypassValve.mo @@ -0,0 +1,62 @@ +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.Continuous.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. +

+", 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..e48f4d8e1ca --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/Subsequences/Validation/HeatExchangerPump.mo @@ -0,0 +1,76 @@ +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.Continuous.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.Continuous.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. +

+", 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..eebeee4103b --- /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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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..d87b08dd458 --- /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.Continuous.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.Continuous.Sources.Constant maxTowFanSpeSig0( + final k=1) + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation(extent={{-120,140},{-100,160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant maxTowFanSpeSig2( + final k=1) + "Maximum cooling tower fan speed signal" + annotation (Placement(transformation(extent={{-120,40},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.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.Continuous.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.Continuous.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..3e3990ab51c --- /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.Continuous.Sources.Sine 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.Continuous.Sources.Constant chiWatFlow( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{-260,0},{-240,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant constTowFanSig( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{-260,-40},{-240,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Sources.Constant chiWatFlow1( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{-150,0},{-130,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TOutWetSig1( + final k=TOutWetBul) + "Measured outdoor air wet bulb temperature" + annotation (Placement(transformation(extent={{-150,100},{-130,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant constTowFanSig1( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{-150,-40},{-130,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Sources.Constant chiWatFlow2( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{-30,0},{-10,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant constTowFanSig2( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{-30,-40},{-10,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Sources.Constant chiWatFlow3( + final k=VChiWat_flow) + "Chilled water flow" + annotation (Placement(transformation(extent={{160,0},{180,20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant constTowFanSig3( + final k=1) + "Cooling tower fan full load signal" + annotation (Placement(transformation(extent={{160,-40},{180,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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..d7e62128518 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Economizers/package.mo @@ -0,0 +1,47 @@ +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.2.3. in ASHRAE RP-1711 Advanced Sequences +of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..d8b8d88d950 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/ControllerTwo.mo @@ -0,0 +1,337 @@ +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=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {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 RP-1711, March 2020 Draft, section 5.1.2.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 RP-1711, 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..55b37f39749 --- /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=DynamicSelect({235,235,235}, if y then {0,255,0} else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} else {235,235,235}), + fillPattern=FillPattern.Solid), Ellipse( extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} else {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 March 2020 Draft RP-1711, section 5.1.2.4.2. +

+", 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..76b702adbb2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/LeastRuntime.mo @@ -0,0 +1,172 @@ +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={{-60,50},{-40,70}}))); + +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={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Greater longer1 + "Runtime of the first device is longer than runtime of the second device" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Greater longer2 + "Runtime of the second device is longer than the runtime of the first device" + annotation (Placement(transformation(extent={{-20,20},{0,40}}))); + + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nDev) "Multiple or" + annotation (Placement(transformation(extent={{130,-10},{150,10}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not1 if lag "Logical not" + annotation (Placement(transformation(extent={{20,50},{40,70}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not2 if lag "Logical not" + annotation (Placement(transformation(extent={{20,20},{40,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3[nDev] if lag "Logical not" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + + Buildings.Controls.OBC.CDL.Logical.And3 and3[nDev] if lag "Logical not" + annotation (Placement(transformation(extent={{100,10},{120,30}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg [nDev]( + final pre_u_start=fill(false, nDev)) if lag "Rising edge" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + + Buildings.Controls.OBC.CDL.Logical.And and1[nDev] if not lag "Logical and" + annotation (Placement(transformation(extent={{100,-70},{120,-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={{-100,-70},{-80,-50}}))); + +equation + connect(uDevSta, accTim.u) + annotation (Line(points={{-180,60},{-62,60}}, color={255,0,255})); + connect(accTim[1].y, longer1.u1) + annotation (Line(points={{-38,60},{-22,60}}, color={0,0,127})); + connect(accTim[2].y, longer1.u2) annotation (Line(points={{-38,60},{-30,60},{-30, + 52},{-22,52}}, color={0,0,127})); + connect(accTim[1].y, longer2.u2) annotation (Line(points={{-38,60},{-30,60},{-30, + 22},{-22,22}}, color={0,0,127})); + connect(accTim[2].y, longer2.u1) annotation (Line(points={{-38,60},{-30,60},{-30, + 30},{-22,30}}, color={0,0,127})); + connect(uDevSta, edg.u) annotation (Line(points={{-180,60},{-120,60},{-120,-10}, + {-102,-10}}, color={255,0,255})); + connect(yRot, yRot) + annotation (Line(points={{180,0},{180,0}}, color={255,0,255})); + connect(longer2.y, not2.u) + annotation (Line(points={{2,30},{18,30}}, color={255,0,255})); + connect(longer1.y, not1.u) + annotation (Line(points={{2,60},{18,60}}, color={255,0,255})); + connect(uPreDevRolSig, not3.u) + annotation (Line(points={{-180,-40},{18,-40}}, color={255,0,255})); + connect(edg.y, and3.u2) annotation (Line(points={{-78,-10},{80,-10},{80,20},{98, + 20}}, color={255,0,255})); + connect(not3.y, and3.u3) annotation (Line(points={{42,-40},{88,-40},{88,12},{98, + 12}}, color={255,0,255})); + connect(not1.y, and3[1].u1) annotation (Line(points={{42,60},{80,60},{80,28},{ + 98,28}}, color={255,0,255})); + connect(not2.y, and3[2].u1) annotation (Line(points={{42,30},{70,30},{70,28},{ + 98,28}}, color={255,0,255})); + connect(mulOr.y, yRot) + annotation (Line(points={{152,0},{180,0}}, color={255,0,255})); + connect(and3.y, mulOr.u) annotation (Line(points={{122,20},{124,20},{124,0},{128, + 0},{128,0}}, color={255,0,255})); + connect(uDevSta, falEdg.u) annotation (Line(points={{-180,60},{-120,60},{-120, + -60},{-102,-60}}, color={255,0,255})); + connect(longer1.y, and1[1].u1) annotation (Line(points={{2,60},{10,60},{10,-20}, + {80,-20},{80,-60},{98,-60}}, color={255,0,255})); + connect(longer2.y, and1[2].u1) annotation (Line(points={{2,30},{10,30},{10,-20}, + {80,-20},{80,-60},{98,-60}}, color={255,0,255})); + connect(and1.y, mulOr.u) annotation (Line(points={{122,-60},{122,0},{128,0}}, + color={255,0,255})); + connect(falEdg.y, and1.u2) annotation (Line(points={{-78,-60},{20,-60},{20, + -68},{98,-68}}, color={255,0,255})); + connect(con.y, accTim.reset) annotation (Line(points={{-78,30},{-70,30},{-70,52}, + {-62,52}}, 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.2.3. and 5.1.2.4.1. of RP1711 March 2020 draft 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..cec7329b8c3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/Subsequences/Scheduler.mo @@ -0,0 +1,251 @@ +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.Continuous.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 y then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if y then {0,255,0} + else {235,235,235}), + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-75,-6},{-89,8}}, + lineColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {235,235,235}), + fillColor=DynamicSelect({235,235,235}, if u1 then {0,255,0} + else {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 RP 1711 5.1.2.4.2, except 5.1.2.4.2 a. +

+

+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..ed9f74289b6 --- /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.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..d2dca7e7970 --- /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.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..b779097a535 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/EquipmentRotation/package.mo @@ -0,0 +1,48 @@ +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 RP1711. +March 2020 draft, section 5.1.2. 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/PlantEnable/DisableChillers.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/DisableChillers.mo new file mode 100644 index 00000000000..0bbe0dc358b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/DisableChillers.mo @@ -0,0 +1,280 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable; +block DisableChillers + "Disable devices when the plant is disabled from chiller mode" + + 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={{-180,220},{-140,260}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-180,180},{-140,220}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatReq[nChi] + "Chilled water requst status for each chiller" + annotation (Placement(transformation(extent={{-180,40},{-140,80}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + 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={{-180,10},{-140,50}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uConWatReq[nChi] + "Condenser water requst status for each chiller" + annotation (Placement(transformation(extent={{-180,-50},{-140,-10}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + 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={{-180,-90},{-140,-50}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uChiWatPumSpe[nChiWatPum] + "Chilled water pump speed" + annotation (Placement(transformation(extent={{-180,-160},{-140,-120}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uConWatPumSpe[nConWatPum] + "Condenser water pump speed" + annotation (Placement(transformation(extent={{-180,-200},{-140,-160}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller commanded on" + annotation(Placement(transformation(extent={{140,180},{180,220}}), + iconTransformation(extent={{100,70},{140,110}}))); + 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={{140,80},{180,120}}), + 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={{140,-30},{180,10}}), + 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={{140,-140},{180,-100}}), + 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={{140,-180},{180,-140}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTow + "Cooling tower commanded on" annotation (Placement(transformation(extent={{140, + -250},{180,-210}}), iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{20,190},{40,210}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nChi] + "Chiller commanded on" + annotation (Placement(transformation(extent={{100,190},{120,210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[nChi]( + final k=fill(false, nChi)) + "Disable chillers" + annotation (Placement(transformation(extent={{20,160},{40,180}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=180) + "Threshold time after chiller being disabled" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + final nin=nChi) + "Check if there is any chilled water request" + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep1( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1( + final nin=nChi) + "Check if there is any condenser water request" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep2( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{40,-20},{60,0}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep3( + final nout=nChiWatPum) + "Replicate boolean input" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booScaRep5( + final nout=nConWatPum) + "Replicate boolean input" + annotation (Placement(transformation(extent={{40,-170},{60,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Logical not" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "No chilled water request" + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + Buildings.Controls.OBC.CDL.Logical.Or cloChiIsoVal + "Close all chilled water isolation valve" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1[nChi]( + final k=fill(0, nChi)) "Close valve" + annotation (Placement(transformation(extent={{-60,130},{-40,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nChi] "Close valve" + annotation (Placement(transformation(extent={{100,90},{120,110}}))); + Buildings.Controls.OBC.CDL.Logical.Or cloChiIsoVal1 + "Close all chilled water isolation valve" + annotation (Placement(transformation(extent={{0,-20},{20,0}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 "No condenser water request" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nChi] + "Close valve" + annotation (Placement(transformation(extent={{100,-20},{120,0}}))); + Buildings.Controls.OBC.CDL.Logical.Or cloPums "Disable pumps" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi2[nChiWatPum] + "Disable pumps" + annotation (Placement(transformation(extent={{100,-130},{120,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi3[nConWatPum] + "Disable pumps" + annotation (Placement(transformation(extent={{100,-170},{120,-150}}))); + +equation + connect(uPla, booScaRep.u) + annotation (Line(points={{-160,200},{18,200}}, color={255,0,255})); + connect(booScaRep.y, logSwi.u2) + annotation (Line(points={{42,200},{98,200}}, color={255,0,255})); + connect(uChi, logSwi.u1) annotation (Line(points={{-160,240},{80,240},{80,208}, + {98,208}}, color={255,0,255})); + connect(con.y, logSwi.u3) annotation (Line(points={{42,170},{80,170},{80,192}, + {98,192}}, color={255,0,255})); + connect(logSwi.y, yChi) + annotation (Line(points={{122,200},{160,200}}, color={255,0,255})); + connect(uPla, not1.u) annotation (Line(points={{-160,200},{-120,200},{-120,100}, + {-102,100}},color={255,0,255})); + connect(not1.y, truDel.u) + annotation (Line(points={{-78,100},{-62,100}}, color={255,0,255})); + connect(uChiWatReq, mulOr.u) + annotation (Line(points={{-160,60},{-102,60}}, color={255,0,255})); + connect(mulOr.y, not2.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(truDel.y, cloChiIsoVal.u1) + annotation (Line(points={{-38,100},{-2,100}}, color={255,0,255})); + connect(not2.y, cloChiIsoVal.u2) annotation (Line(points={{-38,60},{-20,60},{-20, + 92},{-2,92}}, color={255,0,255})); + connect(cloChiIsoVal.y, booScaRep1.u) + annotation (Line(points={{22,100},{38,100}}, color={255,0,255})); + connect(booScaRep1.y, swi.u2) + annotation (Line(points={{62,100},{98,100}}, color={255,0,255})); + connect(con1.y, swi.u1) annotation (Line(points={{-38,140},{80,140},{80,108},{ + 98,108}}, color={0,0,127})); + connect(uChiWatIsoVal, swi.u3) annotation (Line(points={{-160,30},{70,30},{70, + 92},{98,92}}, color={0,0,127})); + connect(swi.y, yChiWatIsoVal) + annotation (Line(points={{122,100},{160,100}}, color={0,0,127})); + connect(truDel.y, cloChiIsoVal1.u1) annotation (Line(points={{-38,100},{-10,100}, + {-10,-10},{-2,-10}}, color={255,0,255})); + connect(mulOr1.y, not3.u) + annotation (Line(points={{-78,-30},{-62,-30}}, color={255,0,255})); + connect(uConWatReq, mulOr1.u) + annotation (Line(points={{-160,-30},{-102,-30}}, color={255,0,255})); + connect(not3.y, cloChiIsoVal1.u2) annotation (Line(points={{-38,-30},{-20,-30}, + {-20,-18},{-2,-18}}, color={255,0,255})); + connect(swi1.y, yConWatIsoVal) + annotation (Line(points={{122,-10},{160,-10}}, color={0,0,127})); + connect(cloChiIsoVal1.y, booScaRep2.u) + annotation (Line(points={{22,-10},{38,-10}}, color={255,0,255})); + connect(booScaRep2.y, swi1.u2) + annotation (Line(points={{62,-10},{98,-10}}, color={255,0,255})); + connect(con1.y, swi1.u1) annotation (Line(points={{-38,140},{80,140},{80,-2},{ + 98,-2}}, color={0,0,127})); + connect(uConWatIsoVal, swi1.u3) annotation (Line(points={{-160,-70},{72,-70},{ + 72,-18},{98,-18}}, color={0,0,127})); + connect(cloChiIsoVal.y, cloPums.u2) annotation (Line(points={{22,100},{30,100}, + {30,40},{-70,40},{-70,-108},{-22,-108}}, color={255,0,255})); + connect(cloChiIsoVal1.y, cloPums.u1) annotation (Line(points={{22,-10},{30,-10}, + {30,-60},{-40,-60},{-40,-100},{-22,-100}}, color={255,0,255})); + connect(cloPums.y, booScaRep3.u) annotation (Line(points={{2,-100},{20,-100},{ + 20,-120},{38,-120}}, color={255,0,255})); + connect(booScaRep3.y, swi2.u2) annotation (Line(points={{62,-120},{98,-120}}, + color={255,0,255})); + connect(con1.y, swi2.u1) annotation (Line(points={{-38,140},{80,140},{80,-112}, + {98,-112}}, color={0,0,127})); + connect(uChiWatPumSpe, swi2.u3) annotation (Line(points={{-160,-140},{70,-140}, + {70,-128},{98,-128}}, color={0,0,127})); + connect(swi2.y, yChiWatPumSpe) + annotation (Line(points={{122,-120},{160,-120}}, color={0,0,127})); + connect(con1.y, swi3.u1) annotation (Line(points={{-38,140},{80,140},{80,-152}, + {98,-152}}, color={0,0,127})); + connect(uConWatPumSpe, swi3.u3) annotation (Line(points={{-160,-180},{70,-180}, + {70,-168},{98,-168}}, color={0,0,127})); + connect(swi3.y, yConWatPumSpe) + annotation (Line(points={{122,-160},{160,-160}}, color={0,0,127})); + connect(cloPums.y, booScaRep5.u) annotation (Line(points={{2,-100},{20,-100},{ + 20,-160},{38,-160}}, color={255,0,255})); + connect(booScaRep5.y, swi3.u2) + annotation (Line(points={{62,-160},{98,-160}}, color={255,0,255})); + connect(cloPums.y, yTow) annotation (Line(points={{2,-100},{20,-100},{20,-230}, + {160,-230}}, 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={{-140,-260},{140,260}})), + Documentation(info=" +

+It disables the devices when the chiller plant is disabled in chiller mode. +It is implemented as provided in sections 5.2.2.5 and 5.2.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..dd37fe513af --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Enable.mo @@ -0,0 +1,292 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable; +block Enable "Sequence to enable and disable plant" + + parameter Boolean have_WSE = true + "Flag to indicate if the plant has waterside economizer"; + + 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 = 1 + "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") + "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.Continuous.Sources.TimeTable enaSch( + final table=schTab, + final smoothness=tabSmo, + final extrapolation=extrapolation) + "Plant enabling schedule allowing operators to lock out the plant during off-hour" + annotation (Placement(transformation(extent={{-140,40},{-120,60}}))); + +protected + 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"; + + Buildings.Controls.OBC.CDL.Continuous.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}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer enaTim1( + final t=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={{-20,-60},{0,-40}}))); + + Buildings.Controls.OBC.CDL.Logical.And disPla + "Disable chiller plant" + annotation (Placement(transformation(extent={{40,-20},{60,0}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch plaSta + "Chiller plant enabling status" + annotation (Placement(transformation(extent={{100,70},{120,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Or3 disPlaCon + "Disable chiller plant conditions" + annotation (Placement(transformation(extent={{40,-80},{60,-60}}))); + + Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not" + 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.Continuous.Sources.Constant chiLocOutTem( + final k=TChiLocOut) + "Outdoor air lockout temperature" + annotation (Placement(transformation(extent={{-180,-120},{-160,-100}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + "Difference between chiller lockout temperature and outdoor temperature" + annotation (Placement(transformation(extent={{-140,-140},{-120,-120}}))); + +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},{-40,50},{-40,-50},{-22,-50}}, + color={255,0,255})); + connect(enaPla.y, plaSta.u) + annotation (Line(points={{62,80},{98,80}}, color={255,0,255})); + connect(plaSta.y, yPla) + annotation (Line(points={{122,80},{210,80}}, color={255,0,255})); + connect(disPlaCon.y, disPla.u2) annotation (Line(points={{62,-70},{80,-70},{80, + -30},{20,-30},{20,-18},{38,-18}}, color={255,0,255})); + connect(not2.y, disPlaCon.u1) annotation (Line(points={{2,-50},{20,-50},{20,-62}, + {38,-62}}, color={255,0,255})); + connect(hasReq.y, not3.u) + annotation (Line(points={{-118,90},{-20,90},{-20,70},{-180,70},{-180,-70},{-142, + -70}}, color={255,0,255})); + connect(not3.y, enaTim1.u) + annotation (Line(points={{-118,-70},{-102,-70}}, color={255,0,255})); + connect(plaSta.y, pre1.u) annotation (Line(points={{122,80},{140,80},{140,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, disPlaCon.u3) annotation (Line(points={{-78,-130},{20,-130},{20, + -78},{38,-78}}, color={255,0,255})); + 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={{62,-10},{80,-10},{80,74}, + {98,74}}, color={255,0,255})); + connect(enaTim1.passed, disPlaCon.u2) annotation (Line(points={{-78,-78},{-20, + -78},{-20,-70},{38,-70}}, color={255,0,255})); + connect(enaTim.passed, disPla.u1) annotation (Line(points={{-118,-18},{-80,-18}, + {-80,-10},{38,-10}}, 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.2.1, +5.2.2.2 and 5.2.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..fc58cde481f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/EnableDevices.mo @@ -0,0 +1,204 @@ +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"; + + 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,10},{-160,50}}), + 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 edg1 + "Becoming not initial stage" + annotation (Placement(transformation(extent={{-20,50},{0,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={{40,90},{60,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 intEqu + "Check if initial stage is 0" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + 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={{100,20},{120,40}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr( + 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 mulOr1( + 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,30},{-140,30},{-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(not1.y, edg1.u) + annotation (Line(points={{-38,60},{-22,60}}, color={255,0,255})); + connect(edg1.y, ecoMod.clr) annotation (Line(points={{2,60},{20,60},{20,94},{38, + 94}}, color={255,0,255})); + connect(edg.y, ecoMod.u) + annotation (Line(points={{-78,100},{38,100}}, color={255,0,255})); + connect(ecoMod.y, yEnaPlaPro) + annotation (Line(points={{62,100},{180,100}}, color={255,0,255})); + connect(ecoMod.y, yLeaPriChiPum) annotation (Line(points={{62,100},{80,100},{80, + -30},{180,-30}}, color={255,0,255})); + connect(ecoMod.y, yLeaConPum) annotation (Line(points={{62,100},{80,100},{80,-60}, + {180,-60}}, color={255,0,255})); + connect(ecoMod.y,yLeaTowCel) annotation (Line(points={{62,100},{80,100},{80,-90}, + {180,-90}}, color={255,0,255})); + connect(conInt.y, intEqu.u2) annotation (Line(points={{-98,0},{-60,0},{-60,22}, + {-42,22}}, color={255,127,0})); + connect(uIni, intEqu.u1) annotation (Line(points={{-180,60},{-120,60},{-120,30}, + {-42,30}}, color={255,127,0})); + connect(intEqu.y, and1.u1) + annotation (Line(points={{-18,30},{98,30}}, color={255,0,255})); + connect(ecoMod.y, and1.u2) annotation (Line(points={{62,100},{80,100},{80,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, mulOr.u) + annotation (Line(points={{-180,-60},{-122,-60}}, color={255,0,255})); + connect(uConWatPum, mulOr1.u) + annotation (Line(points={{-180,-110},{-122,-110}}, color={255,0,255})); + connect(mulOr.y, and2.u1) + annotation (Line(points={{-98,-60},{-62,-60}}, color={255,0,255})); + connect(mulOr1.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})); +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.2.2.4, +section 1 and 2. +

+
    +
  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..5899a4678a7 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/DisableChillers.mo @@ -0,0 +1,90 @@ +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 disDev + "Disable chillers and the associated devices" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.6, + final period=3600) + "Enabled plant" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[2]( + final k={true,false}) + "Enabled chiller" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.7, + final period=3600) + "Chilled water request" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiIsoVal[2]( + final k={1,0}) + "Chilled water isolation valve" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul3( + final width=0.7, + final period=3600) + "Condenser water request" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant conIsoVal1[2]( + final k={1,0}) + "Condenser water isolation valve" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe[2]( + final k={0.75,0}) "Pumps speed" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + +equation + connect(booPul.y, disDev.uPla) annotation (Line(points={{-18,50},{-5,50},{-5,37}, + {58,37}}, color={255,0,255})); + connect(con.y, disDev.uChi) annotation (Line(points={{-58,80},{40,80},{40,39}, + {58,39}}, color={255,0,255})); + connect(booPul2.y, disDev.uChiWatReq[1]) annotation (Line(points={{-58,20},{2, + 20},{2,34},{58,34}}, color={255,0,255})); + connect(con[2].y, disDev.uChiWatReq[2]) annotation (Line(points={{-58,80},{2,80}, + {2,34},{58,34}}, color={255,0,255})); + connect(chiIsoVal.y, disDev.uChiWatIsoVal) annotation (Line(points={{-18,0},{12, + 0},{12,32},{58,32}}, color={0,0,127})); + connect(booPul3.y, disDev.uConWatReq[1]) annotation (Line(points={{-58,-20},{22, + -20},{22,28},{58,28}}, color={255,0,255})); + connect(con[2].y, disDev.uConWatReq[2]) annotation (Line(points={{-58,80},{40, + 80},{40,28},{58,28}}, color={255,0,255})); + connect(conIsoVal1.y, disDev.uConWatIsoVal) annotation (Line(points={{-18,-50}, + {32,-50},{32,26},{58,26}}, color={0,0,127})); + connect(pumSpe.y, disDev.uChiWatPumSpe) annotation (Line(points={{-58,-80},{40, + -80},{40,23},{58,23}}, color={0,0,127})); + connect(pumSpe.y, disDev.uConWatPumSpe) annotation (Line(points={{-58,-80},{40, + -80},{40,21},{58,21}}, 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/Generic/PlantEnable/Validation/DisableChillers.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Generic.PlantEnable.DisableChillers. +

+", 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..b14d5dc8551 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/Enable.mo @@ -0,0 +1,143 @@ +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; 6*3600,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; 6*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.Continuous.Sources.Constant conOutTem( + final k=293.15) "Constant outdoor temperature above lockout" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.TimeTable chiPlaReq2( + final table=[0,1; 6.5*3600,1; 9*3600,2;14*3600,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.Continuous.Sources.Constant conOutTem1( + final k=282.15) + "Constant outdoor temperature" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine outTem1( + final amplitude=7.5, + final freqHz=1/(24*3600), + final offset=280.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. +

+", 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..6b9afc6c937 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/Validation/EnableDevices.mo @@ -0,0 +1,86 @@ +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. +

+", 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..42ea7228864 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/PlantEnable/package.mo @@ -0,0 +1,37 @@ +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 RP1711. +March 2020 draft, section 5.2.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/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..7324ea03c38 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Generic/package.order @@ -0,0 +1,2 @@ +EquipmentRotation +PlantEnable 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..7a316df97a5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Controller.mo @@ -0,0 +1,274 @@ +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)); + + 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) 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.Continuous.Switch swi if have_heaPreConSig + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.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.") + "Asserts 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 and2 + "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}}))); + +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},{-40,82},{-40,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(uChiHeaCon, noWSE.uHeaPreEna) + annotation (Line(points={{-120,120},{-80,120},{-80,42},{38,42}}, + color={255,0,255})); + connect(withWSE.uWSE, uWSE) + annotation (Line(points={{38,-14},{-20,-14},{-20,0},{-120,0}}, + color={255,0,255})); + connect(uChiHeaCon, withWSE.uHeaPreEna) + annotation (Line(points={{-120,120},{-80,120},{-80,-18},{38,-18}}, + color={255,0,255})); + connect(uChiHeaCon, swi.u2) + annotation (Line(points={{-120,120},{-80,120},{-80,-40},{-22,-40}}, + color={255,0,255})); + connect(uHeaPreCon, swi.u1) + annotation (Line(points={{-120,-30},{-40,-30},{-40,-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(uChiHeaCon, chiHeaPreLoo.uHeaPreEna) + annotation (Line(points={{-120,120},{-80,120},{-80,98},{-22,98}}, + color={255,0,255})); + connect(desConWatPumSpe, noWSE.desConWatPumSpe) + annotation (Line(points={{-120,30},{0,30},{0,50},{38,50}}, color={0,0,127})); + connect(havWSE.y, and2.u1) annotation (Line(points={{-38,-90},{-30,-90},{-30,-100}, + {-22,-100}}, color={255,0,255})); + connect(fixSpe.y, and2.u2) annotation (Line(points={{-38,-120},{-30,-120},{-30, + -108},{-22,-108}}, color={255,0,255})); + connect(and2.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})); + +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020), +section 5.2.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..ae032ddd842 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/ControlLoop.mo @@ -0,0 +1,140 @@ +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", + displayUnit="degC") = 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")); + + 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.Continuous.PIDWithReset conPID( + final controllerType=controllerType, + final k=k, + final Ti=Ti, + 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.Continuous.Subtract sub1 + annotation (Placement(transformation(extent={{-70,-30},{-50,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai(final k=1/minChiLif) + "Normalized by minimum allowable lift at minimum load for chiller" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + +equation + connect(TConWatRet, sub1.u1) + annotation (Line(points={{-120,-20},{-80,-20},{-80,-14},{-72,-14}}, + 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(sub1.y, gai.u) + annotation (Line(points={{-48,-20},{-22,-20}}, color={0,0,127})); + connect(gai.y, conPID.u_m) + annotation (Line(points={{2,-20},{30,-20},{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, sub1.u2) annotation (Line(points={{-120,-80},{-80,-80},{ + -80,-26},{-72,-26}}, 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.10 Head pressure control, part 5.2.10.1 and 5.2.10.2. +

+

+1. When head pressure control loop is enabled, 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..eb45f55154c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithWSE.mo @@ -0,0 +1,309 @@ +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 + "Chiller head pressure control loop signal" + annotation (Placement(transformation(extent={{-160,110},{-120,150}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput desConWatPumSpe + "Design condenser water pump speed for current stage" + annotation (Placement(transformation(extent={{-160,40},{-120,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={{-160,-20},{-120,20}}), + 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={{-160,-180},{-120,-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={{120,160},{160,200}}), + 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={{120,50},{160,90}}), + 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={{120,-180},{160,-140}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Line maxCooTowSpeSet + "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{40,120},{60,140}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,140},{20,160}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,140},{-20,160}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hal(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{-40,100},{-20,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hpTowMaxSpe( + final k=minTowSpe) + "Minimum allowable tower speed" + annotation (Placement(transformation(extent={{0,100},{20,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Line conWatPumSpe + "Condenser water pump speed" + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hal1(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one2(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( + final k=minConWatPumSpe) "Minimum condenser water pump speed" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one3(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one4(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=minHeaPreValPos) + "Minimum head pressure control valve position" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer1(final k=0) + "Constant value" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Line heaPreConVal + "Head pressure control valve position" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi + annotation (Placement(transformation(extent={{80,170},{100,190}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + annotation (Placement(transformation(extent={{80,60},{100,80}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 + annotation (Placement(transformation(extent={{80,-120},{100,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi3 + annotation (Placement(transformation(extent={{80,-170},{100,-150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer2(final k=0) + "Constant value" + annotation (Placement(transformation(extent={{-40,-190},{-20,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-100,-150},{-80,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{-80,170},{-60,190}}))); + +equation + connect(zer.y, maxCooTowSpeSet.x1) + annotation (Line(points={{22,150},{30,150},{30,138},{38,138}},color={0,0,127})); + connect(one.y, maxCooTowSpeSet.f1) + annotation (Line(points={{-18,150},{-10,150},{-10,134},{38,134}}, + color={0,0,127})); + connect(hal.y, maxCooTowSpeSet.x2) + annotation (Line(points={{-18,110},{-10,110},{-10,126},{38,126}}, + color={0,0,127})); + connect(hpTowMaxSpe.y, maxCooTowSpeSet.f2) + annotation (Line(points={{22,110},{30,110},{30,122},{38,122}},color={0,0,127})); + connect(uHeaPreCon, maxCooTowSpeSet.u) + annotation (Line(points={{-140,130},{38,130}}, color={0,0,127})); + connect(hal1.y,conWatPumSpe. x1) + annotation (Line(points={{22,50},{30,50},{30,38},{38,38}},color={0,0,127})); + connect(con.y,conWatPumSpe. f2) + annotation (Line(points={{22,0},{30,0},{30,22},{38,22}},color={0,0,127})); + connect(one2.y,conWatPumSpe. x2) + annotation (Line(points={{-18,0},{-10,0},{-10,26},{38,26}}, color={0,0,127})); + connect(uHeaPreCon,conWatPumSpe. u) + annotation (Line(points={{-140,130},{-80,130},{-80,30},{38,30}}, + color={0,0,127})); + connect(zer1.y, heaPreConVal.x1) + annotation (Line(points={{22,-40},{30,-40},{30,-52},{38,-52}},color={0,0,127})); + connect(one3.y, heaPreConVal.f1) + annotation (Line(points={{-18,-40},{-10,-40},{-10,-56},{38,-56}}, + color={0,0,127})); + connect(one4.y, heaPreConVal.x2) + annotation (Line(points={{-18,-80},{-10,-80},{-10,-64},{38,-64}}, + color={0,0,127})); + connect(con1.y, heaPreConVal.f2) + annotation (Line(points={{22,-80},{30,-80},{30,-68},{38,-68}},color={0,0,127})); + connect(uHeaPreCon, heaPreConVal.u) + annotation (Line(points={{-140,130},{-80,130},{-80,-60},{38,-60}}, + color={0,0,127})); + connect(maxCooTowSpeSet.y, swi.u3) + annotation (Line(points={{62,130},{70,130},{70,172},{78,172}}, + color={0,0,127})); + connect(swi.y, yMaxTowSpeSet) + annotation (Line(points={{102,180},{140,180}}, color={0,0,127})); + connect(desConWatPumSpe, swi1.u1) + annotation (Line(points={{-140,60},{-60,60},{-60,78},{78,78}}, color={0,0,127})); + connect(conWatPumSpe.y, swi1.u3) + annotation (Line(points={{62,30},{70,30},{70,62},{78,62}}, + color={0,0,127})); + connect(swi1.y, yConWatPumSpeSet) + annotation (Line(points={{102,70},{140,70}}, color={0,0,127})); + connect(uWSE, swi2.u2) + annotation (Line(points={{-140,0},{-100,0},{-100,-110},{78,-110}}, + color={255,0,255})); + connect(zer2.y, swi3.u3) + annotation (Line(points={{-18,-180},{60,-180},{60,-168},{78,-168}}, + color={0,0,127})); + connect(uHeaPreEna, swi3.u2) + annotation (Line(points={{-140,-160},{78,-160}}, color={255,0,255})); + connect(swi2.y, swi3.u1) + annotation (Line(points={{102,-110},{110,-110},{110,-140},{60,-140}, + {60,-152},{78,-152}}, color={0,0,127})); + connect(swi3.y, yHeaPreConVal) + annotation (Line(points={{102,-160},{140,-160}}, color={0,0,127})); + connect(one.y, swi.u1) + annotation (Line(points={{-18,150},{-10,150},{-10,188},{78,188}}, + color={0,0,127})); + connect(desConWatPumSpe, conWatPumSpe.f1) + annotation (Line(points={{-140,60},{-60,60},{-60,34},{38,34}}, + color={0,0,127})); + connect(one4.y, swi2.u3) + annotation (Line(points={{-18,-80},{-10,-80},{-10,-118},{78,-118}}, + color={0,0,127})); + connect(uHeaPreEna, not1.u) + annotation (Line(points={{-140,-160},{-110,-160},{-110,-140},{-102,-140}}, + color={255,0,255})); + connect(uWSE, or2.u1) + annotation (Line(points={{-140,0},{-100,0},{-100,180},{-82,180}}, + color={255,0,255})); + connect(not1.y, or2.u2) + annotation (Line(points={{-78,-140},{-60,-140},{-60,-120},{-96,-120}, + {-96,172},{-82,172}}, color={255,0,255})); + connect(or2.y, swi.u2) + annotation (Line(points={{-58,180},{78,180}}, color={255,0,255})); + connect(or2.y, swi1.u2) + annotation (Line(points={{-58,180},{-50,180},{-50,70},{78,70}}, + color={255,0,255})); + connect(heaPreConVal.y, swi2.u1) + annotation (Line(points={{62,-60},{70,-60},{70,-102},{78,-102}}, + 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={{-120,-200},{120,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 RP-1711 Advanced Sequences of Operation for HVAC Systems +Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.10 Head pressure control, part 5.2.10.5, 5.2.10.6 and 5.2.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. +

+", +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..f7077ad2e15 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/MappingWithoutWSE.mo @@ -0,0 +1,240 @@ +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={{-140,40},{-100,80}}), + 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={{-140,-20},{-100,20}}), + 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={{-140,-100},{-100,-60}}), + 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={{100,80},{140,120}}), + 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={{100,-60},{140,-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={{100,-100},{140,-60}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Line maxCooTowSpeSet + "Maximum cooling tower speed setpoint" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hal(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hpTowMaxSpe( + final k=minTowSpe) + "Minimum allowable tower speed" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Line lin + "Head pressure control valve position, or condenser water pump speed" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hal1(final k=0.5) + "Constant value" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant fulOpeVal( + final k=1) if have_fixSpeConWatPum "Fully open valve position" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one2(k=1) "Constant one" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minValPos( + final k=minHeaPreValPos) if have_fixSpeConWatPum + "Minimum head pressure control valve position" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer2(final k=0) + "Constant value" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{60,-90},{80,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minPumSpe( + final k=minConWatPumSpe) if not have_fixSpeConWatPum + "Minimum condenser water pump speed" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + +equation + connect(zer.y, maxCooTowSpeSet.x1) + annotation (Line(points={{22,80},{30,80},{30,68},{38,68}},color={0,0,127})); + connect(one.y, maxCooTowSpeSet.f1) + annotation (Line(points={{-18,80},{-10,80},{-10,64},{38,64}}, color={0,0,127})); + connect(hal.y, maxCooTowSpeSet.x2) + annotation (Line(points={{-18,40},{-10,40},{-10,56},{38,56}}, color={0,0,127})); + connect(hpTowMaxSpe.y, maxCooTowSpeSet.f2) + annotation (Line(points={{22,40},{30,40},{30,52},{38,52}},color={0,0,127})); + connect(uHeaPreCon, maxCooTowSpeSet.u) + annotation (Line(points={{-120,60},{38,60}}, color={0,0,127})); + connect(hal1.y, lin.x1) + annotation (Line(points={{22,0},{30,0},{30,-12},{38,-12}}, color={0,0,127})); + connect(fulOpeVal.y, lin.f1) + annotation (Line(points={{-18,0},{-10,0},{-10,-16},{38,-16}}, color={0,0,127})); + connect(minValPos.y, lin.f2) + annotation (Line(points={{22,-50},{30,-50},{30,-28},{38,-28}}, + color={0,0,127})); + connect(one2.y, lin.x2) + annotation (Line(points={{-58,-40},{-50,-40},{-50,-24},{38,-24}}, + color={0,0,127})); + connect(uHeaPreCon, lin.u) + annotation (Line(points={{-120,60},{-60,60},{-60,-20},{38,-20}}, + color={0,0,127})); + connect(uHeaPreEna, swi.u2) + annotation (Line(points={{-120,-80},{58,-80}}, color={255,0,255})); + connect(lin.y, swi.u1) + annotation (Line(points={{62,-20},{80,-20},{80,-40},{40,-40},{40,-72}, + {58,-72}}, color={0,0,127})); + connect(zer2.y, swi.u3) + annotation (Line(points={{-18,-100},{40,-100},{40,-88},{58,-88}}, + color={0,0,127})); + connect(swi.y, yConWatPumSpeSet) + annotation (Line(points={{82,-80},{120,-80}}, color={0,0,127})); + connect(desConWatPumSpe, lin.f1) + annotation (Line(points={{-120,0},{-80,0},{-80,-16},{38,-16}}, + color={0,0,127})); + connect(minPumSpe.y, lin.f2) + annotation (Line(points={{-18,-50},{-10,-50},{-10,-28},{38,-28}}, + color={0,0,127})); + connect(swi.y, yHeaPreConVal) + annotation (Line(points={{82,-80},{90,-80},{90,-40},{120,-40}}, color={0,0,127})); + connect(uHeaPreEna, swi1.u2) + annotation (Line(points={{-120,-80},{-90,-80},{-90,100},{58,100}}, + color={255,0,255})); + connect(maxCooTowSpeSet.y, swi1.u1) + annotation (Line(points={{62,60},{70,60},{70,80},{40,80},{40,108},{58,108}}, + color={0,0,127})); + connect(swi1.y, yMaxTowSpeSet) + annotation (Line(points={{82,100},{120,100}}, color={0,0,127})); + connect(one.y, swi1.u3) + annotation (Line(points={{-18,80},{-10,80},{-10,92},{58,92}}, color={0,0,127})); + +annotation ( + defaultComponentName= "heaPreConEqu", + Icon(coordinateSystem(preserveAspectRatio=false), 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={{-100,-120},{100,120}})), + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.10 Head pressure control, part 5.2.10.3, part 5.2.10.4 and 5.2.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. +

+", +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..333065f25c3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/ControlLoop.mo @@ -0,0 +1,60 @@ +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={{20,40},{40,60}}))); + 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={{-80,60},{-60,80}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine TConWatRet( + final amplitude=-11, + final freqHz=2/10, + final offset=273.15 + 27) "Measured condenser water return temperature" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine TChiWatSup( + final amplitude=1, + final freqHz=1/5, + final offset=273.15 + 6) "Measured chilled water supply temperature" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + +equation + connect(TConWatRet.y, chiHeaPreLoo.TConWatRet) + annotation (Line(points={{-58,20},{-20,20},{-20,50},{18,50}}, color={0,0,127})); + connect(TChiWatSup.y, chiHeaPreLoo.TChiWatSup) + annotation (Line(points={{-58,-20},{0,-20},{0,42},{18,42}}, color={0,0,127})); + connect(booPul.y, chiHeaPreLoo.uHeaPreEna) + annotation (Line(points={{-58,70},{-20,70},{-20,58},{18,58}}, 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/ControlLoop.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.ControlLoop. +

+", 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..c69c220b9ab --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithWSE.mo @@ -0,0 +1,78 @@ +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={{0,50},{20,70}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.HeadPressure.Subsequences.MappingWithWSE + noWSE "Specify setpoints for plant when waterside economizer is disabled" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant enaPreCon( + final k=true) "Constant true" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant enaWSE( + final k=true) "Constant true" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant desPumSpe( + final k=0.75) "Design condenser water pump speed at current stage" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp conLoo( + final duration=5) "Control loop output" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + +equation + connect(conLoo.y, witWSE.uHeaPreCon) + annotation (Line(points={{-38,80},{-24,80},{-24,68},{-2,68}}, color={0,0,127})); + connect(desPumSpe.y, witWSE.desConWatPumSpe) + annotation (Line(points={{-38,40},{-20,40},{-20,64},{-2,64}}, color={0,0,127})); + connect(enaWSE.y, witWSE.uWSE) + annotation (Line(points={{-38,0},{-16,0},{-16,56},{-2,56}}, color={255,0,255})); + connect(enaPreCon.y, witWSE.uHeaPreEna) + annotation (Line(points={{-38,-40},{-12,-40},{-12,52},{-2,52}}, color={255,0,255})); + connect(conLoo.y, noWSE.uHeaPreCon) + annotation (Line(points={{-38,80},{-24,80},{-24,-72},{-2,-72}}, color={0,0,127})); + connect(desPumSpe.y, noWSE.desConWatPumSpe) + annotation (Line(points={{-38,40},{-20,40},{-20,-76},{-2,-76}}, color={0,0,127})); + connect(enaWSE.y, not1.u) + annotation (Line(points={{-38,0},{-2,0}}, color={255,0,255})); + connect(not1.y, noWSE.uWSE) + annotation (Line(points={{22,0},{40,0},{40,-60},{-16,-60},{-16,-84},{-2,-84}}, + color={255,0,255})); + connect(enaPreCon.y, noWSE.uHeaPreEna) + annotation (Line(points={{-38,-40},{-12,-40},{-12,-88},{-2,-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. +

+", 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..816b6397fa1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Subsequences/Validation/MappingWithoutWSE.mo @@ -0,0 +1,66 @@ +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.Constant enaPreCon( + final k=true) "Constant true" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant desPumSpe( + final k=0.75) "Design condenser water pump speed at current stage" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp conLoo( + final duration=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. +

+", 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..876c3d2bc6c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/Validation/Controller.mo @@ -0,0 +1,115 @@ +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) + "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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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})); + + connect(desPumSpe.y, conSpePum.desConWatPumSpe) annotation (Line(points={{-98, + -20},{10,-20},{10,38},{98,38}}, 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. +

+", 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..7adee66a048 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/HeadPressure/package.mo @@ -0,0 +1,47 @@ +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.2.10. in ASHRAE RP-1711 Advanced Sequences +of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..37bc358cd37 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Controller.mo @@ -0,0 +1,193 @@ +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={{-140,60},{-100,100}}), + 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={{-140,-10},{-100,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={{-140,-60},{-100,-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={{100,60},{140,100}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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,20},{60,40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minFlo[nChi]( + final k=minFloSet) "Minimum bypass flow rate at each stage" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum( + final nin=nChi) + "Sum of minimum chilled water flow of all chillers" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide div + "Normalized minimum flow setpoint" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide div1 + "Normalized minimum bypass flow " + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant opeVal( + final k=1) "Valve open" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + +equation + connect(minFlo.y, mulSum.u) + annotation (Line(points={{-58,-80},{-42,-80}},color={0,0,127})); + connect(VChiWat_flow, div1.u1) + annotation (Line(points={{-120,10},{-80,10},{-80,-4},{18,-4}}, color={0,0,127})); + connect(mulSum.y, div1.u2) + annotation (Line(points={{-18,-80},{10,-80},{10,-16},{18,-16}}, + color={0,0,127})); + connect(mulSum.y, div.u2) + annotation (Line(points={{-18,-80},{10,-80},{10,-66},{18,-66}}, + color={0,0,127})); + connect(div1.y, valPos.u_m) + annotation (Line(points={{42,-10},{50,-10},{50,18}}, color={0,0,127})); + connect(div.y, valPos.u_s) + annotation (Line(points={{42,-60},{50,-60},{50,-40},{0,-40},{0,30},{38,30}}, + color={0,0,127})); + connect(uChiWatPum, swi.u2) + annotation (Line(points={{-120,80},{38,80}}, color={255,0,255})); + connect(opeVal.y, swi.u3) + annotation (Line(points={{-18,60},{0,60},{0,72},{38,72}}, color={0,0,127})); + connect(swi.y, yValPos) + annotation (Line(points={{62,80},{120,80}}, color={0,0,127})); + connect(div.u1, VChiWatSet_flow) + annotation (Line(points={{18,-54},{-80,-54},{-80,-40},{-120,-40}}, + color={0,0,127})); + connect(uChiWatPum, valPos.trigger) + annotation (Line(points={{-120,80},{-60,80},{-60,10},{44,10},{44,18}}, + color={255,0,255})); + connect(valPos.y, swi.u1) + annotation (Line(points={{62,30},{80,30},{80,60},{20,60},{20,88},{38,88}}, + 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={{-100,-100},{100,100}})), + Documentation(info=" +

+Block that controls chilled water minimum flow for primary-only +plants with a minimum flow bypass valve, +according to ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.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.Subsequences.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..53fbf9ed037 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/FlowSetpoint.mo @@ -0,0 +1,958 @@ +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,400},{-440,440}}), + 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,360},{-440,400}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-480,320},{-440,360}}), + 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,50},{-440,90}}), + 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,-90},{-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,-300},{-440,-260}}), + 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,-340},{-440,-300}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow + "Stage down logical signal" + annotation (Placement(transformation(extent={{-480,-410},{-440,-370}}), + 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,120},{480,160}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + final parameter Integer chiInd[nChi]={i for i in 1:nChi} + "Chiller index, {1,2,...,n}"; + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con3( + final k=byPasSetTim) + "Duration time to change old setpoint to new setpoint" + annotation (Placement(transformation(extent={{-60,158},{-40,178}}))); + Buildings.Controls.OBC.CDL.Continuous.Line oneMorSet + "Minimum flow setpoint when adding one more chiller" + annotation (Placement(transformation(extent={{100,220},{120,240}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-60,200},{-40,220}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim + "Time after suppress chiller demand" + annotation (Placement(transformation(extent={{-218,410},{-198,430}}))); + Buildings.Controls.OBC.CDL.Continuous.Line oneLeSet + "Minimum flow setpoint when disabling one chiller" + annotation (Placement(transformation(extent={{100,-150},{120,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim1 + "Time after suppress chiller demand" + annotation (Placement(transformation(extent={{-220,-400},{-200,-380}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch dowSet + "Minimum flow chilled water flow setpoint when there is stage-down command" + annotation (Placement(transformation(extent={{240,-130},{260,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-220,-430},{-200,-410}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch byPasSet1 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{400,130},{420,150}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-320,410},{-300,430}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{-320,-400},{-300,-380}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minFlo[nChi]( + final k=minFloSet) + "Minimum chilled water flow through each chiller" + annotation (Placement(transformation(extent={{-400,190},{-380,210}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant maxFlo[nChi]( + final k=maxFloSet) + "Maximum chilled water flow through each chiller" + annotation (Placement(transformation(extent={{-400,150},{-380,170}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer[nChi]( + final k=fill(0,nChi)) "Constant zero" + annotation (Placement(transformation(extent={{-400,110},{-380,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide floRat[nChi] + "Flow rate ratio through each chiller" + annotation (Placement(transformation(extent={{-280,170},{-260,190}}))); + 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,80},{-200,100}}))); + 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,40},{-200,60}}))); + Buildings.Controls.OBC.CDL.Continuous.Max max if have_parChi + "Maximum flow rate ratio of operating chillers after one chiller being enabled" + annotation (Placement(transformation(extent={{-80,80},{-60,100}}))); + Buildings.Controls.OBC.CDL.Continuous.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,40},{-60,60}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nChi]( + final k=chiInd) "Chiller index vector" + annotation (Placement(transformation(extent={{-400,-40},{-380,-20}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intRep( + final nout=nChi) "Replicate integer input" + annotation (Placement(transformation(extent={{-400,-80},{-380,-60}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nChi] "Check equality of two integer inputs" + annotation (Placement(transformation(extent={{-320,-40},{-300,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Xor xor[nChi] "Outputs true if exactly one input is true" + annotation (Placement(transformation(extent={{-220,-40},{-200,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi3[nChi] if have_parChi + "Flow rate ratio of operating chiller" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi4[nChi] if have_parChi + "Maximum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-120,-70},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro2 if have_parChi + "Chilled water flow setpoint after disabling next chiller" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Max max1 if not have_parChi + "Largest minimum flow rate setpoint of operating chillers after one chiller being enabled" + annotation (Placement(transformation(extent={{-20,-200},{0,-180}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMax multiMax1(final nin=nChi) + if not have_parChi + "Largest minimum flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-80,-160},{-60,-140}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-240},{0,-220}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi5[nChi] if not have_parChi + "Minimum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-120,-160},{-100,-140}}))); + 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,-200},{-200,-180}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi6[nChi] if not have_parChi + "Minimum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-100,-240},{-80,-220}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical and" + annotation (Placement(transformation(extent={{-400,-10},{-380,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi9[nChi] if have_parChi + "Flow rate ratio of operating chiller" + annotation (Placement(transformation(extent={{-220,340},{-200,360}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMax multiMax4( + final nin=nChi) if have_parChi + "Maximum flow rate ratio of operating chillers" + annotation (Placement(transformation(extent={{-180,340},{-160,360}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi10[nChi] if have_parChi + "Maximum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-220,300},{-200,320}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum2( + final nin=nChi) if have_parChi + "Sum of maximum chilled water flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-180,300},{-160,320}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro3 if have_parChi + "Chilled water flow setpoint for current operating chillers" + annotation (Placement(transformation(extent={{-60,320},{-40,340}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi11[nChi] if have_parChi + "Maximum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-220,220},{-200,240}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiSum mulSum3( + final nin=nChi) if have_parChi + "Sum of maximum chilled water flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-180,220},{-160,240}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi12[nChi] if have_parChi + "Flow rate ratio of operating chiller" + annotation (Placement(transformation(extent={{-220,260},{-200,280}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMax multiMax5(final nin=nChi) + if have_parChi + "Maximum flow rate ratio of operating chillers" + annotation (Placement(transformation(extent={{-180,260},{-160,280}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro4 if have_parChi + "Chilled water flow setpoint for current operating chillers" + annotation (Placement(transformation(extent={{-60,240},{-40,260}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1 if have_parChi + "Chilled water flow setpoint for current operating chillers" + annotation (Placement(transformation(extent={{-20,60},{0,80}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMax multiMax6( + final nin=nChi) if not have_parChi + "Largest minimum flow rate setpoint of operating chillers" + annotation (Placement(transformation(extent={{-80,-120},{-60,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nChi] if not have_parChi + "Minimum flow rate of operating chiller" + annotation (Placement(transformation(extent={{-120,-120},{-100,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch byPasSet2 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{180,250},{200,270}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch upSet + "Minimum flow chilled water flow setpoint when there is stage-up command" + annotation (Placement(transformation(extent={{240,210},{260,230}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim2 + "Time after suppress chiller demand" + annotation (Placement(transformation(extent={{-220,-360},{-200,-340}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-320,-360},{-300,-340}}))); + Buildings.Controls.OBC.CDL.Continuous.Line oneMorSet1 + "Minimum flow setpoint when adding one more chiller" + annotation (Placement(transformation(extent={{100,-360},{120,-340}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch byPasSet4 + "Minimum flow chilled water flow setpoint" + annotation (Placement(transformation(extent={{160,-310},{180,-290}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch chaSet + "Minimum flow chilled water flow setpoint when there is stage-change command" + annotation (Placement(transformation(extent={{300,40},{320,60}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{300,130},{320,150}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 "Logical and" + annotation (Placement(transformation(extent={{340,130},{360,150}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam[nChi] + "Hold the chiller status when there is any stage change" + annotation (Placement(transformation(extent={{-360,240},{-340,260}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChi] "Boolean to real" + annotation (Placement(transformation(extent={{-400,240},{-380,260}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) "Replicate boolean input" + annotation (Placement(transformation(extent={{-380,30},{-360,50}}))); + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greEquThr[nChi]( + final t=fill(0.5, nChi)) + "Convert real to boolean" + annotation (Placement(transformation(extent={{-320,240},{-300,260}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr( + final t=1) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-400,-180},{-380,-160}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr( + final t=nChi) + "Check if index is in the range" + annotation (Placement(transformation(extent={{-400,-270},{-380,-250}}))); + 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,-270},{-340,-250}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 + "Check if index is in the range" + annotation (Placement(transformation(extent={{-360,-180},{-340,-160}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1 + "Convert boolean to real" + annotation (Placement(transformation(extent={{-320,-180},{-300,-160}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi "Valid index" + annotation (Placement(transformation(extent={{-320,-240},{-300,-220}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply mul3 if not have_parChi + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{-120,-190},{-100,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply mul1[2] if have_parChi + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{-160,40},{-140,60}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaScaRep( + final nout=3) + "Replicate real input" + annotation (Placement(transformation(extent={{-270,-180},{-250,-160}}))); +equation + connect(uStaDow, not2.u) + annotation (Line(points={{-460,-390},{-410,-390},{-410,-420},{-222,-420}}, + color={255,0,255})); + connect(byPasSet1.y, yChiWatMinFloSet) + annotation (Line(points={{422,140},{460,140}}, color={0,0,127})); + connect(and1.y, tim.u) + annotation (Line(points={{-298,420},{-220,420}}, color={255,0,255})); + connect(uStaDow, and3.u1) + annotation (Line(points={{-460,-390},{-322,-390}}, color={255,0,255})); + connect(and3.y, tim1.u) + annotation (Line(points={{-298,-390},{-222,-390}}, color={255,0,255})); + connect(minFlo.y, floRat.u1) + annotation (Line(points={{-378,200},{-300,200},{-300,186},{-282,186}}, + color={0,0,127})); + connect(maxFlo.y, floRat.u2) + annotation (Line(points={{-378,160},{-290,160},{-290,174},{-282,174}}, + color={0,0,127})); + connect(nexDisChi, intRep.u) + annotation (Line(points={{-460,-70},{-402,-70}}, color={255,127,0})); + connect(conInt.y, intEqu.u1) + annotation (Line(points={{-378,-30},{-322,-30}}, color={255,127,0})); + connect(intRep.y, intEqu.u2) + annotation (Line(points={{-378,-70},{-360,-70},{-360,-38},{-322,-38}}, + color={255,127,0})); + connect(intEqu.y, xor.u1) + annotation (Line(points={{-298,-30},{-222,-30}}, color={255,0,255})); + connect(xor.y, swi3.u2) + annotation (Line(points={{-198,-30},{-140,-30},{-140,0},{-122,0}}, + color={255,0,255})); + connect(xor.y, swi4.u2) + annotation (Line(points={{-198,-30},{-140,-30},{-140,-60},{-122,-60}}, + color={255,0,255})); + connect(multiMax2.y, pro2.u1) + annotation (Line(points={{-58,0},{-40,0},{-40,-24},{-22,-24}}, + color={0,0,127})); + connect(mulSum1.y, pro2.u2) + annotation (Line(points={{-58,-60},{-40,-60},{-40,-36},{-22,-36}}, + color={0,0,127})); + connect(swi3.y, multiMax2.u) + annotation (Line(points={{-98,0},{-82,0}}, color={0,0,127})); + connect(swi4.y, mulSum1.u) + annotation (Line(points={{-98,-60},{-82,-60}}, color={0,0,127})); + connect(swi5.y, multiMax1.u) + annotation (Line(points={{-98,-150},{-82,-150}}, color={0,0,127})); + connect(swi6.y, multiMax3.u) + annotation (Line(points={{-78,-230},{-22,-230}}, color={0,0,127})); + connect(multiMax1.y, max1.u1) + annotation (Line(points={{-58,-150},{-40,-150},{-40,-184},{-22,-184}}, + color={0,0,127})); + connect(xor.y, swi6.u2) + annotation (Line(points={{-198,-30},{-140,-30},{-140,-230},{-102,-230}}, + color={255,0,255})); + connect(uStaDow, or2.u2) + annotation (Line(points={{-460,-390},{-410,-390},{-410,-8},{-402,-8}}, + color={255,0,255})); + connect(uStaUp, or2.u1) + annotation (Line(points={{-460,420},{-410,420},{-410,0},{-402,0}}, + color={255,0,255})); + connect(booToRea.y, triSam.u) + annotation (Line(points={{-378,250},{-362,250}}, color={0,0,127})); + connect(or2.y, booRep.u) + annotation (Line(points={{-378,0},{-370,0},{-370,20},{-390,20},{-390,40}, + {-382,40}}, color={255,0,255})); + connect(booRep.y, triSam.trigger) + annotation (Line(points={{-358,40},{-350,40},{-350,238}}, color={255,0,255})); + connect(uChi, booToRea.u) + annotation (Line(points={{-460,340},{-420,340},{-420,250},{-402,250}}, + color={255,0,255})); + connect(uChi, swi9.u2) + annotation (Line(points={{-460,340},{-330,340},{-330,350},{-222,350}}, + color={255,0,255})); + connect(uChi, swi10.u2) + annotation (Line(points={{-460,340},{-330,340},{-330,310},{-222,310}}, + color={255,0,255})); + connect(floRat.y, swi9.u1) + annotation (Line(points={{-258,180},{-250,180},{-250,358},{-222,358}}, + color={0,0,127})); + connect(swi9.y, multiMax4.u) + annotation (Line(points={{-198,350},{-188,350},{-188,350},{-182,350}}, + color={0,0,127})); + connect(maxFlo.y, swi10.u1) + annotation (Line(points={{-378,160},{-290,160},{-290,318},{-222,318}}, + color={0,0,127})); + connect(zer.y, swi9.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,342},{-222,342}}, + color={0,0,127})); + connect(zer.y, swi10.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,302},{-222,302}}, + color={0,0,127})); + connect(swi10.y, mulSum2.u) + annotation (Line(points={{-198,310},{-190,310},{-190,310},{-182,310}}, + color={0,0,127})); + connect(multiMax4.y, pro3.u1) + annotation (Line(points={{-158,350},{-140,350},{-140,336},{-62,336}}, + color={0,0,127})); + connect(mulSum2.y, pro3.u2) + annotation (Line(points={{-158,310},{-140,310},{-140,324},{-62,324}}, + color={0,0,127})); + connect(floRat.y, swi12.u1) + annotation (Line(points={{-258,180},{-250,180},{-250,278},{-222,278}}, + color={0,0,127})); + connect(triSam.y, greEquThr.u) + annotation (Line(points={{-338,250},{-322,250}}, color={0,0,127})); + connect(greEquThr.y, swi12.u2) + annotation (Line(points={{-298,250},{-230,250},{-230,270},{-222,270}}, + color={255,0,255})); + connect(greEquThr.y, swi11.u2) + annotation (Line(points={{-298,250},{-230,250},{-230,230},{-222,230}}, + color={255,0,255})); + connect(zer.y, swi12.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,262},{-222,262}}, + color={0,0,127})); + connect(maxFlo.y, swi11.u1) + annotation (Line(points={{-378,160},{-290,160},{-290,238},{-222,238}}, + color={0,0,127})); + connect(zer.y, swi11.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,222},{-222,222}}, + color={0,0,127})); + connect(swi12.y, multiMax5.u) + annotation (Line(points={{-198,270},{-190,270},{-190,270},{-182,270}}, + color={0,0,127})); + connect(swi11.y, mulSum3.u) + annotation (Line(points={{-198,230},{-190,230},{-190,230},{-182,230}}, + color={0,0,127})); + connect(multiMax5.y, pro4.u1) + annotation (Line(points={{-158,270},{-120,270},{-120,256},{-62,256}}, + color={0,0,127})); + connect(mulSum3.y, pro4.u2) + annotation (Line(points={{-158,230},{-100,230},{-100,244},{-62,244}}, + color={0,0,127})); + connect(multiMax5.y, max.u1) + annotation (Line(points={{-158,270},{-120,270},{-120,96},{-82,96}}, + color={0,0,127})); + connect(mulSum3.y, add2.u1) + annotation (Line(points={{-158,230},{-100,230},{-100,56},{-82,56}}, + color={0,0,127})); + connect(max.y, pro1.u1) + annotation (Line(points={{-58,90},{-40,90},{-40,76},{-22,76}}, color={0,0,127})); + connect(add2.y, pro1.u2) + annotation (Line(points={{-58,50},{-40,50},{-40,64},{-22,64}}, color={0,0,127})); + connect(maxFlo.y, nexChiMaxFlo.u) + annotation (Line(points={{-378,160},{-290,160},{-290,50},{-222,50}}, + color={0,0,127})); + connect(greEquThr.y, xor.u2) + annotation (Line(points={{-298,250},{-230,250},{-230,-38},{-222,-38}}, + color={255,0,255})); + connect(floRat.y, swi3.u1) + annotation (Line(points={{-258,180},{-250,180},{-250,8},{-122,8}}, + color={0,0,127})); + connect(zer.y, swi3.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,-8},{-122,-8}}, + color={0,0,127})); + connect(zer.y, swi4.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,-68},{-122,-68}}, + color={0,0,127})); + connect(maxFlo.y, swi4.u1) + annotation (Line(points={{-378,160},{-290,160},{-290,-52},{-122,-52}}, + color={0,0,127})); + connect(uChi, swi1.u2) + annotation (Line(points={{-460,340},{-330,340},{-330,-110},{-122,-110}}, + color={255,0,255})); + connect(greEquThr.y, swi5.u2) + annotation (Line(points={{-298,250},{-230,250},{-230,-150},{-122,-150}}, + color={255,0,255})); + connect(swi1.y, multiMax6.u) + annotation (Line(points={{-98,-110},{-82,-110}}, + color={0,0,127})); + connect(zer.y, swi1.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,-118},{-122,-118}}, + color={0,0,127})); + connect(zer.y, swi5.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,-158},{-122,-158}}, + color={0,0,127})); + connect(maxFlo.y, swi1.u1) + annotation (Line(points={{-378,160},{-290,160},{-290,-102},{-122,-102}}, + color={0,0,127})); + connect(maxFlo.y, swi5.u1) + annotation (Line(points={{-378,160},{-290,160},{-290,-142},{-122,-142}}, + color={0,0,127})); + connect(maxFlo.y, nexChiMinFlo.u) + annotation (Line(points={{-378,160},{-290,160},{-290,-190},{-222,-190}}, + color={0,0,127})); + connect(maxFlo.y, swi6.u1) + annotation (Line(points={{-378,160},{-290,160},{-290,-222},{-102,-222}}, + color={0,0,127})); + connect(zer.y, swi6.u3) + annotation (Line(points={{-378,120},{-240,120},{-240,-238},{-102,-238}}, + color={0,0,127})); + connect(uUpsDevSta, and1.u2) + annotation (Line(points={{-460,380},{-380,380},{-380,412},{-322,412}}, + color={255,0,255})); + connect(uStaUp, and1.u1) + annotation (Line(points={{-460,420},{-322,420}}, color={255,0,255})); + connect(con2.y, oneMorSet.x1) + annotation (Line(points={{-38,210},{70,210},{70,238},{98,238}}, color={0,0,127})); + connect(pro4.y, oneMorSet.f1) + annotation (Line(points={{-38,250},{60,250},{60,234},{98,234}}, color={0,0,127})); + connect(con3.y, oneMorSet.x2) + annotation (Line(points={{-38,168},{80,168},{80,226},{98,226}}, color={0,0,127})); + connect(pro1.y, oneMorSet.f2) + annotation (Line(points={{2,70},{90,70},{90,222},{98,222}}, + color={0,0,127})); + connect(tim.y, oneMorSet.u) + annotation (Line(points={{-196,420},{50,420},{50,230},{98,230}}, + color={0,0,127})); + connect(con2.y, oneLeSet.x1) + annotation (Line(points={{-38,210},{70,210},{70,-132},{98,-132}}, + color={0,0,127})); + connect(pro4.y, oneLeSet.f1) + annotation (Line(points={{-38,250},{60,250},{60,-136},{98,-136}}, + color={0,0,127})); + connect(con3.y, oneLeSet.x2) + annotation (Line(points={{-38,168},{80,168},{80,-144},{98,-144}}, + color={0,0,127})); + connect(pro2.y, oneLeSet.f2) + annotation (Line(points={{2,-30},{50,-30},{50,-148},{98,-148}}, + color={0,0,127})); + connect(oneMorSet.y, byPasSet2.u3) + annotation (Line(points={{122,230},{170,230},{170,252},{178,252}}, + color={0,0,127})); + connect(pro3.y, byPasSet2.u1) + annotation (Line(points={{-38,330},{40,330},{40,268},{178,268}}, + color={0,0,127})); + connect(uSubCha, byPasSet2.u2) + annotation (Line(points={{-460,-280},{150,-280},{150,260},{178,260}}, + color={255,0,255})); + connect(uOnOff, upSet.u2) + annotation (Line(points={{-460,-320},{220,-320},{220,220},{238,220}}, + color={255,0,255})); + connect(byPasSet2.y, upSet.u1) + annotation (Line(points={{202,260},{220,260},{220,228},{238,228}}, + color={0,0,127})); + connect(oneMorSet.y, upSet.u3) + annotation (Line(points={{122,230},{170,230},{170,212},{238,212}}, + color={0,0,127})); + connect(uStaDow, and2.u2) + annotation (Line(points={{-460,-390},{-410,-390},{-410,-358},{-322,-358}}, + color={255,0,255})); + connect(uSubCha, and2.u1) + annotation (Line(points={{-460,-280},{-420,-280},{-420,-350},{-322,-350}}, + color={255,0,255})); + connect(and2.y, tim2.u) + annotation (Line(points={{-298,-350},{-222,-350}}, color={255,0,255})); + connect(con2.y, oneMorSet1.x1) + annotation (Line(points={{-38,210},{70,210},{70,-342},{98,-342}}, + color={0,0,127})); + connect(pro4.y, oneMorSet1.f1) + annotation (Line(points={{-38,250},{60,250},{60,-346},{98,-346}}, + color={0,0,127})); + connect(con3.y, oneMorSet1.x2) + annotation (Line(points={{-38,168},{80,168},{80,-354},{98,-354}}, + color={0,0,127})); + connect(pro1.y, oneMorSet1.f2) + annotation (Line(points={{2,70},{90,70},{90,-358},{98,-358}}, + color={0,0,127})); + connect(tim2.y, oneMorSet1.u) + annotation (Line(points={{-198,-350},{98,-350}}, color={0,0,127})); + connect(oneMorSet1.y, byPasSet4.u3) + annotation (Line(points={{122,-350},{140,-350},{140,-308},{158,-308}}, + color={0,0,127})); + connect(uUpsDevSta, byPasSet4.u2) + annotation (Line(points={{-460,380},{-430,380},{-430,-300},{158,-300}}, + color={255,0,255})); + connect(pro3.y, byPasSet4.u1) + annotation (Line(points={{-38,330},{40,330},{40,-292},{158,-292}}, + color={0,0,127})); + connect(uOnOff, dowSet.u2) + annotation (Line(points={{-460,-320},{220,-320},{220,-120},{238,-120}}, + color={255,0,255})); + connect(byPasSet4.y, dowSet.u1) + annotation (Line(points={{182,-300},{200,-300},{200,-112},{238,-112}}, + color={0,0,127})); + connect(uUpsDevSta, and3.u2) + annotation (Line(points={{-460,380},{-430,380},{-430,-398},{-322,-398}}, + color={255,0,255})); + connect(tim1.y, oneLeSet.u) + annotation (Line(points={{-198,-390},{30,-390},{30,-140},{98,-140}}, + color={0,0,127})); + connect(oneLeSet.y, dowSet.u3) + annotation (Line(points={{122,-140},{180,-140},{180,-128},{238,-128}}, + color={0,0,127})); + connect(dowSet.y, chaSet.u3) + annotation (Line(points={{262,-120},{270,-120},{270,42},{298,42}}, + color={0,0,127})); + connect(upSet.y, chaSet.u1) + annotation (Line(points={{262,220},{270,220},{270,58},{298,58}}, + color={0,0,127})); + connect(uStaUp, chaSet.u2) + annotation (Line(points={{-460,420},{-410,420},{-410,400},{280,400},{280,50}, + {298,50}}, color={255,0,255})); + connect(not1.y, and4.u1) + annotation (Line(points={{322,140},{338,140}}, color={255,0,255})); + connect(and4.y, byPasSet1.u2) + annotation (Line(points={{362,140},{398,140}}, color={255,0,255})); + connect(not2.y, and4.u2) + annotation (Line(points={{-198,-420},{330,-420},{330,132},{338,132}}, + color={255,0,255})); + connect(chaSet.y, byPasSet1.u3) + annotation (Line(points={{322,50},{380,50},{380,132},{398,132}}, + color={0,0,127})); + connect(pro3.y, byPasSet1.u1) + annotation (Line(points={{-38,330},{380,330},{380,148},{398,148}}, + color={0,0,127})); + connect(uStaUp, not1.u) + annotation (Line(points={{-460,420},{-410,420},{-410,400},{280,400}, + {280,140},{298,140}}, color={255,0,255})); + connect(multiMax1.y, oneMorSet.f1) + annotation (Line(points={{-58,-150},{60,-150},{60,234},{98,234}}, + color={0,0,127})); + connect(multiMax1.y, oneMorSet1.f1) + annotation (Line(points={{-58,-150},{60,-150},{60,-346},{98,-346}}, + color={0,0,127})); + connect(max1.y, oneMorSet.f2) + annotation (Line(points={{2,-190},{90,-190},{90,222},{98,222}}, + color={0,0,127})); + connect(max1.y, oneMorSet1.f2) + annotation (Line(points={{2,-190},{90,-190},{90,-358},{98,-358}}, + color={0,0,127})); + connect(multiMax3.y, oneLeSet.f2) + annotation (Line(points={{2,-230},{50,-230},{50,-148},{98,-148}}, + color={0,0,127})); + connect(multiMax6.y, byPasSet2.u1) + annotation (Line(points={{-58,-110},{40,-110},{40,268},{178,268}}, + color={0,0,127})); + connect(multiMax6.y, byPasSet4.u1) + annotation (Line(points={{-58,-110},{40,-110},{40,-292},{158,-292}}, + color={0,0,127})); + connect(multiMax6.y, byPasSet1.u1) + annotation (Line(points={{-58,-110},{40,-110},{40,180},{380,180},{380,148},{ + 398,148}}, color={0,0,127})); + connect(multiMax1.y, oneLeSet.f1) + annotation (Line(points={{-58,-150},{60,-150},{60,-136},{98,-136}}, + color={0,0,127})); + connect(floRat.y, nexChiRat.u) + annotation (Line(points={{-258,180},{-250,180},{-250,90},{-222,90}}, + color={0,0,127})); + connect(conInt1.y, intSwi.u3) annotation (Line(points={{-338,-260},{-330,-260}, + {-330,-238},{-322,-238}}, color={255,127,0})); + connect(and5.y, booToRea1.u) + annotation (Line(points={{-338,-170},{-322,-170}}, color={255,0,255})); + connect(and5.y, intSwi.u2) annotation (Line(points={{-338,-170},{-330,-170},{-330, + -230},{-322,-230}}, color={255,0,255})); + connect(intGreEquThr.y, and5.u1) + annotation (Line(points={{-378,-170},{-362,-170}}, color={255,0,255})); + connect(intLesEquThr.y, and5.u2) annotation (Line(points={{-378,-260},{-370,-260}, + {-370,-178},{-362,-178}}, color={255,0,255})); + connect(nexEnaChi, intGreEquThr.u) annotation (Line(points={{-460,70},{-420,70}, + {-420,-170},{-402,-170}}, color={255,127,0})); + connect(nexEnaChi, intSwi.u1) annotation (Line(points={{-460,70},{-420,70},{-420, + -222},{-322,-222}}, color={255,127,0})); + connect(nexEnaChi, intLesEquThr.u) annotation (Line(points={{-460,70},{-420,70}, + {-420,-260},{-402,-260}}, color={255,127,0})); + connect(intSwi.y, nexChiMinFlo.index) annotation (Line(points={{-298,-230},{-280, + -230},{-280,-210},{-210,-210},{-210,-202}}, color={255,127,0})); + connect(intSwi.y, nexChiMaxFlo.index) annotation (Line(points={{-298,-230},{-280, + -230},{-280,30},{-210,30},{-210,38}}, color={255,127,0})); + connect(intSwi.y, nexChiRat.index) annotation (Line(points={{-298,-230},{-280, + -230},{-280,70},{-210,70},{-210,78}}, color={255,127,0})); + connect(booToRea1.y, reaScaRep.u) + annotation (Line(points={{-298,-170},{-272,-170}}, color={0,0,127})); + connect(mul3.y, max1.u2) annotation (Line(points={{-98,-180},{-80,-180},{-80,-196}, + {-22,-196}}, color={0,0,127})); + connect(reaScaRep.y[3], mul3.u1) annotation (Line(points={{-248,-169.333},{ + -180,-169.333},{-180,-174},{-122,-174}}, + color={0,0,127})); + connect(reaScaRep.y[1], mul1[1].u2) annotation (Line(points={{-248,-170.667}, + {-180,-170.667},{-180,44},{-162,44}},color={0,0,127})); + connect(reaScaRep.y[2], mul1[2].u2) annotation (Line(points={{-248,-170},{-180, + -170},{-180,44},{-162,44}}, color={0,0,127})); + connect(nexChiMaxFlo.y, mul1[2].u1) annotation (Line(points={{-198,50},{-180,50}, + {-180,56},{-162,56}}, color={0,0,127})); + connect(nexChiRat.y, mul1[1].u1) annotation (Line(points={{-198,90},{-180,90}, + {-180,56},{-162,56}}, color={0,0,127})); + connect(mul1[1].y, max.u2) annotation (Line(points={{-138,50},{-120,50},{-120, + 84},{-82,84}}, color={0,0,127})); + connect(mul1[2].y, add2.u2) annotation (Line(points={{-138,50},{-120,50},{-120, + 44},{-82,44}}, color={0,0,127})); + connect(nexChiMinFlo.y, mul3.u2) annotation (Line(points={{-198,-190},{-180,-190}, + {-180,-186},{-122,-186}}, color={0,0,127})); +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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-440,-440},{440,440}}), graphics={ + Rectangle( + extent={{-398,398},{18,-58}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-398,-82},{18,-278}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-92,394},{14,378}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Plant with parallel chillers"), + Text( + extent={{-80,-78},{18,-94}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Plant with series chillers"), + 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={{-46,102},{18,88}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="enabling additional chiller"), + Text( + extent={{-34,2},{18,-12}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="disabling one chiller"), + Text( + extent={{-54,14},{18,-2}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint when"), + Text( + extent={{-42,-160},{22,-174}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="enabling additional chiller"), + Text( + extent={{-30,-242},{22,-256}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="disabling one chiller"), + Text( + extent={{-92,372},{10,356}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint according to"), + Text( + extent={{-54,360},{10,346}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="current chillers status"), + Text( + extent={{-88,302},{14,286}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="Minimum flow setpoint according to"), + Text( + extent={{-66,290},{14,276}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="chillers status at the moment"), + Text( + extent={{-62,280},{16,266}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="when requiring stage change"), + Text( + extent={{-38,-96},{26,-110}}, + textColor={0,0,127}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + horizontalAlignment=TextAlignment.Right, + textString="current chillers status")}), + Documentation(info=" +

+Block that outputs chilled water minimum flow setpoint for primary-only +plants with a minimum flow bypass valve, +according to ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.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..6fe06bc50d6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/Controller.mo @@ -0,0 +1,86 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Validation; +model Controller "Validate control of minimum bypass valve" + + parameter Integer nChi=3 "Total number of chillers"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Controller + minBypValCon(final nChi=3, final minFloSet={0.005,0.005,0.005}) + "Minimum bypass valve position" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Pulse chiFloSet( + final amplitude=-0.005, + final period=3, + final offset=0.015) "Minimum flow setpoint" + annotation (Placement(transformation(extent={{-80,-82},{-60,-60}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiWatPum( + final width=0.15, + final period=4, + final 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.Continuous.Sources.Sine sin( + final amplitude=0.0025, + final freqHz=1/2, + final offset=0.005) "Output sine wave value" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram( + final height=0.015, + final duration=2, + final startTime=1.2) "Output ramp value" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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. +

+", 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..860bfdfeb76 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/Validation/FlowSetpoint.mo @@ -0,0 +1,219 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.Validation; +model FlowSetpoint + "Validation sequence of specifying minimum bypass flow setpoint" + + parameter Integer nChi=3 "Total number of chillers"; + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.MinimumFlowBypass.FlowSetpoint + staUpMinFlo( + final nChi=nChi, + final 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 + onOffStaUpMinFlo( + final nChi=nChi, + final 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 + staDowMinFlo( + final nChi=nChi, + final 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.Continuous.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.Continuous.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.Continuous.Sources.Constant con( + final k=3) "Index of enabling chiller" + annotation (Placement(transformation(extent={{-140,110},{-120,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) "Zero" + annotation (Placement(transformation(extent={{-140,-190},{-120,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.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[nChi]( + final k={true,true,false}) + "Current chiller status" + annotation (Placement(transformation(extent={{-40,130},{-20,150}}))); + +equation + connect(noOnOff.y, staUpMinFlo.uOnOff) + annotation (Line(points={{-118,60},{76,60},{76,173},{118,173}}, + color={255,0,255})); + connect(noStaCha.y, staUpMinFlo.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, staUpMinFlo.uStaUp) + annotation (Line(points={{-78,200},{68,200},{68,189},{118,189}}, + color={255,0,255})); + connect(not2.y, staUpMinFlo.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, staDowMinFlo.uOnOff) + annotation (Line(points={{-118,60},{76,60},{76,-167},{118,-167}}, + color={255,0,255})); + connect(noStaCha.y, staDowMinFlo.uStaUp) + annotation (Line(points={{-118,20},{92,20},{92,-151},{118,-151}}, + color={255,0,255})); + connect(not2.y, staDowMinFlo.uUpsDevSta) + annotation (Line(points={{-78,170},{72,170},{72,-153},{118,-153}}, + color={255,0,255})); + connect(not1.y, staDowMinFlo.uStaDow) + annotation (Line(points={{-78,200},{68,200},{68,-169},{118,-169}}, + color={255,0,255})); + connect(not1.y, onOffStaUpMinFlo.uStaUp) + annotation (Line(points={{-78,200},{68,200},{68,9},{118,9}}, + color={255,0,255})); + connect(not2.y, onOffStaUpMinFlo.uUpsDevSta) + annotation (Line(points={{-78,170},{72,170},{72,7},{118,7}}, + color={255,0,255})); + connect(haveOnOff.y, onOffStaUpMinFlo.uOnOff) + annotation (Line(points={{-118,-60},{40,-60},{40,-7},{118,-7}}, + color={255,0,255})); + connect(noStaCha.y, onOffStaUpMinFlo.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, staUpMinFlo.uChi) + annotation (Line(points={{-18,140},{80,140},{80,184},{118,184}}, + color={255,0,255})); + connect(chiSta.y, onOffStaUpMinFlo.uChi) + annotation (Line(points={{-18,140},{80,140},{80,4},{118,4}}, + color={255,0,255})); + connect(chiSta.y, staDowMinFlo.uChi) + annotation (Line(points={{-18,140},{80,140},{80,-156},{118,-156}}, + color={255,0,255})); + connect(reaToInt.y, staUpMinFlo.nexEnaChi) + annotation (Line(points={{22,100},{88,100},{88,181},{118,181}}, + color={255,127,0})); + connect(reaToInt2.y, staUpMinFlo.nexDisChi) + annotation (Line(points={{22,-180},{84,-180},{84,179},{118,179}}, + color={255,127,0})); + connect(reaToInt2.y, staDowMinFlo.nexEnaChi) + annotation (Line(points={{22,-180},{84,-180},{84,-159},{118,-159}}, + color={255,127,0})); + connect(reaToInt1.y, staDowMinFlo.nexDisChi) + annotation (Line(points={{22,-120},{88,-120},{88,-161},{118,-161}}, + color={255,127,0})); + connect(reaToInt.y, onOffStaUpMinFlo.nexEnaChi) + annotation (Line(points={{22,100},{88,100},{88,1},{118,1}}, + color={255,127,0})); + connect(reaToInt1.y, onOffStaUpMinFlo.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, staUpMinFlo.uSubCha) annotation (Line(points={{-118,60},{ + 76,60},{76,176},{118,176}}, color={255,0,255})); + connect(noOnOff.y, staDowMinFlo.uSubCha) annotation (Line(points={{-118,60},{ + 76,60},{76,-164},{118,-164}}, color={255,0,255})); + connect(not3.y, onOffStaUpMinFlo.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. +

+", 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..5e671766e9a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/MinimumFlowBypass/package.mo @@ -0,0 +1,46 @@ +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.2.8. in ASHRAE RP-1711 Advanced Sequences +of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..1f93427dbd3 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Controller.mo @@ -0,0 +1,627 @@ +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 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,160},{-280,200}}), + 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,120},{-280,160}}), + 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,90},{-280,130}}), + 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,60},{-280,100}}), + 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,30},{-280,70}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiIsoVal[nChi] if have_heaPum + "Chilled water isolation valve status" + annotation (Placement(transformation(extent={{-320,0},{-280,40}}), + iconTransformation(extent={{-140,-30},{-100,10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla if have_heaPum + "True: plant is just enabled" + annotation(Placement(transformation(extent={{-320,-30},{-280,10}}), + 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,-260},{-280,-220}}), + iconTransformation(extent={{-140,-130},{-100,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yLea + "Lead pump status setpoint" + annotation (Placement(transformation(extent={{280,50},{320,90}}), + 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,20}}), + 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) 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,-10},{-220,10}}))); + 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={{-60,-210},{-40,-190}}))); + 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,100},{20,120}}))); + 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={{0,-110},{20,-90}}))); + 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,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2 if have_heaPum + "Convert real input to integer output" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + 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={{-180,-130},{-160,-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.Edge edg1 if have_heaPum + "Rising edge" + annotation (Placement(transformation(extent={{-100,-30},{-80,-10}}))); + 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.Not not1 if have_heaPum + "Logical not" + annotation (Placement(transformation(extent={{-200,-10},{-180,10}}))); + 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}}))); + +equation + connect(enaDedLeaPum.uLeaChiEna, uLeaChiEna) + annotation (Line(points={{-202,113},{-240,113},{-240,110},{-300,110}}, + color={255,0,255})); + connect(enaDedLeaPum.uLeaChiSta, uLeaChiSta) + annotation (Line(points={{-202,107},{-240,107},{-240,80},{-300,80}}, + color={255,0,255})); + connect(enaDedLeaPum.uLeaChiWatReq, uLeaChiWatReq) + annotation (Line(points={{-202,102},{-230,102},{-230,50},{-300,50}}, + color={255,0,255})); + connect(enaHeaLeaPum.uChiIsoVal, uChiIsoVal) + annotation (Line(points={{-202,70},{-220,70},{-220,20},{-300,20}}, + 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},{40,170},{40,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,140},{100,140},{100,182},{118,182}}, + color={255,0,255})); + connect(booRep.y, leaPumSta.u1) + annotation (Line(points={{22,110},{90,110},{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},{30,-50},{30,-38},{58,-38}}, color={255,127,0})); + connect(pumIndCon.y, intEqu2.u1) + annotation (Line(points={{-198,170},{40,170},{40,-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,140},{100,140},{100,-38},{118,-38}}, + color={255,0,255})); + connect(lasLagPum.y, reaToInt2.u) + annotation (Line(points={{-58,-100},{-42,-100}}, color={0,0,127})); + connect(reaToInt2.y, intRep2.u) + annotation (Line(points={{-18,-100},{-2,-100}}, color={255,127,0})); + connect(intRep2.y, intEqu3.u2) + annotation (Line(points={{22,-100},{30,-100},{30,-98},{58,-98}}, + color={255,127,0})); + connect(pumIndCon.y, intEqu3.u1) + annotation (Line(points={{-198,170},{40,170},{40,-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,4},{-250,4},{-250,-50},{-300,-50}}, + color={0,0,127})); + connect(uChiWatPum, enaLagChiPum.uChiWatPum) + annotation (Line(points={{-300,140},{-260,140},{-260,-3.8},{-242,-3.8}}, + color={255,0,255})); + connect(intToRea.y, lasLagPum.u) + annotation (Line(points={{-198,230},{-160,230},{-160,-100},{-82,-100}}, + 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,140},{100,140},{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={{-62,-192},{-240,-192},{-240,-160},{-300,-160}}, + color={0,0,127})); + connect(pumSpeLocDp.dpChiWat_remote, dpChiWat_remote) + annotation (Line(points={{-62,-204},{-200,-204},{-200,-200},{-300,-200}}, + color={0,0,127})); + connect(pumSpeLocDp.dpChiWatSet_remote, dpChiWatSet_remote) annotation (Line( + points={{-62,-208},{-220,-208},{-220,-240},{-300,-240}}, color={0,0,127})); + connect(dpChiWat_remote, pumSpeRemDp.dpChiWat_remote) annotation (Line(points= + {{-300,-200},{-200,-200},{-200,-240},{-62,-240}}, color={0,0,127})); + connect(dpChiWatSet_remote, pumSpeRemDp.dpChiWatSet_remote) annotation (Line( + points={{-300,-240},{-220,-240},{-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(enaDedLeaPum.yLea, booRep.u) + annotation (Line(points={{-178,110},{-2,110}}, color={255,0,255})); + connect(enaHeaLeaPum.yLea, booRep.u) + annotation (Line(points={{-178,70},{-90,70},{-90,110},{-2,110}}, 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(addPum.y, yChiWatPum) + annotation (Line(points={{262,0},{300,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,140},{-260,140},{-260,-120},{-242,-120}}, + color={255,0,255})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-218,-120},{-182,-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={{-158,-120},{-150,-120},{-150,-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(mulSumInt.y, lasLagPum.index) + annotation (Line(points={{-158,-120},{-70,-120},{-70,-112}}, color={255,127,0})); + connect(enaDedLeaPum.uPla, uPla) + annotation (Line(points={{-202,118},{-240,118},{-240,180},{-300,180}}, + color={255,0,255})); + connect(uChiWatPum, pumSpeLocDp.uChiWatPum) annotation (Line(points={{-300,140}, + {-260,140},{-260,-196},{-62,-196}}, color={255,0,255})); + connect(uChiWatPum, pumSpeRemDp.uChiWatPum) annotation (Line(points={{-300,140}, + {-260,140},{-260,-232},{-62,-232}}, color={255,0,255})); + connect(pumSpeLocDp.yChiWatPumSpe, yPumSpe) + annotation (Line(points={{-38,-200},{300,-200}}, color={0,0,127})); + connect(pumSpeRemDp.yChiWatPumSpe, yPumSpe) annotation (Line(points={{-39,-240}, + {-20,-240},{-20,-200},{300,-200}}, color={0,0,127})); + connect(enaDedLeaPum.yLea, yLea) + annotation (Line(points={{-178,110},{-90,110},{-90,70},{300,70}}, color={255,0,255})); + connect(enaHeaLeaPum.yLea, yLea) + annotation (Line(points={{-178,70},{300,70}}, color={255,0,255})); + connect(enaLagChiPum.yUp, enaNexLag.u) annotation (Line(points={{-218,4},{-210, + 4},{-210,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(enaLagChiPum.yDown, not1.u) annotation (Line(points={{-218,-4},{-210,-4}, + {-210,0},{-202,0}}, color={255,0,255})); + connect(not1.y, disLasLag.u) + annotation (Line(points={{-178,0},{-42,0}}, 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(mulAnd.y, edg1.u) + annotation (Line(points={{-118,-20},{-102,-20}}, color={255,0,255})); + connect(edg1.y, enaNexLag.clr) annotation (Line(points={{-78,-20},{-60,-20},{-60, + 24},{-2,24}}, color={255,0,255})); + connect(edg1.y, disLasLag.clr) annotation (Line(points={{-78,-20},{-60,-20},{-60, + -6},{-42,-6}}, color={255,0,255})); + connect(addPum.y, pre1.u) annotation (Line(points={{262,0},{270,0},{270,-100}, + {210,-100},{210,-120},{218,-120}}, 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(pumSpeLocDp.dpChiWatPumSet_local, dpChiWatPumSet_local) annotation ( + Line(points={{-38,-206},{200,-206},{200,-240},{300,-240}}, color={0,0,127})); + connect(uEnaPla, enaHeaLeaPum.uEnaPla) annotation (Line(points={{-300,-10},{-270, + -10},{-270,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,-144},{156,-256}}, + 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 RP-1711, (Draft on March 23, 2020), +section 5.2.6.1 to section 5.2.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..69ed1b8ad2a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLag_primary_dP.mo @@ -0,0 +1,292 @@ +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={{-180,60},{-140,100}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiWatPum[nPum] + "Chilled water pump status" + annotation (Placement(transformation(extent={{-180,-20},{-140,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={{140,20},{180,60}}), + 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={{140,-100},{180,-60}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=(-1)*relFloHys, + final uHigh=relFloHys) + "Check if condition for enabling next lag pump is satisfied" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=(-1)*relFloHys, + final uHigh=relFloHys) + "Check if condition for disabling last lag pump is satisfied" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter chiWatFloRat( + final k=1/VChiWat_flow_nominal) "Chiller water flow ratio" + annotation (Placement(transformation(extent={{-120,70},{-100,90}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=staCon) "Add parameter" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar2( + final p=staCon) "Add parameter" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=timPer) + "Check if the time is greater than delay time period" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim1( + final t=timPer) + "Check if the time is greater than delay time period" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + +protected + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nPum] + "Convert boolean input to integer number" + annotation (Placement(transformation(extent={{-130,-10},{-110,10}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum numOpePum(final nin=nPum) + "Total number of operating pumps" + annotation (Placement(transformation(extent={{-90,-10},{-70,10}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Convert integer to real" + annotation (Placement(transformation(extent={{-50,-10},{-30,10}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar1( + final p=-1) "Add real inputs" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Find inputs difference" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + "Find inputs difference" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch enaNexLag + "Enabling next lag pump" + annotation (Placement(transformation(extent={{100,30},{120,50}}))); + Buildings.Controls.OBC.CDL.Logical.Switch shuLasLag + "Shut off last lag pump" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=true) + "Logical true" + annotation (Placement(transformation(extent={{40,110},{60,130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Logical false" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg "Rising edge" + annotation (Placement(transformation(extent={{-40,-150},{-20,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{0,-150},{20,-130}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre "Breaks algebraic loops" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg1 "Rising edge" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1 "Breaks algebraic loops" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{40,70},{60,90}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter nomPum( + final k=1/nPum_nominal) + "Pump number ratio" + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter nomPum1( + final k=1/nPum_nominal) + "Pump number ratio" + annotation (Placement(transformation(extent={{-40,-50},{-20,-30}}))); + +equation + connect(VChiWat_flow,chiWatFloRat. u) + annotation (Line(points={{-160,80},{-122,80}}, color={0,0,127})); + connect(uChiWatPum,booToInt. u) + annotation (Line(points={{-160,0},{-132,0}}, color={255,0,255})); + connect(booToInt.y,numOpePum. u) + annotation (Line(points={{-108,0},{-92,0}}, + color={255,127,0})); + connect(numOpePum.y,intToRea. u) + annotation (Line(points={{-68,0},{-52,0}},color={255,127,0})); + connect(sub2.y,hys. u) + annotation (Line(points={{-58,40},{-42,40}}, color={0,0,127})); + connect(sub1.y,hys1. u) + annotation (Line(points={{-58,-80},{-42,-80}}, color={0,0,127})); + connect(addPar.y, sub2.u2) + annotation (Line(points={{62,0},{70,0},{70,20},{-90,20},{-90,34},{-82,34}}, + color={0,0,127})); + connect(intToRea.y, addPar1.u) + annotation (Line(points={{-28,0},{-10,0},{-10,-20},{-90,-20},{-90,-40},{-82, + -40}}, + color={0,0,127})); + connect(addPar2.y, sub1.u1) + annotation (Line(points={{22,-40},{30,-40},{30,-60},{-90,-60},{-90,-74},{-82, + -74}}, color={0,0,127})); + connect(chiWatFloRat.y, sub2.u1) + annotation (Line(points={{-98,80},{-90,80},{-90,46},{-82,46}}, color={0,0,127})); + connect(chiWatFloRat.y, sub1.u2) + annotation (Line(points={{-98,80},{-90,80},{-90,60},{-100,60},{-100,-86}, + {-82,-86}}, color={0,0,127})); + connect(con.y, enaNexLag.u1) + annotation (Line(points={{62,120},{90,120},{90,48},{98,48}}, color={255,0,255})); + connect(con.y, shuLasLag.u3) + annotation (Line(points={{62,120},{90,120},{90,-88},{98,-88}}, color={255,0,255})); + connect(shuLasLag.y, yDown) + annotation (Line(points={{122,-80},{160,-80}}, color={255,0,255})); + connect(enaNexLag.y, yUp) + annotation (Line(points={{122,40},{160,40}}, color={255,0,255})); + connect(con1.y, enaNexLag.u3) + annotation (Line(points={{62,-40},{80,-40},{80,32},{98,32}}, + color={255,0,255})); + connect(con1.y, shuLasLag.u1) + annotation (Line(points={{62,-40},{80,-40},{80,-72},{98,-72}}, + color={255,0,255})); + connect(edg.y, not1.u) + annotation (Line(points={{-18,-140},{-2,-140}}, color={255,0,255})); + connect(edg.u, pre.y) + annotation (Line(points={{-42,-140},{-58,-140}}, color={255,0,255})); + connect(hys1.y, and2.u1) + annotation (Line(points={{-18,-80},{-14,-80},{-14,-120},{38,-120}}, + color={255,0,255})); + connect(not1.y, and2.u2) + annotation (Line(points={{22,-140},{30,-140},{30,-128},{38,-128}}, + color={255,0,255})); + connect(and2.y, tim1.u) + annotation (Line(points={{62,-120},{80,-120},{80,-104},{-6,-104},{-6,-80}, + {-2,-80}}, color={255,0,255})); + connect(edg1.y, not2.u) + annotation (Line(points={{-18,100},{-2,100}}, color={255,0,255})); + connect(edg1.u, pre1.y) + annotation (Line(points={{-42,100},{-58,100}}, color={255,0,255})); + connect(not2.y, and1.u1) + annotation (Line(points={{22,100},{30,100},{30,80},{38,80}}, color={255,0,255})); + connect(hys.y, and1.u2) + annotation (Line(points={{-18,40},{-12,40},{-12,72},{38,72}}, color={255,0,255})); + connect(and1.y, tim.u) + annotation (Line(points={{62,80},{70,80},{70,66},{-6,66},{-6,40},{-2,40}}, + color={255,0,255})); + connect(tim.passed, enaNexLag.u2) annotation (Line(points={{22,32},{60,32},{60, + 40},{98,40}}, color={255,0,255})); + connect(tim.passed, pre1.u) annotation (Line(points={{22,32},{60,32},{60,60},{ + -86,60},{-86,100},{-82,100}}, color={255,0,255})); + connect(tim1.passed, shuLasLag.u2) annotation (Line(points={{22,-88},{60,-88}, + {60,-80},{98,-80}}, color={255,0,255})); + connect(tim1.passed, pre.u) annotation (Line(points={{22,-88},{60,-88},{60,-100}, + {-100,-100},{-100,-140},{-82,-140}}, color={255,0,255})); + connect(intToRea.y, nomPum.u) + annotation (Line(points={{-28,0},{-2,0}}, color={0,0,127})); + connect(nomPum.y, addPar.u) + annotation (Line(points={{22,0},{38,0}}, color={0,0,127})); + connect(addPar1.y, nomPum1.u) + annotation (Line(points={{-58,-40},{-42,-40}}, color={0,0,127})); + connect(nomPum1.y, addPar2.u) + annotation (Line(points={{-18,-40},{-2,-40}}, color={0,0,127})); + +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={{-140,-160},{140,160}})), + Documentation(info=" +

+Block that enable and disable lag primary chilled water pump, for plants +with headered primary chilled water pumps, +according to ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.6 Primary chilled water pumps, part 5.2.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..6c300f7f3b6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_dedicated.mo @@ -0,0 +1,140 @@ +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March, 2020), +section 5.2.6 Primary chilled water pumps, part 5.2.6.5. +

+

+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..7af8cae6e5d --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/EnableLead_headered.mo @@ -0,0 +1,104 @@ +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"; + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiIsoVal[nChi] + "True: chilled water isolation valve commended on" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uEnaPla + "True: plant is just enabled" + 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={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(final k=true) + "Logical true" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Logical false" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(final nin=nChi) + "Check if there is any chiller enabled" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Check if enabling lead pump" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); +equation + connect(con.y,leaPumSta. u1) + annotation (Line(points={{-18,60},{30,60},{30,8},{38,8}},color={255,0,255})); + connect(con1.y,leaPumSta. u3) + annotation (Line(points={{-18,-60},{30,-60},{30,-8},{38,-8}}, + color={255,0,255})); + connect(leaPumSta.y, yLea) + annotation (Line(points={{62,0},{120,0}}, color={255,0,255})); + connect(uChiIsoVal, mulOr.u) + annotation (Line(points={{-120,0},{-82,0}}, + color={255,0,255})); + connect(mulOr.y, or2.u1) + annotation (Line(points={{-58,0},{-22,0}}, color={255,0,255})); + connect(uEnaPla, or2.u2) annotation (Line(points={{-120,-40},{-40,-40},{-40, + -8},{-22,-8}}, + color={255,0,255})); + connect(or2.y, leaPumSta.u2) + annotation (Line(points={{2,0},{38,0}}, 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,150},{100,110}}, + textColor={0,0,255}, + textString="%name"), + Text( + extent={{-94,12},{-40,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uChiIsoVal"), + Text( + extent={{42,12},{96,-10}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yLeaPum"), + Text( + extent={{-96,-50},{-48,-66}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="uEnaPla")}), + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March, 2020), +section 5.2.6 Primary chilled water pumps, part 1 and 2. +

+
    +
  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 commanded open, shall be disabled +when chiller CHW isolation valves are commanded closed. +
  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..67e5afd50f3 --- /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.Continuous.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.Continuous.Line pumSpe "Pump speed" + annotation (Placement(transformation(extent={{100,50},{120,70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMax maxRemDP( + final nin=nSen) + "Highest output from differential pressure control loops" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Line locDpSet + "Local differential pressure setpoint" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant locDp_min( + final k=minLocDp) + "Minimum local differential pressure" + annotation (Placement(transformation(extent={{40,-70},{60,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant locDp_max( + final k=maxLocDp) + "Maximum local differential pressure " + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_min( + final k=minPumSpe) "Minimum pump speed" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_max( + final k=maxPumSpe) "Maximum pump speed" + annotation (Placement(transformation(extent={{-20,90},{0,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide div[nSen] + "Normalized pressure difference" + annotation (Placement(transformation(extent={{-40,-110},{-20,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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 RP-1711 (Draft on March 23, 2020), +section 5.2.6 Primary chilled water pumps, part 5.2.6.9, 5.2.6.10 and 5.2.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..a7f93d1bfc3 --- /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", + displayUnit="h")=0.5 "Time constant of integrator block" + annotation(Dialog(group="Speed controller")); + parameter Real Td( + final unit="s", + final quantity="Time", + displayUnit="h")=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.Continuous.MultiMax maxLoo( + final nin=nSen) "Maximum DP loop output" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Line pumSpe "Pump speed" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant pumSpe_min( + final k=minPumSpe) "Minimum pump speed" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant pumSpe_max( + final k=maxPumSpe) "Maximum pump speed" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one(final k=1) + "Constant one" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.6 Primary chilled water pumps, part 5.2.6.7 and 5.2.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..5e0c21cc10a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLag_primary_dP.mo @@ -0,0 +1,88 @@ +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},{0,30}}))); + + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler nexLagPumTri + "Next lag pump enabling trigger" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler lasLagPumTri + "Last lag pump disabling trigger" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con[2]( + final k=fill(true, 2)) "Constant true" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=0.25, + final freqHz=1/3600, + final offset=0.25) "Measured chilled water flow rate" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin1( + final freqHz=1/3600) "Generate sine wave" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + +equation + connect(con[1].y, enaLagChiPum.uChiWatPum[1]) + annotation (Line(points={{-58,0},{-40,0},{-40,14.8667},{-22,14.8667}}, + color={255,0,255})); + connect(con[2].y, enaLagChiPum.uChiWatPum[2]) + annotation (Line(points={{-58,0},{-40,0},{-40,16.2},{-22,16.2}}, + color={255,0,255})); + connect(con1.y, enaLagChiPum.uChiWatPum[3]) + annotation (Line(points={{-58,-40},{-40,-40},{-40,17.5333},{-22,17.5333}}, + color={255,0,255})); + connect(sin.y, enaLagChiPum.VChiWat_flow) + annotation (Line(points={{-58,40},{-40,40},{-40,24},{-22,24}}, + color={0,0,127})); + connect(sin1.y, nexLagPumTri.u) + annotation (Line(points={{2,60},{38,60}}, color={0,0,127})); + connect(enaLagChiPum.yUp, nexLagPumTri.trigger) + annotation (Line(points={{2,24},{50,24},{50,48.2}}, color={255,0,255})); + connect(sin1.y, lasLagPumTri.u) + annotation (Line(points={{2,60},{20,60},{20,0},{38,0}}, color={0,0,127})); + connect(enaLagChiPum.yDown, lasLagPumTri.trigger) + annotation (Line(points={{2,16},{10,16},{10,-20},{50,-20},{50,-11.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/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. +

+", 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..e92fc561a2c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_dedicated.mo @@ -0,0 +1,89 @@ +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={{40,10},{60,30}}))); + 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={{40,-30},{60,-10}}))); + + Buildings.Controls.OBC.CDL.Logical.TrueHoldWithReset leaChiProOn( + final duration=2000) "Lead chiller proven on status" + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse leaChiEna( + final period=3600, + final shift=300) "Lead chiller enabling status" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + 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.Pulse enaPla( + final period=7200, + final shift=200) + "Plant enabling status" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + +equation + connect(leaChiEna.y, enaLeaChiPum.uLeaChiEna) annotation (Line(points={{-58,40}, + {20,40},{20,23},{38,23}}, color={255,0,255})); + connect(leaChiEna.y, disLeaChiPum.uLeaChiEna) annotation (Line(points={{-58,40}, + {20,40},{20,-17},{38,-17}}, color={255,0,255})); + connect(leaChiEna.y, lat.u) annotation (Line(points={{-58,40},{20,40},{20,-20}, + {-40,-20},{-40,-40},{-22,-40}}, color={255,0,255})); + connect(lat.y, disLeaChiPum.uLeaChiWatReq) + 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(leaChiEna.y, leaChiProOn.u) annotation (Line(points={{-58,40},{-50,40}, + {-50,10},{-42,10}}, color={255,0,255})); + connect(leaChiProOn.y, enaLeaChiPum.uLeaChiSta) annotation (Line(points={{-18,10}, + {10,10},{10,17},{38,17}}, color={255,0,255})); + connect(leaChiProOn.y, disLeaChiPum.uLeaChiSta) annotation (Line(points={{-18,10}, + {10,10},{10,-23},{38,-23}}, color={255,0,255})); + connect(leaChiProOn.y, enaLeaChiPum.uLeaChiWatReq) annotation (Line(points={{ + -18,10},{10,10},{10,12},{38,12}}, color={255,0,255})); + connect(enaPla.y, enaLeaChiPum.uPla) annotation (Line(points={{-58,80},{28,80}, + {28,28},{38,28}}, color={255,0,255})); + connect(enaPla.y, disLeaChiPum.uPla) annotation (Line(points={{-58,80},{28,80}, + {28,-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/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. +

+", 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..b68f329b8bf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/EnableLead_headered.mo @@ -0,0 +1,69 @@ +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=3) + "Enable lead chilled water pump based on the status of chilled water isolation valves" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse isoVal( + final period=3600, + final shift=300) "Isolation valve status" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse isoVal1( + final period=3600, + final shift=600) "Isolation valve status" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse isoVal2( + final period=3600, + final shift=1000) "Isolation valve status" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Logical false" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + +equation + connect(isoVal.y, enaLeaChiPum.uChiIsoVal[3]) + annotation (Line(points={{2,60},{20,60},{20,0.666667},{38,0.666667}}, + color={255,0,255})); + connect(isoVal1.y, enaLeaChiPum.uChiIsoVal[2]) + annotation (Line(points={{2,0},{38,0}}, color={255,0,255})); + connect(isoVal2.y, enaLeaChiPum.uChiIsoVal[1]) + annotation (Line(points={{2,-60},{20,-60},{20,-0.666667},{38,-0.666667}}, + color={255,0,255})); + connect(con1.y, enaLeaChiPum.uEnaPla) annotation (Line(points={{-38,-30},{10,-30}, + {10,-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/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..61b6bc32d5a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_localDp.mo @@ -0,0 +1,88 @@ +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.Continuous.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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,-5},{18,-5}}, + color={0,0,127})); + connect(remPreSen2.y, chiPumSpe.dpChiWat_remote[2]) + annotation (Line(points={{-38,-40},{-20,-40},{-20,-3},{18,-3}}, + 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. +

+", 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..cb0da5889f0 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Subsequences/Validation/Speed_primary_remoteDp.mo @@ -0,0 +1,78 @@ +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.Continuous.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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,-1},{18,-1}}, color={0,0,127})); + connect(remPreSen2.y, chiPumSpe.dpChiWat_remote[2]) annotation (Line(points={ + {-38,-40},{-28,-40},{-28,1},{18,1}}, 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. +

+", 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..05d3db138c5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/Validation/Controller.mo @@ -0,0 +1,187 @@ +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.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.Logical.Sources.Constant con(final k=true) + "Constant true" + annotation (Placement(transformation(extent={{-20,130},{0,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Constant difPreSet( + final k=8.5*6894.75) + "Pressure difference setpoint" + annotation (Placement(transformation(extent={{-60,-140},{-40,-120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Pre enaStaRet[3]( + final pre_u_start={true,true,false}) + "Pump enabled status return" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + Buildings.Controls.OBC.CDL.Logical.TrueHoldWithReset leaChiProOn( + final duration=2000) + "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.Sources.Constant con1( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-108,110},{-88,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(enaStaRet.y, heaNoLoc.uChiWatPum) annotation (Line(points={{-38,90},{44, + 90},{44,167},{78,167}}, color={255,0,255})); + connect(con.y, heaNoLoc.uChiIsoVal[1]) + annotation (Line(points={{2,140},{36,140},{36,159},{78,159}}, color={255,0,255})); + connect(con.y, heaNoLoc.uChiIsoVal[2]) + annotation (Line(points={{2,140},{36,140},{36,159},{78,159}}, color={255,0,255})); + connect(heaNoLoc.yChiWatPum, enaStaRet.u) annotation (Line(points={{102,160},{ + 120,160},{120,110},{-80,110},{-80,90},{-62,90}}, color={255,0,255})); + 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(con1.y, heaNoLoc.uEnaPla) annotation (Line(points={{-86,120},{40,120}, + {40,157},{78,157}}, 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..0bdbf6ec5bf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/ChilledWater/package.mo @@ -0,0 +1,33 @@ +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.2.6 Primary chilled water pumps, +in ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), + 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..ddcaba49fd6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Controller.mo @@ -0,0 +1,316 @@ +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.Continuous.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.Continuous.Abs abs if not fixSpe + "Absolute difference" + annotation (Placement(transformation(extent={{-40,-100},{-20,-80}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.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..7b95a0956bb --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_dedicated.mo @@ -0,0 +1,146 @@ +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.9 Condenser water pumps, part 5.2.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..5662a8eb72c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/EnableLead_headered.mo @@ -0,0 +1,133 @@ +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.9 Condenser water pumps, part 5.2.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..d2b4e3f6b2f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Speed.mo @@ -0,0 +1,267 @@ +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} + "Chiller 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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.Subtract sub1[totSta] if not fixSpe + "Add two real inputs" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant con4( + final k=0) if not have_WSE + "Constant zero" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Continuous.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}}))); + +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(uChiSta, conWatPumOn1.index) annotation (Line(points={{-160,100},{-130, + 100},{-130,-80},{30,-80},{30,-72}},color={255,127,0})); + 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})); + +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.9 Condenser water pumps, part 5.2.9.5 and 5.2.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..5403e28cf80 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_dedicated.mo @@ -0,0 +1,84 @@ +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. +

+", 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..562172c3639 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/EnableLead_headered.mo @@ -0,0 +1,65 @@ +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. +

+", 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..a98f6ed7478 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/Subsequences/Validation/Speed.mo @@ -0,0 +1,65 @@ +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.Continuous.Sources.Ramp ramp( + final duration=1, + final height=3) "Block that generates ramp signal" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Continuous.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. +

+", 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..27149ce0c79 --- /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.Continuous.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.Continuous.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.Continuous.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.Continuous.Switch meaPumSpe "Measured pump speed" + annotation (Placement(transformation(extent={{-10,-46},{10,-26}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer(final k=0) + "Zero pump speed" + annotation (Placement(transformation(extent={{-80,-66},{-60,-46}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch pumSpeSet "Pump speed setpoint" + annotation (Placement(transformation(extent={{-10,-16},{10,4}}))); + Buildings.Controls.OBC.CDL.Continuous.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..0477fe1b151 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/CondenserWater/package.mo @@ -0,0 +1,31 @@ +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.2.9 Condener water water pumps, +in ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), 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..d8ad0b31f1f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Pumps/package.mo @@ -0,0 +1,48 @@ +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.2.9 Condenser water pumps and +section 5.2.6 Primary chilled water pumps, in +ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..a388b93c9d2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterPlantReset.mo @@ -0,0 +1,243 @@ +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", + displayUnit="h")=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", + displayUnit="h")=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,-60},{160,-20}}), + 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={{20,50},{40,70}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Sample last reset value when there is chiller stage change" + annotation (Placement(transformation(extent={{60,50},{80,70}}))); + Buildings.Controls.OBC.CDL.Logical.TrueHoldWithReset truHol( + final duration=holTim) + "Hold the true input with given time" + annotation (Placement(transformation(extent={{-20,-50},{0,-30}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Check if the input changes from false to true" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Switch plant reset value depends on if there is chiller stage change" + annotation (Placement(transformation(extent={{80,-50},{100,-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}}))); + +equation + connect(not1.y, mulAnd.u) + annotation (Line(points={{-78,60},{-62,60}}, color={255,0,255})); + connect(TChiWatSupResReq, triRes.numOfReq) + annotation (Line(points={{-140,20},{10,20},{10,52},{18,52}}, + color={255,127,0})); + connect(mulAnd.y, not2.u) + annotation (Line(points={{-38,60},{-22,60}}, color={255,0,255})); + connect(not2.y, triRes.uDevSta) + annotation (Line(points={{2,60},{10,60},{10,68},{18,68}}, + 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={{42,60},{58,60}}, color={0,0,127})); + connect(truHol.y, swi.u2) + annotation (Line(points={{2,-40},{78,-40}}, color={255,0,255})); + connect(triRes.y, swi.u3) + annotation (Line(points={{42,60},{50,60},{50,-48},{78,-48}}, + color={0,0,127})); + connect(triSam.y, swi.u1) + annotation (Line(points={{82,60},{100,60},{100,-20},{60,-20},{60,-32},{78,-32}}, + color={0,0,127})); + connect(edg.y, triSam.trigger) + annotation (Line(points={{2,0},{70,0},{70,48}}, color={255,0,255})); + connect(swi.y, yChiWatPlaRes) + annotation (Line(points={{102,-40},{140,-40}}, color={0,0,127})); + connect(chaPro, truHol.u) + annotation (Line(points={{-140,-40},{-22,-40}},color={255,0,255})); + connect(chaPro, edg.u) + annotation (Line(points={{-140,-40},{-60,-40},{-60,0},{-22,0}}, + color={255,0,255})); + +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft March 23, 2020), section 5.2.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..c3b9c42e80a --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/ChilledWaterSupply.mo @@ -0,0 +1,235 @@ +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", + 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 min=TChiWatSupMin, + 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.Continuous.Line chiWatPumPre[nRemDpSen] + "Chilled water pump differential pressure setpoint" + annotation (Placement(transformation(extent={{40,40},{60,60}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zerRes[nRemDpSen]( + final k=fill(minSet, nRemDpSen)) "Minimum plant reset" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant oneRes( + final k=maxSet) "Maximum plant reset" + annotation (Placement(transformation(extent={{-60,-100},{-40,-80}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Sources.Constant maxChiWatTem( + final k=TChiWatSupMax) + "Maximum chilled water supply temperature" + annotation (Placement(transformation(extent={{-20,-40},{0,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minChiWatTem( + final k=TChiWatSupMin) + "Minimum chilled water supply temperature" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft March 23, 2020), section 5.2.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..17b8be854b5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterPlantReset.mo @@ -0,0 +1,113 @@ +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,60},{80,80}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.SetPoints.ChilledWaterPlantReset + devRes "Validate chilled water plant reset affected by device status" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Sources.Constant uChiWatPum[2]( + final k={true,false}) "Plant status" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1 + "Convert real to integer" + annotation (Placement(transformation(extent={{0,40},{20,60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final period=2700, + final width=0.3) + "Generate pulse signal of type Boolean" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Switch between two Real signals" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1(final k=0) + "Zero request when device is OFF" + annotation (Placement(transformation(extent={{-80,-60},{-60,-40}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3 + "Convert real to integer" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep(nout=2) + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.TimeTable timTabLin1( + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + final 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,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.TimeTable timTabLin2( + final smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments, + final 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,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1(final period=3600) + "Generate pulse signal of type Boolean" + annotation (Placement(transformation(extent={{0,10},{20,30}}))); + +equation + connect(uChiWatPum.y, plaRes.uChiWatPum) + annotation (Line(points={{-58,80},{40,80},{40,76},{58,76}}, color={255,0,255})); + connect(con1.y,swi. u1) + annotation (Line(points={{-58,-50},{-52,-50},{-52,-42},{-42,-42}}, + color={0,0,127})); + connect(booPul.y,swi. u2) + annotation (Line(points={{-58,-20},{-48,-20},{-48,-50},{-42,-50}}, + color={255,0,255})); + connect(booPul.y,not1. u) + annotation (Line(points={{-58,-20},{-42,-20}},color={255,0,255})); + connect(not1.y, booRep.u) + annotation (Line(points={{-18,-20},{-2,-20}}, color={255,0,255})); + connect(booRep.y, devRes.uChiWatPum) + annotation (Line(points={{22,-20},{40,-20},{40,-24},{58,-24}}, color={255,0,255})); + connect(reaToInt1.y, plaRes.TChiWatSupResReq) + annotation (Line(points={{22,50},{40,50},{40,70},{58,70}}, color={255,127,0})); + connect(reaToInt3.y, devRes.TChiWatSupResReq) + annotation (Line(points={{22,-50},{40,-50},{40,-30},{58,-30}}, color={255,127,0})); + connect(timTabLin1.y[1], reaToInt1.u) + annotation (Line(points={{-18,50},{-2,50}}, color={0,0,127})); + connect(timTabLin2.y[1], swi.u3) + annotation (Line(points={{-58,-80},{-52,-80},{-52,-58},{-42,-58}}, + color={0,0,127})); + connect(swi.y, reaToInt3.u) + annotation (Line(points={{-18,-50},{-2,-50}}, color={0,0,127})); + connect(booPul1.y, plaRes.chaPro) + annotation (Line(points={{22,20},{50,20},{50,64},{58,64}}, color={255,0,255})); + connect(booPul1.y, devRes.chaPro) + annotation (Line(points={{22,20},{50,20},{50,-36},{58,-36}}, 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. +

+", 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 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..d2861d39111 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/Validation/ChilledWaterSupply.mo @@ -0,0 +1,48 @@ +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.Continuous.Sources.Ramp ram(final duration=3600) + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + +equation + connect(ram.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..98382339fed --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/SetPoints/package.mo @@ -0,0 +1,27 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant; +package SetPoints + +annotation (preferredView="info", Documentation(info=" +

+This package contains chilled water plant reset control sequences. +The implementation is based on section 5.2.5.2. in ASHRAE RP-1711 Advanced Sequences +of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), + 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..c09ee7486e9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Down.mo @@ -0,0 +1,947 @@ +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( + final unit="s", + final quantity="Time", + 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( + final unit="s", + final quantity="Time", + displayUnit="s")=30 + "Waiting time after enabling next head pressure control" + annotation (Dialog(group="Disable last chiller", enable=have_ponyChiller)); + parameter Real proOnTim( + final unit="s", + final quantity="Time", + 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( + final unit="s", + final quantity="Time", + 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( + final unit="s", + final quantity="Time", + displayUnit="s") + "Time to reset minimum by-pass flow" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real minFloSet[nChi]( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s") + "Minimum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real maxFloSet[nChi]( + final unit="m3/s", + final quantity="VolumeFlowRate", + displayUnit="m3/s") + "Maximum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real aftByPasSetTim( + final unit="s", + final quantity="Time", + 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,300},{-280,340}}), + 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,120},{-100,160}}))); + 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,100},{-100,140}}))); + 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 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,330},{320,370}}), + 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,-170},{140,-130}}))); + 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,-210},{140,-170}}))); + +protected + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if stage setpoint dicreases" + annotation (Placement(transformation(extent={{-240,340},{-220,360}}))); + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Staging.Processes.Subsequences.NextChiller + nexChi(final nChi=nChi) "Identify next enabling chiller" + annotation (Placement(transformation(extent={{-40,310},{-20,330}}))); + 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.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={{100,-380},{120,-360}}))); + 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={{-80,-20},{-60,0}}))); + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesEquThr( + final t=0.5) + "Check if the disabled chiller has chilled water request" + annotation (Placement(transformation(extent={{-40,-20},{-20,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={{40,70},{60,90}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{-80,-130},{-60,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesEquThr1( + final t=0.5) + "Check if the disabled chiller is not requiring condenser water" + annotation (Placement(transformation(extent={{-40,-130},{-20,-110}}))); + Buildings.Controls.OBC.CDL.Logical.And3 and5 "Logical and" + annotation (Placement(transformation(extent={{60,-130},{80,-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,340},{-160,360}}))); + 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={{200,-380},{220,-360}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre + "Break algebraic loop" + annotation (Placement(transformation(extent={{160,-380},{180,-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.Continuous.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}}))); + +equation + connect(nexChi.yEnaSmaChi,dowSta. nexEnaChi) + annotation (Line(points={{-18,311},{30,311},{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,316},{20,316},{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},{-82,-10}}, color={0,0,127})); + connect(curDisChi.y, lesEquThr.u) + annotation (Line(points={{-58,-10},{-42,-10}}, color={0,0,127})); + connect(nexChi.yOnOff, logSwi2.u2) + annotation (Line(points={{-18,320},{0,320},{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,316},{20,316},{20,120},{-140,120},{-140,-30}, + {-70,-30},{-70,-22}}, color={255,127,0})); + connect(lesEquThr.y, and1.u2) + annotation (Line(points={{-18,-10},{120,-10},{120,12},{138,12}}, + color={255,0,255})); + 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,316},{20,316},{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,320},{0,320},{0,80},{38,80}}, color={255,0,255})); + connect(booRep4.y, swi.u2) + annotation (Line(points={{62,80},{138,80}}, color={255,0,255})); + connect(uChiWatIsoVal, swi.u3) + annotation (Line(points={{-300,100},{80,100},{80,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},{-82,-120}},color={0,0,127})); + connect(curDisChi1.y, lesEquThr1.u) + annotation (Line(points={{-58,-120},{-42,-120}}, color={0,0,127})); + connect(logSwi2.y, and5.u1) + annotation (Line(points={{82,20},{90,20},{90,-20},{10,-20},{10,-112},{58,-112}}, + color={255,0,255})); + connect(lesEquThr1.y, and5.u3) + annotation (Line(points={{-18,-120},{10,-120},{10,-128},{58,-128}}, + 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,316},{20,316},{20,120},{-140,120},{-140,-140}, + {-70,-140},{-70,-132}}, color={255,127,0})); + connect(nexChi.yOnOff, booRep1.u) + annotation (Line(points={{-18,320},{0,320},{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(and5.y, disHeaCon.uUpsDevSta) + annotation (Line(points={{82,-120},{160,-120},{160,-96},{198,-96}}, + color={255,0,255})); + connect(nexChi.yLasDisChi, disHeaCon.nexChaChi) + annotation (Line(points={{-18,316},{20,316},{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,320},{0,320},{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(lat.y, minBypSet.chaPro) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328}, + {-260,-366}, {98,-366}}, color={255,0,255})); + connect(VChiWat_flow, minBypSet.VChiWat_flow) + annotation (Line(points={{-300,190},{-170,190},{-170,-374},{98,-374}}, + 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,350},{-140,350},{-140,328},{-260,328},{-260,240}, + {58,240}}, color={255,0,255})); + connect(lat.y, disChiIsoVal.chaPro) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328},{-260,52}, + {198,52}}, color={255,0,255})); + connect(lat.y, and4.u2) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328},{-260,22}, + {-42,22}}, color={255,0,255})); + connect(lat.y, logSwi2.u3) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328},{-260,12}, + {58,12}}, color={255,0,255})); + connect(lat.y, disHeaCon.chaPro) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328},{-260,-100}, + {198,-100}}, color={255,0,255})); + connect(lat.y, minChiWatFlo.uStaDow) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328},{-260,-329}, + {98,-329}}, color={255,0,255})); + connect(lat.y,disNexCWP. uStaDow) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328},{-260,-162}, + {98,-162}}, color={255,0,255})); + connect(lat.y, yStaPro) + annotation (Line(points={{-158,350},{300,350}},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,316},{20,316},{20,-321},{98,-321}}, + color={255,127,0})); + connect(nexChi.yEnaSmaChi, minChiWatFlo.nexEnaChi) + annotation (Line(points={{-18,311},{30,311},{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={{222,-370},{260,-370},{260,-390},{-190,-390}, + {-190,344},{-182,344}}, 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(minBypSet.yMinBypRes, pre.u) + annotation (Line(points={{122,-370},{158,-370}}, color={255,0,255})); + connect(pre.y, edg1.u) + annotation (Line(points={{182,-370},{198,-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={{222,-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={{222,-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(lat1.y, minBypSet.uUpsDevSta) + annotation (Line(points={{262,-260},{270,-260},{270,-290},{-40,-290}, + {-40,-362},{98,-362}}, 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(chiWatMinSet.y, minBypSet.VMinChiWat_setpoint) + annotation (Line(points={{222,-330},{240,-330},{240,-350},{60,-350}, + {60,-378},{98,-378}}, color={0,0,127})); + connect(nexChi.yOnOff, dowSta.uOnOff) + annotation (Line(points={{-18,320},{0,320},{0,228},{58,228}}, + color={255,0,255})); + connect(edg1.y, dowSta.clr) + annotation (Line(points={{222,-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(lat3.y, and5.u2) + annotation (Line(points={{222,-30},{240,-30},{240,-50},{40,-50},{40,-120}, + {58,-120}}, color={255,0,255})); + connect(edg1.y, lat3.clr) + annotation (Line(points={{222,-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={{222,-370},{260,-370},{260,-390},{-190,-390}, + {-190,-136},{198,-136}}, color={255,0,255})); + connect(lat.y, nexChi.chaPro) + annotation (Line(points={{-158,350},{-140,350},{-140,328},{-260,328}, + {-260,313},{-42,313}}, color={255,0,255})); + connect(uStaSet, nexChi.uStaSet) + annotation (Line(points={{-300,380},{-60,380},{-60,327},{-42,327}}, + color={255,127,0})); + connect(nexChi.uChiSet, uChiSet) + annotation (Line(points={{-42,320},{-300,320}}, color={255,0,255})); + connect(uStaSet, cha.u) + annotation (Line(points={{-300,380},{-260,380},{-260,350},{-242,350}}, + color={255,127,0})); + connect(cha.down, lat.u) + annotation (Line(points={{-218,344},{-200,344},{-200,350},{-182,350}}, + 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},{-100, + 224},{-100,130},{-300,130}}, color={255,0,255})); + connect(uChiHeaCon, logSwi.u3) annotation (Line(points={{-300,130},{-100,130}, + {-100,-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})); +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,148},{-26,134}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="yOpeParLoaRatMin", + visible=need_reduceChillerDemand), + Text( + extent={{-96,126},{-60,114}}, + 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,-142},{96,-156}}, + textColor={255,127,0}, + textString="yConWatPumNum"), + Text( + extent={{28,-180},{98,-194}}, + 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)}), +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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.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.Subsequences.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..1bcfa573441 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/CHWIsoVal.mo @@ -0,0 +1,392 @@ +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", + displayUnit="h") + "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 chaPro + "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.Continuous.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.Continuous.Sources.Constant con8( + final k=endValPos) + "Ending valve position" + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con6( + final k=iniValPos) + "Initial isolation valve position" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con9( + final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Switch swi1[nChi] "Logical switch" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.And3 and5 + "Check if the isolation valve has been fully open" + annotation (Placement(transformation(extent={{140,130},{160,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}}))); + +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(chaPro, 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(chaPro, 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},{90,-60},{90,-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},{-120,-220},{-120,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},{120,220},{120,148},{138,148}}, + color={255,0,255})); + connect(and5.y, yEnaChiWatIsoVal) + annotation (Line(points={{162,140},{200,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},{138,140}}, 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}, + {-110,-230},{-110,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(lat2.y, and5.u3) annotation (Line(points={{-18,120},{0,120},{0,132},{138, + 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="chaPro"), + 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 (chaPro=true). It will also generate +status to indicate if the valve reset process has finished. +This development is based on ASHRAE RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.4.16, item 5 and section 5.2.4.17, item 3, 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..088bd255468 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DisableChiller.mo @@ -0,0 +1,458 @@ +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", + displayUnit="h") = 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 yReaDemLim + "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 + 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.Continuous.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.Continuous.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, yReaDemLim) + 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="yReaDemLim")}), + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.4.17, +item 1.e and f. 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.2.4.17, item 2. +

+

+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..693900349cf --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/DownStart.mo @@ -0,0 +1,604 @@ +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", + displayUnit="h")=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", + displayUnit="h") + "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", + displayUnit="h")=60 + "Time after setpoint achieved" + annotation (Dialog(group="Reset bypass")); + parameter Real waiTim( + final unit="s", + final quantity="Time", + displayUnit="h")=30 + "Waiting time after enabling next head pressure control" + annotation (Dialog(group="Head pressure control")); + parameter Real chaChiWatIsoTim( + final unit="s", + final quantity="Time", + displayUnit="h") + "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", + displayUnit="h")=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.Continuous.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.Continuous.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.chaPro) + 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,106},{58,106}}, + color={0,0,127})); + connect(uStaDow, enaHeaCon.chaPro) + 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.chaPro) + 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.yReaDemLim, 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,102},{58,102}}, + 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,108},{-20,108},{-20,66},{-2,66}}, + color={255,0,255})); + connect(disChi.yReaDemLim, 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,-60},{-20,-60},{-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,108},{-20,108},{-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})); +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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.4.17, item 1 and 2. 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.Subsequences.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..8fe79095874 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableCWPump.mo @@ -0,0 +1,207 @@ +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.Conversions.IntegerToReal intToRea + "Convert integer input to real output" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logicla and" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{40,-20},{60,0}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert integer input to real output" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea1 + "Convert integer input to real output" + annotation (Placement(transformation(extent={{-100,-50},{-80,-30}}))); + +equation + connect(uStaSet, intToRea.u) + annotation (Line(points={{-140,-80},{-102,-80}}, color={255,127,0})); + 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},{-2,80}}, color={255,0,255})); + connect(intToRea.y, swi1.u1) + annotation (Line(points={{-78,-80},{-40,-80},{-40,88},{-2,88}}, + color={0,0,127})); + 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},{-2,10}}, color={255,0,255})); + connect(intToRea.y, swi2.u1) + annotation (Line(points={{-78,-80},{-40,-80},{-40,18},{-2,18}}, + color={0,0,127})); + connect(uStaUp, swi.u2) + annotation (Line(points={{-140,40},{38,40}}, color={255,0,255})); + connect(swi1.y, swi.u1) + annotation (Line(points={{22,80},{30,80},{30,48},{38,48}}, + color={0,0,127})); + connect(uStaDow, swi3.u2) + annotation (Line(points={{-140,-10},{38,-10}}, color={255,0,255})); + connect(swi2.y, swi3.u1) + annotation (Line(points={{22,10},{30,10},{30,-2},{38,-2}}, + color={0,0,127})); + connect(intToRea.y, swi3.u3) + annotation (Line(points={{-78,-80},{-40,-80},{-40,-18},{38,-18}}, + color={0,0,127})); + connect(swi3.y, swi.u3) + annotation (Line(points={{62,-10},{70,-10},{70,20},{30,20},{30,32},{38,32}}, + color={0,0,127})); + connect(swi.y, reaToInt.u) + annotation (Line(points={{62,40},{78,40}}, color={0,0,127})); + connect(reaToInt.y, yChiSta) + annotation (Line(points={{102,40},{140,40}}, color={255,127,0})); + connect(uChiSta, intToRea1.u) + annotation (Line(points={{-140,-40},{-102,-40}}, color={255,127,0})); + connect(intToRea1.y, swi1.u3) + annotation (Line(points={{-78,-40},{-20,-40},{-20,72},{-2,72}}, color={0,0,127})); + connect(intToRea1.y, swi2.u3) + annotation (Line(points={{-78,-40},{-20,-40},{-20,2},{-2,2}}, color={0,0,127})); + +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..b8e9980c7d2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/EnableChiller.mo @@ -0,0 +1,407 @@ +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", + displayUnit="h") = 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 + 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.Continuous.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={{68,104},{148,96}}, + 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={{46,-76},{124,-84}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable +small chiller"), + Text( + extent={{70,94},{262,74}}, + 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={{72,76},{284,54}}, + 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={{82,-122},{162,-130}}, + 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={{24,-132},{236,-154}}, + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.4.16, +item 6 and item 7.a. 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..e2c8235f757 --- /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", + displayUnit="h")=10 + "Threshold time to enable head pressure control after condenser water pump being reset"; + parameter Real waiTim( + final unit="s", + final quantity="Time", + displayUnit="h") = 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 chaPro + "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.Continuous.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.Continuous.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{100,-30},{120,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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(chaPro, 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(chaPro, 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(chaPro, 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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020): +

+

+In stage-up process, section 5.2.4.16, item 4: +

+ +

+In stage-up process when requires smaller chiller being shut off and larger chiller +being enabled, section 5.2.4.16, item 7.c: +

+ +

+In stage-down process, section 5.2.4.17, item 4: +

+ +

+In stage-down process when requires smaller chiller being enabled and larger chiller +being disabled, section 5.2.4.17, item 1.c: +

+ +", 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..ba1f106a5e8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/NextChiller.mo @@ -0,0 +1,303 @@ +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={{-260,110},{-220,150}}), + iconTransformation(extent={{-140,50},{-100,90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiSet[nChi] + "Vector of chillers status setpoint" + annotation (Placement(transformation(extent={{-260,-40},{-220,0}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "True: in the stage change process" + annotation (Placement(transformation(extent={{-260,-180},{-220,-140}}), + iconTransformation(extent={{-140,-90},{-100,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yNexEnaChi + "Next enabling chiller index" + annotation (Placement(transformation(extent={{220,140},{260,180}}), + iconTransformation(extent={{100,70},{140,110}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yDisSmaChi + "Smaller chiller to be disabled in staging-up process" + annotation (Placement(transformation(extent={{220,90},{260,130}}), + iconTransformation(extent={{100,20},{140,60}}))); + 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={{220,-40},{260,0}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yLasDisChi + "Disable last chiller when it is in stage-down process" + annotation (Placement(transformation(extent={{220,-120},{260,-80}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yEnaSmaChi + "Smaller chiller to be enabled in stage-down process" + annotation (Placement(transformation(extent={{220,-180},{260,-140}}), + iconTransformation(extent={{100,-110},{140,-70}}))); + + Buildings.Controls.OBC.CDL.Integers.Change cha + "Check if it is stage up or stage down" + annotation (Placement(transformation(extent={{-200,120},{-180,140}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg[nChi] + "Check if the chiller is being enabled" + annotation (Placement(transformation(extent={{-200,30},{-180,50}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg[nChi] + "Check if the chiller is being disabled" + annotation (Placement(transformation(extent={{-200,-110},{-180,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Latch enaChi[nChi] + "True when the chiller should be enabled" + annotation (Placement(transformation(extent={{-120,30},{-100,50}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge endPro + "True: chiller stage change is end" + annotation (Placement(transformation(extent={{-200,-170},{-180,-150}}))); + Buildings.Controls.OBC.CDL.Logical.Latch disChi[nChi] + "True when the chiller should be disabled" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyEnaChi(final nin=nChi) + "Check if there is any enabling chiller" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyDisChi(final nin=nChi) + "Check if there is any disabling chiller" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And enaDis + "Check if enabling and disabling chillers at the same process" + annotation (Placement(transformation(extent={{-20,-30},{0,-10}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt[nChi] + "Find out the index of enabling chiller" + annotation (Placement(transformation(extent={{-20,30},{0,50}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt1[nChi] + "Find out the index of disabling chiller" + annotation (Placement(transformation(extent={{-20,-110},{0,-90}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum enaChiInd(final nin = nChi) + "Enabling chiller index" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum disChiInd(final nin = nChi) + "Disabling chiller index" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Latch upPro + "True when it is in stage up process" + annotation (Placement(transformation(extent={{-120,150},{-100,170}}))); + Buildings.Controls.OBC.CDL.Logical.Latch dowPro + "True when it is in stage down process" + annotation (Placement(transformation(extent={{-120,80},{-100,100}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt2 + "Find out the index of enabling chiller" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt3 + "Staging up process and it requires chiller on and off" + annotation (Placement(transformation(extent={{120,110},{140,130}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt4 + "Disabling chiller during stage up process" + annotation (Placement(transformation(extent={{180,100},{200,120}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt5 + "Find out the index of disabling chiller" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt6 + "Staging down process and it requires chiller on and off" + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply proInt7 + "Enabling chiller during stage down process" + annotation (Placement(transformation(extent={{180,-170},{200,-150}}))); + +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={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nChi] + "Boolean to integer" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + 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={{-80,150},{-60,170}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt4 + "Boolean to integer" + annotation (Placement(transformation(extent={{-80,80},{-60,100}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiIndVec[nChi]( + final k=chiInd) + "Vector of chiller index" + annotation (Placement(transformation(extent={{-120,-10},{-100,10}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-160,-170},{-140,-150}}))); + +equation + connect(uChiSet, edg.u) annotation (Line(points={{-240,-20},{-210,-20},{-210,40}, + {-202,40}}, color={255,0,255})); + connect(uChiSet, falEdg.u) annotation (Line(points={{-240,-20},{-210,-20},{-210, + -100},{-202,-100}}, color={255,0,255})); + connect(chaPro, endPro.u) + annotation (Line(points={{-240,-160},{-202,-160}}, color={255,0,255})); + connect(edg.y, enaChi.u) + annotation (Line(points={{-178,40},{-122,40}}, color={255,0,255})); + connect(falEdg.y, disChi.u) + annotation (Line(points={{-178,-100},{-122,-100}}, color={255,0,255})); + connect(endPro.y, booRep.u) + annotation (Line(points={{-178,-160},{-162,-160}}, color={255,0,255})); + connect(booRep.y, enaChi.clr) annotation (Line(points={{-138,-160},{-130,-160}, + {-130,34},{-122,34}}, color={255,0,255})); + connect(booRep.y, disChi.clr) annotation (Line(points={{-138,-160},{-130,-160}, + {-130,-106},{-122,-106}}, color={255,0,255})); + connect(enaChi.y, anyEnaChi.u) annotation (Line(points={{-98,40},{-90,40},{-90, + -20},{-82,-20}},color={255,0,255})); + connect(anyEnaChi.y, enaDis.u1) annotation (Line(points={{-58,-20},{-22,-20}}, + color={255,0,255})); + connect(disChi.y, anyDisChi.u) annotation (Line(points={{-98,-100},{-90,-100}, + {-90,-60},{-82,-60}},color={255,0,255})); + connect(anyDisChi.y, enaDis.u2) annotation (Line(points={{-58,-60},{-30,-60},{ + -30,-28},{-22,-28}}, color={255,0,255})); + connect(enaDis.y, yOnOff) annotation (Line(points={{2,-20},{240,-20}}, + color={255,0,255})); + connect(uStaSet, cha.u) + annotation (Line(points={{-240,130},{-202,130}}, color={255,127,0})); + connect(disChi.y, booToInt1.u) + annotation (Line(points={{-98,-100},{-82,-100}}, color={255,0,255})); + connect(enaChi.y, booToInt.u) + annotation (Line(points={{-98,40},{-82,40}}, color={255,0,255})); + connect(booToInt.y, proInt.u1) annotation (Line(points={{-58,40},{-40,40},{-40, + 46},{-22,46}}, color={255,127,0})); + connect(booToInt1.y, proInt1.u2) annotation (Line(points={{-58,-100},{-40,-100}, + {-40,-106},{-22,-106}}, color={255,127,0})); + connect(chiIndVec.y, proInt.u2) annotation (Line(points={{-98,0},{-40,0},{-40, + 34},{-22,34}}, color={255,127,0})); + connect(proInt.y, enaChiInd.u) + annotation (Line(points={{2,40},{18,40}}, color={255,127,0})); + connect(chiIndVec.y, proInt1.u1) annotation (Line(points={{-98,0},{-40,0},{-40, + -94},{-22,-94}}, color={255,127,0})); + connect(proInt1.y, disChiInd.u) + annotation (Line(points={{2,-100},{18,-100}}, color={255,127,0})); + connect(cha.up, upPro.u) annotation (Line(points={{-178,136},{-140,136},{-140, + 160},{-122,160}}, color={255,0,255})); + connect(cha.down, dowPro.u) annotation (Line(points={{-178,124},{-140,124},{-140, + 90},{-122,90}}, color={255,0,255})); + connect(endPro.y, upPro.clr) annotation (Line(points={{-178,-160},{-170,-160}, + {-170,154},{-122,154}}, color={255,0,255})); + connect(endPro.y, dowPro.clr) annotation (Line(points={{-178,-160},{-170,-160}, + {-170,84},{-122,84}}, color={255,0,255})); + connect(enaDis.y, booToInt2.u) annotation (Line(points={{2,-20},{20,-20},{20,-60}, + {38,-60}}, color={255,0,255})); + connect(upPro.y, booToInt3.u) + annotation (Line(points={{-98,160},{-82,160}}, color={255,0,255})); + connect(booToInt3.y, proInt2.u1) annotation (Line(points={{-58,160},{-20,160}, + {-20,166},{118,166}}, color={255,127,0})); + connect(enaChiInd.y, proInt2.u2) annotation (Line(points={{42,40},{80,40},{80, + 154},{118,154}}, color={255,127,0})); + connect(proInt2.y, yNexEnaChi) + annotation (Line(points={{142,160},{240,160}}, color={255,127,0})); + connect(booToInt3.y, proInt3.u1) annotation (Line(points={{-58,160},{-20,160}, + {-20,126},{118,126}},color={255,127,0})); + connect(booToInt2.y, proInt3.u2) annotation (Line(points={{62,-60},{70,-60},{70, + 114},{118,114}},color={255,127,0})); + connect(proInt3.y, proInt4.u1) annotation (Line(points={{142,120},{160,120},{160, + 116},{178,116}}, color={255,127,0})); + connect(disChiInd.y, proInt4.u2) annotation (Line(points={{42,-100},{90,-100}, + {90,104},{178,104}}, color={255,127,0})); + connect(proInt4.y, yDisSmaChi) + annotation (Line(points={{202,110},{240,110}}, color={255,127,0})); + connect(dowPro.y, booToInt4.u) + annotation (Line(points={{-98,90},{-82,90}}, color={255,0,255})); + connect(booToInt4.y, proInt5.u1) annotation (Line(points={{-58,90},{100,90},{100, + -94},{118,-94}}, color={255,127,0})); + connect(disChiInd.y, proInt5.u2) annotation (Line(points={{42,-100},{90,-100}, + {90,-106},{118,-106}}, color={255,127,0})); + connect(proInt5.y, yLasDisChi) + annotation (Line(points={{142,-100},{240,-100}}, color={255,127,0})); + connect(booToInt2.y, proInt6.u2) annotation (Line(points={{62,-60},{70,-60},{70, + -146},{118,-146}}, color={255,127,0})); + connect(booToInt4.y, proInt6.u1) annotation (Line(points={{-58,90},{100,90},{100, + -134},{118,-134}}, color={255,127,0})); + connect(proInt6.y, proInt7.u1) annotation (Line(points={{142,-140},{160,-140}, + {160,-154},{178,-154}}, color={255,127,0})); + connect(enaChiInd.y, proInt7.u2) annotation (Line(points={{42,40},{80,40},{80, + -166},{178,-166}}, color={255,127,0})); + connect(proInt7.y, yEnaSmaChi) + annotation (Line(points={{202,-160},{240,-160}}, color={255,127,0})); + +annotation ( + defaultComponentName="nexChi", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-220,-180},{220,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={{-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,100},{98,80}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yNexEnaChi"), + Text( + extent={{-98,-62},{-64,-74}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + Text( + extent={{50,52},{98,32}}, + textColor={255,127,0}, + pattern=LinePattern.Dash, + textString="yDisSmaChi"), + Text( + extent={{50,-28},{98,-48}}, + 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,8},{96,-4}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yOnOff"), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="?")}), +Documentation(info=" +

+This block identifies index of next enable (yNexEnaChi and +yEnaSmaChi) or disable 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). +

+", 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..db6ae244864 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ReduceDemand.mo @@ -0,0 +1,343 @@ +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", + displayUnit="h") = 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,140},{-160,180}}), + 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,110},{-160,150}}), + 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,20},{-160,60}}), + iconTransformation(extent={{-140,-10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaDow "Stage down status: true=stage-down" + annotation (Placement(transformation(extent={{-200,-20},{-160,20}}), + 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,-60},{-160,-20}}), + iconTransformation(extent={{-140,-70},{-100,-30}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-200,-130},{-160,-90}}), + 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,70},{200,110}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiDemRed + "Indicate if the chiller demand reduction process has finished" + annotation (Placement(transformation(extent={{160,30},{200,70}}), + 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,120},{20,140}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-60,150},{-40,170}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi4[nChi] + "Current setpoint to chillers" + annotation (Placement(transformation(extent={{120,80},{140,100}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con[nChi]( + final k=fill(0.2, nChi)) "Constant value to avoid zero as the denominator" + annotation (Placement(transformation(extent={{-140,-170},{-120,-150}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nChi] + "Change zero input to a given constant if the chiller is not enabled" + annotation (Placement(transformation(extent={{-80,-120},{-60,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-120},{20,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide div[nChi] + "Output result of first input divided by second input" + annotation (Placement(transformation(extent={{-40,-120},{-20,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nChi] "Logical not" + annotation (Placement(transformation(extent={{40,-120},{60,-100}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd(final nin=nChi) + "Current chillers demand have been lower than 80%" + annotation (Placement(transformation(extent={{80,-120},{100,-100}}))); + 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,170}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nChi) + "Replicate boolean input " + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{120,40},{140,60}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + "Minimum cycling operative partial load ratio" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2( + final k=chiDemRedFac) + "Demand reducing factor of current operating chillers" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Max max "Maximum value of two real inputs" + annotation (Placement(transformation(extent={{0,10},{20,30}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep(final nout=nChi) + "Replicate real input" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[nChi] + "Percentage of the current load" + annotation (Placement(transformation(extent={{80,120},{100,140}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar[nChi]( + final p=fill(1e-6, nChi)) + "Add a small value to avoid potentially zero denominator" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=holChiDemTim) + "Check if the demand limit has been 5 minutes" + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Or or2 "Logical or" + annotation (Placement(transformation(extent={{120,-80},{140,-60}}))); + +equation + connect(booRep.y, triSam.trigger) + annotation (Line(points={{-38,160},{-20,160},{-20,110},{10,110},{10,118}}, + color={255,0,255})); + connect(uChiLoa, triSam.u) + annotation (Line(points={{-180,130},{-2,130}}, color={0,0,127})); + connect(uChiLoa, swi4.u3) + annotation (Line(points={{-180,130},{-140,130},{-140,82},{118,82}}, color={0,0,127})); + connect(uChi, swi.u2) + annotation (Line(points={{-180,-110},{-82,-110}}, color={255,0,255})); + connect(con.y, swi.u3) + annotation (Line(points={{-118,-160},{-100,-160},{-100,-118},{-82,-118}}, + color={0,0,127})); + connect(swi.y, div.u2) + annotation (Line(points={{-58,-110},{-50,-110},{-50,-116},{-42,-116}}, + color={0,0,127})); + connect(uChiLoa, div.u1) + annotation (Line(points={{-180,130},{-140,130},{-140,-80},{-50,-80}, + {-50,-104},{-42,-104}}, color={0,0,127})); + connect(div.y, hys.u) + annotation (Line(points={{-18,-110},{-2,-110}}, color={0,0,127})); + connect(hys.y, not1.u) + annotation (Line(points={{22,-110},{38,-110}}, color={255,0,255})); + connect(not1.y, mulAnd.u) + annotation (Line(points={{62,-110},{78,-110}}, color={255,0,255})); + connect(swi4.y,yChiDem) + annotation (Line(points={{142,90},{180,90}}, color={0,0,127})); + connect(uDemLim, edg.u) + annotation (Line(points={{-180,160},{-102,160}}, color={255,0,255})); + connect(edg.y, booRep.u) + annotation (Line(points={{-78,160},{-62,160}}, color={255,0,255})); + connect(uDemLim, booRep1.u) + annotation (Line(points={{-180,160},{-120,160},{-120,100},{-82,100}}, + color={255,0,255})); + connect(booRep1.y, swi4.u2) + annotation (Line(points={{-58,100},{-40,100},{-40,90},{118,90}}, + color={255,0,255})); + connect(uDemLim, and2.u1) + annotation (Line(points={{-180,160},{-120,160},{-120,50},{118,50}}, + color={255,0,255})); + connect(and2.y, yChiDemRed) + annotation (Line(points={{142,50},{180,50}}, color={255,0,255})); + connect(uStaDow, and1.u1) + annotation (Line(points={{-180,0},{-102,0}}, color={255,0,255})); + connect(uOnOff, and1.u2) + annotation (Line(points={{-180,-40},{-130,-40},{-130,-8},{-102,-8}}, + color={255,0,255})); + connect(yOpeParLoaRatMin, swi1.u1) + annotation (Line(points={{-180,40},{-60,40},{-60,8},{-42,8}}, + color={0,0,127})); + connect(and1.y, swi1.u2) + annotation (Line(points={{-78,0},{-42,0}}, color={255,0,255})); + connect(con1.y, swi1.u3) + annotation (Line(points={{-78,-30},{-60,-30},{-60,-8},{-42,-8}}, + color={0,0,127})); + connect(swi1.y, max.u2) + annotation (Line(points={{-18,0},{-10,0},{-10,14},{-2,14}}, color={0,0,127})); + connect(con2.y, max.u1) + annotation (Line(points={{-18,30},{-10,30},{-10,26},{-2,26}}, + color={0,0,127})); + connect(max.y, reaRep.u) + annotation (Line(points={{22,20},{58,20}}, color={0,0,127})); + connect(triSam.y, pro.u1) + annotation (Line(points={{22,130},{40,130},{40,136},{78,136}}, + color={0,0,127})); + connect(reaRep.y, pro.u2) + annotation (Line(points={{82,20},{90,20},{90,100},{60,100},{60,124},{78,124}}, + color={0,0,127})); + connect(pro.y, swi4.u1) + annotation (Line(points={{102,130},{110,130},{110,98},{118,98}}, + color={0,0,127})); + connect(triSam.y, addPar.u) + annotation (Line(points={{22,130},{40,130},{40,-20},{58,-20}}, + color={0,0,127})); + connect(addPar.y, swi.u1) + annotation (Line(points={{82,-20},{100,-20},{100,-52},{-100,-52},{-100,-102}, + {-82,-102}}, color={0,0,127})); + connect(uDemLim, tim.u) + annotation (Line(points={{-180,160},{-120,160},{-120,-70},{-42,-70}}, + color={255,0,255})); + connect(mulAnd.y, or2.u2) + annotation (Line(points={{102,-110},{110,-110},{110,-78},{118,-78}}, + color={255,0,255})); + connect(or2.y, and2.u2) + annotation (Line(points={{142,-70},{150,-70},{150,0},{100,0},{100,42}, + {118,42}}, color={255,0,255})); + connect(tim.passed, or2.u1) + annotation (Line(points={{-18,-78},{40,-78},{40,-70},{118,-70}}, + 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={{-17,9.5},{17,-9.5}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + origin={-81,11.5}, + rotation=0, + textString="yOpeParLoaRatMin")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-180},{160,180}})), + Documentation(info=" +

+Block that reduces demand of current operating chillers when there is a stage-up +command, according to ASHRAE RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.4.16, item 1 which specifies how to start the stage-up +process of the current operating chillers; and section 5.2.4.17, item 1.a 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..ad5c2b0e723 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/ResetMinBypass.mo @@ -0,0 +1,207 @@ +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", + displayUnit="h") = 60 + "Time after setpoint achieved"; + parameter Real relFloDif=0.05 + "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,60},{-160,100}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput chaPro + "Indicate if there is stage change" + annotation (Placement(transformation(extent={{-200,20},{-160,60}}), + 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,-40},{-160,0}}), + iconTransformation(extent={{-140,-60},{-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,-100},{-160,-60}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yMinBypRes + "True: minimum chilled water flow bypass setpoint has been resetted successfully" + annotation (Placement(transformation(extent={{160,60},{200,100}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=relFloDif - 0.01, + final uHigh=relFloDif + 0.01) + "Check if chiller water flow rate is different from its setpoint" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.And3 and1 "Logical and" + annotation (Placement(transformation(extent={{120,70},{140,90}}))); + 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,-30},{60,-10}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide div + "Flow rate error divided by its setpoint" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=1e-6) + "Add a small positive to avoid zero output" + annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + 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,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{0,-30},{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,30},{60,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Abs abs "Absolute value" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract floDif + "Checkout the flow rate difference" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-20,-70},{0,-50}}))); + +equation + connect(uUpsDevSta, and2.u1) + annotation (Line(points={{-180,80},{-82,80}}, color={255,0,255})); + connect(chaPro, and2.u2) + annotation (Line(points={{-180,40},{-140,40},{-140,72},{-82,72}}, + color={255,0,255})); + connect(and2.y, and1.u1) + annotation (Line(points={{-58,80},{-10,80},{-10,88},{118,88}}, + color={255,0,255})); + connect(and1.y,yMinBypRes) + annotation (Line(points={{142,80},{180,80}}, color={255,0,255})); + connect(chaPro, not1.u) + annotation (Line(points={{-180,40},{-140,40},{-140,20},{-122,20}}, + color={255,0,255})); + connect(lat.y, and1.u2) + annotation (Line(points={{102,40},{108,40},{108,80},{118,80}}, + color={255,0,255})); + connect(VMinChiWat_setpoint, addPar.u) + annotation (Line(points={{-180,-80},{-142,-80}}, color={0,0,127})); + connect(div.y, hys.u) + annotation (Line(points={{-78,-60},{-62,-60}}, color={0,0,127})); + connect(not1.y, edg1.u) + annotation (Line(points={{-98,20},{-82,20}}, color={255,0,255})); + connect(edg1.y, lat.clr) + annotation (Line(points={{-58,20},{70,20},{70,34},{78,34}}, + color={255,0,255})); + connect(and3.y, tim.u) + annotation (Line(points={{22,-20},{38,-20}}, color={255,0,255})); + connect(addPar.y, div.u2) + annotation (Line(points={{-118,-80},{-110,-80},{-110,-66},{-102,-66}}, + color={0,0,127})); + connect(and3.y, edg2.u) + annotation (Line(points={{22,-20},{30,-20},{30,40},{38,40}}, + color={255,0,255})); + connect(edg2.y, lat.u) + annotation (Line(points={{62,40},{78,40}}, color={255,0,255})); + connect(VChiWat_flow, floDif.u1) + annotation (Line(points={{-180,-20},{-140,-20},{-140,-14},{-122,-14}}, color={0,0,127})); + connect(floDif.y, abs.u) + annotation (Line(points={{-98,-20},{-82,-20}}, color={0,0,127})); + connect(abs.y, div.u1) + annotation (Line(points={{-58,-20},{-40,-20},{-40,-40},{-110,-40},{-110,-54}, + {-102,-54}}, color={0,0,127})); + connect(hys.y, not2.u) + annotation (Line(points={{-38,-60},{-22,-60}}, color={255,0,255})); + connect(and2.y, and3.u1) + annotation (Line(points={{-58,80},{-10,80},{-10,-20},{-2,-20}}, + color={255,0,255})); + connect(not2.y, and3.u2) + annotation (Line(points={{2,-60},{10,-60},{10,-40},{-10,-40},{-10,-28}, + {-2,-28}}, color={255,0,255})); + connect(tim.passed, and1.u3) + annotation (Line(points={{62,-28},{114,-28},{114,72},{118,72}}, + color={255,0,255})); + connect(VMinChiWat_setpoint, floDif.u2) annotation (Line(points={{-180,-80},{-150, + -80},{-150,-26},{-122,-26}}, color={0,0,127})); + +annotation ( + defaultComponentName="minBypRes", + 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={{50,8},{98,-8}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="yMinBypRes"), + Text( + extent={{-98,-32},{-50,-46}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VChiWat_flow"), + Text( + extent={{-98,-72},{-30,-88}}, + textColor={0,0,127}, + pattern=LinePattern.Dash, + textString="VMinChiWat_setpoint"), + Text( + extent={{-98,46},{-66,36}}, + textColor={255,0,255}, + pattern=LinePattern.Dash, + textString="chaPro"), + 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")}), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-160,-100},{160,100}})), + Documentation(info=" +

+Block that generates minimum bypass flow reset status when there is +stage-change command. +This development is based on ASHRAE RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.4.16, item 2. +

+

+When there is stage-change command (chaPro = 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..ef62cde338f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/UpEnd.mo @@ -0,0 +1,723 @@ +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", + displayUnit="h") = 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", + displayUnit="h") + "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", + displayUnit="h") + "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", + displayUnit="h")=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={{-240,220},{-200,260}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uStaUp "Stage-up command" + annotation (Placement(transformation(extent={{-240,190},{-200,230}}), + 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={{-240,160},{-200,200}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller status: true=ON" + annotation (Placement(transformation(extent={{-240,130},{-200,170}}), + 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={{-240,90},{-200,130}}), + 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={{-240,50},{-200,90}}), + 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={{-240,0},{-200,40}}), + 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={{-240,-30},{-200,10}}), + 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={{-240,-90},{-200,-50}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiHeaCon[nChi] + "Chillers head pressure control status" + annotation (Placement(transformation(extent={{-240,-120},{-200,-80}}), + 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={{-240,-190},{-200,-150}}), + 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={{-240,-220},{-200,-180}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChi[nChi] + "Chiller enabling status" + annotation (Placement(transformation(extent={{200,200},{240,240}}), + 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={{200,40},{240,80}}), + iconTransformation(extent={{100,30},{140,70}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yChiHeaCon[nChi] + "Chiller head pressure control enabling status" + annotation (Placement(transformation(extent={{200,-70},{240,-30}}), + 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={{200,-130},{240,-90}}), + 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={{200,-210},{240,-170}}), + iconTransformation(extent={{100,-90},{140,-50}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput endStaTri + "Staging end trigger" + annotation (Placement(transformation(extent={{200,-250},{240,-210}}), + 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={{-100,180},{-80,200}}))); + 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={{60,-20},{80,0}}))); + 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={{40,-80},{60,-60}}))); + 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={{40,-140},{60,-120}}))); + 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={{40,-190},{60,-170}}))); + Buildings.Controls.OBC.CDL.Logical.And and4 "Logical and" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2( + final k=true) "True constant" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 "Logical and" + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3(final k=false) + "False constant" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{-160,100},{-140,120}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanExtractor curDisChi(final nin=nChi) + "Current disabling chiller" + annotation (Placement(transformation(extent={{-160,10},{-140,30}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanExtractor curDisChi1(final nin=nChi) + "Current disabling chiller" + annotation (Placement(transformation(extent={{-160,-80},{-140,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nChi] + "Logical switch" + annotation (Placement(transformation(extent={{160,-60},{180,-40}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4(final nout=nChi) + "Replicate boolean input" + annotation (Placement(transformation(extent={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch chiWatIso[nChi] + "Chilled water isolation valve" + annotation (Placement(transformation(extent={{160,50},{180,70}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi4 + "Logical switch" + annotation (Placement(transformation(extent={{160,-170},{180,-150}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch chiWatByp + "Chilled water bypass flow setpoint" + annotation (Placement(transformation(extent={{160,-120},{180,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi5 "Logical switch" + annotation (Placement(transformation(extent={{60,-240},{80,-220}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch chiWatByp1 + "Chilled water bypass flow setpoint" + annotation (Placement(transformation(extent={{100,-140},{120,-120}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Maintain ON signal when the chiller has been proven on" + annotation (Placement(transformation(extent={{-60,160},{-40,180}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre + "Break algebraic loop" + annotation (Placement(transformation(extent={{120,-240},{140,-220}}))); + 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,-240},{180,-220}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat2 + "Maintain ON signal when the chilled water isolation valve has been closed" + annotation (Placement(transformation(extent={{120,-30},{140,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat3 + "Maintain ON signal when the chiller head pressure control has been disabled" + annotation (Placement(transformation(extent={{100,-90},{120,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 + "Check if the disabled chiller is not requiring chilled water" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 + "Check if the disabled chiller is not requiring condenser water" + annotation (Placement(transformation(extent={{-120,-80},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{-80,18},{-60,38}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and" + annotation (Placement(transformation(extent={{-78,-80},{-58,-60}}))); + Buildings.Controls.OBC.CDL.Integers.LessEqualThreshold intLesEquThr( + final t=nChi) "Check if index is in the range" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold intGreEquThr( + final t=1) "Check if index is in the range" + annotation (Placement(transformation(extent={{0,140},{20,160}}))); + Buildings.Controls.OBC.CDL.Logical.And and2 "Check if index is in the range" + annotation (Placement(transformation(extent={{40,140},{60,160}}))); + Buildings.Controls.OBC.CDL.Integers.Switch intSwi "Valid index" + annotation (Placement(transformation(extent={{100,110},{120,130}}))); + 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={{40,90},{60,110}}))); +equation + connect(uOnOff, not2.u) + annotation (Line(points={{-220,110},{-162,110}}, color={255,0,255})); + connect(nexDisChi, disChiIsoVal.nexChaChi) + annotation (Line(points={{-220,70},{-180,70},{-180,-2},{58,-2}}, + color={255,127,0})); + connect(uChiWatIsoVal,disChiIsoVal. uChiWatIsoVal) + annotation (Line(points={{-220,-10},{50,-10},{50,-5},{58,-5}}, + color={0,0,127})); + connect(and4.y,disChiIsoVal.uUpsDevSta) + annotation (Line(points={{22,40},{30,40},{30,-15},{58,-15}}, color={255,0,255})); + connect(con2.y,disChiIsoVal. chaPro) + annotation (Line(points={{-58,-40},{10,-40},{10,-18},{58,-18}}, + color={255,0,255})); + connect(con2.y, disHeaCon.chaPro) + annotation (Line(points={{-58,-40},{10,-40},{10,-70},{38,-70}}, color={255,0,255})); + connect(and5.y, disHeaCon.uUpsDevSta) + annotation (Line(points={{2,-70},{20,-70},{20,-66},{38,-66}}, + color={255,0,255})); + connect(nexDisChi, disHeaCon.nexChaChi) + annotation (Line(points={{-220,70},{-180,70},{-180,-90},{20,-90},{20,-74}, + {38,-74}}, color={255,127,0})); + connect(disHeaCon.uChiHeaCon, uChiHeaCon) + annotation (Line(points={{38,-78},{30,-78},{30,-100},{-220,-100}}, + color={255,0,255})); + connect(con3.y, minChiWatSet.uStaDow) + annotation (Line(points={{-138,-150},{-20,-150},{-20,-139},{38,-139}}, + color={255,0,255})); + connect(con2.y, minBypSet.chaPro) + annotation (Line(points={{-58,-40},{10,-40},{10,-176},{38,-176}}, + color={255,0,255})); + connect(minBypSet.VChiWat_flow, VChiWat_flow) + annotation (Line(points={{38,-184},{-20,-184},{-20,-170},{-220,-170}}, + color={0,0,127})); + connect(not2.y, booRep4.u) + annotation (Line(points={{-138,110},{-130,110},{-130,60},{-82,60}}, + color={255,0,255})); + connect(uChiHeaCon, logSwi3.u1) + annotation (Line(points={{-220,-100},{130,-100},{130,-42},{158,-42}}, + color={255,0,255})); + connect(disHeaCon.yChiHeaCon, logSwi3.u3) + annotation (Line(points={{62,-76},{80,-76},{80,-58},{158,-58}}, + color={255,0,255})); + connect(logSwi3.y, yChiHeaCon) + annotation (Line(points={{182,-50},{220,-50}}, color={255,0,255})); + connect(booRep4.y, logSwi3.u2) + annotation (Line(points={{-58,60},{40,60},{40,-50},{158,-50}}, + color={255,0,255})); + connect(booRep4.y, chiWatIso.u2) + annotation (Line(points={{-58,60},{158,60}}, color={255,0,255})); + connect(uChiWatIsoVal, chiWatIso.u1) + annotation (Line(points={{-220,-10},{50,-10},{50,68},{158,68}}, + color={0,0,127})); + connect(disChiIsoVal.yChiWatIsoVal, chiWatIso.u3) + annotation (Line(points={{82,-16},{90,-16},{90,52},{158,52}}, + color={0,0,127})); + connect(chiWatIso.y, yChiWatIsoVal) + annotation (Line(points={{182,60},{220,60}}, color={0,0,127})); + connect(not2.y, logSwi4.u2) + annotation (Line(points={{-138,110},{-130,110},{-130,-160},{158,-160}}, + color={255,0,255})); + connect(con2.y, logSwi4.u1) + annotation (Line(points={{-58,-40},{10,-40},{10,-152},{158,-152}}, + color={255,0,255})); + connect(minBypSet.yMinBypRes, logSwi4.u3) + annotation (Line(points={{62,-180},{120,-180},{120,-168},{158,-168}}, + color={255,0,255})); + connect(not2.y, chiWatByp.u2) + annotation (Line(points={{-138,110},{-130,110},{-130,-110},{158,-110}}, + color={255,0,255})); + connect(chiWatByp.y,yChiWatMinSet) + annotation (Line(points={{182,-110},{220,-110}}, color={0,0,127})); + connect(not2.y, logSwi5.u2) + annotation (Line(points={{-138,110},{-130,110},{-130,-230},{58,-230}}, + color={255,0,255})); + connect(logSwi4.y, logSwi5.u3) + annotation (Line(points={{182,-160},{190,-160},{190,-210},{40,-210}, + {40,-238},{58,-238}}, color={255,0,255})); + connect(logSwi5.y, yEndSta) + annotation (Line(points={{82,-230},{100,-230},{100,-190},{220,-190}}, + color={255,0,255})); + connect(nexEnaChi, enaChi.nexEnaChi) + annotation (Line(points={{-220,240},{-126,240},{-126,199},{-102,199}}, + color={255,127,0})); + connect(uStaUp, enaChi.uStaUp) + annotation (Line(points={{-220,210},{-140,210},{-140,196},{-102,196}}, + color={255,0,255})); + connect(uEnaChiWatIsoVal, enaChi.uEnaChiWatIsoVal) + annotation (Line(points={{-220,180},{-160,180},{-160,192},{-102,192}}, + color={255,0,255})); + connect(uChi, enaChi.uChi) + annotation (Line(points={{-220,150},{-140,150},{-140,188},{-102,188}}, + color={255,0,255})); + connect(uOnOff, enaChi.uOnOff) + annotation (Line(points={{-220,110},{-190,110},{-190,184},{-102,184}}, + color={255,0,255})); + connect(nexDisChi, enaChi.nexDisChi) + annotation (Line(points={{-220,70},{-110,70},{-110,181},{-102,181}}, + color={255,127,0})); + connect(enaChi.yChi, yChi) + annotation (Line(points={{-78,198},{-40,198},{-40,220},{220,220}}, + color={255,0,255})); + connect(uChi, minChiWatSet.uChi) + annotation (Line(points={{-220,150},{-170,150},{-170,-126},{38,-126}}, + color={255,0,255})); + connect(nexDisChi, minChiWatSet.nexDisChi) + annotation (Line(points={{-220,70},{-180,70},{-180,-131},{38,-131}}, + color={255,127,0})); + connect(uOnOff, minChiWatSet.uOnOff) + annotation (Line(points={{-220,110},{-190,110},{-190,-137},{38,-137}}, + color={255,0,255})); + connect(minChiWatSet.yChiWatMinFloSet, minBypSet.VMinChiWat_setpoint) + annotation (Line(points={{62,-130},{70,-130},{70,-146},{30,-146},{30,-188}, + {38,-188}}, color={0,0,127})); + connect(con3.y, minChiWatSet.uUpsDevSta) + annotation (Line(points={{-138,-150},{-20,-150},{-20,-123},{38,-123}}, + color={255,0,255})); + connect(minChiWatSet.yChiWatMinFloSet, chiWatByp1.u1) + annotation (Line(points={{62,-130},{70,-130},{70,-122},{98,-122}}, + color={0,0,127})); + connect(VMinChiWat_setpoint, chiWatByp1.u3) + annotation (Line(points={{-220,-200},{80,-200},{80,-138},{98,-138}}, + color={0,0,127})); + connect(VMinChiWat_setpoint, chiWatByp.u1) + annotation (Line(points={{-220,-200},{140,-200},{140,-102},{158,-102}}, + color={0,0,127})); + connect(chiWatByp1.y, chiWatByp.u3) + annotation (Line(points={{122,-130},{150,-130},{150,-118},{158,-118}}, + color={0,0,127})); + connect(nexEnaChi, minChiWatSet.nexEnaChi) + annotation (Line(points={{-220,240},{-126,240},{-126,-129},{38,-129}}, + color={255,127,0})); + connect(enaChi.yNewChiEna, lat1.u) + annotation (Line(points={{-78,182},{-70,182},{-70,170},{-62,170}}, + color={255,0,255})); + connect(lat1.y, and4.u1) + annotation (Line(points={{-38,170},{-30,170},{-30,40},{-2,40}}, + color={255,0,255})); + connect(lat1.y, minChiWatSet.uStaUp) + annotation (Line(points={{-38,170},{-30,170},{-30,-121},{38,-121}}, + color={255,0,255})); + connect(lat1.y, logSwi5.u1) + annotation (Line(points={{-38,170},{-30,170},{-30,-222},{58,-222}}, + color={255,0,255})); + connect(logSwi5.y, pre.u) + annotation (Line(points={{82,-230},{118,-230}}, color={255,0,255})); + connect(pre.y, edg1.u) + annotation (Line(points={{142,-230},{158,-230}}, color={255,0,255})); + connect(edg1.y, endStaTri) + annotation (Line(points={{182,-230},{220,-230}}, color={255,0,255})); + connect(edg1.y, lat1.clr) + annotation (Line(points={{182,-230},{190,-230},{190,-210},{-50,-210},{-50,140}, + {-70,140},{-70,164},{-62,164}}, color={255,0,255})); + connect(disChiIsoVal.yEnaChiWatIsoVal, lat2.u) + annotation (Line(points={{82,-4},{100,-4},{100,-20},{118,-20}}, + color={255,0,255})); + connect(lat2.y, and5.u2) + annotation (Line(points={{142,-20},{160,-20},{160,-34},{-40,-34},{-40,-78}, + {-22,-78}}, color={255,0,255})); + connect(edg1.y, lat2.clr) + annotation (Line(points={{182,-230},{190,-230},{190,-250},{-50,-250}, + {-50,-26},{118,-26}}, color={255,0,255})); + connect(disHeaCon.yEnaHeaCon, lat3.u) + annotation (Line(points={{62,-64},{90,-64},{90,-80},{98,-80}}, color={255,0,255})); + connect(lat3.y, chiWatByp1.u2) + annotation (Line(points={{122,-80},{140,-80},{140,-94},{80,-94},{80,-130}, + {98,-130}}, color={255,0,255})); + connect(lat3.y, minChiWatSet.uSubCha) + annotation (Line(points={{122,-80},{140,-80},{140,-94},{20,-94},{20,-134}, + {38,-134}}, color={255,0,255})); + connect(lat3.y, minBypSet.uUpsDevSta) + annotation (Line(points={{122,-80},{140,-80},{140,-94},{20,-94},{20,-172}, + {38,-172}}, color={255,0,255})); + connect(edg1.y, lat3.clr) + annotation (Line(points={{182,-230},{190,-230},{190,-250},{-50,-250}, + {-50,-86},{98,-86}}, color={255,0,255})); + connect(con3.y, disHeaCon.uEnaPla) + annotation (Line(points={{-138,-150},{16,-150},{16,-62},{38,-62}}, + color={255,0,255})); + connect(uChiWatReq, curDisChi.u) + annotation (Line(points={{-220,20},{-162,20}}, color={255,0,255})); + connect(uConWatReq, curDisChi1.u) + annotation (Line(points={{-220,-70},{-162,-70}}, color={255,0,255})); + connect(curDisChi.y, not1.u) + annotation (Line(points={{-138,20},{-122,20}}, color={255,0,255})); + connect(curDisChi1.y, not3.u) + annotation (Line(points={{-138,-70},{-122,-70}}, color={255,0,255})); + connect(nexDisChi, intLesEquThr.u) annotation (Line(points={{-220,70},{-110,70}, + {-110,100},{-2,100}}, color={255,127,0})); + connect(nexDisChi, intGreEquThr.u) annotation (Line(points={{-220,70},{-110,70}, + {-110,150},{-2,150}}, color={255,127,0})); + connect(intGreEquThr.y, and2.u1) + annotation (Line(points={{22,150},{38,150}}, color={255,0,255})); + connect(intLesEquThr.y, and2.u2) annotation (Line(points={{22,100},{30,100},{30, + 142},{38,142}}, color={255,0,255})); + connect(and2.y, intSwi.u2) annotation (Line(points={{62,150},{80,150},{80,120}, + {98,120}}, color={255,0,255})); + connect(nexDisChi, intSwi.u1) annotation (Line(points={{-220,70},{-110,70},{-110, + 128},{98,128}}, color={255,127,0})); + connect(conInt.y, intSwi.u3) annotation (Line(points={{62,100},{90,100},{90,112}, + {98,112}}, color={255,127,0})); + connect(intSwi.y, curDisChi.index) annotation (Line(points={{122,120},{130,120}, + {130,80},{-176,80},{-176,4},{-150,4},{-150,8}}, color={255,127,0})); + connect(intSwi.y, curDisChi1.index) annotation (Line(points={{122,120},{130,120}, + {130,80},{-176,80},{-176,-86},{-150,-86},{-150,-82}}, color={255,127,0})); + connect(not1.y, and1.u2) + annotation (Line(points={{-98,20},{-82,20}}, color={255,0,255})); + connect(and1.y, and4.u2) annotation (Line(points={{-58,28},{-40,28},{-40,32},{ + -2,32}}, color={255,0,255})); + connect(not3.y, and3.u1) + annotation (Line(points={{-98,-70},{-80,-70}}, color={255,0,255})); + connect(and3.y, and5.u1) + annotation (Line(points={{-56,-70},{-22,-70}}, color={255,0,255})); + connect(and2.y, and1.u1) annotation (Line(points={{62,150},{80,150},{80,120},{ + -90,120},{-90,28},{-82,28}}, color={255,0,255})); + connect(and2.y, and3.u2) annotation (Line(points={{62,150},{80,150},{80,120},{ + -90,120},{-90,-78},{-80,-78}}, color={255,0,255})); +annotation ( + defaultComponentName="endUp", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-200,-260},{200,260}}), graphics={ + Rectangle( + extent={{-198,38},{198,-38}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{52,32},{194,24}}, + 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={{-198,-62},{198,-98}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{76,-64},{192,-72}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Disable head +pressure control"), + Rectangle( + extent={{-198,-102},{198,-198}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-182,-166},{-66,-174}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Reset minimum +bypass setpoint"), + Rectangle( + extent={{-198,-202},{198,-258}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{-168,-212},{-52,-220}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="End stage-up process"), + Rectangle( + extent={{-198,238},{198,62}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{48,198},{190,190}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Right, + textString="Enable next chiller")}), + 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,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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, +2020), section 5.2.4.16, item 6 and 7. 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.Subsequences.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..6638a9111ee --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/CHWIsoVal.mo @@ -0,0 +1,137 @@ +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.Continuous.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.Continuous.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.Continuous.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},{-102,14}}, + 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.chaPro) + 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,5},{-70,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,16}, + {-102,16}}, 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},{118,4}}, color={0,0,127})); + connect(disChiIsoVal.yChiWatIsoVal[2], zerOrdHol1.u) + annotation (Line(points={{142,-5},{150,-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,6},{118,6}}, + 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.chaPro) + 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. +

+", 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..b53a0a150a5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DisableChiller.mo @@ -0,0 +1,169 @@ +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,76.6667},{-82,76.6667}}, + 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, + 81.3333},{-50,81.3333},{-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,79.3333},{-82,79.3333}}, 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,76.6667},{100,76.6667}}, + 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, + 81.3333},{132,81.3333},{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,79.3333},{100,79.3333}}, 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. +

+", 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..6545623383b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithOn.mo @@ -0,0 +1,313 @@ +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.Continuous.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{-100,-250},{-80,-230}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zerLoa( + final k=0) "Zero load" + annotation (Placement(transformation(extent={{-180,100},{-160,120}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant chiFlo1( + final k=2) "Chilled water flow" + annotation (Placement(transformation(extent={{-180,10},{-160,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant nexDisChi1( + final k=2) "Next disable chiller" + annotation (Placement(transformation(extent={{-180,-230},{-160,-210}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch chiOneLoa "Chiller one" + annotation (Placement(transformation(extent={{-100,100},{-80,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiLoa2( + final k=1000) "Chiller load" + annotation (Placement(transformation(extent={{-180,60},{-160,80}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant nexEnaChi3( + final k=1) "Next enable chiller" + annotation (Placement(transformation(extent={{-180,-70},{-160,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer4(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-180,-110},{-160,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant fulOpe( + final k=1) "Full open" + annotation (Placement(transformation(extent={{-180,-190},{-160,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zerOpe( + final k=0) "Zero open" + annotation (Placement(transformation(extent={{-180,-150},{-160,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch chiIsoVal2 + "Chilled water isolation valve one" + annotation (Placement(transformation(extent={{-100,-190},{-80,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch chiLoa1[2] "Chiller load" + annotation (Placement(transformation(extent={{120,150},{140,170}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer3[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{60,100},{80,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiLoa3(final k=1000) + "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.Continuous.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}}))); + +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(chiFlo1.y, staStaDow1.VChiWat_flow) + annotation (Line(points={{-158,20},{-44,20},{-44,142},{-2,142}}, + color={0,0,127})); + 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})); + +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. +

+", 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..de27a5b8e70 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/DownStartWithoutOn.mo @@ -0,0 +1,191 @@ +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.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-40,-250},{-20,-230}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant nexDisChi( + final k=2) "Next disable chiller" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-120,-270},{-100,-250}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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. +

+", 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..5a3a7d71b05 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableCWPump.mo @@ -0,0 +1,138 @@ +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.Continuous.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.Continuous.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.Continuous.Sources.Constant staTwo( + final k=2) "Chiller stage index" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.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. +

+", 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..a21807c7a15 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/EnableChiller.mo @@ -0,0 +1,150 @@ +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,76.6667},{-82,76.6667}}, + 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, + 89.3333},{-50,89.3333},{-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,79.3333},{-82,79.3333}}, 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,76.6667},{98,76.6667}}, + 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, + 89.3333},{130,89.3333},{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,79.3333},{98,79.3333}}, 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. +

+", 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..72853057dd8 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/HeadControl.mo @@ -0,0 +1,282 @@ +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.chaPro) + 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.chaPro) + 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.chaPro) + 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.chaPro) + 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. +

+", 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..7fee2337864 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/NextChiller.mo @@ -0,0 +1,376 @@ +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}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta( + final k=2) "Stage two" + annotation (Placement(transformation(extent={{-260,230},{-240,250}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-260,190},{-240,210}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-180,210},{-160,230}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet + "Stage setpoint index" + annotation (Placement(transformation(extent={{-140,210},{-120,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 notIn( + final k=false) "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.Continuous.Sources.Constant upSta1( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{40,230},{60,250}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta1( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{40,190},{60,210}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{120,210},{140,230}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet1 + "Stage setpoint index" + annotation (Placement(transformation(extent={{160,210},{180,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 notIn1( + final k=false) "Not in the process" + 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.Continuous.Sources.Constant upSta2( + final k=2) "Stage two" + annotation (Placement(transformation(extent={{-260,-130},{-240,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta2( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-260,-90},{-240,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-180,-110},{-160,-90}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet2 + "Stage setpoint index" + annotation (Placement(transformation(extent={{-140,-110},{-120,-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 notIn2( + final k=false) "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.Continuous.Sources.Constant upSta3( + final k=2) "Stage two" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta3( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger staSet3 "Stage setpoint index" + annotation (Placement(transformation(extent={{160,-110},{180,-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 notIn3( + final k=false) "Not in the process" + annotation (Placement(transformation(extent={{80,-310},{100,-290}}))); + +equation + connect(booPul.y, staUp.u) + annotation (Line(points={{-238,160},{-222,160}}, color={255,0,255})); + connect(staUp.y, swi.u2) + annotation (Line(points={{-198,160},{-190,160},{-190,220},{-182,220}}, + color={255,0,255})); + connect(dowSta.y, swi.u3) + annotation (Line(points={{-238,200},{-220,200},{-220,212},{-182,212}}, + color={0,0,127})); + connect(upSta.y, swi.u1) + annotation (Line(points={{-238,240},{-220,240},{-220,228},{-182,228}}, + color={0,0,127})); + connect(swi.y, staSet.u) + annotation (Line(points={{-158,220},{-142,220}}, color={0,0,127})); + 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(booPul4.y, inPro.u1) annotation (Line(points={{-238,40},{-220,40},{-220, + 48},{-142,48}}, color={255,0,255})); + connect(notIn.y, inPro.u3) annotation (Line(points={{-198,20},{-160,20},{-160, + 32},{-142,32},{-142,32}}, color={255,0,255})); + connect(staSet.y, nexChi.uStaSet) annotation (Line(points={{-118,220},{-80,220}, + {-80,187},{-62,187}}, color={255,127,0})); + connect(chiSet.y, nexChi.uChiSet) annotation (Line(points={{-118,100},{-100,100}, + {-100,180},{-62,180}}, color={255,0,255})); + connect(inPro.y, nexChi.chaPro) 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, swi1.u2) annotation (Line(points={{102,160},{110,160},{110,220}, + {118,220}}, color={255,0,255})); + connect(dowSta1.y, swi1.u3) annotation (Line(points={{62,200},{80,200},{80,212}, + {118,212}}, color={0,0,127})); + connect(upSta1.y, swi1.u1) annotation (Line(points={{62,240},{80,240},{80,228}, + {118,228}}, color={0,0,127})); + connect(swi1.y, staSet1.u) + annotation (Line(points={{142,220},{158,220}}, 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(booPul5.y, inPro1.u1) annotation (Line(points={{62,40},{80,40},{80,48}, + {158,48}}, color={255,0,255})); + connect(notIn1.y, inPro1.u3) annotation (Line(points={{102,20},{140,20},{140,32}, + {158,32}}, color={255,0,255})); + connect(staSet1.y, nexChi1.uStaSet) annotation (Line(points={{182,220},{220,220}, + {220,187},{238,187}}, color={255,127,0})); + connect(chiSet1.y, nexChi1.uChiSet) annotation (Line(points={{182,100},{200,100}, + {200,180},{238,180}}, color={255,0,255})); + connect(inPro1.y, nexChi1.chaPro) 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, swi2.u2) annotation (Line(points={{-198,-160},{-190,-160},{-190, + -100},{-182,-100}}, color={255,0,255})); + connect(swi2.y, staSet2.u) + annotation (Line(points={{-158,-100},{-142,-100}}, color={0,0,127})); + 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(booPul6.y, inPro2.u1) annotation (Line(points={{-238,-280},{-220,-280}, + {-220,-272},{-142,-272}}, color={255,0,255})); + connect(notIn2.y, inPro2.u3) annotation (Line(points={{-198,-300},{-160,-300}, + {-160,-288},{-142,-288}}, color={255,0,255})); + connect(staSet2.y, nexChi2.uStaSet) annotation (Line(points={{-118,-100},{-80, + -100},{-80,-133},{-62,-133}}, color={255,127,0})); + connect(chiSet2.y, nexChi2.uChiSet) annotation (Line(points={{-118,-220},{-100, + -220},{-100,-140},{-62,-140}}, color={255,0,255})); + connect(inPro2.y, nexChi2.chaPro) annotation (Line(points={{-118,-280},{-80,-280}, + {-80,-147},{-62,-147}}, color={255,0,255})); + connect(dowSta2.y, swi2.u1) annotation (Line(points={{-238,-80},{-200,-80},{-200, + -92},{-182,-92}}, color={0,0,127})); + connect(upSta2.y, swi2.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, swi3.u2) annotation (Line(points={{102,-160},{110,-160},{110, + -100},{118,-100}}, color={255,0,255})); + connect(swi3.y, staSet3.u) + annotation (Line(points={{142,-100},{158,-100}}, color={0,0,127})); + 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},{152,-240}, + {152,-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(booPul7.y, inPro3.u1) annotation (Line(points={{62,-280},{80,-280},{80, + -272},{158,-272}}, color={255,0,255})); + connect(notIn3.y, inPro3.u3) annotation (Line(points={{102,-300},{140,-300},{140, + -288},{158,-288}}, color={255,0,255})); + connect(staSet3.y, nexChi3.uStaSet) annotation (Line(points={{182,-100},{220,-100}, + {220,-133},{238,-133}}, color={255,127,0})); + connect(chiSet3.y, nexChi3.uChiSet) annotation (Line(points={{182,-220},{200,-220}, + {200,-140},{238,-140}}, color={255,0,255})); + connect(inPro3.y, nexChi3.chaPro) annotation (Line(points={{182,-280},{220,-280}, + {220,-147},{238,-147}}, color={255,0,255})); + connect(dowSta3.y, swi3.u1) annotation (Line(points={{62,-80},{100,-80},{100,-92}, + {118,-92}}, color={0,0,127})); + connect(upSta3.y, swi3.u3) annotation (Line(points={{62,-120},{100,-120},{100, + -108},{118,-108}}, color={0,0,127})); + +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. +

+", 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..106fc120f2f --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ReduceDemand.mo @@ -0,0 +1,200 @@ +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.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-160,50},{-140,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiLoa( + final k=1000) "Chiller load" + annotation (Placement(transformation(extent={{-260,50},{-240,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zerLoa( + final k=0) "Zero chiller load" + annotation (Placement(transformation(extent={{-260,10},{-240,30}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{140,-50},{160,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiLoa1( + final k=1000) "Chiller load" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.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. +

+", 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..8a6cece67ce --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/ResetMinBypass.mo @@ -0,0 +1,81 @@ +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={{40,38},{60,58}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1( + final width=0.15, + final period=600) "Boolean pulse" + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + Buildings.Controls.OBC.CDL.Logical.Not staUp "Stage up command" + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); + Buildings.Controls.OBC.CDL.Logical.Not upStrDev + "Upstream device reset status" + annotation (Placement(transformation(extent={{-40,40},{-20,60}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.2, + final period=600) "Boolean pulse" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-80},{-20,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-40},{-20,-20}}))); + +equation + connect(booPul2.y, upStrDev.u) + annotation (Line(points={{-58,50},{-42,50}}, color={255,0,255})); + connect(booPul1.y, staUp.u) + annotation (Line(points={{-58,10},{-42,10}}, color={255,0,255})); + connect(upStrDev.y, minBypRes.uUpsDevSta) + annotation (Line(points={{-18,50},{0,50},{0,56},{38,56}}, color={255,0,255})); + connect(staUp.y, minBypRes.chaPro) + annotation (Line(points={{-18,10},{4,10},{4,52},{38,52}}, color={255,0,255})); + connect(meaFlo.y, minBypRes.VChiWat_flow) + annotation (Line(points={{-18,-30},{8,-30},{8,44},{38,44}}, color={0,0,127})); + connect(minFloSet.y, minBypRes.VMinChiWat_setpoint) + annotation (Line(points={{-18,-70},{12,-70},{12,40},{38,40}}, color={0,0,127})); + +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. +

+", 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..ad85965ce79 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithOff.mo @@ -0,0 +1,239 @@ +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.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant nexEnaChi1(final k=2) + "Next enable chiller" + annotation (Placement(transformation(extent={{-180,170},{-160,190}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi3 "Logical switch" + annotation (Placement(transformation(extent={{-100,-20},{-80,0}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer4(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-180,-40},{-160,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant nexDisChi2(final k=1) + "Next disable chiller" + annotation (Placement(transformation(extent={{-180,0},{-160,20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant fulOpe(final k=1) + "Full open" + annotation (Placement(transformation(extent={{-180,-80},{-160,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant chiWatFlo1(final k=1) + "Chilled water flow rate" + annotation (Placement(transformation(extent={{-180,-210},{-160,-190}}))); + Buildings.Controls.OBC.CDL.Continuous.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. +

+", 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..68c3140b735 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Subsequences/Validation/UpEndWithoutOff.mo @@ -0,0 +1,175 @@ +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}}))); + +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.Continuous.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.Continuous.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-60,140},{-40,160}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant nexEnaChi( + final k=2) "Next enable chiller" + annotation (Placement(transformation(extent={{-140,160},{-120,180}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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})); + +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. +

+", 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..4266d7d90f5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Up.mo @@ -0,0 +1,899 @@ +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]( + unit="m3/s", + displayUnit="m3/s")={0.0089,0.0089} + "Minimum chilled water flow through each chiller" + annotation (Dialog(group="Reset CHW minimum flow setpoint")); + parameter Real maxFloSet[nChi]( + unit="m3/s", + displayUnit="m3/s")={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,100},{-240,140}}), + 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 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,170},{280,210}}), + 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,90},{280,130}}), + 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,-290},{280,-250}}), + 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,160},{-60,180}}))); + 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.Continuous.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.Continuous.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.Continuous.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={{100,60},{120,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,140},{0,160}}))); + 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,230},{-20,250}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.ModelTime modTim + "Simulation time" + annotation (Placement(transformation(extent={{-200,220},{-180,240}}))); + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr(final t=1) + "Check if it has passed initial time" + annotation (Placement(transformation(extent={{-140,220},{-120,240}}))); + 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}}))); + +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},{-180,125},{-180,120},{-260,120}}, + 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.chaPro) + 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,76},{-156,76},{-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.chaPro) + annotation (Line(points={{-118,150},{-100,150},{-100,-140},{58,-140}}, + color={255,0,255})); + connect(nexChi.yNexEnaChi, enaHeaCon.nexChaChi) + annotation (Line(points={{-58,179},{-36,179},{-36,-144},{58,-144}}, + color={255,127,0})); + connect(nexChi.yNexEnaChi, enaChiIsoVal.nexChaChi) + annotation (Line(points={{-58,179},{-36,179},{-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.chaPro) + annotation (Line(points={{-118,150},{-100,150},{-100,-208},{58,-208}}, + color={255,0,255})); + connect(nexChi.yNexEnaChi, endUp.nexEnaChi) + annotation (Line(points={{-58,179},{-36,179},{-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},{100,124},{100,110},{260,110}}, + 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,-270},{260,-270}}, + 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,174},{-40,174},{-40,-268},{18,-268}}, + color={255,127,0})); + connect(nexChi.yOnOff, minChiWatFlo.uOnOff) + annotation (Line(points={{-58,170},{-44,170},{-44,33},{18,33}}, + color={255,0,255})); + connect(nexChi.yOnOff, endUp.uOnOff) + annotation (Line(points={{-58,170},{-44,170},{-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,190},{260,190}}, + 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,179},{-36,179},{-36,41},{18,41}}, + color={255,127,0})); + connect(nexChi.yDisSmaChi, minChiWatFlo.nexDisChi) + annotation (Line(points={{-58,174},{-40,174},{-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,170},{-44,170},{-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,72},{58,72}}, + 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(chiDemRed.yChiDemRed, lat1.u) annotation (Line(points={{-58,116},{-32, + 116},{-32,100},{-22,100}}, color={255,0,255})); + 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(minBypSet.yMinBypRes, lat2.u) annotation (Line(points={{82,80},{90,80}, + {90,70},{98,70}}, color={255,0,255})); + connect(lat2.y, yTowStaUp) annotation (Line(points={{122,70},{140,70},{140,0}, + {260,0}}, color={255,0,255})); + connect(lat2.y, enaNexCWP.uUpsDevSta) annotation (Line(points={{122,70},{140,70}, + {140,14},{-20,14},{-20,-2},{-2,-2}}, color={255,0,255})); + connect(lat2.y, and2.u2) annotation (Line(points={{122,70},{140,70},{140,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,-242},{0,-242},{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},{98,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,177},{-82,177}}, color={255,127,0})); + connect(lat.y, nexChi.chaPro) annotation (Line(points={{-118,150},{-100,150},{ + -100,163},{-82,163}}, color={255,0,255})); + connect(nexChi.uChiSet, uChiSet) + annotation (Line(points={{-82,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},{-22,150}}, color={255,0,255})); + connect(con.y, or2.u2) annotation (Line(points={{-178,30},{-96,30},{-96,142},{ + -22,142}}, color={255,0,255})); + connect(or2.y, minBypSet.uUpsDevSta) annotation (Line(points={{2,150},{10,150}, + {10,88},{58,88}}, color={255,0,255})); + connect(or2.y, minChiWatFlo.uUpsDevSta) annotation (Line(points={{2,150},{10,150}, + {10,47},{18,47}}, color={255,0,255})); + connect(modTim.y, greThr.u) + annotation (Line(points={{-178,230},{-142,230}}, color={0,0,127})); + 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(greThr.y, logSwi1.u2) annotation (Line(points={{-118,230},{-80,230},{-80, + 240},{-42,240}}, color={255,0,255})); + connect(and1.y, logSwi1.u3) annotation (Line(points={{-78,300},{-60,300},{-60, + 232},{-42,232}}, color={255,0,255})); + connect(cha.up, logSwi1.u1) annotation (Line(points={{-178,156},{-170,156},{-170, + 248},{-42,248}}, color={255,0,255})); + connect(logSwi1.y, lat.u) annotation (Line(points={{-18,240},{0,240},{0,210},{ + -160,210},{-160,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})); +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,-182},{100,-194}}, + 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")}), +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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.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.Subsequences.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..e43d0137089 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithOnOff.mo @@ -0,0 +1,382 @@ +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.Continuous.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.1, + final period=1500) "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.Continuous.Sources.Constant chiLoa1( + final k=2) "Chiller load" + annotation (Placement(transformation(extent={{-200,-60},{-180,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant fulOpe1(final k=1) + "Full open isolation valve" + annotation (Placement(transformation(extent={{-200,-260},{-180,-240}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch chiOneLoa "Chiller one load" + annotation (Placement(transformation(extent={{-120,-20},{-100,0}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant chiLoa3( + final k=1000) + "Chiller load" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant zerOpe2( + final k=0) "Closed isolation valve" + annotation (Placement(transformation(extent={{-200,-220},{-180,-200}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant upSta2( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,190},{-180,210}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta2( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-200,230},{-180,250}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant staOne( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-200,-140},{-180,-120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staTwo( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,-180},{-180,-160}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{80,180},{100,200}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg + "Check if the down process has ended" + annotation (Placement(transformation(extent={{80,210},{100,230}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "True when it is not in process" + annotation (Placement(transformation(extent={{120,210},{140,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,94},{18,94}}, + color={0,0,127})); + connect(chiOneLoa.y, dowProCon.uChiLoa[1]) + annotation (Line(points={{-98,-10},{-90,-10},{-90,91.5},{18,91.5}}, + color={0,0,127})); + connect(chiTwoLoa.y, dowProCon.uChiLoa[2]) + annotation (Line(points={{-98,-50},{-88,-50},{-88,92.5},{18,92.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(dowProCon.yStaPro, falEdg.u) annotation (Line(points={{42,99},{56,99}, + {56,220},{78,220}}, color={255,0,255})); + connect(falEdg.y, lat.u) + annotation (Line(points={{102,220},{118,220}}, color={255,0,255})); + connect(fal.y, lat.clr) annotation (Line(points={{102,190},{110,190},{110,214}, + {118,214}}, color={255,0,255})); + connect(lat.y, chiSta.u2) annotation (Line(points={{142,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})); + +annotation ( + experiment(StopTime=1500, 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. +

+", 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..88071a5b9ee --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/DownWithoutOnOff.mo @@ -0,0 +1,268 @@ +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.Continuous.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.075, + 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.Continuous.Sources.Constant chiLoa[2]( + final k=fill(2, 2)) + "Chiller load" + annotation (Placement(transformation(extent={{-140,-30},{-120,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-60,200},{-40,220}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta2(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,180},{-120,200}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dowSta2(final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-140,220},{-120,240}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staOne(final k=1) "Stage one" + annotation (Placement(transformation(extent={{-140,-150},{-120,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staTwo(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,-190},{-120,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.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,84},{38,84}}, + 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,82},{38,82}}, + 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. +

+", 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..c4a9b81a3ca --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithOnOff.mo @@ -0,0 +1,344 @@ +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.Continuous.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.Continuous.Sources.Constant fulLoa(final k=2) + "Full load" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Switch loaTwo "Chiller load two" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant chiLoa3( + final k=1000) + "Chiller load" + annotation (Placement(transformation(extent={{80,160},{100,180}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant zerOpe( + final k=0) "Closed isolation valve" + annotation (Placement(transformation(extent={{-200,-270},{-180,-250}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant fulOpe( + final k=1) "Full open isolation valve" + annotation (Placement(transformation(extent={{-200,-230},{-180,-210}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch IsoValOne "Logical switch" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Sources.Constant dowSta( + final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-200,190},{-180,210}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,220},{-180,240}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant staOne( + final k=1) "Stage one" + annotation (Placement(transformation(extent={{-200,-150},{-180,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staTwo( + final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-200,-110},{-180,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.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,80.5},{60, + 80.5},{60,70},{78,70}}, color={255,0,255})); + connect(upProCon.yChi[2], chiTwoSta.u) annotation (Line(points={{42,81.5},{58, + 81.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(chiTwoDem.y, chiLoa[2].u1) annotation (Line(points={{102,140},{120,140}, + {120,148},{138,148}}, 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})); +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. +

+", 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..2298a172f6c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/Processes/Validation/UpWithoutOnOff.mo @@ -0,0 +1,249 @@ +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.Continuous.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.1, + final period=1500) "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.Continuous.Sources.Constant chiLoa[2]( + final k=fill(2, 2)) + "Chiller load" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Switch swi1[2] "Logical switch" + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dowSta(final k=1) + "Stage one" + annotation (Placement(transformation(extent={{-140,170},{-120,190}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant upSta(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,210},{-120,230}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant staOne(final k=1) "Stage one" + annotation (Placement(transformation(extent={{-140,-140},{-120,-120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staTwo(final k=2) + "Stage two" + annotation (Placement(transformation(extent={{-140,-100},{-120,-80}}))); + Buildings.Controls.OBC.CDL.Continuous.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,49},{94,49}, + {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=1500, 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. +

+", 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..86be5a1e1c9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/SetpointController.mo @@ -0,0 +1,839 @@ +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](unit="W", displayUnit="W") + "Design chiller capacities vector" + annotation (Dialog(tab="General", group="Chiller configuration parameters")); + + parameter Real chiMinCap[nChi](unit="W", displayUnit="W") + "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={{-442,-280},{-402,-240}}), + iconTransformation(extent={{-140,170},{-100,210}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChiAva[nChi] + "Chiller availability status vector" + annotation (Placement(transformation(extent={{-442,-220},{-402,-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( + nSta=nSta, + nChi=nChi, + staMat=staMat) "Calculates chiller status setpoint vector" + annotation (Placement(transformation(extent={{40,-240},{60,-220}}))); + + Buildings.Controls.OBC.CDL.Continuous.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={{-422,-200},{-382,-200},{-382,-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},{-422,-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. +

+

+Implemented according to ASHRAE RP-1711 March 2020 Draft, section 5.2.4.1 - 17. +

+

+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..4fbfd41be54 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Capacities.mo @@ -0,0 +1,338 @@ +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,130},{240,170}}), + 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.Continuous.Switch swi2 "Switch" + annotation (Placement(transformation(extent={{160,50},{180,70}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi4 "Switch" + annotation (Placement(transformation(extent={{160,-100},{180,-80}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Multiply mul + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{30,140},{50,160}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply mul1 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,-130},{80,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply mul2 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply mul3 + "Ensure zero output when the index is out of range" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + Buildings.Controls.OBC.CDL.Continuous.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(yMin, yMin) + annotation (Line(points={{220,-20},{220,-20}}, 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},{122,180},{122,150},{220, + 150}}, color={0,0,127})); + connect(yUpMin, yUpMin) + annotation (Line(points={{220,-90},{220,-90}}, 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},{-14,80},{-14, + 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 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. +

+

+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..c57502adb1b --- /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.Continuous.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.Continuous.Sources.Constant density( + final k = rhoWat) + "Water density" + annotation (Placement(transformation(extent={{-120,-110},{-100,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant speHeaCap( + final k = cpWat) + "Specific heat capacity of water" + annotation (Placement(transformation(extent={{-120,-160},{-100,-140}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minLim( + final k=0) + "Minimum capacity requirement limit" + annotation (Placement(transformation(extent={{60,-30},{80,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + "Find input difference" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.MovingAverage movMea( + final delta=avePer) + "Moving average" + annotation (Placement(transformation(extent={{60,-80},{80,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro "Product" + annotation (Placement(transformation(extent={{20,-80},{40,-60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1 "Product" + annotation (Placement(transformation(extent={{-80,-130},{-60,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro2 "Product" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.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 1711 March 2020 Draft, section 5.2.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 1711 March 2020 Draft, section 5.2.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..b9af35363ec --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Change.mo @@ -0,0 +1,474 @@ +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}}))); + + CDL.Conversions.BooleanToInteger booToInt + "Convert boolean input to integer output" + annotation (Placement(transformation(extent={{-120,140},{-100,160}}))); + CDL.Integers.Multiply mulInt "Stage zero when the plant is not enabled" + annotation (Placement(transformation(extent={{240,160},{260,180}}))); +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.Continuous.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.Continuous.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.Edge edg2 + "Boolean signal change" + annotation (Placement(transformation(extent={{-40,-180},{-20,-160}}))); + + 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.Logical.Pre pre "Previous value" + annotation (Placement(transformation(extent={{0,-240},{20,-220}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.And3 and6 "Logical not" + annotation (Placement(transformation(extent={{-200,-90},{-180,-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=0, + final falseHoldDuration=delayStaCha) + "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.Logical.Pre pre1 "Previous value" + annotation (Placement(transformation(extent={{400,-260},{420,-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.Continuous.Sources.ModelTime modTim + "Simulation time" + annotation (Placement(transformation(extent={{182,-220},{202,-200}}))); + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr(final t=1) + "Check if it has passed initial time" + annotation (Placement(transformation(extent={{240,-220},{260,-200}}))); + 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}}))); +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(and2.y,or1. u2) annotation (Line(points={{22,-130},{30,-130},{30,-58}, + {38,-58}}, color={255,0,255})); + connect(tim.y,lesEquThr. u) annotation (Line(points={{-58,-230},{-42,-230}}, + color={0,0,127})); + connect(lesEquThr.y,pre. u) annotation (Line(points={{-18,-230},{-2,-230}}, + color={255,0,255})); + connect(pre.y,and1. u2) annotation (Line(points={{22,-230},{40,-230},{40,-260}, + {-160,-260},{-160,-198},{-142,-198}}, 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(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(staChaHol1.y,edg2. u) + annotation (Line(points={{-58,-170},{-42,-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(not3.y, and6.u1) annotation (Line(points={{-238,-60},{-220,-60},{-220, + -72},{-202,-72}}, color={255,0,255})); + connect(or2.y, and6.u2) annotation (Line(points={{-358,-80},{-202,-80}}, + color={255,0,255})); + connect(and6.y, and1.u1) annotation (Line(points={{-178,-80},{-160,-80},{-160, + -190},{-142,-190}}, color={255,0,255})); + connect(and6.y, edg1.u) + annotation (Line(points={{-178,-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},{-160,120},{-160,-80}, + {-178,-80}}, color={255,0,255})); + connect(lat1.y, switch2.u2) annotation (Line(points={{122,200},{158,200}}, + 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, or1.u1) annotation (Line(points={{-58,-80},{0,-80},{0,-50},{38, + -50}}, 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(not1.y, pre1.u) + annotation (Line(points={{394,-250},{398,-250}}, color={255,0,255})); + connect(pre1.y, and6.u3) annotation (Line(points={{422,-250},{430,-250},{430,-280}, + {-280,-280},{-280,-88},{-202,-88}}, + 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(modTim.y,greThr. u) + annotation (Line(points={{204,-210},{238,-210}}, color={0,0,127})); + connect(greThr.y,logSwi1. u2) annotation (Line(points={{262,-210},{340,-210}, + {340,-122},{378,-122}}, + color={255,0,255})); + connect(edg2.y, and2.u2) annotation (Line(points={{-18,-170},{-10,-170},{-10,-138}, + {-2,-138}}, color={255,0,255})); + connect(and6.y, and2.u1) annotation (Line(points={{-178,-80},{-160,-80},{-160, + -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(greThr.y, logSwi2.u2) annotation (Line(points={{262,-210},{340,-210}, + {340,-82},{378,-82}}, color={255,0,255})); + connect(greThr.y, logSwi3.u2) annotation (Line(points={{262,-210},{340,-210}, + {340,-42},{378,-42}}, 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(logSwi2.y, staChaHol3.u) annotation (Line(points={{402,-82},{420,-82}, + {420,-100},{320,-100},{320,-250},{338,-250}}, 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})); + 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 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. +

+

+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 1711 March 2020 Draft 5.2.4.15.1. 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..257e17b7618 --- /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={{-240,0},{-200,40}}), + 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={{200,-20},{240,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={{-180,10},{-160,30}}))); + + 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={{-140,10},{-120,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant staIndMatr[nSta,nChi]( + final k=staIndMat) "Matrix with stage index in each column" + annotation (Placement(transformation(extent={{-140,-40},{-120,-20}}))); + + 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={{-80,10},{-60,30}}))); + + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiStaMatr[nSta,nChi]( + final k=staMat) "Staging matrix" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixMax matMax( + final nRow=nSta, + final nCol=nChi, + final rowMax=false) "Column-wise matrix maximum" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold chiInSta[nChi](t=fill(0.5, nChi)) + "Identifies chillers designated to operate in a given stage" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + + 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={{20,-10},{40,10}}))); + + 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,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea[nSta,nChi] + "Type converter" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + +equation + connect(intRep.y, intRep1.u) + annotation (Line(points={{-158,20},{-142,20}}, color={255,127,0})); + connect(intRep1.y, intEqu1.u1) + annotation (Line(points={{-118,20},{-82,20}}, color={255,127,0})); + connect(matMax.y, chiInSta.u) + annotation (Line(points={{122,0},{138,0}}, color={0,0,127})); + connect(staIndMatr.y, intEqu1.u2) annotation (Line(points={{-118,-30},{-100,-30}, + {-100,12},{-82,12}}, color={255,127,0})); + connect(chiInSta.y, yChi) + annotation (Line(points={{162,0},{220,0}}, + color={255,0,255})); + connect(proInt.y, intToRea.u) + annotation (Line(points={{42,0},{58,0}}, color={255,127,0})); + connect(intToRea.y, matMax.u) + annotation (Line(points={{82,0},{98,0}}, color={0,0,127})); + connect(booToInt.y, proInt.u1) annotation (Line(points={{-18,20},{0,20},{0,6}, + {18,6}}, color={255,127,0})); + connect(intEqu1.y, booToInt.u) + annotation (Line(points={{-58,20},{-42,20}}, color={255,0,255})); + connect(chiStaMatr.y, proInt.u2) annotation (Line(points={{-38,-30},{0,-30},{0, + -6},{18,-6}}, color={255,127,0})); + connect(u, intRep.u) annotation (Line(points={{-220,20},{-182,20}}, + color={255,127,0})); + annotation (defaultComponentName = "chiInd", + 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,-60},{200,60}})), +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 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..c45a0ec4edd --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Configurator.mo @@ -0,0 +1,310 @@ +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.Continuous.Sort sort1( + final nin=nChi) "Ascending sort" + annotation (Placement(transformation(extent={{-140,160},{-120,180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1[nChi] + "Subtracts signals" + annotation (Placement(transformation(extent={{-100,160},{-80,180}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiMax multiMax( + final nin=nChi) "Maximum value in a vector input" + annotation (Placement(transformation(extent={{-60,160},{-40,180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Abs abs "Absolute values" + annotation (Placement(transformation(extent={{-20,160},{0,180}}))); + + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesThr1( + final t=0.5) "Less threshold" + annotation (Placement(transformation(extent={{20,160},{40,180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiDesCaps[nChi]( + final k=chiDesCap) "Design chiller capacities vector" + annotation (Placement(transformation(extent={{-200,100},{-180,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiMinCaps[nChi]( + final k=chiMinCap) "Chiller unload capacities vector" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixGain staDesCaps( + final K=staMat) "Matrix gain for design capacities" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.MatrixGain staMinCaps( + final K=staMat) "Matrix gain from minimal capacities" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant chiStaMat[nSta,nChi]( + final k=staMat) "Staging matrix" + annotation (Placement(transformation(extent={{-200,-170},{-180,-150}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant staType[nSta,nChi]( + final k=chiTypMat) "Chiller stage type matrix" + annotation (Placement(transformation(extent={{-200,-110},{-180,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[nSta,nChi] + "Element-wise product" + annotation (Placement(transformation(extent={{-140,-130},{-120,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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},{-28,-120}, + {-28,-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 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. +

+

+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..06d2c272968 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Down.mo @@ -0,0 +1,333 @@ +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.Continuous.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.And3 and1 if have_WSE + "Or for staging up" + annotation (Placement(transformation(extent={{20,-70},{40,-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.Continuous.Subtract sub1 if have_WSE + "Temperature difference" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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}}))); + +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(uWseSta, and1.u3) annotation (Line(points={{-200,-130},{10,-130},{10, + -68},{18,-68}}, + color={255,0,255})); + connect(hysTSup.y, and1.u1) annotation (Line(points={{-18,-60},{-10,-60},{-10, + -52},{18,-52}}, 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},{0,-100},{0,-60}, + {18,-60}}, 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(and1.y, logSwi.u3) annotation (Line(points={{42,-60},{80,-60},{80,-8}, + {98,-8}}, 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})); + 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 RP1711 March 2020 draft, section 5.2.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..fa0670cea61 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/EfficiencyCondition.mo @@ -0,0 +1,84 @@ +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.Continuous.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.Continuous.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. implemented according to the specification provided in 5.2.4.15., 1711 March 2020 Draft.

+", +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..0c42d577d61 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/FailsafeCondition.mo @@ -0,0 +1,224 @@ +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.Continuous.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.Continuous.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.Continuous.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.Continuous.Subtract sub0 + "Adder for temperatures" + annotation (Placement(transformation(extent={{-100,70},{-80,90}}))); + + Buildings.Controls.OBC.CDL.Continuous.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) + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.2.4.15. 1711 March 2020 Draft. 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..3ce30e39a64 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Initial.mo @@ -0,0 +1,214 @@ +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.Continuous.Sources.Constant staZer( + final k=0) + "Zero stage" + annotation (Placement(transformation(extent={{0,100},{20,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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 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.

+

Determines the initial stage upon plant startup for both plants with and without a WSE. Implemented according to section 5.2.4.15. 1711 March 2020 Draft, under 8. (primary-only) and 15. (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..713aa0eeb4b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/PartLoadRatios.mo @@ -0,0 +1,711 @@ +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.Continuous.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.Continuous.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.Continuous.Sources.Constant posDisTypMult( + final k=posDisMult) + "Positive displacement chiller type SPLR multiplier" + annotation (Placement(transformation(extent={{-140,-120},{-120,-100}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{160,60},{180,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{100,-190},{120,-170}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Divide minOpePlrUp + "Calculates minimum OPLR of one stage up" + annotation (Placement(transformation(extent={{-200,-200},{-180,-180}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide opePlrUp + "Calculates operating part load ratio at the next stage up" + annotation (Placement(transformation(extent={{-200,-150},{-180,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant const( + final k=0.9) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{-200,-360},{-180,-340}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + if anyVsdCen "Subtract" + annotation (Placement(transformation(extent={{-80,-420},{-60,-400}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide div if anyVsdCen + "Division" + annotation (Placement(transformation(extent={{-20,-370},{0,-350}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant const1( + final k=0.4) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{-200,-480},{-180,-460}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant const2( + final k=1.4) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{-200,-560},{-180,-540}}))); + + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + if anyVsdCen "Subtract" + annotation (Placement(transformation(extent={{-80,-500},{-60,-480}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply mult0 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{-140,-460},{-120,-440}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply mult1 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{-140,-540},{-120,-520}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply mult2 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{40,-440},{60,-420}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply mult3 if anyVsdCen "Multiplier" + annotation (Placement(transformation(extent={{100,-510},{120,-490}}))); + + Buildings.Controls.OBC.CDL.Continuous.Add add3 if anyVsdCen "Add" + annotation (Placement(transformation(extent={{160,-482},{180,-462}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant const3( + final k=-1) if not anyVsdCen + "Constant" + annotation (Placement(transformation(extent={{100,20},{120,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.GreaterThreshold greThr( + final t=-0.5) + "Less than threshold" + annotation (Placement(transformation(extent={{260,200},{280,220}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr1( + final t=-0.5) "Less than threshold" + annotation (Placement(transformation(extent={{200,-110},{220,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Divide opePlrDow + "Calculates operating part load ratio of the next stage down" + annotation (Placement(transformation(extent={{-200,-90},{-180,-70}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi4 "Switch" + annotation (Placement(transformation(extent={{160,-170},{180,-150}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Max max if anyVsdCen "Maximum" + annotation (Placement(transformation(extent={{220,-420},{240,-400}}))); + + Buildings.Controls.OBC.CDL.Continuous.Min min if anyVsdCen "Minimum" + annotation (Placement(transformation(extent={{260,-380},{280,-360}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant maxLim( + final k=varSpeStaMax) if anyVsdCen "Constant" + annotation (Placement(transformation(extent={{160,-360},{180,-340}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Switch swi5 + "Logical switch" + annotation (Placement(transformation(extent={{320,220},{340,240}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi6 + "Logical switch" + annotation (Placement(transformation(extent={{260,-110},{280,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant smaNum( + final k=small) "Small constant" + annotation (Placement(transformation(extent={{-360,-54},{-340,-34}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max1 + "Maximum output to avoid zero denominator in downstream" + annotation (Placement(transformation(extent={{-300,-60},{-280,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max2 + "Maximum output to avoid zero denominator in downstream" + annotation (Placement(transformation(extent={{-300,-110},{-280,-90}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max3 + "Maximum output to avoid zero denominator in downstream" + annotation (Placement(transformation(extent={{-300,-170},{-280,-150}}))); + + Buildings.Controls.OBC.CDL.Continuous.MovingAverage movMea( + final delta=avePer) if anyVsdCen + 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.2.4.5., 9., 10. and stage part load ratios (SPLR, up or down) per section 5.2.4.5.13 (July Draft).

+

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 Type

Any Constant Speed Centrifugal

All Positive Displacement

Any Variable Speed and no Constant Speed Centrifugal

Next Available Up

yStaUp=conSpeCenMult

N/A

N/A

Current

yStaDown=conSpeCenMult

yStaUp=posDisMult

yStaUp=f(uLif, uLifMin, uLifMax)

Next Available Down

N/A

yStaDown=posDisMult

yStaDown=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..eac9c9a93c1 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Status.mo @@ -0,0 +1,354 @@ +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.Continuous.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.Continuous.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(yAvaUp, yAvaUp) + annotation (Line(points={{460,80},{460,80}}, color={255,127,0})); + 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 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.

+

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

+ +

The purpose of this sequence is to:

+ +

The sequences are implemented according to 1711 March 2020 Draft, section 5.2.4.15.

+", +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..ce0d2696757 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Up.mo @@ -0,0 +1,378 @@ +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.Or3 orStaUp "Or for staging up" + annotation (Placement(transformation(extent={{-20,110},{0,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.Continuous.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.Continuous.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,-50},{-40,-30}}))); + + 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.Continuous.Subtract sub1 if have_WSE + "Temperature difference" + annotation (Placement(transformation(extent={{-110,-40},{-90,-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,-50},{0,-30}}))); + + 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.Edge edg "Rising edge" + annotation (Placement(transformation(extent={{-20,-190},{0,-170}}))); + + 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(effCon.y, orStaUp.u1) annotation (Line(points={{-78,180},{-40,180},{-40, + 128},{-22,128}}, color={255,0,255})); + connect(faiSafCon.y, orStaUp.u2) annotation (Line(points={{-78,100},{-50,100}, + {-50,120},{-22,120}}, color={255,0,255})); + 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={{2,120},{10,120},{10,88}, + {78,88}}, color={255,0,255})); + connect(sub1.y, hysTSup1.u) + annotation (Line(points={{-88,-30},{-80,-30},{-80,-40},{-62,-40}}, 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,-40},{-22,-40}}, 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,-40},{10,-40},{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={{-88,-30},{-80,-30},{-80,0}, + {-62,0}}, color={0,0,127})); + connect(TChiWatSup, sub1.u1) annotation (Line(points={{-180,-70},{-130,-70},{-130, + -24},{-112,-24}}, color={0,0,127})); + connect(TChiWatSupSet, sub1.u2) annotation (Line(points={{-180,-30},{-140,-30}, + {-140,-36},{-112,-36}}, color={0,0,127})); + connect(uAvaCur, not1.u) + annotation (Line(points={{-180,20},{-122,20}}, color={255,0,255})); + connect(not1.y, orStaUp.u3) annotation (Line(points={{-98,20},{-40,20},{-40,112}, + {-22,112}}, 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(edg.y, lat.u) + annotation (Line(points={{2,-180},{38,-180}}, color={255,0,255})); + 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(uPla, edg.u) + annotation (Line(points={{-180,-180},{-22,-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. +Implemented according to 1711 March 2020 Draft, section 5.2.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.EnableWithChiller. +

+", +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..939ff7af312 --- /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.Continuous.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.Continuous.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.Generic.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..a99ea42f0f9 --- /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.Continuous.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.Continuous.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.Generic.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..5f37688752f --- /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.Continuous.Sources.Constant TCWSupSet( + final k=TChiWatSupSet) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,10},{-120,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Constant TCWSupSet1( + final k=TChiWatSupSet) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Constant TCWSupSet2( + final k= TChiWatSupSet) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Generic.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..98b60d681a9 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/Subsequences/Validation/Change.mo @@ -0,0 +1,343 @@ +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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.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={{160,-10},{170,-10},{170, + -24},{178,-24}}, color={255,127,0})); + connect(addInt5.y, maxInt2.u1) annotation (Line(points={{160,-190},{170,-190}, + {170,-204},{178,-204}}, color={255,127,0})); + connect(addInt1.y, maxInt.u1) annotation (Line(points={{160,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..8a493fe9b0f --- /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.Continuous.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.Continuous.Sources.Constant dpChiWatSet( + final k=65*6895) "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,0},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TCWSup( + final k=273.15 + 14) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-160,-60},{-140,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpChiWat( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-40},{-100,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant splrDown( + final k=0.8) + "Staging down part load ratio" + annotation (Placement(transformation(extent={{-160,100},{-140,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.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.Continuous.Sources.Constant TowFanSpeMax( + final k=0.9) + "Maximum cooling tower speed signal" + annotation (Placement(transformation(extent={{-120,40},{-100,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{60,0},{80,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TCWSup1( + final k=273.15 + 14) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{20,-60},{40,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpChiWat1( + final k=62*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{60,-40},{80,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant TowFanSpeMax1( + final k=0.9) + "Maximum cooling tower speed signal" + annotation (Placement(transformation(extent={{60,40},{80,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.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..9bf2764c19f --- /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.Continuous.Sources.Sine 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.Continuous.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..6ea4de20821 --- /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.Continuous.Sources.Constant TCWSup( + final k=273.15 + 18) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWat( + final k=64.1*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpChiWatSet( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-100,60},{-80,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{60,60},{80,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.Sources.Sine 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..54bb7fe2acb --- /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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Constant tunPar( + final k=0.06) + "Assume a constant tuning parameter" + annotation (Placement(transformation(extent={{-80,40},{-60,60}}))); + + Buildings.Controls.OBC.CDL.Continuous.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..58e36478b89 --- /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.Continuous.Max max "Maximum" + annotation (Placement(transformation(extent={{-340,360},{-320,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max1 "Maximum" + annotation (Placement(transformation(extent={{-120,360},{-100,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max2 "Maximum" + annotation (Placement(transformation(extent={{100,360},{120,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max3 "Maximum" + annotation (Placement(transformation(extent={{340,360},{360,380}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max4 "Maximum" + annotation (Placement(transformation(extent={{-340,0},{-320,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max5 "Maximum" + annotation (Placement(transformation(extent={{-120,0},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Max max6 "Maximum" + annotation (Placement(transformation(extent={{100,0},{120,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Sources.Constant lowLim( + final k=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-420,340},{-400,360}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant capDes[3]( + final k={10e5,15e5,25e5}) + "Stage design capacities" + annotation (Placement(transformation(extent={{-380,300},{-360,320}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Constant lowLim4( + final k=0) + "Capacity requirement" + annotation (Placement(transformation(extent={{-420,-20},{-400,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant capDes1[3]( + final k={10e5,15e5,25e5}) "Stage design capacities" + annotation (Placement(transformation(extent={{-380,-60},{-360,-40}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Constant Lift( + final k=16) "Chiller lift" + annotation (Placement(transformation(extent={{-420,-130},{-400,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant LiftMin( + final k=10) "Minimum chiller lift" + annotation (Placement(transformation(extent={{-420,-220},{-400,-200}}))); + + Buildings.Controls.OBC.CDL.Continuous.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..7869dd85989 --- /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.Generic.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..b4e8258a7ee --- /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.Continuous.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.Continuous.Sources.Constant dpChiWatSet( + final k=65*6895) "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.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.Continuous.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{60,10},{80,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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..ba12d4bb174 --- /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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.AddParameter wseTPre( + final p=-3) "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{0,200},{20,220}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.GreaterThreshold greThr( + final t=0.5) "Greater threshold" + annotation (Placement(transformation(extent={{-20,10},{0,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.AddParameter wseTPre1( + final p=-3) + "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.GreaterThreshold greThr1( + final t=0.5) "Greater than threshold" + annotation (Placement(transformation(extent={{-20,-220},{0,-200}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpChiWat( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWatSet( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zero( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWat1( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,-180},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zero1( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,-180},{-180,-160}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant tunPar( + final k=0.06) + "Assume a constant tuning parameter" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter TOutWet( + final p=-10) + "Predicted WSE outlet temperature" + annotation (Placement(transformation(extent={{-60,120},{-40,140}}))); + + Buildings.Controls.OBC.CDL.Continuous.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..f507f8a40df --- /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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.Sources.Constant dpChiWat( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWatSet( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,60},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TCWSup( + final k=273.15 + 14) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-120,100},{-100,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zero( + final k=0) "Constant" + annotation (Placement(transformation(extent={{-200,60},{-180,80}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant dpChiWat1( + final k=65*6895) + "Chilled water differential pressure" + annotation (Placement(transformation(extent={{-120,-230},{-100,-210}}))); + + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant dpChiWatSet1( + final k=65*6895) + "Chilled water differential pressure setpoint" + annotation (Placement(transformation(extent={{-120,-180},{-100,-160}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TCWSup1( + final k=273.15 + 14) + "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-120,-140},{-100,-120}}))); + + Buildings.Controls.OBC.CDL.Continuous.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..6556d3efecc --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/SetPoints/package.mo @@ -0,0 +1,8 @@ +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.2.4. in ASHRAE RP-1711, Draft on March 23, 2020.

+")); +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..47605f86b47 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Staging/package.mo @@ -0,0 +1,42 @@ +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020).

+"), + 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..65ceef20be5 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Controller.mo @@ -0,0 +1,597 @@ +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 + "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(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](unit="W")={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]( + unit="K", + displayUnit="degC")={12,12} "Minimum LIFT of each chiller" + annotation (Dialog(tab="Fan speed", group="Return temperature control")); + parameter Real TConWatSup_nominal[nChi]( + unit="K", + displayUnit="degC")={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]( + unit="K", + displayUnit="degC")={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]( + unit="K", + displayUnit="degC")={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} + "Chiller 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.BooleanInput uLeaConWatPum + "Enabling status of lead condenser water pump" + annotation (Placement(transformation(extent={{-140,-190},{-100,-150}}), + iconTransformation(extent={{-140,-170},{-100,-130}}))); + 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,-52},{0,-32}}))); + 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.Continuous.Switch swi[nTowCel] "Logical switch" + annotation (Placement(transformation(extent={{60,-160},{80,-140}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-46},{20,-46},{20,-110},{120,-110}}, color={255,0,255})); + connect(towSta.yIsoVal, yIsoVal) + annotation (Line(points={{2,-42},{40,-42},{40,-70},{120,-70}}, color={0,0,127})); + connect(towSta.yTowSta, swi.u2) + annotation (Line(points={{2,-46},{20,-46},{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(swi.y,ySpeSet) + annotation (Line(points={{82,-150},{120,-150}}, 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,-33},{-64,-33},{-64,-100},{-120,-100}}, color={255,127,0})); + connect(towSta.uIsoVal, uIsoVal) + annotation (Line(points={{-22,-49},{-40,-49},{-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,-51},{-22,-51}}, color={255,0,255})); + connect(towSta.uChiStaSet, uChiStaSet) annotation (Line(points={{-22,-35},{-60, + -35},{-60,-120},{-120,-120}}, color={255,127,0})); + connect(towSta.uTowStaCha, uTowStaCha) annotation (Line(points={{-22,-37},{-56, + -37},{-56,-150},{-120,-150}}, color={255,0,255})); + connect(uWse, towSta.uWse) annotation (Line(points={{-120,180},{-48,180},{-48, + -39},{-22,-39}}, color={255,0,255})); + connect(towSta.uLeaConWatPum, uLeaConWatPum) annotation (Line(points={{-22,-43}, + {-52,-43},{-52,-170},{-120,-170}}, color={255,0,255})); + connect(uConWatPumSpe, towSta.uConWatPumSpe) annotation (Line(points={{-120,-20}, + {-72,-20},{-72,-45},{-22,-45}}, color={0,0,127})); + connect(towSta.yLeaCel, yLeaCel) annotation (Line(points={{2,-38},{40,-38},{40, + -30},{120,-30}}, color={255,0,255})); + connect(uEnaPla, towSta.uEnaPla) annotation (Line(points={{-120,-70},{-34,-70}, + {-34,-41},{-22,-41}}, 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={{-96,-140},{-8,-156}}, + textColor={255,0,255}, + textString="uLeaConWatPum"), + 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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.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..a92d5087b10 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Controller.mo @@ -0,0 +1,442 @@ +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), + displayUnit=fill("degC",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,20},{-100,60}}), + 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,-40},{-100,0}}), + 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,-20},{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},{-82,41},{-82,40},{-120,40}}, + 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,-20},{-120,-20}}, + 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,40},{-60,40},{-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},{80,-40},{80,0},{120,0}}, + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.12.2, item +1, 2, and 4. +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..190c0d3f3db --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Controller.mo @@ -0,0 +1,250 @@ +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.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{0,30},{20,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Continuous.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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.12.2, +item 4. 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..f639ff643ec --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/IntegratedOperation.mo @@ -0,0 +1,313 @@ +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}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer[nChi]( + final k=fill(0, nChi)) "Zero constant" + annotation (Placement(transformation(extent={{-120,70},{-100,90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.MultiSum totLoa( + final nin=nChi) "Total load of operating chillers" + annotation (Placement(transformation(extent={{-20,50},{0,70}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Divide div "Output first input divided by second input" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide div1 "Output first input divided by second input" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(final nin=nChi) "Logical or" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Line lin "Linear interpolation" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer1( + final k=yMin) "Load control minimum limit" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one( + final k=yMax) + "Load control maximum limit" + annotation (Placement(transformation(extent={{-40,-70},{-20,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minTowSpe( + final k=fanSpeMin) + "Minimum speed" + annotation (Placement(transformation(extent={{-40,-30},{-20,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Switch fanSpe "Logical switch" + annotation (Placement(transformation(extent={{120,-90},{140,-70}}))); + 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.And3 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}}))); + +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, lin.u) + annotation (Line(points={{102,100},{120,100},{120,0},{40,0},{40,-40}, + {58,-40}}, color={0,0,127})); + connect(zer1.y, lin.x1) + annotation (Line(points={{22,-20},{30,-20},{30,-32},{58,-32}}, color={0,0,127})); + connect(minTowSpe.y, lin.f1) + annotation (Line(points={{-18,-20},{-10,-20},{-10,-36},{58,-36}}, color={0,0,127})); + connect(maxTowSpe.y, lin.f2) + annotation (Line(points={{22,-60},{30,-60},{30,-48},{58,-48}}, color={0,0,127})); + connect(one.y, lin.x2) + annotation (Line(points={{-18,-60},{-10,-60},{-10,-44},{58,-44}}, color={0,0,127})); + connect(mulOr.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(lin.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, mulOr.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(mulOr.y, and3.u1) + annotation (Line(points={{-98,20},{-90,20},{-90,28},{-62,28}}, color={255,0,255})); + connect(falEdg.y, and3.u2) + annotation (Line(points={{-98,-60},{-80,-60},{-80,20},{-62,20}}, + color={255,0,255})); + connect(uWse, and3.u3) + annotation (Line(points={{-180,0},{-70,0},{-70,12},{-62,12}}, color={255,0,255})); + connect(and3.y, loaCon.trigger) + annotation (Line(points={{-38,20},{84,20},{84,88}}, 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})); + +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.12.2, +item 4.a. +

+

+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..1708fecf511 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/IntegratedOperation.mo @@ -0,0 +1,81 @@ +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}) + "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=3600) "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.Continuous.Sources.Constant con(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{0,-40},{20,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=0.2*1e4, + final freqHz=1/1200, + final offset=1.1*1e4, + final startTime=180) "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,-23},{68,-23}}, color={255,0,255})); + connect(chiSta1.y, intOpe.uChi[2]) + annotation (Line(points={{-18,50},{60,50},{60,-21},{68,-21}}, color={255,0,255})); + connect(con.y, intOpe.chiLoa[2]) + annotation (Line(points={{-58,-60},{40,-60},{40,-29},{68,-29}}, 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,-31},{68,-31}}, 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. +

+", 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..88eac484b41 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/Validation/WSEOperation.mo @@ -0,0 +1,94 @@ +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( + final fanSpeMin=0.1, + final fanSpeMax=1, + final chiWatCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI) + "Tower fan speed control when there is only waterside economizer is running" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.05, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not fanSpeSwi "Two fan speed switch" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine chiSup( + final amplitude=0.5, + final freqHz=1/1800, + final offset=273.15 + 7.1) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiSupSet( + final k=273.15 + 7) + "Chilled water supply water setpoint" + annotation (Placement(transformation(extent={{20,-90},{40,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{20,10},{40,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con(final k=0.1) + "Minimum fan speed" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram( + final height=0.2, + final duration=3600, + final offset=0.1, + final startTime=1750) "Tower speed" + annotation (Placement(transformation(extent={{-80,30},{-60,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram1( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-20,-60},{0,-40}}))); + +equation + connect(booPul.y, fanSpeSwi.u) + annotation (Line(points={{-58,80},{-42,80}}, color={255,0,255})); + connect(con.y, swi.u3) + annotation (Line(points={{-58,0},{-20,0},{-20,12},{18,12}}, color={0,0,127})); + connect(fanSpeSwi.y, swi.u2) + annotation (Line(points={{-18,80},{0,80},{0,20},{18,20}}, color={255,0,255})); + connect(swi.y,wseOpe.uFanSpe) + annotation (Line(points={{42,20},{50,20},{50,8},{58,8}}, color={0,0,127})); + connect(chiSupSet.y, wseOpe.TChiWatSupSet) + annotation (Line(points={{42,-80},{50,-80},{50,-8},{58,-8}}, color={0,0,127})); + connect(ram.y, swi.u1) + annotation (Line(points={{-58,40},{-20,40},{-20,28},{18,28}}, color={0,0,127})); + connect(chiSup.y, add2.u1) + annotation (Line(points={{-58,-30},{-40,-30},{-40,-44},{-22,-44}}, color={0,0,127})); + connect(ram1.y, add2.u2) + annotation (Line(points={{-58,-70},{-40,-70},{-40,-56},{-22,-56}}, color={0,0,127})); + connect(add2.y, wseOpe.TChiWatSup) + annotation (Line(points={{2,-50},{20,-50},{20,0},{58,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/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. +

+", 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 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..bb1a2676019 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Subsequences/WSEOperation.mo @@ -0,0 +1,305 @@ +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={{-180,80},{-140,120}}), + 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={{-180,-60},{-140,-20}}), + 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={{-180,-140},{-140,-100}}), + 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={{140,40},{180,80}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Logical.And and2 "Logical and" + annotation (Placement(transformation(extent={{40,130},{60,150}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=cheCycOffTim) + "Count the time when fan is at minimum speed and the chilled water supply temperature drops below setpoint" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minTowSpe( + final k=fanSpeMin) "Minimum tower speed" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract dFanSpe + "Different between measured fan speed and the minimum fan speed" + annotation (Placement(transformation(extent={{-90,90},{-70,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys2( + final uLow=fanSpeChe, + final uHigh=fanSpeChe + 0.005) + "Check if tower fan speed is greater than minimum speed" + annotation (Placement(transformation(extent={{-40,90},{-20,110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract dTChiSup + "Difference between chilled water supply temperature and its setpoint" + annotation (Placement(transformation(extent={{-110,-50},{-90,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=-0.1, + final uHigh=0.1) + "Check if chilled water supply temperature is greater than setpoint" + annotation (Placement(transformation(extent={{-40,130},{-20,150}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not" + annotation (Placement(transformation(extent={{0,130},{20,150}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg + "Output true at the moment when input becomes true" + annotation (Placement(transformation(extent={{-40,50},{-20,70}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{40,50},{60,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{100,50},{120,70}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{-40,-50},{-20,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{-60,-130},{-40,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=yMin) + "Minimum output from chilled water supply temperature control loop, default to be zero" + annotation (Placement(transformation(extent={{40,-110},{60,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one( + final k=yMax) + "Maximum output from chilled water supply temperature control loop" + annotation (Placement(transformation(extent={{-20,-150},{0,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant maxTowSpe( + final k=fanSpeMax) + "Maximum tower fan speed" + annotation (Placement(transformation(extent={{40,-150},{60,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Line lin + "Output the value of the input x along a line specified by two points" + annotation (Placement(transformation(extent={{100,-130},{120,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Output true at the moment when input becomes true" + annotation (Placement(transformation(extent={{40,-30},{60,-10}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel( + final delayTime=minCycOffTim) + "Minimum time of fan cycling off" + annotation (Placement(transformation(extent={{0,10},{20,30}}))); + Buildings.Controls.OBC.CDL.Logical.And and1 "Logical and" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat1 + "Logical latch, maintain ON signal until condition changes" + annotation (Placement(transformation(extent={{-40,10},{-20,30}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre + "Breaks algebraic loops by an infinitesimal small time delay" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + +equation + connect(uFanSpe, dFanSpe.u1) + annotation (Line(points={{-160,100},{-126,100},{-126,106},{-92,106}}, + color={0,0,127})); + connect(dFanSpe.y, hys2.u) + annotation (Line(points={{-68,100},{-42,100}}, color={0,0,127})); + connect(hys2.y, not2.u) + annotation (Line(points={{-18,100},{-2,100}}, color={255,0,255})); + connect(TChiWatSup, dTChiSup.u1) + annotation (Line(points={{-160,-40},{-136,-40},{-136,-34},{-112,-34}}, + color={0,0,127})); + connect(TChiWatSupSet, dTChiSup.u2) + annotation (Line(points={{-160,-120},{-112,-120},{-112,-46}}, + color={0,0,127})); + connect(hys1.y, not1.u) + annotation (Line(points={{-18,140},{-2,140}}, color={255,0,255})); + connect(dTChiSup.y, hys1.u) + annotation (Line(points={{-88,-40},{-60,-40},{-60,140},{-42,140}}, + color={0,0,127})); + connect(not1.y, and2.u1) + annotation (Line(points={{22,140},{38,140}}, color={255,0,255})); + connect(not2.y, and2.u2) + annotation (Line(points={{22,100},{30,100},{30,132},{38,132}}, color={255,0,255})); + connect(and2.y, tim.u) + annotation (Line(points={{62,140},{78,140}}, color={255,0,255})); + connect(edg.y, lat.u) + annotation (Line(points={{-18,60},{38,60}}, color={255,0,255})); + connect(lat.y, swi.u2) + annotation (Line(points={{62,60},{98,60}}, color={255,0,255})); + connect(dTChiSup.y, hys3.u) + annotation (Line(points={{-88,-40},{-42,-40}}, color={0,0,127})); + connect(lat.y, chiWatTemCon.trigger) + annotation (Line(points={{62,60},{74,60},{74,-80},{-70,-80},{-70,-140}, + {-56,-140},{-56,-132}}, color={255,0,255})); + connect(zer.y, lin.x1) + annotation (Line(points={{62,-100},{80,-100},{80,-112},{98,-112}}, color={0,0,127})); + connect(chiWatTemCon.y, lin.u) + annotation (Line(points={{-38,-120},{98,-120}}, color={0,0,127})); + connect(one.y, lin.x2) + annotation (Line(points={{2,-140},{20,-140},{20,-124},{98,-124}}, color={0,0,127})); + connect(maxTowSpe.y, lin.f2) + annotation (Line(points={{62,-140},{80,-140},{80,-128},{98,-128}}, color={0,0,127})); + connect(lin.y, swi.u3) + annotation (Line(points={{122,-120},{130,-120},{130,-60},{86,-60},{86,52}, + {98,52}}, color={0,0,127})); + connect(swi.y,ySpeSet) + annotation (Line(points={{122,60},{160,60}}, color={0,0,127})); + connect(minTowSpe.y, dFanSpe.u2) + annotation (Line(points={{-98,20},{-92,20},{-92,94}}, color={0,0,127})); + connect(minTowSpe.y, lin.f1) + annotation (Line(points={{-98,20},{-80,20},{-80,-100},{20,-100},{20,-116}, + {98,-116}},color={0,0,127})); + connect(hys3.y, and1.u2) + annotation (Line(points={{-18,-40},{-10,-40},{-10,-28},{-2,-28}}, + color={255,0,255})); + connect(and1.y, edg1.u) + annotation (Line(points={{22,-20},{38,-20}}, color={255,0,255})); + connect(edg1.y, lat.clr) + annotation (Line(points={{62,-20},{68,-20},{68,40},{30,40},{30,54},{38,54}}, + color={255,0,255})); + connect(zer.y, swi.u1) + annotation (Line(points={{62,-100},{80,-100},{80,68},{98,68}}, color={0,0,127})); + connect(edg.y, lat1.u) + annotation (Line(points={{-18,60},{0,60},{0,40},{-50,40},{-50,20},{-42,20}}, + color={255,0,255})); + connect(lat1.y, truDel.u) + annotation (Line(points={{-18,20},{-2,20}}, color={255,0,255})); + connect(and1.y, pre.u) + annotation (Line(points={{22,-20},{30,-20},{30,-50},{38,-50}}, color={255,0,255})); + connect(pre.y, lat1.clr) + annotation (Line(points={{62,-50},{68,-50},{68,-70},{-50,-70},{-50,14}, + {-42,14}}, color={255,0,255})); + connect(truDel.y, and1.u1) + annotation (Line(points={{22,20},{30,20},{30,0},{-10,0},{-10,-20},{-2,-20}}, + color={255,0,255})); + connect(tim.passed, edg.u) + annotation (Line(points={{102,132},{120,132},{120,80},{-50,80},{-50,60}, + {-42,60}}, color={255,0,255})); + connect(TChiWatSupSet, chiWatTemCon.u_s) + annotation (Line(points={{-160,-120},{-62,-120}}, color={0,0,127})); + connect(TChiWatSup, chiWatTemCon.u_m) annotation (Line(points={{-160,-40},{ + -110,-40},{-110,-152},{-50,-152},{-50,-132}}, color={0,0,127})); +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={{-140,-160},{140,160}})), +Documentation(info=" +

+Block that output cooling tower fan speed yTowSpe when only waterside +economizer is running. This is implemented +according to ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.12.2, +item 4.b. +

+
    +
  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..15d847bf194 --- /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.2.12.2, item 4 in ASHRAE RP-1711, Draft 6 (July 25, 2019). +

+"), +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..d4d0897a17c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/EnabledWSE/Validation/Controller.mo @@ -0,0 +1,137 @@ +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 "Tower fan speed control when waterside economizer is enabled" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul( + final width=0.05, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not fanSpeSwi "Two fan speed switch" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine chiSup( + final amplitude=0.5, + final freqHz=1/1800, + final offset=273.15 + 7.1) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-100,-110},{-80,-90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiSupSet( + final k=273.15 + 7) + "Chilled water supply water setpoint" + annotation (Placement(transformation(extent={{0,-150},{20,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con(final k=0.1) + "Minimum fan speed" + annotation (Placement(transformation(extent={{-100,-80},{-80,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram( + final height=0.2, + final duration=3600, + final offset=0.1, + final startTime=1750) "Tower speed" + annotation (Placement(transformation(extent={{-100,-40},{-80,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram1( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-100,-150},{-80,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-40,-130},{-20,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{0,100},{20,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{-100,80},{-80,100}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine sin( + final amplitude=0.2*1e4, + final freqHz=1/1200, + final offset=1.1*1e4, + final startTime=180) "Chiller load" + annotation (Placement(transformation(extent={{-100,120},{-80,140}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1(final width=0.5, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-100,30},{-80,50}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiSta1 "First chiller status" + annotation (Placement(transformation(extent={{-60,30},{-40,50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta2( + final k=false) "Second chiller status" + annotation (Placement(transformation(extent={{0,60},{20,80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse wseSta( + final width=0.95, + final period=3600) + "Waterside economizer enabling status" + annotation (Placement(transformation(extent={{0,0},{20,20}}))); + +equation + connect(booPul.y, fanSpeSwi.u) + annotation (Line(points={{-78,0},{-62,0}}, color={255,0,255})); + connect(con.y, swi.u3) + annotation (Line(points={{-78,-70},{-40,-70},{-40,-58},{-2,-58}}, + color={0,0,127})); + connect(fanSpeSwi.y, swi.u2) + annotation (Line(points={{-38,0},{-20,0},{-20,-50},{-2,-50}}, color={255,0,255})); + connect(ram.y, swi.u1) + annotation (Line(points={{-78,-30},{-40,-30},{-40,-42},{-2,-42}}, + color={0,0,127})); + connect(chiSup.y, add2.u1) + annotation (Line(points={{-78,-100},{-60,-100},{-60,-114},{-42,-114}}, + color={0,0,127})); + connect(ram1.y, add2.u2) + annotation (Line(points={{-78,-140},{-60,-140},{-60,-126},{-42,-126}}, + color={0,0,127})); + connect(booPul1.y, chiSta1.u) + annotation (Line(points={{-78,40},{-62,40}}, color={255,0,255})); + connect(con1.y, swi1.u3) + annotation (Line(points={{-78,90},{-60,90},{-60,102},{-2,102}}, color={0,0,127})); + connect(sin.y, swi1.u1) + annotation (Line(points={{-78,130},{-60,130},{-60,118},{-2,118}}, color={0,0,127})); + connect(chiSta1.y, swi1.u2) + annotation (Line(points={{-38,40},{-20,40},{-20,110},{-2,110}}, color={255,0,255})); + connect(chiSta2.y, wseOpe.uChi[2]) + annotation (Line(points={{22,70},{50,70},{50,6},{98,6}}, color={255,0,255})); + connect(chiSta1.y, wseOpe.uChi[1]) + annotation (Line(points={{-38,40},{50,40},{50,6},{98,6}}, color={255,0,255})); + connect(swi1.y, wseOpe.chiLoa[1]) + annotation (Line(points={{22,110},{60,110},{60,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={{22,10},{40,10},{40,2},{98,2}}, color={255,0,255})); + connect(swi.y,wseOpe.uFanSpe) + annotation (Line(points={{22,-50},{60,-50},{60,-2},{98,-2}}, color={0,0,127})); + connect(add2.y, wseOpe.TChiWatSup) + annotation (Line(points={{-18,-120},{70,-120},{70,-6},{98,-6}}, color={0,0,127})); + connect(chiSupSet.y, wseOpe.TChiWatSupSet) + annotation (Line(points={{22,-140},{80,-140},{80,-9},{98,-9}}, 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. +

+", 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..7dbc86674a7 --- /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.2.12.2, item 4 in ASHRAE RP-1711, Draft on March 23, 2020. +

+"), +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..51dc30d0020 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Controller.mo @@ -0,0 +1,620 @@ +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), + displayUnit=fill("degC",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,90},{-160,130}}), + 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.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},{60,-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,-220},{60,-200}}))); + +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.Continuous.MultiplyByParameter parLoaRat( + final k=1/desCap) "Plant partial load ratio" + annotation (Placement(transformation(extent={{-120,100},{-100,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Line plrTowMaxSpe + "Tower maximum speed resetted by partial load ratio" + annotation (Placement(transformation(extent={{-20,100},{0,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi + annotation (Placement(transformation(extent={{120,-10},{140,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 + "Switch between when waterside economizer is enabled and disabled" + annotation (Placement(transformation(extent={{100,200},{120,220}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant zer( + final k=0) "Zero constant" + annotation (Placement(transformation(extent={{-60,130},{-40,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hal( + final k=0.5) "Constant 0.5" + annotation (Placement(transformation(extent={{-120,70},{-100,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant uppPlrTowMaxSpe( + final k=1) + "Upper bound of tower maximum speed" + annotation (Placement(transformation(extent={{-60,70},{-40,90}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant zer2( + final k=0) if not have_WSE + "Zero constant" + annotation (Placement(transformation(extent={{40,160},{60,180}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-250},{-120,-230}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nConWatPum] + "Convert boolean input to integer output" + annotation (Placement(transformation(extent={{-100,-250},{-80,-230}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=nConWatPum) "Sum up integer inputs" + annotation (Placement(transformation(extent={{-20,-250},{0,-230}}))); + +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,110},{-122,110}}, color={0,0,127})); + connect(zer.y, plrTowMaxSpe.x1) + annotation (Line(points={{-38,140},{-30,140},{-30,118},{-22,118}}, + color={0,0,127})); + connect(lowPlrTowMaxSpe.y, plrTowMaxSpe.f1) + annotation (Line(points={{-98,140},{-70,140},{-70,114},{-22,114}}, + color={0,0,127})); + connect(parLoaRat.y, plrTowMaxSpe.u) + annotation (Line(points={{-98,110},{-22,110}}, color={0,0,127})); + connect(hal.y, plrTowMaxSpe.x2) + annotation (Line(points={{-98,80},{-70,80},{-70,106},{-22,106}}, + color={0,0,127})); + connect(uppPlrTowMaxSpe.y, plrTowMaxSpe.f2) + annotation (Line(points={{-38,80},{-30,80},{-30,102},{-22,102}}, + color={0,0,127})); + connect(uChi, conWatRetSet.uChi) + annotation (Line(points={{-180,210},{-140,210},{-140,-62},{38,-62}}, + color={255,0,255})); + connect(parLoaRat.y, conWatRetSet.uOpeParLoaRat) annotation (Line(points={{-98, + 110},{-80,110},{-80,-67},{38,-67}}, color={0,0,127})); + connect(conWatRetSet.TChiWatSupSet, TChiWatSupSet) + annotation (Line(points={{38,-73},{-80,-73},{-80,-80},{-180,-80}}, + color={0,0,127})); + connect(conWatRetSet.uPla, uPla) + annotation (Line(points={{38,-78},{-60,-78},{-60,-120},{-180,-120}}, + color={255,0,255})); + connect(enaTow.uMaxTowSpeSet, uMaxTowSpeSet) + annotation (Line(points={{38,30},{-120,30},{-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={{62,-70},{80,-70},{80,-100},{26,-100},{26,-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,110},{20,110},{20,-140},{38,-140}}, + color={0,0,127})); + connect(conWatRetSet.TConWatRetSet, lesCouTowSpe.TConWatRetSet) + annotation (Line(points={{62,-70},{80,-70},{80,-100},{26,-100},{26,-200},{38,-200}}, + color={0,0,127})); + connect(TConWatRet, lesCouTowSpe.TConWatRet) + annotation (Line(points={{-180,-160},{-100,-160},{-100,-202},{38,-202}}, + color={0,0,127})); + connect(uConWatPumSpe, lesCouTowSpe.uConWatPumSpe) + annotation (Line(points={{-180,-200},{-80,-200},{-80,-208},{38,-208}}, + color={0,0,127})); + connect(lesCouTowSpe.TConWatSup, TConWatSup) + annotation (Line(points={{38,-212},{-40,-212},{-40,-280},{-180,-280}}, + color={0,0,127})); + connect(uMaxTowSpeSet, lesCouTowSpe.uMaxTowSpeSet) + annotation (Line(points={{-180,40},{-120,40},{-120,-215},{38,-215}}, + color={0,0,127})); + connect(plrTowMaxSpe.y, lesCouTowSpe.plrTowMaxSpe) + annotation (Line(points={{2,110},{20,110},{20,-220},{38,-220}}, + color={0,0,127})); + connect(enaTow.yTow, swi.u2) + annotation (Line(points={{62,20},{80,20},{80,0},{118,0}}, color={255,0,255})); + connect(couTowSpe.ySpeSet, swi.u1) + annotation (Line(points={{62,-130},{100,-130},{100,8},{118,8}}, + color={0,0,127})); + connect(lesCouTowSpe.ySpeSet, swi.u1) + annotation (Line(points={{62,-210},{100,-210},{100,8},{118,8}}, + color={0,0,127})); + connect(zer1.y, swi.u3) + annotation (Line(points={{62,-20},{80,-20},{80,-8},{118,-8}}, + 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,0},{150,0},{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,-240},{-142,-240}}, + color={0,0,127})); + connect(proOn.y, booToInt.u) + annotation (Line(points={{-118,-240},{-102,-240}}, color={255,0,255})); + connect(mulSumInt.y, enaTow.uConWatPumNum) + annotation (Line(points={{2,-240},{14,-240},{14,10},{38,10}}, + color={255,127,0})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{-78,-240},{-50,-240},{-50,-240},{-22,-240}}, + color={255,127,0})); + connect(conWatRetSet.TConWatRetSet, enaTow.TTowSet) annotation (Line( + points={{62,-70},{80,-70},{80,-40},{0,-40},{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,-217},{38,-217}}, + color={255,0,255})); + connect(uPla, lesCouTowSpe.uPla) + annotation (Line(points={{-180,-120},{-60,-120},{-60,-205},{38,-205}}, + color={255,0,255})); + +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={{-240,270},{200,210}}, + 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")}), + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.12.2, +item 2. 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..ba4adfbb37e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Coupled.mo @@ -0,0 +1,232 @@ +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,30},{-120,70}}), + 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,0},{-120,40}}), + 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,-40},{-120,0}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uChi[nChi] + "Chiller enabling status: true=ON" + annotation (Placement(transformation(extent={{-160,-80},{-120,-40}}), + 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,-120},{-120,-80}}), + 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,-60},{160,-20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.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}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minTowSpe( + final k=fanSpeMin) "Minimum tower speed" + annotation (Placement(transformation(extent={{-80,110},{-60,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Line CWRTSpd + "Fan speed calculated based on return water temperature control loop" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=yMin) "Zero constant" + annotation (Placement(transformation(extent={{0,110},{20,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one( + final k=yMax) "Constant one" + annotation (Placement(transformation(extent={{0,50},{20,70}}))); + Buildings.Controls.OBC.CDL.Continuous.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,30}}))); + 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,30}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMin fanSpe(final nin=3) + "Cooling tower fan speed" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-70},{0,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{80,-50},{100,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one1[nChi]( + final k=fill(1, nChi)) "Constant one" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + +equation + connect(TConWatRet, conPID.u_m) + annotation (Line(points={{-140,50},{-70,50},{-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,20},{-102,20}}, color={0,0,127})); + connect(proOn.y, anyProOn.u) + annotation (Line(points={{-78,20},{-62,20}}, color={255,0,255})); + connect(anyProOn.y, conPID.trigger) + annotation (Line(points={{-38,20},{0,20},{0,40},{-76,40},{-76,68}}, + color={255,0,255})); + connect(uChi, swi1.u2) + annotation (Line(points={{-140,-60},{-62,-60}}, color={255,0,255})); + connect(one1.y, swi1.u3) + annotation (Line(points={{-78,-80},{-70,-80},{-70,-68},{-62,-68}}, + color={0,0,127})); + connect(uMaxTowSpeSet, swi1.u1) + annotation (Line(points={{-140,-20},{-80,-20},{-80,-52},{-62,-52}}, + color={0,0,127})); + connect(swi1.y, maxSpe.u) + annotation (Line(points={{-38,-60},{-30,-60},{-30,-60},{-22,-60}}, + color={0,0,127})); + connect(CWRTSpd.y, fanSpe.u[1]) + annotation (Line(points={{102,80},{110,80},{110,40},{10,40},{10,-60.6667},{ + 18,-60.6667}},color={0,0,127})); + connect(maxSpe.y, fanSpe.u[2]) + annotation (Line(points={{2,-60},{18,-60}}, color={0,0,127})); + connect(plrTowMaxSpe, fanSpe.u[3]) + annotation (Line(points={{-140,-100},{10,-100},{10,-59.3333},{18,-59.3333}}, + color={0,0,127})); + connect(anyProOn.y, swi.u2) + annotation (Line(points={{-38,20},{0,20},{0,-40},{78,-40}}, color={255,0,255})); + connect(zer.y, swi.u3) + annotation (Line(points={{22,120},{60,120},{60,-48},{78,-48}}, + color={0,0,127})); + connect(fanSpe.y, swi.u1) + annotation (Line(points={{42,-60},{50,-60},{50,-32},{78,-32}}, color={0,0,127})); + connect(swi.y,ySpeSet) + annotation (Line(points={{102,-40},{140,-40}}, 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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, +2020), section 5.2.12.2, item 2.e-f. +

+ +", 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..adc78634710 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Enable.mo @@ -0,0 +1,378 @@ +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 = 0.01 "Lower threshold value to check fan speed"; + parameter Real fanSpeMin = 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={{-220,160},{-180,200}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uFanSpe( + final min=0, + final max=1, + final unit="1") "Measured tower fan speed" + annotation (Placement(transformation(extent={{-220,100},{-180,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={{-220,20},{-180,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={{-220,-20},{-180,20}}), + 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={{-220,-140},{-180,-100}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uConWatPumNum + "Number of enabled condenser water pumps" + annotation (Placement(transformation(extent={{-220,-180},{-180,-140}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yTow + "Tower fan status: true=enable any number of fans; false=disable all fans" + annotation (Placement(transformation(extent={{180,-180},{220,-140}}), + iconTransformation(extent={{100,-20},{140,20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Subtract sub0[nChi] + "DIfference between enabled chiller head pressure control maximum tower speed and the minimum tower speed" + annotation (Placement(transformation(extent={{-70,150},{-50,170}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{-40,150},{-20,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={{40,150},{60,170}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nChi] "Logical not" + annotation (Placement(transformation(extent={{0,150},{20,170}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim( + final t=cheMaxTowSpe) + "Count the time when the chiller head pressure control maximum tower speed equals tower minimum speed" + annotation (Placement(transformation(extent={{80,150},{100,170}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{-140,170},{-120,190}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-100,150},{-80,170}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub1 + "Difference between tower fan speed and the minimum fan speed" + annotation (Placement(transformation(extent={{-90,110},{-70,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys2( + final uLow=fanSpeChe, + final uHigh=2*fanSpeChe) + "Check if tower fan speed is greater than minimum speed" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 + "Check if tower fan speed equals to the minimum speed" + annotation (Placement(transformation(extent={{0,110},{20,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub2 + "Difference between the return water temperature and the adjusted setpoint" + annotation (Placement(transformation(extent={{-90,30},{-70,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys3( + final uLow=0.1, final uHigh=0.15) + "Check if tower temperature is a delta below setpoint" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + 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={{80,70},{100,90}}))); + Buildings.Controls.OBC.CDL.Logical.Or disTow "Disable tower fans" + annotation (Placement(transformation(extent={{120,110},{140,130}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1(final nin=nTowCel) + "True when any tower fan is enaled" + annotation (Placement(transformation(extent={{-140,-130},{-120,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Not not3 "No enabled tower fan" + annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim1( + final t=cheTowOff) + "Count the time when all tower cells are off" + annotation (Placement(transformation(extent={{-20,-130},{0,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub3 + "Difference between the return water temperature and the adjusted setpoint" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys4( + final uLow=0.1, + final uHigh=0.15) + "Check if tower temperature is above the adjusted setpoint" + annotation (Placement(transformation(extent={{20,-50},{40,-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={{20,-10},{40,10}}))); + Buildings.Controls.OBC.CDL.Logical.And3 enaTow + "Check if tower fans should be enabled" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu + "Check integer number equality" + annotation (Placement(transformation(extent={{-80,-170},{-60,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt( + final k=0) "Zero constant" + annotation (Placement(transformation(extent={{-140,-190},{-120,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minTowSpe[nChi]( + final k=fill(fanSpeMin, nChi)) + "Minimum tower speed" + annotation (Placement(transformation(extent={{-140,70},{-120,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one[nChi]( + final k=fill(1, nChi)) "Constant one" + annotation (Placement(transformation(extent={{-140,130},{-120,150}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=5/9) "Tower temperature setpoint plus 1 degF" + annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar1( + final p=-5/9) + "Temperature of a delta value below the tower temperature setpoint" + annotation (Placement(transformation(extent={{-140,30},{-120,50}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim2( + final t=cheMinFanSpe) + "Count the time when the tower fan is at minimum speed" + annotation (Placement(transformation(extent={{40,110},{60,130}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi2 "Logical switch" + annotation (Placement(transformation(extent={{140,-170},{160,-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={{80,-190},{100,-170}}))); + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1 "Logical switch" + annotation (Placement(transformation(extent={{140,-100},{160,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Or chaTow "Change tower status" + annotation (Placement(transformation(extent={{120,30},{140,50}}))); + +equation + connect(sub0.y, hys.u) + annotation (Line(points={{-48,160},{-42,160}}, color={0,0,127})); + connect(hys.y, not1.u) + annotation (Line(points={{-18,160},{-2,160}}, color={255,0,255})); + connect(mulOr.y, tim.u) + annotation (Line(points={{62,160},{78,160}}, color={255,0,255})); + connect(uMaxTowSpeSet, hys1.u) + annotation (Line(points={{-200,180},{-142,180}}, color={0,0,127})); + connect(hys1.y, swi.u2) + annotation (Line(points={{-118,180},{-110,180},{-110,160},{-102,160}}, + color={255,0,255})); + connect(uMaxTowSpeSet, swi.u1) + annotation (Line(points={{-200,180},{-160,180},{-160,168},{-102,168}}, + color={0,0,127})); + connect(one.y, swi.u3) + annotation (Line(points={{-118,140},{-110,140},{-110,152},{-102,152}}, + color={0,0,127})); + connect(swi.y, sub0.u1) + annotation (Line(points={{-78,160},{-76,160},{-76,166},{-72,166}}, + color={0,0,127})); + connect(uFanSpe, sub1.u1) + annotation (Line(points={{-200,120},{-146,120},{-146,126},{-92,126}}, + color={0,0,127})); + connect(sub1.y, hys2.u) + annotation (Line(points={{-68,120},{-42,120}}, color={0,0,127})); + connect(hys2.y, not2.u) + annotation (Line(points={{-18,120},{-2,120}}, color={255,0,255})); + connect(sub2.y, hys3.u) + annotation (Line(points={{-68,40},{-42,40}}, color={0,0,127})); + connect(hys3.y, and2.u2) + annotation (Line(points={{-18,40},{70,40},{70,72},{78,72}}, color={255,0,255})); + connect(and2.y, disTow.u2) + annotation (Line(points={{102,80},{110,80},{110,112},{118,112}}, + color={255,0,255})); + connect(mulOr1.y, not3.u) + annotation (Line(points={{-118,-120},{-62,-120}}, color={255,0,255})); + connect(not3.y, tim1.u) + annotation (Line(points={{-38,-120},{-22,-120}}, color={255,0,255})); + connect(TTow, sub3.u1) + annotation (Line(points={{-200,0},{-80,0},{-80,-34},{-62,-34}}, + color={0,0,127})); + connect(sub3.y, hys4.u) + annotation (Line(points={{-38,-40},{18,-40}}, color={0,0,127})); + connect(mulAnd.y, enaTow.u1) + annotation (Line(points={{42,0},{50,0},{50,-32},{58,-32}}, color={255,0,255})); + connect(hys4.y, enaTow.u2) + annotation (Line(points={{42,-40},{58,-40}}, color={255,0,255})); + connect(not1.y, mulOr.u) + annotation (Line(points={{22,160},{38,160}}, color={255,0,255})); + connect(hys.y, mulAnd.u) + annotation (Line(points={{-18,160},{-10,160},{-10,0},{18,0}}, color={255,0,255})); + connect(uTow, mulOr1.u) + annotation (Line(points={{-200,-120},{-142,-120}}, color={255,0,255})); + connect(uConWatPumNum, intEqu.u1) + annotation (Line(points={{-200,-160},{-82,-160}}, color={255,127,0})); + connect(conInt.y, intEqu.u2) + annotation (Line(points={{-118,-180},{-100,-180},{-100,-168},{-82,-168}}, + color={255,127,0})); + connect(TTowSet, addPar1.u) + annotation (Line(points={{-200,40},{-172,40},{-172,40},{-142,40}}, color={0,0,127})); + connect(addPar1.y, sub2.u1) + annotation (Line(points={{-118,40},{-106,40},{-106,46},{-92,46}}, color={0,0,127})); + connect(TTowSet, addPar.u) + annotation (Line(points={{-200,40},{-160,40},{-160,-80},{-142,-80}}, color={0,0,127})); + connect(not2.y, tim2.u) + annotation (Line(points={{22,120},{38,120}}, color={255,0,255})); + connect(disFan1.y, logSwi2.u1) + annotation (Line(points={{102,-180},{120,-180},{120,-152},{138,-152}}, + color={255,0,255})); + connect(intEqu.y, logSwi2.u2) + annotation (Line(points={{-58,-160},{138,-160}}, + color={255,0,255})); + connect(logSwi2.y, yTow) + annotation (Line(points={{162,-160},{200,-160}}, color={255,0,255})); + connect(mulOr1.y, logSwi1.u3) + annotation (Line(points={{-118,-120},{-100,-120},{-100,-98},{138,-98}}, + color={255,0,255})); + connect(enaTow.y, chaTow.u2) + annotation (Line(points={{82,-40},{100,-40},{100,32},{118,32}}, color={255,0,255})); + connect(disTow.y, chaTow.u1) + annotation (Line(points={{142,120},{150,120},{150,60},{100,60},{100,40}, + {118,40}}, color={255,0,255})); + connect(chaTow.y, logSwi1.u2) + annotation (Line(points={{142,40},{150,40},{150,-60},{120,-60},{120,-90}, + {138,-90}}, color={255,0,255})); + connect(logSwi1.y, logSwi2.u3) + annotation (Line(points={{162,-90},{170,-90},{170,-140},{130,-140},{130,-168}, + {138,-168}}, color={255,0,255})); + connect(enaTow.y, logSwi1.u1) + annotation (Line(points={{82,-40},{100,-40},{100,-82},{138,-82}}, + color={255,0,255})); + connect(tim2.passed, and2.u1) annotation (Line(points={{62,112},{70,112},{70,80}, + {78,80}}, color={255,0,255})); + connect(tim.passed, disTow.u1) annotation (Line(points={{102,152},{110,152},{110, + 120},{118,120}}, color={255,0,255})); + connect(tim1.passed, enaTow.u3) annotation (Line(points={{2,-128},{50,-128},{50, + -48},{58,-48}}, color={255,0,255})); + connect(addPar.y, sub3.u2) annotation (Line(points={{-118,-80},{-80,-80},{-80, + -46},{-62,-46}}, color={0,0,127})); + connect(TTow, sub2.u2) annotation (Line(points={{-200,0},{-100,0},{-100,34},{-92, + 34}}, color={0,0,127})); + connect(minTowSpe.y, sub0.u2) annotation (Line(points={{-118,80},{-60,80},{-60, + 142},{-76,142},{-76,154},{-72,154}}, color={0,0,127})); + connect(minTowSpe[1].y, sub1.u2) annotation (Line(points={{-118,80},{-102,80}, + {-102,114},{-92,114}}, color={0,0,127})); + +annotation ( + defaultComponentName="enaTow", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-180,-200},{180,200}}), graphics={ + Rectangle( + extent={{-178,18},{178,-138}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-178,198},{178,22}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-178,-142},{178,-198}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{74,194},{152,184}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Disable tower fans"), + Text( + extent={{72,14},{150,4}}, + pattern=LinePattern.None, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + textColor={0,0,127}, + horizontalAlignment=TextAlignment.Left, + textString="Enable tower fans"), + Text( + extent={{-104,-178},{68,-198}}, + 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(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")}), +Documentation(info=" +

+Block that outputs signal yTowSta for enabling and disabling cooling tower +fan. This is implemented according to ASHRAE RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, +2020), section 5.2.12.2, item 2.j-l. +

+

+1. Disable the tower fans if either: +

+ +

+2. Enable the tower fans if: +

+ +

+3. When all condenser water pumps are commanded OFF, disable the PID loop and +stop all tower fans. +

+

+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..5d159907f56 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/LessCoupled.mo @@ -0,0 +1,369 @@ +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 = 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.Continuous.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.Continuous.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.Continuous.Sources.Constant minTowSpe( + final k=fanSpeMin) "Minimum tower speed" + annotation (Placement(transformation(extent={{-20,-10},{0,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer1( + final k=ySupConMin) + "Zero constant" + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one1( + final k=ySupConMax) "Maximum speed" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Line CWSTSpd + "Fan speed calculated based on supply water temperature control" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.MultiMin fanSpe(final nin=3) + "Cooling tower fan speed" + annotation (Placement(transformation(extent={{60,-130},{80,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer2(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{60,-180},{80,-160}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant one2[nChi]( + final k=fill(1,nChi)) "Constant one" + annotation (Placement(transformation(extent={{-160,-160},{-140,-140}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Timer tim(final t=iniPlaTim) + "Count the time after plant being enabled" + annotation (Placement(transformation(extent={{-140,90},{-120,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch delTem "Temperature difference value" + annotation (Placement(transformation(extent={{60,90},{80,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract meaTemDif + "Difference of the condenser return and supply water temperature" + annotation (Placement(transformation(extent={{-140,130},{-120,150}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Subtract conWatSupSet + "Condenser water supply temperature setpoint" + annotation (Placement(transformation(extent={{100,140},{120,160}}))); + Buildings.Controls.OBC.CDL.Continuous.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, tim.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(tim.passed, delTem.u2) annotation (Line(points={{-118,92},{-40,92},{-40, + 100},{58,100}}, color={255,0,255})); + 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})); + +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 RP-1711 Advanced Sequences of Operation for +HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, +2020), section 5.2.12.2, item 2.g-i. +

+ +", 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..c595ada1ca6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Setpoint.mo @@ -0,0 +1,284 @@ +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), + displayUnit=fill("degC",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={{-220,60},{-180,100}}), + 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={{-220,0},{-180,40}}), + 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={{-220,-70},{-180,-30}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enabling status" + annotation (Placement(transformation(extent={{-220,-130},{-180,-90}}), + 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={{180,-130},{220,-90}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Add conWatRet + "Condenser water return temperature" + annotation (Placement(transformation(extent={{80,-40},{100,-20}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.MultiMin lifMax( + final nin=nChi) "Maximum chiller LIFT" + annotation (Placement(transformation(extent={{-80,130},{-60,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiLifMin[nChi]( + final k=LIFT_min) + "Minimum LIFT of chillers" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zeoCon[nChi]( + final k=fill(0, nChi)) "Zero constant" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nChi] "Logical switch" + annotation (Placement(transformation(extent={{-80,70},{-60,90}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMax lifMin( + final nin=nChi) "Minimum enabled chiller LIFT" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract coeA + "Coefficient A" + annotation (Placement(transformation(extent={{0,90},{20,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract coeB "Coefficient B" + annotation (Placement(transformation(extent={{80,130},{100,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro "Product of inputs" + annotation (Placement(transformation(extent={{80,40},{100,60}}))); + Buildings.Controls.OBC.CDL.Continuous.Add add2 + annotation (Placement(transformation(extent={{120,40},{140,60}}))); + Buildings.Controls.OBC.CDL.Continuous.Min min "Minimum value of two inputs" + annotation (Placement(transformation(extent={{-20,-20},{0,0}}))); + Buildings.Controls.OBC.CDL.Continuous.Max tarLif "Target chiller LIFT" + annotation (Placement(transformation(extent={{20,-20},{40,0}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zeoTim( + final k=0) "Zero constant" + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant maxRamTim( + final k=ramTim) + "Time to change the return water temperature from initial value to setpoint" + annotation (Placement(transformation(extent={{-20,-150},{0,-130}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay delPlaEna( + final delayTime=iniPlaTim) + "Delay plant enabling status" + annotation (Placement(transformation(extent={{-140,-120},{-120,-100}}))); + Buildings.Controls.OBC.CDL.Logical.Timer chaTim + "Count the time after starting to ramp condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-80,-120},{-60,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.Line lin + "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{140,-120},{160,-100}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant desConWatRet[nChi]( + final k=TConWatRet_nominal) + "Design condenser water return (condenser leaving) temperature of each chiller" + annotation (Placement(transformation(extent={{-160,130},{-140,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minChiWatSup[nChi]( + final k=TChiWatSupMin) + "Lowest chilled water supply temperature setpoint" + annotation (Placement(transformation(extent={{-160,90},{-140,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract maxLif[nChi] + "Maximum LIFT of each chiller" + annotation (Placement(transformation(extent={{-120,130},{-100,150}}))); + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=-10*5/9) + "Output sum of input and a parameter" + annotation (Placement(transformation(extent={{-20,-90},{0,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiMin lowDesConWatRet( + final nin=nChi) + "Lowest design condenser water return temperature" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=1.1) "Gain factor" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + +equation + connect(uChi, swi.u2) + annotation (Line(points={{-200,80},{-82,80}}, color={255,0,255})); + connect(zeoCon.y, swi.u3) + annotation (Line(points={{-98,60},{-90,60},{-90,72},{-82,72}}, + color={0,0,127})); + connect(chiLifMin.y, swi.u1) + annotation (Line(points={{-98,100},{-90,100},{-90,88},{-82,88}}, + color={0,0,127})); + connect(lifMax.y, coeA.u1) + annotation (Line(points={{-58,140},{-10,140},{-10,106},{-2,106}}, color={0,0,127})); + connect(lifMin.y, coeA.u2) + annotation (Line(points={{-18,80},{-10,80},{-10,94},{-2,94}}, color={0,0,127})); + connect(lifMax.y, coeB.u1) + annotation (Line(points={{-58,140},{-10,140},{-10,146},{78,146}}, color={0,0,127})); + connect(coeB.y, add2.u1) + annotation (Line(points={{102,140},{110,140},{110,56},{118,56}}, color={0,0,127})); + connect(pro.y, add2.u2) + annotation (Line(points={{102,50},{110,50},{110,44},{118,44}}, color={0,0,127})); + connect(lifMax.y, min.u2) + annotation (Line(points={{-58,140},{-50,140},{-50,-16},{-22,-16}}, + color={0,0,127})); + connect(add2.y, min.u1) + annotation (Line(points={{142,50},{160,50},{160,20},{-40,20},{-40,-4},{-22,-4}}, + color={0,0,127})); + connect(min.y, tarLif.u2) + annotation (Line(points={{2,-10},{10,-10},{10,-16},{18,-16}}, + color={0,0,127})); + connect(lifMin.y, tarLif.u1) + annotation (Line(points={{-18,80},{10,80},{10,-4},{18,-4}}, color={0,0,127})); + connect(tarLif.y, conWatRet.u1) + annotation (Line(points={{42,-10},{60,-10},{60,-24},{78,-24}}, + color={0,0,127})); + connect(TChiWatSupSet, conWatRet.u2) + annotation (Line(points={{-200,-50},{60,-50},{60,-36},{78,-36}}, + color={0,0,127})); + connect(swi.y, lifMin.u) + annotation (Line(points={{-58,80},{-42,80}}, color={0,0,127})); + connect(uPla, delPlaEna.u) + annotation (Line(points={{-200,-110},{-142,-110}}, + color={255,0,255})); + connect(delPlaEna.y, chaTim.u) + annotation (Line(points={{-118,-110},{-82,-110}}, color={255,0,255})); + connect(zeoTim.y, lin.x1) + annotation (Line(points={{62,-80},{80,-80},{80,-102},{138,-102}}, + color={0,0,127})); + connect(chaTim.y, lin.u) + annotation (Line(points={{-58,-110},{138,-110}}, color={0,0,127})); + connect(maxRamTim.y, lin.x2) + annotation (Line(points={{2,-140},{20,-140},{20,-114},{138,-114}}, + color={0,0,127})); + connect(conWatRet.y, lin.f2) + annotation (Line(points={{102,-30},{120,-30},{120,-118},{138,-118}}, + color={0,0,127})); + connect(lin.y, TConWatRetSet) + annotation (Line(points={{162,-110},{200,-110}}, color={0,0,127})); + connect(uOpeParLoaRat, pro.u2) + annotation (Line(points={{-200,20},{-60,20},{-60,44},{78,44}}, color={0,0,127})); + connect(desConWatRet.y, maxLif.u1) + annotation (Line(points={{-138,140},{-130,140},{-130,146},{-122,146}}, color={0,0,127})); + connect(maxLif.y,lifMax.u) + annotation (Line(points={{-98,140},{-82,140}}, color={0,0,127})); + connect(lowDesConWatRet.y, addPar.u) + annotation (Line(points={{-58,-80},{-22,-80}}, color={0,0,127})); + connect(addPar.y, lin.f1) + annotation (Line(points={{2,-80},{20,-80},{20,-106},{138,-106}}, color={0,0,127})); + connect(desConWatRet.y, lowDesConWatRet.u) + annotation (Line(points={{-138,140},{-130,140},{-130,-80},{-82,-80}}, + color={0,0,127})); + connect(minChiWatSup.y, maxLif.u2) annotation (Line(points={{-138,100},{-134,100}, + {-134,134},{-122,134}}, color={0,0,127})); + connect(coeA.y, gai.u) + annotation (Line(points={{22,100},{38,100}}, color={0,0,127})); + connect(gai.y, coeB.u2) annotation (Line(points={{62,100},{70,100},{70,134},{78, + 134}}, color={0,0,127})); + connect(gai.y, pro.u1) annotation (Line(points={{62,100},{70,100},{70,56},{78, + 56}}, color={0,0,127})); +annotation ( + defaultComponentName="conWatRetSet", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-180,-160},{180,160}})), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}), + graphics={ + Text( + extent={{-120,146},{100,108}}, + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – Central +Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.12.2, item 2.d and m. +

+

+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..0d11cf74cab --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Coupled.mo @@ -0,0 +1,122 @@ +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 + "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.Continuous.Sources.Sine conRet( + final amplitude=2, + 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.Continuous.Sources.Ramp ram1( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,80},{-60,100}}))); + Buildings.Controls.OBC.CDL.Continuous.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-20,80},{0,100}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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={{-80,40},{-60,60}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant zer[2]( + final k=fill(0,2)) "Constant zero" + annotation (Placement(transformation(extent={{-40,-60},{-20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.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,90},{-40,90},{-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={{-58,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. +

+", 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..f0cb16e0b47 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Enable.mo @@ -0,0 +1,177 @@ +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.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant hpTowSpe2( + final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-260,60},{-240,80}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant towFanSpe1( + final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-40,30},{-20,50}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.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.Continuous.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.Continuous.Sources.Constant towFanSpe2(final k=0.1) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{140,30},{160,50}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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,60},{-142,60}}, + color={0,0,127})); + connect(hpTowSpe2.y, enaTow.uMaxTowSpeSet[2]) + annotation (Line(points={{-238,70},{-180,70},{-180,60},{-142,60}}, + 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,40},{-142,40}}, + color={255,127,0})); + connect(hpTowSpe3.y, disTow.uMaxTowSpeSet[1]) + annotation (Line(points={{-18,90},{0,90},{0,60},{38,60}}, color={0,0,127})); + connect(hpTowSpe4.y, disTow.uMaxTowSpeSet[2]) + annotation (Line(points={{-58,70},{0,70},{0,60},{38,60}}, 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,40},{38,40}}, + color={255,127,0})); + connect(hpTowSpe5.y, disTow1.uMaxTowSpeSet[1]) + annotation (Line(points={{162,90},{180,90},{180,60},{218,60}}, + color={0,0,127})); + connect(hpTowSpe6.y, disTow1.uMaxTowSpeSet[2]) + annotation (Line(points={{122,70},{180,70},{180,60},{218,60}}, + 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,40},{218,40}}, + 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. +

+", 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..15badcb3112 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/LessCoupled.mo @@ -0,0 +1,151 @@ +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.Continuous.Sources.Sine conRet( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 32) "Condenser water return temperature" + annotation (Placement(transformation(extent={{-80,130},{-60,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram1( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,100},{-60,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Add add2 "Add real inputs" + annotation (Placement(transformation(extent={{-20,100},{0,120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant conRetSet( + final k=273.15 + 32) "Condenser water return temperature setpoint" + annotation (Placement(transformation(extent={{-20,130},{0,150}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{-80,50},{-60,70}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-80},{-60,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{50,-140},{70,-120}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine conSup( + final amplitude=2, + final freqHz=1/1800, + final offset=273.15 + 29) "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram2( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Add add1 "Add real inputs" + annotation (Placement(transformation(extent={{-20,20},{0,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi[2] "Logical switch" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer[2]( + final 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( + final width=0.2, final period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-80,-110},{-60,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse chiSta2( + final width=0.1, final period=3600) "Chiller one enabling status" + annotation (Placement(transformation(extent={{-80,-150},{-60,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant plaEna( + final 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. +

+", 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..f2a3cbf8480 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Subsequences/Validation/Setpoint.mo @@ -0,0 +1,89 @@ +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( + final nChi=2, + final LIFT_min={12,14}, + final 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( + final width=0.15, final 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( + final k=false) "Constant false" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp parLoaRat( + final height=0.6, final duration=3600) + "Partial load ratio" + annotation (Placement(transformation(extent={{-80,-10},{-60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer(final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiWatSupSet( + final k=273.15 + 6.5) + "Chilled water supply setpoint" + annotation (Placement(transformation(extent={{0,-70},{20,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.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},{58,27}}, + color={255,0,255})); + connect(con.y, conWatRetSet.uChi[2]) + annotation (Line(points={{-18,30},{40,30},{40,29},{58,29}}, + 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. +

+", 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..de53048af05 --- /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.2.12.2, item 2 in ASHRAE RP-1711, Draft 6 (July 25, 2019). +

+"), +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..6b39864722b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/ReturnWaterTemperature/Validation/Controller.mo @@ -0,0 +1,266 @@ +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(final 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(final 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.Continuous.Sources.Ramp speWSE( + final height=0.9, final 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( + final width=0.2, final period=3600, + shift=-3000) + "Waterside economizer enabling status" + annotation (Placement(transformation(extent={{-360,50},{-340,70}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp plaCap( + final height=8e5, + final duration=3600, + final offset=1e5) "Real operating chiller plant capacity" + annotation (Placement(transformation(extent={{-360,20},{-340,40}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.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.Continuous.Add add1 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-270},{-280,-250}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Add add3 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-190},{-280,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant hpTowSpe1(final k=0.5) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-320,0},{-300,20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant hpTowSpe2(final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-360,-40},{-340,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant towFanSpe3(final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,-60},{-300,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.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,110},{-340,130}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant chiSta2(final k=false) + "Chiller two enabling status" + annotation (Placement(transformation(extent={{-360,80},{-340,100}}))); + Buildings.Controls.OBC.CDL.Logical.Or3 or3 "Logical or" + annotation (Placement(transformation(extent={{-260,-150},{-240,-130}}))); + 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,110},{-300,130}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,180},{-300,200}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi "Logical switch" + annotation (Placement(transformation(extent={{-240,150},{-220,170}}))); + Buildings.Controls.OBC.CDL.Continuous.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(chiSta2.y, or3.u2) + annotation (Line(points={{-338,90},{-286,90},{-286,-140},{-262,-140}}, + color={255,0,255})); + connect(wseSta.y, or3.u3) + annotation (Line(points={{-338,60},{-292,60},{-292,-148},{-262,-148}}, + 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, or3.u1) + annotation (Line(points={{-298,120},{-280,120},{-280,-132},{-262,-132}}, + 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})); + +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. +

+", 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..17c70604e23 --- /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.2.12.2, item 2 in ASHRAE RP-1711, Draft on March 23, 2020. +

+"), +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..b2346eb2c0c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/Validation/Controller.mo @@ -0,0 +1,319 @@ +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 plant 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 plant 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 plant 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.Continuous.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.Continuous.Sources.Sine 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.Continuous.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.Continuous.Add add1 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-270},{-280,-250}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Add add3 "Add real inputs" + annotation (Placement(transformation(extent={{-300,-190},{-280,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Sources.Constant hpTowSpe2(final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-360,-70},{-340,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant towFanSpe3(final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,110},{-300,130}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Or3 or3 "Logical or" + annotation (Placement(transformation(extent={{-260,-150},{-240,-130}}))); + 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.Continuous.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,-50},{-300,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-240,-30},{-220,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi2 "Logical switch" + annotation (Placement(transformation(extent={{-260,260},{-240,280}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1(final k=0) + "Zero constant" + annotation (Placement(transformation(extent={{-360,240},{-340,260}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine 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.Continuous.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.Continuous.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(chiSta2.y, or3.u2) + annotation (Line(points={{-338,180},{-286,180},{-286,-140},{-262,-140}}, + color={255,0,255})); + connect(wseSta.y, or3.u3) + annotation (Line(points={{-338,150},{-292,150},{-292,-148},{-262,-148}}, + 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(chiSta1.y, not1.u) + annotation (Line(points={{-338,210},{-322,210}}, color={255,0,255})); + connect(not1.y, or3.u1) + annotation (Line(points={{-298,210},{-280,210},{-280,-132},{-262,-132}}, + 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})); + +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. +

+", 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..522b177dd44 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/FanSpeed/package.mo @@ -0,0 +1,47 @@ +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.2.12.2 in +ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..c74d5308c4a --- /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 uLeaConWatPum + "Enabling status of lead condenser water pump" + 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.uLeaConWatPum, uLeaConWatPum) annotation (Line(points={{-42,84}, + {-62,84},{-62,-20},{-120,-20}}, 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})); +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={{-98,76},{-44,64}}, + textColor={255,127,0}, + textString="uChiStaSet"), + Text( + extent={{-98,96},{-60,84}}, + textColor={255,127,0}, + textString="uChiSta"), + Text( + extent={{-98,56},{-38,44}}, + textColor={255,0,255}, + textString="uTowStaCha"), + Text( + extent={{-100,36},{-70,24}}, + textColor={255,0,255}, + textString="uWse", + visible=have_WSE), + Text( + extent={{-98,-4},{-20,-16}}, + textColor={255,0,255}, + textString="uLeaConWatPum"), + Text( + extent={{-98,-24},{-20,-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")}), +Documentation(info=" +

+Block controls cooling tower fan staging. This is implemented accoding to +ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), section 5.2.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..e9486538600 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/CellsNumber.mo @@ -0,0 +1,343 @@ +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 uLeaConWatPum + "Enabling status of lead condenser water pump" + annotation (Placement(transformation(extent={{-300,-140},{-260,-100}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + 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,-20},{300,20}}), + 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}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swi + "Chiller stage index to identify total number of enabling cells" + annotation (Placement(transformation(extent={{-120,90},{-100,110}}))); + +protected + Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt + "Convert real input to integer output" + annotation (Placement(transformation(extent={{220,-10},{240,10}}))); + 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.Continuous.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.Continuous.Sources.Constant con4[totSta]( + final k=staVec) "Stage indicator array" + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract sub4[totSta] "Sum of real inputs" + annotation (Placement(transformation(extent={{20,-50},{40,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greEquThr[totSta]( + final t=fill(-0.1,totSta)) "Check stage indicator" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[totSta] + "Convert boolean input to integer" + annotation (Placement(transformation(extent={{100,-50},{120,-30}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum mulSumInt( + final nin=totSta) "Sun of input vector " + annotation (Placement(transformation(extent={{140,-50},{160,-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={{180,-10},{200,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con5[totSta]( + final k=towCelOnSet) + "Number of enabling cells at each stage" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Logical.Latch leaCel + "Lead cell status" + annotation (Placement(transformation(extent={{140,-130},{160,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Not conPumOff + "All condenser water pumps are off" + annotation (Placement(transformation(extent={{80,-170},{100,-150}}))); + Buildings.Controls.OBC.CDL.Integers.Equal norOpe + "Normal operation, not in the chiller stage changeprocess" + annotation (Placement(transformation(extent={{-220,90},{-200,110}}))); + Buildings.Controls.OBC.CDL.Continuous.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}}))); + +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},{0,-20},{0,-34},{18,-34}}, + color={0,0,127})); + connect(con4.y, sub4.u2) + annotation (Line(points={{-18,-70},{0,-70},{0,-46},{18,-46}}, + color={0,0,127})); + connect(greEquThr.y, booToInt.u) + annotation (Line(points={{82,-40},{98,-40}}, color={255,0,255})); + connect(sub4.y, greEquThr.u) + annotation (Line(points={{42,-40},{58,-40}}, color={0,0,127})); + connect(con5.y, celOnNum.u) + annotation (Line(points={{162,0},{178,0}}, color={0,0,127})); + connect(mulSumInt.y, celOnNum.index) + annotation (Line(points={{162,-40},{190,-40},{190,-12}}, color={255,127,0})); + connect(celOnNum.y, reaToInt.u) + annotation (Line(points={{202,0},{218,0}}, color={0,0,127})); + connect(booToInt.y, mulSumInt.u) + annotation (Line(points={{122,-40},{138,-40}}, color={255,127,0})); + connect(uConWatPumSpe, proOn.u) + annotation (Line(points={{-280,-160},{-222,-160}}, color={0,0,127})); + connect(uLeaConWatPum, leaCel.u) + annotation (Line(points={{-280,-120},{138,-120}}, color={255,0,255})); + connect(conPumOff.y, leaCel.clr) + annotation (Line(points={{102,-160},{120,-160},{120,-126},{138,-126}}, + color={255,0,255})); + connect(uChiSta, norOpe.u1) + annotation (Line(points={{-280,100},{-222,100}}, color={255,127,0})); + connect(norOpe.y, swi.u2) + annotation (Line(points={{-198,100},{-122,100}}, color={255,0,255})); + 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,0},{280,0}}, 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(mulOr.y, conPumOff.u) + annotation (Line(points={{-118,-160},{78,-160}}, color={255,0,255})); + connect(uEnaPla, or2.u1) + annotation (Line(points={{-280,-90},{198,-90}}, color={255,0,255})); + connect(leaCel.y, or2.u2) annotation (Line(points={{162,-120},{180,-120},{180, + -98},{198,-98}}, color={255,0,255})); + connect(or2.y, yLeaCel) + annotation (Line(points={{222,-90},{280,-90}}, 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={{-96,-54},{-18,-66}}, + textColor={255,0,255}, + textString="uLeaConWatPum"), + 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")}), + 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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.12.1, +

+ +

+The number of enabled tower cells shall be set by chiller stage 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..72add109040 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/StageProcesses.mo @@ -0,0 +1,414 @@ +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,270},{-200,310}}), + 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,30},{-200,70}}), + 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,-200},{-200,-160}}), + 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,70},{240,110}}), + 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,-220},{240,-180}}), + 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,-320},{240,-280}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + +protected + Buildings.Controls.OBC.CDL.Continuous.Switch swi2[nTowCel] "Logical switch" + annotation (Placement(transformation(extent={{100,100},{120,120}}))); + Buildings.Controls.OBC.CDL.Logical.Timer tim + "Count the time after changing up-stream device status" + annotation (Placement(transformation(extent={{-120,210},{-100,230}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con9(final k=0) + "Constant zero" + annotation (Placement(transformation(extent={{-40,230},{-20,250}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con7( + final k=chaTowCelIsoTim) "Time to change cooling tower isolation valve" + annotation (Placement(transformation(extent={{-120,180},{-100,200}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con8(final k=1) + "Fully open valve" + annotation (Placement(transformation(extent={{-40,180},{-20,200}}))); + Buildings.Controls.OBC.CDL.Continuous.Line lin1 + "Chilled water isolation valve setpoint" + annotation (Placement(transformation(extent={{20,210},{40,230}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=nTowCel) + "Replicate real input" + annotation (Placement(transformation(extent={{100,140},{120,160}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi[nTowCel] "Logical switch" + annotation (Placement(transformation(extent={{160,80},{180,100}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep( + final nout=nTowCel) + "Replicate boolean input" + annotation (Placement(transformation(extent={{60,20},{80,40}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-60},{-120,-40}}))); + Buildings.Controls.OBC.CDL.Continuous.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,-90},{-120,-70}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd1(final nin=nTowCel) + "Logical and" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + Buildings.Controls.OBC.CDL.Logical.And and5 + "Check if the isolation valve has been fully open" + annotation (Placement(transformation(extent={{100,-100},{120,-80}}))); + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greEquThr( + final t=chaTowCelIsoTim) + "Check if it has past the target time of open isolation valve " + annotation (Placement(transformation(extent={{0,-120},{20,-100}}))); + Buildings.Controls.OBC.CDL.Logical.And and1[nTowCel] + "True: cells should be enabled" + annotation (Placement(transformation(extent={{20,-170},{40,-150}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=nTowCel) + "Replicate boolean input" + annotation (Placement(transformation(extent={{140,-100},{160,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1[nTowCel]( + final k=fill(true, nTowCel)) "Enable cells" + annotation (Placement(transformation(extent={{-60,-150},{-40,-130}}))); + Buildings.Controls.OBC.CDL.Logical.Switch enaNexCel[nTowCel] + "Enable next cells" + annotation (Placement(transformation(extent={{80,-170},{100,-150}}))); + Buildings.Controls.OBC.CDL.Logical.And and2[nTowCel] "Logical and" + annotation (Placement(transformation(extent={{-120,140},{-100,160}}))); + Buildings.Controls.OBC.CDL.Logical.Not not1[nTowCel] "Logical and" + annotation (Placement(transformation(extent={{-60,140},{-40,160}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd enaCel( + final nin=nTowCel) "New cells should be enabled" + annotation (Placement(transformation(extent={{-20,140},{0,160}}))); + Buildings.Controls.OBC.CDL.Continuous.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={{60,140},{80,160}}))); + Buildings.Controls.OBC.CDL.Logical.And enaPro "Enabling cells process" + annotation (Placement(transformation(extent={{-60,-10},{-40,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical and" + annotation (Placement(transformation(extent={{-100,80},{-80,100}}))); + Buildings.Controls.OBC.CDL.Logical.And disPro "Disabling cells process" + annotation (Placement(transformation(extent={{-20,80},{0,100}}))); + Buildings.Controls.OBC.CDL.Logical.Switch newTowCell[nTowCel] + "New tower cell status" + annotation (Placement(transformation(extent={{160,-210},{180,-190}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2( + final nout=nTowCel) "In the enabling process" + annotation (Placement(transformation(extent={{80,-210},{100,-190}}))); + Buildings.Controls.OBC.CDL.Logical.Switch disExiCel[nTowCel] + "Disable existing cells" + annotation (Placement(transformation(extent={{80,-250},{100,-230}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep3( + final nout=nTowCel) "In the disabling process" + annotation (Placement(transformation(extent={{0,-250},{20,-230}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr staPro(nin=nTowCel) + "In tower staging process" + annotation (Placement(transformation(extent={{60,280},{80,300}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr opeVal( + final nin=nTowCel) "Check if there is any opened valve" + annotation (Placement(transformation(extent={{0,-30},{20,-10}}))); + Buildings.Controls.OBC.CDL.Logical.And and3 + "Check if the opened valves are fully open" + annotation (Placement(transformation(extent={{140,-30},{160,-10}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nTowCel] + "Convert boolean input to integer" + annotation (Placement(transformation(extent={{0,-60},{20,-40}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nTowCel] + "Convert boolean input to integer" + annotation (Placement(transformation(extent={{0,-90},{20,-70}}))); + Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nTowCel] + "Check if the opened valves are fully open" + annotation (Placement(transformation(extent={{40,-60},{60,-40}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4( + final nout=nTowCel) "In the disabling process" + annotation (Placement(transformation(extent={{60,-290},{80,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Or celChaSta[nTowCel] + "True: there are cells changed status" + annotation (Placement(transformation(extent={{-60,-310},{-40,-290}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge falEdg[nTowCel] + "Check if there is any cell being disabled" + annotation (Placement(transformation(extent={{-120,-290},{-100,-270}}))); + Buildings.Controls.OBC.CDL.Logical.Edge edg[nTowCel] + "Check if there is any cell being enabled" + annotation (Placement(transformation(extent={{-120,-330},{-100,-310}}))); + 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={{-20,-310},{0,-290}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat[nTowCel] "Change cells status" + annotation (Placement(transformation(extent={{-100,280},{-80,300}}))); + Buildings.Controls.OBC.CDL.Logical.Edge havCha[nTowCel] "Edge" + annotation (Placement(transformation(extent={{-180,280},{-160,300}}))); + Buildings.Controls.OBC.CDL.Logical.And and4[nTowCel] + "True: cells should be disabled" + annotation (Placement(transformation(extent={{-140,-210},{-120,-190}}))); + Buildings.Controls.OBC.CDL.Logical.Switch disExiCel1[nTowCel] + "Disable existing cells" + annotation (Placement(transformation(extent={{-60,-230},{-40,-210}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2[nTowCel]( + final k=fill(false, nTowCel)) "Disable cells" + annotation (Placement(transformation(extent={{-140,-160},{-120,-140}}))); +equation + connect(con9.y, lin1.x1) + annotation (Line(points={{-18,240},{10,240},{10,228},{18,228}}, + color={0,0,127})); + connect(con7.y, lin1.x2) + annotation (Line(points={{-98,190},{-60,190},{-60,216},{18,216}}, + color={0,0,127})); + connect(con8.y, lin1.f2) + annotation (Line(points={{-18,190},{-10,190},{-10,212},{18,212}}, + color={0,0,127})); + connect(tim.y, lin1.u) + annotation (Line(points={{-98,220},{18,220}}, color={0,0,127})); + connect(reaRep.y, swi2.u1) + annotation (Line(points={{122,150},{140,150},{140,130},{80,130},{80,118},{98, + 118}},color={0,0,127})); + connect(swi2.y, swi.u1) + annotation (Line(points={{122,110},{140,110},{140,98},{158,98}}, + color={0,0,127})); + connect(uIsoVal, swi2.u3) + annotation (Line(points={{-220,50},{30,50},{30,102},{98,102}}, + color={0,0,127})); + connect(booRep.y, swi.u2) + annotation (Line(points={{82,30},{140,30},{140,90},{158,90}}, + color={255,0,255})); + connect(uIsoVal, swi.u3) + annotation (Line(points={{-220,50},{30,50},{30,82},{158,82}}, + color={0,0,127})); + connect(swi.y, yIsoVal) + annotation (Line(points={{182,90},{220,90}}, color={0,0,127})); + connect(greEquThr.y, and5.u2) + annotation (Line(points={{22,-110},{70,-110},{70,-98},{98,-98}}, + color={255,0,255})); + connect(uIsoVal, hys4.u) + annotation (Line(points={{-220,50},{-160,50},{-160,-80},{-142,-80}}, + color={0,0,127})); + connect(uIsoVal, hys3.u) + annotation (Line(points={{-220,50},{-160,50},{-160,-50},{-142,-50}}, + color={0,0,127})); + connect(tim.y, greEquThr.u) + annotation (Line(points={{-98,220},{-70,220},{-70,-110},{-2,-110}}, + color={0,0,127})); + connect(and5.y, booRep1.u) + annotation (Line(points={{122,-90},{138,-90}}, color={255,0,255})); + connect(booRep1.y, and1.u1) + annotation (Line(points={{162,-90},{180,-90},{180,-132},{0,-132},{0,-160},{18, + -160}}, color={255,0,255})); + connect(and1.y, enaNexCel.u2) + annotation (Line(points={{42,-160},{78,-160}}, color={255,0,255})); + connect(con1.y, enaNexCel.u1) annotation (Line(points={{-38,-140},{60,-140},{60, + -152},{78,-152}}, color={255,0,255})); + connect(uTowSta, enaNexCel.u3) annotation (Line(points={{-220,-180},{60,-180}, + {60,-168},{78,-168}}, color={255,0,255})); + connect(celPosSet.y, reaRep.u) + annotation (Line(points={{82,150},{98,150}}, color={0,0,127})); + connect(uTowSta, and2.u2) annotation (Line(points={{-220,-180},{-180,-180},{-180, + 142},{-122,142}}, color={255,0,255})); + connect(and2.y, not1.u) + annotation (Line(points={{-98,150},{-62,150}}, color={255,0,255})); + connect(not1.y, enaCel.u) annotation (Line(points={{-38,150},{-22,150}}, + color={255,0,255})); + connect(enaCel.y, celPosSet.u2) + annotation (Line(points={{2,150},{58,150}}, color={255,0,255})); + connect(lin1.y, celPosSet.u1) annotation (Line(points={{42,220},{50,220},{50,158}, + {58,158}}, color={0,0,127})); + connect(con9.y, celPosSet.u3) annotation (Line(points={{-18,240},{10,240},{10, + 142},{58,142}}, color={0,0,127})); + connect(enaCel.y, enaPro.u1) annotation (Line(points={{2,150},{20,150},{20,120}, + {-120,120},{-120,0},{-62,0}}, color={255,0,255})); + connect(enaCel.y, not2.u) annotation (Line(points={{2,150},{20,150},{20,120},{ + -120,120},{-120,90},{-102,90}}, color={255,0,255})); + connect(not2.y, disPro.u1) + annotation (Line(points={{-78,90},{-22,90}}, color={255,0,255})); + connect(booRep2.y, newTowCell.u2) + annotation (Line(points={{102,-200},{158,-200}}, color={255,0,255})); + connect(enaNexCel.y, newTowCell.u1) annotation (Line(points={{102,-160},{120,-160}, + {120,-192},{158,-192}}, color={255,0,255})); + connect(booRep3.y, disExiCel.u2) + annotation (Line(points={{22,-240},{78,-240}}, color={255,0,255})); + connect(uTowSta, disExiCel.u3) annotation (Line(points={{-220,-180},{60,-180}, + {60,-248},{78,-248}}, color={255,0,255})); + connect(disPro.y, booRep3.u) annotation (Line(points={{2,90},{20,90},{20,60},{ + -100,60},{-100,-240},{-2,-240}}, color={255,0,255})); + connect(enaPro.y, booRep2.u) annotation (Line(points={{-38,0},{-30,0},{-30,-200}, + {78,-200}}, color={255,0,255})); + connect(disExiCel.y, newTowCell.u3) annotation (Line(points={{102,-240},{140,-240}, + {140,-208},{158,-208}}, color={255,0,255})); + connect(newTowCell.y, yTowSta) + annotation (Line(points={{182,-200},{220,-200}}, color={255,0,255})); + connect(con9.y, lin1.f1) annotation (Line(points={{-18,240},{10,240},{10,224}, + {18,224}}, color={0,0,127})); + connect(staPro.y, tim.u) annotation (Line(points={{82,290},{100,290},{100,260}, + {-140,260},{-140,220},{-122,220}}, color={255,0,255})); + connect(staPro.y, disPro.u2) annotation (Line(points={{82,290},{100,290},{100, + 260},{-140,260},{-140,70},{-40,70},{-40,82},{-22,82}}, color={255,0,255})); + connect(staPro.y, enaPro.u2) annotation (Line(points={{82,290},{100,290},{100, + 260},{-140,260},{-140,-8},{-62,-8}}, color={255,0,255})); + connect(hys3.y, booToInt.u) + annotation (Line(points={{-118,-50},{-2,-50}},color={255,0,255})); + connect(hys4.y, booToInt1.u) + annotation (Line(points={{-118,-80},{-2,-80}}, color={255,0,255})); + connect(booToInt.y, intEqu.u1) + annotation (Line(points={{22,-50},{38,-50}}, color={255,127,0})); + connect(booToInt1.y, intEqu.u2) annotation (Line(points={{22,-80},{30,-80},{30, + -58},{38,-58}}, color={255,127,0})); + connect(intEqu.y, mulAnd1.u) annotation (Line(points={{62,-50},{78,-50}}, + color={255,0,255})); + connect(hys3.y, opeVal.u) annotation (Line(points={{-118,-50},{-20,-50},{-20,-20}, + {-2,-20}}, color={255,0,255})); + connect(opeVal.y, and3.u1) + annotation (Line(points={{22,-20},{138,-20}}, color={255,0,255})); + connect(mulAnd1.y, and3.u2) annotation (Line(points={{102,-50},{120,-50},{120, + -28},{138,-28}}, color={255,0,255})); + connect(and3.y, and5.u1) annotation (Line(points={{162,-20},{180,-20},{180,-70}, + {70,-70},{70,-90},{98,-90}}, color={255,0,255})); + connect(staPro.y, booRep.u) annotation (Line(points={{82,290},{100,290},{100,260}, + {-140,260},{-140,30},{58,30}}, color={255,0,255})); + connect(uTowSta, falEdg.u) annotation (Line(points={{-220,-180},{-180,-180},{-180, + -280},{-122,-280}}, color={255,0,255})); + connect(uTowSta, edg.u) annotation (Line(points={{-220,-180},{-180,-180},{-180, + -320},{-122,-320}}, color={255,0,255})); + connect(booRep4.y, lat.clr) annotation (Line(points={{82,-280},{100,-280},{100, + -260},{-150,-260},{-150,284},{-102,284}}, color={255,0,255})); + connect(falEdg.y, celChaSta.u1) annotation (Line(points={{-98,-280},{-80,-280}, + {-80,-300},{-62,-300}}, color={255,0,255})); + connect(edg.y, celChaSta.u2) annotation (Line(points={{-98,-320},{-80,-320},{-80, + -308},{-62,-308}}, color={255,0,255})); + connect(celChaSta.y, endStaPro.u) annotation (Line(points={{-38,-300},{-22,-300}}, + color={255,0,255})); + connect(uChaCel, havCha.u) annotation (Line(points={{-220,290},{-182,290}}, + color={255,0,255})); + connect(havCha.y, lat.u) annotation (Line(points={{-158,290},{-102,290}}, + color={255,0,255})); + connect(lat.y, staPro.u) + annotation (Line(points={{-78,290},{58,290}}, color={255,0,255})); + connect(lat.y, and2.u1) annotation (Line(points={{-78,290},{-60,290},{-60,266}, + {-168,266},{-168,150},{-122,150}}, color={255,0,255})); + connect(lat.y, swi2.u2) annotation (Line(points={{-78,290},{-60,290},{-60,266}, + {-168,266},{-168,110},{98,110}}, color={255,0,255})); + connect(lat.y, and1.u2) annotation (Line(points={{-78,290},{-60,290},{-60,266}, + {-168,266},{-168,-168},{18,-168}}, color={255,0,255})); + connect(endStaPro.y, yEndSta) + annotation (Line(points={{2,-300},{220,-300}}, color={255,0,255})); + connect(endStaPro.y, booRep4.u) annotation (Line(points={{2,-300},{20,-300},{20, + -280},{58,-280}}, color={255,0,255})); + connect(uTowSta, and4.u2) annotation (Line(points={{-220,-180},{-180,-180},{-180, + -208},{-142,-208}}, color={255,0,255})); + connect(uChaCel, and4.u1) annotation (Line(points={{-220,290},{-190,290},{-190, + -200},{-142,-200}}, color={255,0,255})); + connect(and4.y, disExiCel1.u2) annotation (Line(points={{-118,-200},{-80,-200}, + {-80,-220},{-62,-220}}, color={255,0,255})); + connect(uTowSta, disExiCel1.u3) annotation (Line(points={{-220,-180},{-180,-180}, + {-180,-228},{-62,-228}}, color={255,0,255})); + connect(con2.y, disExiCel1.u1) annotation (Line(points={{-118,-150},{-70,-150}, + {-70,-212},{-62,-212}}, color={255,0,255})); + connect(disExiCel1.y, disExiCel.u1) annotation (Line(points={{-38,-220},{50,-220}, + {50,-232},{78,-232}}, color={255,0,255})); +annotation ( + defaultComponentName="towCelStaPro", + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-200,-340},{200,340}}), graphics={ + Rectangle( + extent={{-138,-2},{178,-138}}, + fillColor={210,210,210}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Text( + extent={{12,-120},{144,-144}}, + 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 RP-1711 Advanced Sequences of Operation +for HVAC Systems Phase II – Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.12.1, item 5 and 6 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..7c0784bc24c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/CellsNumber.mo @@ -0,0 +1,94 @@ +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( + final width=0.15, + final period=3600, + final shift=300) "Water side economizer status" + annotation (Placement(transformation(extent={{-60,-40},{-40,-20}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp chiStaGen( + final height=1.2, + final duration=3600, + final 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( + final k=1) "Current chiller stage" + annotation (Placement(transformation(extent={{-60,80},{-40,100}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.75, + final 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.Continuous.Sources.Constant conWatPumSpe[2]( + final k=fill(0.5, 2)) "Condenser water pump speed" + annotation (Placement(transformation(extent={{-60,-110},{-40,-90}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pul( + final width=0.05, final period=3600) + "Boolean pulse" + annotation (Placement(transformation(extent={{-100,-70},{-80,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Not leaConPum "Lead condenser water pump status" + annotation (Placement(transformation(extent={{-60,-70},{-40,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{20,-110},{40,-90}}))); +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(pul.y, leaConPum.u) + annotation (Line(points={{-78,-60},{-62,-60}}, color={255,0,255})); + connect(leaConPum.y, enaTowCel.uLeaConWatPum) + annotation (Line(points={{-38,-60},{0,-60},{0,-6},{58,-6}}, color={255,0,255})); + connect(con.y, enaTowCel.uEnaPla) annotation (Line(points={{42,-100},{50,-100}, + {50,-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/Towers/Staging/Subsequences/Validation/CellsNumber.mos" + "Simulate and plot"), + Documentation(info=" +

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

+", 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..50fb06376da --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/ChangeCells.mo @@ -0,0 +1,56 @@ +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.Logical.Sources.Constant con2[4]( + final k={true,true,false,false}) + "Enabling cells index" + annotation (Placement(transformation(extent={{-60,-50},{-40,-30}}))); + 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}}))); + +equation + connect(celNum.y[1], enaTowCel.uCelNum) annotation (Line(points={{-38,40},{0,40}, + {0,4},{18,4}}, color={255,127,0})); + connect(con2.y, enaTowCel.uTowSta) annotation (Line(points={{-38,-40},{0,-40}, + {0,-4},{18,-4}}, 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. +

+", 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..0caec195cba --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Subsequences/Validation/StageProcesses.mo @@ -0,0 +1,115 @@ +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.Continuous.Switch swi[4] "Logical switch" + annotation (Placement(transformation(extent={{0,-50},{20,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.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. +

+", 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..aa71b1df72e --- /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.2.12.1 in ASHRAE RP-1711, Draft 6 (July 25, 2019). +

+"), +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..be3d67fc60c --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/Validation/Controller.mo @@ -0,0 +1,129 @@ +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,-40},{60,-20}}))); + Buildings.Controls.OBC.CDL.Logical.Pre pre1[2] "Actual cells status" + annotation (Placement(transformation(extent={{80,-60},{100,-40}}))); + Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[2]( + final samplePeriod=fill(2, 2)) "Actual isolation valve positions" + annotation (Placement(transformation(extent={{80,-100},{100,-80}}))); + 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={{-80,-70},{-60,-50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp chiStaGen( + final height=1.2, + final duration=3600, + final offset=1) "Generate chiller stage" + annotation (Placement(transformation(extent={{-120,10},{-100,30}}))); + Buildings.Controls.OBC.CDL.Conversions.RealToInteger chiStaSet + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-80,10},{-60,30}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul2( + final width=0.75, + final period=3600) "Boolean pulse" + annotation (Placement(transformation(extent={{-120,-30},{-100,-10}}))); + Buildings.Controls.OBC.CDL.Logical.Not StaTow "Stage tower cells" + annotation (Placement(transformation(extent={{-80,-30},{-60,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant conWatPumSpe[2]( + final k=fill(0.5, 2)) "Condenser water pump speed" + annotation (Placement(transformation(extent={{-80,-130},{-60,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pul( + final width=0.05, + final period=3600) + "Boolean pulse" + annotation (Placement(transformation(extent={{-120,-100},{-100,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Not leaConPum "Lead condenser water pump status" + annotation (Placement(transformation(extent={{-80,-100},{-60,-80}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1( + final k=false) + "Constant false" + annotation (Placement(transformation(extent={{-120,120},{-100,140}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant chiStaSet2( + final k=1) + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-80,90},{-60,110}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Pulse pul1( + final width=0.001, + final period=3600) + "Block that generates pulse signal of type Integer at simulation start time and has infinite number of periods" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + Buildings.Controls.OBC.CDL.Integers.Subtract intSub + "Chiller stage setpoint" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); +equation + connect(pre1.y, towSta.uTowSta) + annotation (Line(points={{102,-50},{120,-50},{120,-10},{-14,-10},{-14,-39},{ + 38,-39}}, color={255,0,255})); + connect(towSta.yIsoVal, zerOrdHol.u) + annotation (Line(points={{62,-30},{72,-30},{72,-90},{78,-90}}, color={0,0,127})); + connect(zerOrdHol.y, towSta.uIsoVal) + annotation (Line(points={{102,-90},{120,-90},{120,-110},{-20,-110},{-20,-37}, + {38,-37}}, color={0,0,127})); + connect(chiStaGen.y,chiStaSet. u) + annotation (Line(points={{-98,20},{-82,20}}, color={0,0,127})); + connect(booPul2.y,StaTow. u) + annotation (Line(points={{-98,-20},{-82,-20}}, color={255,0,255})); + connect(pul.y,leaConPum. u) + annotation (Line(points={{-98,-90},{-82,-90}}, color={255,0,255})); + connect(chiStaSet.y, towSta.uChiStaSet) annotation (Line(points={{-58,20},{24, + 20},{24,-23},{38,-23}}, color={255,127,0})); + connect(StaTow.y, towSta.uTowStaCha) annotation (Line(points={{-58,-20},{-40,-20}, + {-40,-25},{38,-25}}, color={255,0,255})); + connect(wseSta.y, towSta.uWse) annotation (Line(points={{-58,-60},{-34,-60},{-34, + -27},{38,-27}}, color={255,0,255})); + connect(leaConPum.y, towSta.uLeaConWatPum) annotation (Line(points={{-58,-90}, + {-30,-90},{-30,-31},{38,-31}}, color={255,0,255})); + connect(conWatPumSpe.y, towSta.uConWatPumSpe) annotation (Line(points={{-58,-120}, + {-26,-120},{-26,-33},{38,-33}}, color={0,0,127})); + connect(towSta.yTowSta, pre1.u) annotation (Line(points={{62,-34},{68,-34},{68, + -50},{78,-50}}, color={255,0,255})); + connect(con1.y, towSta.uEnaPla) annotation (Line(points={{-98,130},{0,130},{0, + -29},{38,-29}}, color={255,0,255})); + connect(pul1.y, intSub.u2) annotation (Line(points={{-98,60},{-48,60},{-48,74}, + {-42,74}}, color={255,127,0})); + connect(chiStaSet2.y, intSub.u1) annotation (Line(points={{-58,100},{-52,100}, + {-52,86},{-42,86}}, color={255,127,0})); + connect(intSub.y, towSta.uChiSta) annotation (Line(points={{-18,80},{20,80},{20, + -21},{38,-21}}, color={255,127,0})); +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. +

+", 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..a18ce6a6b97 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Staging/package.mo @@ -0,0 +1,47 @@ +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.2.12.1 in +ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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/Controller.mo b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/Controller.mo new file mode 100644 index 00000000000..90809ef9c9b --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/Controller.mo @@ -0,0 +1,270 @@ +within Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Validation; +model Controller "Validation sequence of controlling tower" + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.Controller + towCon( + nChi=2, + nTowCel=2, + nConWatPum=2, + have_WSE=true) + "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.Continuous.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.Continuous.Sources.Sine 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.Continuous.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.Continuous.Add conWatSupTem + "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-300,-210},{-280,-190}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Sine 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.Continuous.Add conWatRetTem + "Condenser water return temperature" + annotation (Placement(transformation(extent={{-300,-130},{-280,-110}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Sources.Constant hpTowSpe2(final k=0) + "Head pressure control maximum tower speed" + annotation (Placement(transformation(extent={{-360,-10},{-340,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant towFanSpe3(final k=0.2) + "Measured tower fan speed" + annotation (Placement(transformation(extent={{-320,170},{-300,190}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Or3 or3 "Logical or" + annotation (Placement(transformation(extent={{-140,-80},{-120,-60}}))); + Buildings.Controls.OBC.CDL.Logical.Not chiOneSta "Chiller one status" + annotation (Placement(transformation(extent={{-320,260},{-300,280}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) "Constant zero" + annotation (Placement(transformation(extent={{-320,10},{-300,30}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch swi1 "Logical switch" + annotation (Placement(transformation(extent={{-240,30},{-220,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Switch chiOneLoa "Chiller one load" + annotation (Placement(transformation(extent={{-260,320},{-240,340}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant chiTwoLoa(final k=0) + "Chiller two load" + annotation (Placement(transformation(extent={{-360,300},{-340,320}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Sine 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.Continuous.Sources.Sine chiSup( + final amplitude=0.5, + final freqHz=1/1800, + final offset=273.15 + 7.1) "Chilled water supply temperature" + annotation (Placement(transformation(extent={{-360,140},{-340,160}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp ram1( + final height=3, + final duration=3600, + final startTime=1500) "Ramp" + annotation (Placement(transformation(extent={{-360,100},{-340,120}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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.Continuous.Hysteresis leaConPum( + final uLow=0.005, final uHigh=0.01) + "Lead condenser water pump status" + annotation (Placement(transformation(extent={{-240,-190},{-220,-170}}))); + 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(chiTwoSta.y, or3.u2) annotation (Line(points={{-338,240},{-194,240},{-194, + -70},{-142,-70}}, color={255,0,255})); + connect(chiSta1.y, chiOneSta.u) + annotation (Line(points={{-338,270},{-322,270}}, color={255,0,255})); + connect(chiOneSta.y, or3.u1) annotation (Line(points={{-298,270},{-188,270},{-188, + -62},{-142,-62}}, 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={{-118,-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(conWatPumSpe1[1].y, leaConPum.u) annotation (Line(points={{-278,-160}, + {-260,-160},{-260,-180},{-242,-180}}, color={0,0,127})); + connect(leaConPum.y, towCon.uLeaConWatPum) annotation (Line(points={{-218, + -180},{114,-180},{114,345},{198,345}}, + color={255,0,255})); + connect(wseSta.y, wseSta1.u) + annotation (Line(points={{-338,210},{-322,210}}, color={255,0,255})); + connect(wseSta1.y, or3.u3) annotation (Line(points={{-298,210},{-200,210},{-200, + -78},{-142,-78}}, 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})); +annotation (experiment(StopTime=3600.0, Tolerance=1e-06), + __Dymola_Commands(file="modelica://Buildings/Resources/Scripts/Dymola/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/Controller.mos" + "Simulate and plot"), + Documentation(info=" +

+This example validates + +Buildings.Controls.OBC.ASHRAE.PrimarySystem.ChillerPlant.Towers.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={{-400,-420},{400,420}}))); +end Controller; 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..29db13d38e2 --- /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.Continuous.Sources.Sine 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/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..6c1e6b00faa --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/Validation/package.order @@ -0,0 +1,2 @@ +Controller +WaterLevel 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..52605573b67 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/WaterLevel.mo @@ -0,0 +1,103 @@ +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.Continuous.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 + annotation (Placement(transformation(extent={{40,-10},{60,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant minWatLev( + final k=watLevMin) "Minimum water level" + annotation (Placement(transformation(extent={{-40,-90},{-20,-70}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (Draft on March 23, 2020), +section 5.2.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..017e653e6c6 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Towers/package.mo @@ -0,0 +1,47 @@ +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.2.12 in +ASHRAE RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..f7c31985d12 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/Validation/Controller.mo @@ -0,0 +1,335 @@ +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.Continuous.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.TrueDelay truDel( + final delayTime=120, + final delayOnInit=true) + annotation (Placement(transformation(extent={{240,50},{260,70}}))); + Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1( + final delayTime=120, + final delayOnInit=true) + annotation (Placement(transformation(extent={{240,10},{260,30}}))); + 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.Continuous.Sources.Ramp TChiWatSup( + final height=4, + final duration=7200, + final offset=273.15 + 7) "Chilled water supply" + annotation (Placement(transformation(extent={{-280,-10},{-260,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TOutWet( + final k=283.15) + "Outdoor wet bulb temperatur" + annotation (Placement(transformation(extent={{-280,30},{-260,50}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TOut1( + final k=313.15) + "Outdoor dry bulb temperature" + annotation (Placement(transformation(extent={{-260,-190},{-240,-170}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Ramp TChiWatRet( + final height=5, + final duration=3600, + final offset=273.15 + 15) "Chilled water return temperature" + annotation (Placement(transformation(extent={{-240,10},{-220,30}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Constant TConWatRet( + final k=307.15) + "Condenser water return temperature" + annotation (Placement(transformation(extent={{-220,-250},{-200,-230}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant TConWatSup( + final k=305.15) + "Condenser water supply temperature" + annotation (Placement(transformation(extent={{-260,-230},{-240,-210}}))); + Buildings.Controls.OBC.CDL.Continuous.Max max1 + annotation (Placement(transformation(extent={{120,-150},{140,-130}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[2] + annotation (Placement(transformation(extent={{220,-50},{240,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro[2] + annotation (Placement(transformation(extent={{260,-30},{280,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.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,60},{-240,80}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[2] + annotation (Placement(transformation(extent={{-240,160},{-220,180}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[2] + annotation (Placement(transformation(extent={{-200,-138},{-180,-118}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiOneSta + "Chiller one status" + annotation (Placement(transformation(extent={{160,50},{180,70}}))); + Buildings.Controls.OBC.CDL.Logical.Pre chiTwoSta + "Chiller two status" + annotation (Placement(transformation(extent={{160,10},{180,30}}))); + 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.Continuous.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,-120},{140,-100}}))); + 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={{220,-20},{240,0}}))); + Buildings.Controls.OBC.CDL.Logical.Pre conWatPum[2]( + final pre_u_start=fill(false, 2)) + "Condenser water pump status setpoint" + annotation (Placement(transformation(extent={{120,-50},{140,-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,-80},{140,-60}}))); + Buildings.Controls.OBC.CDL.Continuous.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.Continuous.Sources.Ramp chiWatFlo( + final height=0.002, + final duration=10800, + final offset=0.0075) "Chilled water flow" + annotation (Placement(transformation(extent={{-300,-210},{-280,-190}}))); + 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.Continuous.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}}))); +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,60},{158,60}}, color={255,0,255})); + connect(chiPlaCon.yChi[2], chiTwoSta.u) annotation (Line(points={{90,102.5},{114, + 102.5},{114,20},{158,20}}, color={255,0,255})); + connect(chiOneSta.y, truDel.u) + annotation (Line(points={{182,60},{238,60}}, color={255,0,255})); + connect(chiTwoSta.y, truDel1.u) + annotation (Line(points={{182,20},{238,20}}, 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={{-258,40},{-150,40},{-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,20},{-128,20},{-128,80},{-30,80}}, + color={0,0,127})); + connect(TChiWatSup.y, chiPlaCon.TChiWatSup) + annotation (Line(points={{-258,0},{-144,0},{-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(max1.y, chiPlaCon.uFanSpe) annotation (Line(points={{142,-140},{170,-140}, + {170,-200},{-60,-200},{-60,-130},{-30,-130}}, 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(chiOneSta.y, chiPlaCon.uChiIsoVal[1]) annotation (Line(points={{182,60}, + {200,60},{200,250},{-120,250},{-120,167.5},{-30,167.5}}, color={255, + 0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiIsoVal[2]) annotation (Line(points={{182,20}, + {190,20},{190,240},{-110,240},{-110,172.5},{-30,172.5}}, color={255,0, + 255})); + connect(chiOneSta.y, chiPlaCon.uChiConIsoVal[1]) annotation (Line(points={{182,60}, + {200,60},{200,250},{-120,250},{-120,207.5},{-30,207.5}}, color= + {255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiConIsoVal[2]) annotation (Line(points={{182,20}, + {190,20},{190,240},{-110,240},{-110,212.5},{-30,212.5}}, color={ + 255,0,255})); + 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,-110},{118,-110}}, color={0,0,127})); + connect(zerOrdHol.y, chiPlaCon.uIsoVal) annotation (Line(points={{142,-110},{180, + -110},{180,-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},{118,-40}}, color={255,0,255})); + connect(conWatPum.y, chiPlaCon.uConWatPum) annotation (Line(points={{142,-40}, + {210,-40},{210,-230},{-100,-230},{-100,-90},{-30,-90}}, + color={255,0,255})); + connect(conWatPum.y, booToRea.u) + annotation (Line(points={{142,-40},{218,-40}}, + color={255,0,255})); + connect(zerOrdHol1.y, pro.u1) annotation (Line(points={{242,-10},{250,-10},{ + 250,-14},{258,-14}}, + color={0,0,127})); + connect(booToRea.y, pro.u2) annotation (Line(points={{242,-40},{250,-40},{250, + -26},{258,-26}}, + color={0,0,127})); + connect(pro.y, chiPlaCon.uConWatPumSpe) annotation (Line(points={{282,-20},{300, + -20},{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,-70},{118,-70}}, color={0,0,127})); + connect(zerOrdHol2.y, chiPlaCon.uChiWatIsoVal) annotation (Line(points={{142,-70}, + {190,-70},{190,-220},{-80,-220},{-80,-40},{-30,-40}}, color={0,0, + 127})); + connect(dpChiWat.y, chiPlaCon.dpChiWat_remote[1]) annotation (Line(points={{-238,70}, + {-180,70},{-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(chiWatFlo.y, chiPlaCon.VChiWat_flow) annotation (Line(points={{-278,-200}, + {-160,-200},{-160,130},{-30,130}}, color={0,0,127})); + connect(chiOneSta.y, booToRea1[1].u) annotation (Line(points={{182,60},{200, + 60},{200,250},{-260,250},{-260,170},{-242,170}}, color={255,0,255})); + connect(chiTwoSta.y, booToRea1[2].u) annotation (Line(points={{182,20},{190, + 20},{190,240},{-254,240},{-254,170},{-242,170}}, color={255,0,255})); + connect(chiOneSta.y, chiPlaCon.uChi[1]) annotation (Line(points={{182,60},{200, + 60},{200,250},{-120,250},{-120,117.5},{-30,117.5}},color={255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChi[2]) annotation (Line(points={{182,20},{190, + 20},{190,240},{-110,240},{-110,122.5},{-30,122.5}}, + color={255,0,255})); + connect(chiOneSta.y, chiPlaCon.uChiWatReq[1]) annotation (Line(points={{182,60}, + {200,60},{200,250},{-120,250},{-120,197.5},{-30,197.5}}, color={255, + 0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiWatReq[2]) annotation (Line(points={{182,20}, + {190,20},{190,240},{-110,240},{-110,202.5},{-30,202.5}}, color={255,0, + 255})); + connect(chiOneSta.y, chiPlaCon.uConWatReq[1]) annotation (Line(points={{182,60}, + {200,60},{200,250},{-120,250},{-120,187.5},{-30,187.5}}, color={255, + 0,255})); + connect(chiTwoSta.y, chiPlaCon.uConWatReq[2]) annotation (Line(points={{182,20}, + {190,20},{190,240},{-110,240},{-110,192.5},{-30,192.5}}, color={255,0, + 255})); + connect(chiPlaCon.yConWatPumSpe, zerOrdHol1.u) annotation (Line(points={{90,50}, + {140,50},{140,-10},{218,-10}}, + color={0,0,127})); + connect(chiOneSta.y, chiPlaCon.uChiHeaCon[1]) annotation (Line(points={{182,60}, + {200,60},{200,250},{-120,250},{-120,-32.5},{-30,-32.5}}, + color={255,0,255})); + connect(chiTwoSta.y, chiPlaCon.uChiHeaCon[2]) annotation (Line(points={{182,20}, + {190,20},{190,240},{-110,240},{-110,-27.5},{-30,-27.5}}, + color={255,0,255})); + + 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})); +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. +

+", 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..583f9442b6e --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/ChillerPlant/package.mo @@ -0,0 +1,26 @@ +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 RP-1711 Advanced Sequences of +Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), + 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..b403f5b6301 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.mo @@ -0,0 +1,48 @@ +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 RP-1711 Advanced Sequences of Operation for HVAC Systems Phase II – +Central Plants and Hydronic Systems (draft version on March 23, 2020). +

+"), +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..d4fd55856a2 --- /dev/null +++ b/Buildings/Controls/OBC/ASHRAE/PrimarySystem/package.order @@ -0,0 +1,2 @@ +BoilerPlant +ChillerPlant diff --git a/Buildings/Controls/OBC/ASHRAE/package.order b/Buildings/Controls/OBC/ASHRAE/package.order index f718b0a1739..a20c96ab04e 100644 --- a/Buildings/Controls/OBC/ASHRAE/package.order +++ b/Buildings/Controls/OBC/ASHRAE/package.order @@ -1 +1,2 @@ G36 +PrimarySystem \ No newline at end of file diff --git a/Buildings/Examples/BoilerPlant/Baseclasses/BoilerPlant.mo b/Buildings/Examples/BoilerPlant/Baseclasses/BoilerPlant.mo new file mode 100644 index 00000000000..936ed42d343 --- /dev/null +++ b/Buildings/Examples/BoilerPlant/Baseclasses/BoilerPlant.mo @@ -0,0 +1,914 @@ +within Buildings.Examples.BoilerPlant.Baseclasses; +model BoilerPlant "Boiler plant model for closed loop testing" + replaceable package MediumA = + Buildings.Media.Air; + + replaceable package MediumW = + Buildings.Media.Water + "Medium model"; + + parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal = boiEff1[1]*boiCap1 + boiEff2[1]*boiCap2 + "Nominal heat flow rate of radiator" + annotation(dialog(group="Plant parameters")); + + parameter Real TPlaHotWatSetMax( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 353.15 + "The maximum allowed hot-water setpoint temperature for the plant" + annotation(Dialog(group="Boiler parameters")); + + parameter Real THotWatSetMinConBoi( + final unit="K", + displayUnit="K", + final quantity="ThermodynamicTemperature") = 305.37 + "The minimum allowed hot-water setpoint temperature for condensing boilers" + annotation(Dialog(group="Boiler parameters")); + + parameter Modelica.Units.SI.HeatFlowRate boiCap1= 2200000 + "Boiler capacity for boiler-1" + annotation(dialog(group="Boiler parameters")); + + parameter Modelica.Units.SI.HeatFlowRate boiCap2= 2200000 + "Boiler capacity for boiler-2" + annotation(dialog(group="Boiler parameters")); + + parameter Real boiEff1[6]( + final unit="1", + displayUnit="1") = {0.6246, 0.7711, -1.2077*10e-15, 0.008576, -0.005933, 0.003156} + "Efficiency for boiler-1" + annotation(dialog(group="Boiler parameters")); + + parameter Real boiEff2[6]( + final unit="1", + displayUnit="1") = {0.6246, 0.7711, -1.2077*10e-15, 0.008576, -0.005933, 0.003156} + "Efficiency for boiler-2" + annotation(dialog(group="Boiler parameters")); + + parameter Modelica.Units.SI.MassFlowRate mSec_flow_nominal=0.113*1000 + "Secondary load nominal mass flow rate" + annotation(dialog(group="Plant parameters")); + + parameter Modelica.Units.SI.Temperature TBoiSup_nominal = 273.15+70 + "Boiler nominal supply water temperature" + annotation(dialog(group="Boiler parameters")); + + parameter Modelica.Units.SI.Temperature TBoiRet_min = 273.15+60 + "Boiler minimum return water temperature" + annotation(dialog(group="Boiler parameters")); + + parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal1=mSec_flow_nominal + "Boiler-1 nominal mass flow rate" + annotation(dialog(group="Boiler parameters")); + + parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal2=mSec_flow_nominal + "Boiler-2 nominal mass flow rate" + annotation(dialog(group="Boiler parameters")); + + constant Buildings.Fluid.Boilers.Data.Lochinvar.Crest.FBdash2501 perBoiOri + "Original record for boiler performance data is scaled below"; + + parameter Buildings.Fluid.Boilers.Data.Lochinvar.Crest.FBdash2501 perBoi1( + final Q_flow_nominal = boiCap1, + final VWat = boiCap1/perBoiOri.Q_flow_nominal*perBoiOri.VWat, + final mDry = boiCap1/perBoiOri.Q_flow_nominal*perBoiOri.mDry, + final m_flow_nominal = boiCap1/perBoiOri.Q_flow_nominal*perBoiOri.m_flow_nominal) + "Boiler performance data, scaled to while keeping dp_nominal constant" + annotation (Placement(transformation(extent={{260,162},{280,182}}))); + + parameter Buildings.Fluid.Boilers.Data.Lochinvar.Crest.FBdash2501 perBoi2( + final Q_flow_nominal = boiCap2, + final VWat = boiCap2/perBoiOri.Q_flow_nominal*perBoiOri.VWat, + final mDry = boiCap2/perBoiOri.Q_flow_nominal*perBoiOri.mDry, + final m_flow_nominal = boiCap2/perBoiOri.Q_flow_nominal*perBoiOri.m_flow_nominal) + "Boiler performance data, scaled to while keeping dp_nominal constant" + annotation (Placement(transformation(extent={{260,192},{280,212}}))); + + parameter Modelica.Units.SI.PressureDifference dpValve_nominal_value=6000 + "Nominal pressure drop of fully open valve, used if CvData=Buildings.Fluid.Types.CvTypes.OpPoint"; + + parameter Modelica.Units.SI.PressureDifference dpFixed_nominal_value=1000 + "Pressure drop of pipe and other resistances that are in series"; + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypePla= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="PI parameters", group="Plant supply water temperature controller")); + + parameter Real kPla( + final unit="1", + displayUnit="1", + final min=0)=10e-3 + "Gain of controller" + annotation(Dialog(tab="PI parameters", group="Plant supply water temperature controller")); + + parameter Real TiPla( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=90 + "Time constant of integrator block" + annotation(Dialog(tab="PI parameters", group="Plant supply water temperature controller", + enable = (controllerTypePla == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or controllerTypePla == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdPla( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=0.1 + "Time constant of derivative block" + annotation(Dialog(tab="PI parameters", group="Plant supply water temperature controller", + enable = (controllerTypePla == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or controllerTypePla == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeBoi1= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="PI parameters", group="Boiler-1 supply water temperature controller")); + + parameter Real kBoi1( + final unit="1", + displayUnit="1", + final min=0)=10e-3 + "Gain of controller" + annotation(Dialog(tab="PI parameters", group="Boiler-1 supply water temperature controller")); + + parameter Real TiBoi1( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=90 + "Time constant of integrator block" + annotation(Dialog(tab="PI parameters", group="Boiler-1 supply water temperature controller", + enable = (controllerTypeBoi1 == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or controllerTypeBoi1 == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdBoi1( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=0.1 + "Time constant of derivative block" + annotation(Dialog(tab="PI parameters", group="Boiler-1 supply water temperature controller", + enable = (controllerTypeBoi1 == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or controllerTypeBoi1 == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeBoi2= + Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller" + annotation(Dialog(tab="PI parameters", group="Boiler-2 supply water temperature controller")); + + parameter Real kBoi2( + final unit="1", + displayUnit="1", + final min=0)=10e-3 + "Gain of controller" + annotation(Dialog(tab="PI parameters", group="Boiler-2 supply water temperature controller")); + + parameter Real TiBoi2( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=90 + "Time constant of integrator block" + annotation(Dialog(tab="PI parameters", group="Boiler-2 supply water temperature controller", + enable = (controllerTypeBoi2 == Buildings.Controls.OBC.CDL.Types.SimpleController.PI + or controllerTypeBoi2 == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + parameter Real TdBoi2( + final unit="s", + displayUnit="s", + final quantity="time", + final min=0)=0.1 + "Time constant of derivative block" + annotation(Dialog(tab="PI parameters", group="Boiler-2 supply water temperature controller", + enable = (controllerTypeBoi2 == Buildings.Controls.OBC.CDL.Types.SimpleController.PD + or controllerTypeBoi2 == Buildings.Controls.OBC.CDL.Types.SimpleController.PID))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uBoiSta[2] + "Boiler status signal" + annotation (Placement(transformation(extent={{-360,140},{-320,180}}), + iconTransformation(extent={{-140,70},{-100,110}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPumSta[1] + "Pump status signal" + annotation (Placement(transformation(extent={{-360,20},{-320,60}}), + iconTransformation(extent={{-140,10},{-100,50}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uPla + "Plant enable signal" + annotation (Placement(transformation(extent={{-360,180},{-320,220}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uHotIsoVal[2]( + final unit="1", + displayUnit="1") + "Hot water isolation valve signal" + annotation (Placement(transformation(extent={{-360,60},{-320,100}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uPumSpe( + final unit="1", + displayUnit="1") + "Pump speed signal" + annotation (Placement(transformation(extent={{-360,-20},{-320,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput uBypValSig( + final unit="1", + displayUnit="1") + "Bypass valve signal" + annotation (Placement(transformation(extent={{-360,-60},{-320,-20}}), + iconTransformation(extent={{-140,-50},{-100,-10}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TBoiHotWatSupSet[2]( + final unit=fill("K", 2), + displayUnit=fill("degC", 2), + final quantity=fill("ThermodynamicTemperature", 2)) + "Boiler hot water supply temperature setpoint vector" + annotation (Placement(transformation(extent={{-360,-130},{-320,-90}}), + iconTransformation(extent={{-140,-110},{-100,-70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TZon( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured zone air temperature" + annotation (Placement(transformation(extent={{-360,-90},{-320,-50}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput TPlaHotWatSupSet( + final unit=fill("K", 2), + displayUnit=fill("degC", 2), + final quantity=fill("ThermodynamicTemperature", 2)) + "Plant hot water supply temperature setpoint" + annotation (Placement(transformation(extent={{-360,-180},{-320,-140}}), + iconTransformation(extent={{-140,-140},{-100,-100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yBoiSta[2] + "Boiler status signal" + annotation (Placement(transformation(extent={{320,-90},{360,-50}}), + iconTransformation(extent={{100,-70},{140,-30}}))); + + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yPumSta[1] + "Pump status signal" + annotation (Placement(transformation(extent={{320,-130},{360,-90}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySupTem( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured supply temperature" + annotation (Placement(transformation(extent={{320,80},{360,120}}), + iconTransformation(extent={{100,60},{140,100}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetTem( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured return temperature" + annotation (Placement(transformation(extent={{320,40},{360,80}}), + iconTransformation(extent={{100,30},{140,70}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatDp[1]( + final unit="Pa", + displayUnit="Pa") + "Hot water differential pressure between supply and return" + annotation (Placement(transformation(extent={{320,-10},{360,30}}), + iconTransformation(extent={{100,0},{140,40}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput VHotWat_flow( + final unit="m3/s", + displayUnit="m3/s", + final quantity="VolumeFlowRate") + "Measured flowrate in primary circuit" + annotation (Placement(transformation(extent={{320,-50},{360,-10}}), + iconTransformation(extent={{100,-40},{140,0}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHotWatIsoVal[2]( + final unit="1", + displayUnit="1") + "Measured boiler hot water isolation valve position" + annotation (Placement(transformation(extent={{320,-170},{360,-130}}), + iconTransformation(extent={{100,-130},{140,-90}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yBypValPos( + final unit="1", + displayUnit="1") + "Measured bypass valve position" + annotation (Placement(transformation(extent={{320,130},{360,170}}), + iconTransformation(extent={{100,90},{140,130}}))); + + Modelica.Fluid.Interfaces.FluidPort_a port_a( + redeclare package Medium = MediumW) + "HW inlet port" + annotation (Placement(transformation(extent={{30,230},{50,250}}), + iconTransformation(extent={{60,130},{80,150}}))); + + Modelica.Fluid.Interfaces.FluidPort_b port_b( + redeclare package Medium = MediumW) + "HW outlet port" + annotation (Placement(transformation(extent={{-50,230},{-30,250}}), + iconTransformation(extent={{-80,130},{-60,150}}))); + + Buildings.Fluid.Sources.Boundary_pT preSou( + redeclare package Medium = MediumW, + p=100000, + nPorts=1) + "Source for pressure and to account for thermal expansion of water" + annotation (Placement(transformation(extent={{18,-78},{-2,-58}}))); + + Buildings.Fluid.Boilers.BoilerTable boi2( + redeclare package Medium = MediumW, + allowFlowReversal=false, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + per=perBoi2) "Boiler-2" + annotation (Placement(transformation(extent={{110,-220},{90,-200}}))); + + Buildings.Fluid.Boilers.BoilerTable boi1( + redeclare package Medium = MediumW, + allowFlowReversal=false, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final per=perBoi1) "Boiler-1" + annotation (Placement(transformation(extent={{110,-160},{90,-140}}))); + + Buildings.Fluid.Movers.SpeedControlled_y pum( + redeclare package Medium = MediumW, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final allowFlowReversal=false, + redeclare Buildings.Fluid.Movers.Data.Generic per( + final pressure(V_flow={0,2*mSec_flow_nominal/1000}, + final dp={2*75000,0})), + final inputType=Buildings.Fluid.Types.InputType.Continuous, + final addPowerToMedium=false, + final riseTime=60) + "Hot water primary pump-1" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={-30,-50}))); + + Buildings.Fluid.FixedResistances.Junction spl1( + redeclare package Medium = MediumW, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final m_flow_nominal={mBoi_flow_nominal2,-mSec_flow_nominal,mBoi_flow_nominal1}, + final dp_nominal={0,0,0}) + "Splitter" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={-30,-150}))); + + Buildings.Fluid.FixedResistances.Junction spl4( + redeclare package Medium = MediumW, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final m_flow_nominal={mSec_flow_nominal,-mSec_flow_nominal,-mSec_flow_nominal}, + final dp_nominal={0,0,0}) + "Splitter" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={-30,40}))); + + Buildings.Fluid.Actuators.Valves.TwoWayLinear val( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal, + final dpValve_nominal=dpValve_nominal_value, + final dpFixed_nominal=dpFixed_nominal_value) + "Minimum flow bypass valve" + annotation (Placement(transformation(extent={{80,30},{100,50}}))); + + Buildings.Fluid.FixedResistances.Junction spl5( + redeclare package Medium = MediumW, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final m_flow_nominal={mSec_flow_nominal,mSec_flow_nominal,-mSec_flow_nominal}, + final dp_nominal={0,0,0}) + "Splitter" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=270, + origin={210,40}))); + + Buildings.Fluid.Actuators.Valves.TwoWayLinear val2( + redeclare package Medium = MediumW, + final m_flow_nominal=mBoi_flow_nominal2, + final dpValve_nominal=dpValve_nominal_value, + final use_inputFilter=true, + final init=Modelica.Blocks.Types.Init.InitialState, + final y_start=0, + final dpFixed_nominal=dpFixed_nominal_value) + "Isolation valve for boiler-2" + annotation (Placement(transformation(extent={{0,-220},{20,-200}}))); + + Buildings.Fluid.Actuators.Valves.TwoWayLinear val1( + redeclare package Medium = MediumW, + final m_flow_nominal=mBoi_flow_nominal1, + final dpValve_nominal=dpValve_nominal_value, + final init=Modelica.Blocks.Types.Init.InitialState, + final y_start=0, + final dpFixed_nominal=dpFixed_nominal_value) + "Isolation valve for boiler-1" + annotation (Placement(transformation(extent={{0,-160},{20,-140}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1[2] + "Boolean to Real conversion" + annotation (Placement(transformation(extent={{-160,150},{-140,170}}))); + + Buildings.Fluid.Sensors.RelativePressure senRelPre( + redeclare package Medium = MediumW) + "Differential pressure sensor between hot water supply and return" + annotation (Placement(transformation(extent={{80,70},{100,90}}))); + + Buildings.Fluid.Sensors.VolumeFlowRate senVolFlo( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal/1000) + "Volume flow-rate through primary circuit" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={-30,-10}))); + + Buildings.Fluid.Sensors.TemperatureTwoPort senTem( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "HW supply temperature sensor" + annotation (Placement(transformation(extent={{-20,110},{0,130}}))); + + Buildings.Fluid.Sensors.TemperatureTwoPort senTem1( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "HW return temperature sensor before water enters return plumbing" + annotation (Placement(transformation(extent={{60,110},{80,130}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep( + final nout=1) + "Real replicator" + annotation (Placement(transformation(extent={{280,0},{300,20}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys2( + final uLow=0.05, + final uHigh=0.09) + "Check if pumps are on" + annotation (Placement(transformation(extent={{100,-40},{120,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Timer timPumSta(final t=120) + "Output pump proven on signal when pump status is enabled for two minutes" + annotation (Placement(transformation(extent={{140,-40},{160,-20}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Hold pump enable status until change process is completed" + annotation (Placement(transformation(extent={{-300,30},{-280,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi + "Switch to signal from controller once enabling process has been completed" + annotation (Placement(transformation(extent={{-260,30},{-240,50}}))); + + Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[2] + "Switch to signal from controller once enabling process has been completed" + annotation (Placement(transformation(extent={{-210,150},{-190,170}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat1[2] + "Hold boiler enable status until boiler is proven on" + annotation (Placement(transformation(extent={{-260,150},{-240,170}}))); + + Buildings.Controls.OBC.CDL.Continuous.PIDWithReset conPIDBoi[2]( + final controllerType={controllerTypeBoi1,controllerTypeBoi2}, + final k={kBoi1,kBoi2}, + final Ti={TiBoi1,TiBoi2}, + final Td={TdBoi1,TdBoi2}, + final yMax=fill(1, 2), + final yMin=fill(0, 2), + final xi_start=fill(0.2, 2)) + "PI controller for operating boilers to regulating hot water supply temperature" + annotation (Placement(transformation(extent={{40,-130},{60,-110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply pro1[2] + "Product of boiler power and current status" + annotation (Placement(transformation(extent={{-120,-130},{-100,-110}}))); + + Buildings.Fluid.FixedResistances.Junction spl6( + redeclare package Medium = MediumW, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final m_flow_nominal={-mBoi_flow_nominal1,mSec_flow_nominal,-mBoi_flow_nominal2}, + final dp_nominal={0,0,0}) + "Splitter" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=0, + origin={150,-150}))); + + Buildings.Fluid.Sensors.RelativePressure senRelPre1( + redeclare package Medium = MediumW) + "Differential pressure sensor between hot water supply and return" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={-70,-10}))); + + Buildings.Controls.OBC.CDL.Continuous.LessThreshold lesThr[2]( + final t=fill(0.02, 2), + final h=fill(0.02/10, 2)) + "Determine if boilers are disabled" + annotation (Placement(transformation(extent={{180,-130},{200,-110}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre2[2] + "Logical pre block" + annotation (Placement(transformation(extent={{240,-86},{260,-66}}))); + + Buildings.Controls.OBC.CDL.Logical.Latch lat2[2] + "Determine boiler enable status based on PLR and hold it till the boiler disable limit is passed" + annotation (Placement(transformation(extent={{280,-80},{300,-60}}))); + + Buildings.Fluid.FixedResistances.PlugFlowPipe pipe( + redeclare package Medium = MediumW, + final allowFlowReversal=false, + final m_flow_nominal=mSec_flow_nominal, + final have_pipCap=false, + final length=2000, + final dIns=0.0508, + final kIns=0.0389) + "Dynamic pipe element to represent duct loss" + annotation (Placement(transformation(extent={{130,110},{150,130}}))); + + Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TRoo + "Room temperature of boiler room" + annotation (Placement(transformation(extent={{-280,-80},{-260,-60}}))); + + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1( + final nout=1) + "Boolean replicator" + annotation (Placement(transformation(extent={{280,-120},{300,-100}}))); + + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThr3[2]( + final t=fill(0.02,2), + final h=fill(0.02/10, 2)) + "Check if boiler is enabled" + annotation (Placement(transformation(extent={{180,-210},{200,-190}}))); + + Buildings.Controls.OBC.CDL.Logical.Pre pre3[2] + "Logical pre block" + annotation (Placement(transformation(extent={{240,-210},{260,-190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Switch swiPum + "Switch for pump" + annotation (Placement(transformation(extent={{-220,-20},{-200,0}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant zer( + final k=0) + "Zero output signal" + annotation (Placement(transformation(extent={{-300,-30},{-280,-10}}))); + + Buildings.Controls.OBC.CDL.Continuous.PIDWithReset conPIDPla( + final controllerType=controllerTypePla, + final k=kPla, + final Ti=TiPla, + final Td=TdPla, + final yMax=1, + final yMin=0) + "PI controller for setting boiler supply temperature setpoint" + annotation (Placement(transformation(extent={{-10,170},{10,190}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg[2] + "Detect changes to boiler status setpoints" + annotation (Placement(transformation(extent={{-170,110},{-150,130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Line lin[2] + "Intrapolate plant supply temperature PI signal to boiler supply temperature setpoint" + annotation (Placement(transformation(extent={{-180,-190},{-160,-170}}))); + + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaScaRep( + final nout=2) + "Replicate plant PI signal to each boiler PI controller" + annotation (Placement(transformation(extent={{140,170},{160,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con[2]( + final k=fill(0, 2)) + "Support point for boiler setpoint" + annotation (Placement(transformation(extent={{-240,-150},{-220,-130}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con1[2]( + final k=fill(1, 2)) + "Support point for boiler setpoint" + annotation (Placement(transformation(extent={{-240,-210},{-220,-190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con2[2]( + final k=fill(TPlaHotWatSetMax, 2)) + "Max boiler plant supply temperature" + annotation (Placement(transformation(extent={{-280,-190},{-260,-170}}))); + + Buildings.Controls.OBC.CDL.Logical.Edge edg1 + "Detect plant enable signal becoming true" + annotation (Placement(transformation(extent={{-130,170},{-110,190}}))); + + Buildings.Controls.OBC.CDL.Continuous.Multiply mul + "Send zero signal when the plant is disabled" + annotation (Placement(transformation(extent={{100,170},{120,190}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea + "Convert plant enable Boolean signal to Real signal" + annotation (Placement(transformation(extent={{60,190},{80,210}}))); + + Buildings.Fluid.Sensors.TemperatureTwoPort senTem2( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "HW return temperature sensor in primary circuit" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=-90, + origin={210,-10}))); + + Buildings.Fluid.Sensors.VolumeFlowRate senVolFlo1( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "Volume flow-rate through minimum flow bypass branch" + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + + Buildings.Fluid.Sensors.TemperatureTwoPort senTem3( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "HW return temperature sensor" + annotation (Placement(transformation(extent={{120,30},{140,50}}))); + + Buildings.Fluid.Sensors.VolumeFlowRate senVolFlo2( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "Volume flow-rate through secondary circuit" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={-30,104}))); + + Buildings.Fluid.Sensors.TemperatureTwoPort senTem4( + redeclare package Medium = MediumW, + final m_flow_nominal=mSec_flow_nominal) + "HW return temperature sensor after water exits return plumbing" + annotation (Placement(transformation(extent={{180,110},{200,130}}))); + +equation + connect(val1.port_a, spl1.port_3) + annotation (Line(points={{0,-150},{-20,-150}}, color={0,127,255})); + connect(val2.port_a, spl1.port_1) annotation (Line(points={{0,-210},{-30,-210}, + {-30,-160}}, color={0,127,255})); + + connect(spl4.port_2, senRelPre.port_a) annotation (Line(points={{-30,50},{-30, + 80},{80,80}}, color={0,127,255})); + + connect(senRelPre.port_b, spl5.port_1) annotation (Line(points={{100,80},{210, + 80},{210,50}}, color={0,127,255})); + + connect(senVolFlo.port_b, spl4.port_1) annotation (Line(points={{-30,0},{-30,30}}, + color={0,127,255})); + + connect(senVolFlo.V_flow, VHotWat_flow) annotation (Line(points={{-41,-10},{ + -41,16},{180,16},{180,-30},{340,-30}}, color={0,0,127})); + + connect(senTem.T, ySupTem) annotation (Line(points={{-10,131},{-10,140},{270, + 140},{270,100},{340,100}}, color={0,0,127})); + + connect(reaRep.y, yHotWatDp) + annotation (Line(points={{302,10},{340,10}}, color={0,0,127})); + + connect(senRelPre.p_rel, reaRep.u) annotation (Line(points={{90,71},{90,66},{240, + 66},{240,10},{278,10}}, color={0,0,127})); + + connect(hys2.y, timPumSta.u) + annotation (Line(points={{122,-30},{138,-30}}, color={255,0,255})); + connect(lat.y, logSwi.u2) + annotation (Line(points={{-278,40},{-262,40}}, color={255,0,255})); + connect(lat.y, logSwi.u1) annotation (Line(points={{-278,40},{-270,40},{-270, + 48},{-262,48}}, color={255,0,255})); + connect(uBoiSta, lat1.u) + annotation (Line(points={{-340,160},{-262,160}}, color={255,0,255})); + connect(lat1.y, logSwi1.u2) + annotation (Line(points={{-238,160},{-212,160}}, color={255,0,255})); + connect(logSwi1.y, booToRea1.u) + annotation (Line(points={{-188,160},{-162,160}}, color={255,0,255})); + connect(uBoiSta, logSwi1.u3) annotation (Line(points={{-340,160},{-310,160},{ + -310,140},{-220,140},{-220,152},{-212,152}}, color={255,0,255})); + connect(lat1.y, logSwi1.u1) annotation (Line(points={{-238,160},{-220,160},{ + -220,168},{-212,168}}, color={255,0,255})); + connect(booToRea1.y, pro1.u1) annotation (Line(points={{-138,160},{-130,160},{ + -130,-114},{-122,-114}}, color={0,0,127})); + connect(boi1.port_a, spl6.port_1) + annotation (Line(points={{110,-150},{140,-150}}, color={0,127,255})); + connect(boi2.port_a, spl6.port_3) annotation (Line(points={{110,-210},{150,-210}, + {150,-160}}, color={0,127,255})); + connect(senTem1.port_a, port_a) + annotation (Line(points={{60,120},{40,120},{40,240}}, color={0,127,255})); + connect(val.y_actual, yBypValPos) annotation (Line(points={{95,47},{120,47},{120, + 150},{340,150}}, color={0,0,127})); + connect(pre2.y, lat2.clr) annotation (Line(points={{262,-76},{278,-76}}, + color={255,0,255})); + connect(lat2.y, yBoiSta) + annotation (Line(points={{302,-70},{340,-70}}, color={255,0,255})); + connect(lesThr.y, pre2.u) annotation (Line(points={{202,-120},{220,-120},{220, + -76},{238,-76}}, color={255,0,255})); + connect(TZon, TRoo.T) + annotation (Line(points={{-340,-70},{-282,-70}}, color={0,0,127})); + connect(pum.port_b, senVolFlo.port_a) + annotation (Line(points={{-30,-40},{-30,-20}}, color={0,127,255})); + connect(senRelPre1.port_a, spl1.port_2) annotation (Line(points={{-70,-20},{-70, + -140},{-30,-140}}, color={0,127,255})); + connect(senRelPre1.port_b, spl4.port_1) + annotation (Line(points={{-70,0},{-70,30},{-30,30}}, color={0,127,255})); + connect(booRep1.y, yPumSta) + annotation (Line(points={{302,-110},{340,-110}}, color={255,0,255})); + connect(timPumSta.passed, booRep1.u) annotation (Line(points={{162,-38},{230,-38}, + {230,-110},{278,-110}}, color={255,0,255})); + connect(uPumSta[1], logSwi.u3) annotation (Line(points={{-340,40},{-308,40},{-308, + 20},{-270,20},{-270,32},{-262,32}}, color={255,0,255})); + connect(uPumSta[1], lat.u) + annotation (Line(points={{-340,40},{-302,40}}, color={255,0,255})); + connect(uBypValSig, val.y) annotation (Line(points={{-340,-40},{-120,-40},{-120, + 60},{90,60},{90,52}}, color={0,0,127})); + connect(spl1.port_2, pum.port_a) + annotation (Line(points={{-30,-140},{-30,-60}}, color={0,127,255})); + connect(senTem.port_b, port_b) annotation (Line(points={{0,120},{10,120},{10, + 160},{-40,160},{-40,240}}, color={0,127,255})); + connect(preSou.ports[1], pum.port_a) annotation (Line(points={{-2,-68},{-30,-68}, + {-30,-60}}, color={0,127,255})); + connect(greThr3.y, pre3.u) + annotation (Line(points={{202,-200},{238,-200}}, color={255,0,255})); + connect(pre3.y, lat2.u) annotation (Line(points={{262,-200},{266,-200},{266,-70}, + {278,-70}}, color={255,0,255})); + connect(TRoo.port, pipe.heatPort) annotation (Line(points={{-260,-70},{-140, + -70},{-140,100},{100,100},{100,130},{140,130}}, + color={191,0,0})); + connect(boi1.heatPort, TRoo.port) annotation (Line(points={{100,-142.8},{100, + -86},{-120,-86},{-120,-70},{-260,-70}}, color={191,0,0})); + connect(boi2.heatPort, TRoo.port) annotation (Line(points={{100,-202.8},{100,-180}, + {84,-180},{84,-86},{-120,-86},{-120,-70},{-260,-70}}, color={191,0,0})); + connect(timPumSta.passed, lat.clr) annotation (Line(points={{162,-38},{230,-38}, + {230,-232},{-314,-232},{-314,34},{-302,34}}, color={255,0,255})); + connect(lat2.y, lat1.clr) annotation (Line(points={{302,-70},{306,-70},{306, + 220},{-300,220},{-300,154},{-262,154}}, color={255,0,255})); + connect(val1.port_b,boi1. port_b) + annotation (Line(points={{20,-150},{90,-150}}, color={0,127,255})); + connect(val2.port_b, boi2.port_b) + annotation (Line(points={{20,-210},{90,-210}}, color={0,127,255})); + connect(boi1.T, conPIDBoi[1].u_m) + annotation (Line(points={{89,-142},{50,-142},{50,-132}}, color={0,0,127})); + connect(boi2.T, conPIDBoi[2].u_m) + annotation (Line(points={{89,-202},{50,-202},{50,-132}}, color={0,0,127})); + connect(hys2.u, pum.y_actual) + annotation (Line(points={{98,-30},{-37,-30},{-37,-39}}, color={0,0,127})); + connect(uPumSpe, swiPum.u1) annotation (Line(points={{-340,0},{-300,0},{-300,-2}, + {-222,-2}}, color={0,0,127})); + connect(zer.y, swiPum.u3) annotation (Line(points={{-278,-20},{-270,-20},{-270, + -18},{-222,-18}}, color={0,0,127})); + connect(logSwi.y, swiPum.u2) annotation (Line(points={{-238,40},{-228,40},{-228, + -10},{-222,-10}}, color={255,0,255})); + connect(swiPum.y, pum.y) annotation (Line(points={{-198,-10},{-100,-10},{-100, + -50},{-42,-50}}, color={0,0,127})); + connect(senTem.T, conPIDPla.u_m) annotation (Line(points={{-10,131},{-10,140}, + {0,140},{0,168}}, color={0,0,127})); + connect(TPlaHotWatSupSet, conPIDPla.u_s) annotation (Line(points={{-340,-160}, + {-90,-160},{-90,180},{-12,180}}, color={0,0,127})); + connect(uBoiSta, edg.u) annotation (Line(points={{-340,160},{-310,160},{-310,120}, + {-172,120}}, color={255,0,255})); + connect(reaScaRep.y, lin.u) annotation (Line(points={{162,180},{172,180},{172, + 20},{-190,20},{-190,-180},{-182,-180}}, color={0,0,127})); + connect(con.y, lin.x1) annotation (Line(points={{-218,-140},{-186,-140},{-186, + -172},{-182,-172}}, color={0,0,127})); + connect(con1.y, lin.x2) annotation (Line(points={{-218,-200},{-186,-200},{-186, + -184},{-182,-184}}, color={0,0,127})); + connect(con2.y, lin.f2) annotation (Line(points={{-258,-180},{-200,-180},{-200, + -188},{-182,-188}}, color={0,0,127})); + connect(pro1.y, conPIDBoi.u_s) + annotation (Line(points={{-98,-120},{38,-120}}, color={0,0,127})); + connect(TBoiHotWatSupSet, lin.f1) annotation (Line(points={{-340,-110},{-200,-110}, + {-200,-176},{-182,-176}}, color={0,0,127})); + connect(lin.y, pro1.u2) annotation (Line(points={{-158,-180},{-130,-180},{-130, + -126},{-122,-126}}, color={0,0,127})); + connect(conPIDBoi[1].y, boi1.y) annotation (Line(points={{62,-120},{128,-120}, + {128,-142},{112,-142}}, color={0,0,127})); + connect(conPIDBoi[2].y, boi2.y) annotation (Line(points={{62,-120},{128,-120}, + {128,-202},{112,-202}}, color={0,0,127})); + connect(conPIDBoi.y, lesThr.u) + annotation (Line(points={{62,-120},{178,-120}}, color={0,0,127})); + connect(conPIDBoi.y, greThr3.u) annotation (Line(points={{62,-120},{128,-120}, + {128,-200},{178,-200}}, color={0,0,127})); + connect(edg.y, conPIDBoi.trigger) annotation (Line(points={{-148,120},{-80,120}, + {-80,-190},{44,-190},{44,-132}}, color={255,0,255})); + connect(uPla, edg1.u) annotation (Line(points={{-340,200},{-140,200},{-140,180}, + {-132,180}}, color={255,0,255})); + connect(edg1.y, conPIDPla.trigger) annotation (Line(points={{-108,180},{-100, + 180},{-100,150},{-6,150},{-6,168}}, color={255,0,255})); + connect(mul.y, reaScaRep.u) + annotation (Line(points={{122,180},{138,180}}, color={0,0,127})); + connect(conPIDPla.y, mul.u2) annotation (Line(points={{12,180},{20,180},{20, + 174},{98,174}}, color={0,0,127})); + connect(booToRea.y, mul.u1) annotation (Line(points={{82,200},{90,200},{90,186}, + {98,186}}, color={0,0,127})); + connect(uPla, booToRea.u) + annotation (Line(points={{-340,200},{58,200}}, color={255,0,255})); + connect(uHotIsoVal[1], val1.y) annotation (Line(points={{-340,70},{-50,70},{-50, + -100},{10,-100},{10,-138}}, color={0,0,127})); + connect(uHotIsoVal[2], val2.y) annotation (Line(points={{-340,90},{-50,90},{-50, + -180},{10,-180},{10,-198}}, color={0,0,127})); + connect(val1.y_actual, yHotWatIsoVal[1]) annotation (Line(points={{15,-143},{32, + -143},{32,-170},{290,-170},{290,-160},{340,-160}}, color={0,0,127})); + connect(val2.y_actual, yHotWatIsoVal[2]) annotation (Line(points={{15,-203},{32, + -203},{32,-170},{290,-170},{290,-140},{340,-140}}, color={0,0,127})); + connect(senTem2.port_b, spl6.port_2) annotation (Line(points={{210,-20},{210, + -150},{160,-150}}, + color={0,127,255})); + connect(spl4.port_3, senVolFlo1.port_a) + annotation (Line(points={{-20,40},{20,40}}, color={0,127,255})); + connect(senVolFlo1.port_b, val.port_a) + annotation (Line(points={{40,40},{80,40}}, color={0,127,255})); + connect(val.port_b, senTem3.port_a) + annotation (Line(points={{100,40},{120,40}}, color={0,127,255})); + connect(senTem3.port_b, spl5.port_3) + annotation (Line(points={{140,40},{200,40}}, color={0,127,255})); + connect(spl4.port_2, senVolFlo2.port_a) + annotation (Line(points={{-30,50},{-30,94}}, color={0,127,255})); + connect(senVolFlo2.port_b, senTem.port_a) annotation (Line(points={{-30,114}, + {-30,120},{-20,120}}, color={0,127,255})); + connect(senTem1.port_b, pipe.port_a) + annotation (Line(points={{80,120},{130,120}}, color={0,127,255})); + connect(spl5.port_2, senTem2.port_a) + annotation (Line(points={{210,30},{210,0}}, color={0,127,255})); + connect(pipe.port_b, senTem4.port_a) + annotation (Line(points={{150,120},{180,120}}, color={0,127,255})); + connect(senTem4.port_b, spl5.port_1) annotation (Line(points={{200,120},{210, + 120},{210,50}}, color={0,127,255})); + connect(senTem2.T, yRetTem) annotation (Line(points={{221,-10},{250,-10},{250, + 60},{340,60}}, color={0,0,127})); + annotation (defaultComponentName="boiPla", + Documentation(info=" +

+ This model implements a primary-only, condensing boiler plant with a headered, + variable-speed primary pump, as defined in ASHRAE RP-1711, March 2020 draft. +

+ ", revisions=" + + "), + Diagram(coordinateSystem(preserveAspectRatio=false, + extent={{-320,-240},{320,240}})), + Icon(coordinateSystem(extent={{-100,-140},{100,140}}), + graphics={ + Rectangle( + extent={{-100,140},{100,-140}}, + lineColor={28,108,200}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-100,-140},{100,-180}}, + textColor={0,0,255}, + textString="%name"), + Rectangle( + extent={{-40,-18},{40,-98}}, + lineColor={0,0,255}, + pattern=LinePattern.None, + fillColor={95,95,95}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-60,-54},{60,-60}}, + lineColor={0,0,255}, + pattern=LinePattern.None, + fillColor={0,0,255}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{0,-60},{60,-54}}, + lineColor={0,0,255}, + pattern=LinePattern.None, + fillColor={255,0,0}, + fillPattern=FillPattern.Solid), + Polygon( + points={{0,-80},{-12,-98},{14,-98},{0,-80}}, + pattern=LinePattern.None, + smooth=Smooth.None, + fillColor={255,255,0}, + fillPattern=FillPattern.Solid, + lineColor={0,0,0}), + Ellipse(extent={{-80,58},{-50,26}}, lineColor={28,108,200}), + Polygon( + points={{-80,40},{-50,40},{-66,58},{-80,40}}, + lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Line(points={{-66,-40},{-66,-12}}, color={28,108,200}), + Line(points={{-66,58},{-66,134}},color={28,108,200}), + Line(points={{70,132},{70,-44},{70,-50}},color={28,108,200}), + Polygon(points={{-80,26},{-80,26}}, lineColor={28,108,200}), + Polygon( + points={{-76,-12},{-54,-12},{-66,0},{-76,-12}}, + lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Polygon( + points={{-76,12},{-54,12},{-66,0},{-76,12}}, + lineColor={28,108,200}, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid), + Line(points={{-66,12},{-66,26}}, color={28,108,200}), + Ellipse( + extent={{-82,-40},{-52,-72}}, + lineColor={28,108,200}, + lineThickness=0.5), + Ellipse( + extent={{56,-38},{86,-70}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={28,108,200}, + fillPattern=FillPattern.Solid)})); +end BoilerPlant; diff --git a/Buildings/Examples/BoilerPlant/Baseclasses/SimplifiedZoneWithRadiator.mo b/Buildings/Examples/BoilerPlant/Baseclasses/SimplifiedZoneWithRadiator.mo new file mode 100644 index 00000000000..0d311f75a47 --- /dev/null +++ b/Buildings/Examples/BoilerPlant/Baseclasses/SimplifiedZoneWithRadiator.mo @@ -0,0 +1,147 @@ +within Buildings.Examples.BoilerPlant.Baseclasses; +model SimplifiedZoneWithRadiator "Zone model" + + replaceable package MediumW =Buildings.Media.Water + "Water medium model"; + + parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal = 4359751.36 + "Nominal heat flow rate of radiator" + annotation(Dialog(group="Radiator")); + + parameter Modelica.Units.SI.Temperature TRadSup_nominal = 273.15+70 + "Radiator nominal supply water temperature" + annotation(Dialog(group="Radiator")); + + parameter Modelica.Units.SI.Temperature TRadRet_nominal = 273.15+50 + "Radiator nominal return water temperature" + annotation(Dialog(group="Radiator")); + + parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=0.000604*1000 + "Radiator nominal mass flow rate" + annotation(Dialog(group="Radiator")); + + parameter Modelica.Units.SI.PressureDifference dpRad_nominal = 0 + "Nominal pressure drop across radiator" + annotation(Dialog(group="Radiator")); + + parameter Modelica.Units.SI.Volume V=1200 + "Room volume" + annotation(Dialog(group="Zone")); + + parameter Real zonTheCap( + final unit="J/K", + displayUnit="J/K", + final quantity="HeatCapacity") = 2*V*1.2*1500+V*1.2*1006 + "Zone thermal capacitance" + annotation(Dialog(group="Zone")); + + parameter Modelica.Units.SI.Temperature TAir_nominal=273.15 + 23.9 + "Air temperature at nominal condition" + annotation(Dialog(group="Zone")); + + parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal = V*1.2*6/3600 + "Nominal mass flow rate" + annotation(Dialog(group="Zone")); + + Buildings.Controls.OBC.CDL.Interfaces.RealInput QFlo + "Power added to zone" + annotation (Placement(transformation(extent={{-138,-20},{-98,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TZon( + final unit="K", + displayUnit="degC", + final quantity="ThermodynamicTemperature") + "Measured zone temperature" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + + Modelica.Fluid.Interfaces.FluidPort_a port_a( + redeclare package Medium = MediumW) + "HHW inlet port" + annotation (Placement(transformation(extent={{-50,-110},{-30,-90}}), + iconTransformation(extent={{-50,-110},{-30,-90}}))); + + Modelica.Fluid.Interfaces.FluidPort_b port_b( + redeclare package Medium = MediumW) + "HHW outlet port" + annotation (Placement(transformation(extent={{30,-110},{50,-90}}), + iconTransformation(extent={{30,-110},{50,-90}}))); + + Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad( + redeclare package Medium = MediumW, + final m_flow_nominal=mRad_flow_nominal, + final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial, + final Q_flow_nominal=Q_flow_nominal, + final T_a_nominal=TRadSup_nominal, + final T_b_nominal=TRadRet_nominal, + final TAir_nominal=TAir_nominal, + final dp_nominal=dpRad_nominal) + "Radiator for zone heating loads" + annotation (Placement(transformation(extent={{-10,-60},{10,-40}}))); + + Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor zonTem + "Zone temperature sensor" + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + + Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap( + final C=zonTheCap, + final T(fixed=true)) + "Heat capacity for furniture and walls" + annotation (Placement(transformation(extent={{-10,0},{10,20}}))); + + Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea + "Apply heating load on the zone" + annotation (Placement(transformation(extent={{-58,-10},{-38,10}}))); + +equation + connect(zonTem.T, TZon) + annotation (Line(points={{81,0},{120,0}}, color={0,0,127})); + connect(QFlo, preHea.Q_flow) + annotation (Line(points={{-118,0},{-58,0}}, color={0,0,127})); + connect(port_a, rad.port_a) annotation (Line(points={{-40,-100},{-40,-50},{-10, + -50}}, color={0,127,255})); + connect(port_b, rad.port_b) annotation (Line(points={{40,-100},{40,-50},{10,-50}}, + color={0,127,255})); + connect(zonTem.port, heaCap.port) annotation (Line(points={{60,0},{0,0}}, + color={191,0,0})); + connect(preHea.port, heaCap.port) + annotation (Line(points={{-38,0},{0,0}}, color={191,0,0})); + connect(rad.heatPortCon, heaCap.port) + annotation (Line(points={{-2,-42.8},{-2,0},{0,0}}, color={191,0,0})); + connect(rad.heatPortRad, heaCap.port) + annotation (Line(points={{2,-42.8},{2,0},{0,0}}, color={191,0,0})); + annotation (defaultComponentName="zon", + 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={{-100,140},{100,100}}, + textColor={0,0,255}, + textString="%name")}), + Diagram( + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-100},{100,100}})), + Documentation(info=" +

+ This is a simplified zone model consisting of a thermal capacitor zonTheCap + to represent the termal capacity of the zone. The heating load on the zone is + applied by the ideal source QFlo and is met by the radiator + rad. +

+ ", revisions=" + + ")); +end SimplifiedZoneWithRadiator; diff --git a/Buildings/Examples/BoilerPlant/Baseclasses/package.mo b/Buildings/Examples/BoilerPlant/Baseclasses/package.mo new file mode 100644 index 00000000000..4c31fd83920 --- /dev/null +++ b/Buildings/Examples/BoilerPlant/Baseclasses/package.mo @@ -0,0 +1,18 @@ +within Buildings.Examples.BoilerPlant; +package Baseclasses "Package containing baseclasses for example model" + extends Modelica.Icons.BasesPackage; + + annotation(Documentation(info=" +

+ This package contains the baseclasses for the boiler plant model + + Buildings.Examples.BoilerPlant.Baseclasses.BoilerPlant and the simplified + thermal zone model + + Buildings.Examples.BoilerPlant.Baseclasses.SimplifiedZoneWithRadiator + used to demonstrate the use of the implemented boiler plant controller + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller. +

+ ")); +end Baseclasses; diff --git a/Buildings/Examples/BoilerPlant/Baseclasses/package.order b/Buildings/Examples/BoilerPlant/Baseclasses/package.order new file mode 100644 index 00000000000..33c8ea16744 --- /dev/null +++ b/Buildings/Examples/BoilerPlant/Baseclasses/package.order @@ -0,0 +1,2 @@ +BoilerPlant +SimplifiedZoneWithRadiator diff --git a/Buildings/Examples/BoilerPlant/ClosedLoopTest.mo b/Buildings/Examples/BoilerPlant/ClosedLoopTest.mo new file mode 100644 index 00000000000..047c1d69c28 --- /dev/null +++ b/Buildings/Examples/BoilerPlant/ClosedLoopTest.mo @@ -0,0 +1,307 @@ +within Buildings.Examples.BoilerPlant; +model ClosedLoopTest "Closed loop testing model" + extends Modelica.Icons.Example; + + replaceable package MediumA = Buildings.Media.Air + "Medium model"; + + replaceable package MediumW = Buildings.Media.Water + "Medium model"; + + parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=113.45 + "Radiator nominal mass flow rate"; + + parameter Real boiDesCap( + final unit="W", + displayUnit="W", + final quantity="Power")= 5134933.83 + "Total boiler plant design capacity"; + + parameter Real boiCapRat( + final unit="1", + displayUnit="1") = 0.4 + "Ratio of boiler-1 capacity to total capacity"; + + Buildings.Examples.BoilerPlant.Baseclasses.BoilerPlant boiPla( + final Q_flow_nominal=boiDesCap, + final boiCap1=(1 - boiCapRat)*boiDesCap, + final boiCap2=boiCapRat*boiDesCap, + final mSec_flow_nominal=mRad_flow_nominal, + final TBoiSup_nominal=333.15, + final TBoiRet_min=323.15, + final dpValve_nominal_value=20000, + final dpFixed_nominal_value=1000, + final controllerTypeBoi1=Buildings.Controls.OBC.CDL.Types.SimpleController.PI, + final controllerTypeBoi2=Buildings.Controls.OBC.CDL.Types.SimpleController.PI) + "Boiler plant model" + annotation (Placement(transformation(extent={{40,-14},{60,14}}))); + + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller boiPlaCon( + final controllerType_priPum=Buildings.Controls.OBC.CDL.Types.SimpleController.PI, + final controllerType_bypVal=Buildings.Controls.OBC.CDL.Types.SimpleController.PI, + final have_priOnl=true, + final have_heaPriPum=true, + final have_varPriPum=true, + final have_varSecPum=false, + final nSenPri=1, + final nPumPri_nominal=1, + final nPumSec=0, + final nSenSec=0, + final nPumSec_nominal=0, + final TPlaHotWatSetMax=273.15 + 50, + final triAmoVal=-1.111, + final resAmoVal=1.667, + final maxResVal=3.889, + final VHotWatPri_flow_nominal=0.02, + final maxLocDpPri=50000, + final minLocDpPri=50000, + final VHotWatSec_flow_nominal=1e-6, + final nBoi=2, + final boiTyp={Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler, + Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.BoilerTypes.condensingBoiler}, + final nSta=3, + final staMat=[1,0; 0,1; 1,1], + final boiDesCap={boiCapRat*boiDesCap*0.8,(1 - boiCapRat)*boiDesCap*0.8}, + final boiFirMin={0.2,0.3}, + final minFloSet={0.2*boiCapRat*mRad_flow_nominal/2000,0.3*(1 - boiCapRat)*mRad_flow_nominal/2000}, + final maxFloSet={boiCapRat*mRad_flow_nominal/2000,(1 - boiCapRat)*mRad_flow_nominal/2000}, + final bypSetRat=0.000005, + final nPumPri=1, + final TMinSupNonConBoi=333.2, + final k_bypVal=1, + final Ti_bypVal=90, + final Td_bypVal=10e-9, + final boiDesFlo=boiPlaCon.maxFloSet, + final k_priPum=0.1, + final Ti_priPum=75, + final Td_priPum=10e-9, + final minPriPumSpeSta={0,0,0}, + final speConTypPri=Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Types.PrimaryPumpSpeedControlTypes.remoteDP) + "Boiler plant controller" + annotation (Placement(transformation(extent={{-40,-34},{-20,34}}))); + + Buildings.Controls.OBC.CDL.Continuous.PID conPID( + final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI, + final k=10e-2, + final Ti=300) + "Radiator valve controller" + annotation (Placement(transformation(extent={{50,100},{70,120}}))); + + Buildings.Examples.BoilerPlant.Baseclasses.SimplifiedZoneWithRadiator zon( + final Q_flow_nominal=4359751.36, + final TRadSup_nominal=333.15, + final TRadRet_nominal=323.15, + final mRad_flow_nominal=96.323, + dpRad_nominal(displayUnit="Pa") = 40000, + final V=126016.35, + final zonTheCap=6987976290) + "Zone thermal model with radiator" + annotation (Placement(transformation(extent={{40,60},{60,80}}))); + + Buildings.Fluid.Actuators.Valves.TwoWayLinear val( + redeclare package Medium = Media.Water, + final m_flow_nominal=mRad_flow_nominal, + final dpValve_nominal(displayUnit="bar") = 20000, + final dpFixed_nominal(displayUnit="bar") = 1000) + "Minimum flow bypass valve" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=90, + origin={44,38}))); + +protected + Buildings.Controls.OBC.CDL.Logical.Sources.Constant con3[2]( + final k=fill(true,2)) + "Constant boiler availability status" + annotation (Placement(transformation(extent={{-110,-10},{-90,10}}))); + + Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat( + final filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos")) + "Weather data reader" + annotation (Placement(transformation(extent={{-120,50},{-100,70}}))); + + Buildings.BoundaryConditions.WeatherData.Bus weaBus + "Weather bus" + annotation (Placement(transformation(extent={{-90,50},{-70,70}}), + iconTransformation(extent={{-60,50},{-40,70}}))); + + Modelica.Blocks.Sources.CombiTimeTable timTab( + final tableOnFile=true, + final tableName="tab1", + final fileName=ModelicaServices.ExternalReferences.loadResource( + "modelica://Buildings/Resources/Data/Examples/BoilerPlant/ClosedLoopTest.txt"), + final columns={2,5}, + final extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic, + final smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments, + final table=[-6,0;8,10000;18,0], + final timeScale=60) + "Time table for internal heat gain" + annotation (Placement(transformation(extent={{-100,90},{-80,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys( + final uLow=0.05, + final uHigh=0.1) + "Check if radiator control valve opening is above threshold for enabling boiler plant" + annotation (Placement(transformation(extent={{80,100},{100,120}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt + "Boolean to Integer conversion" + annotation (Placement(transformation(extent={{160,100},{180,120}}))); + + Buildings.Controls.OBC.CDL.Continuous.Hysteresis hys1( + final uLow=0.85, + final uHigh=0.9) + "Check if radiator control valve opening is above threshold for rasing HHW supply temperature" + annotation (Placement(transformation(extent={{90,20},{110,40}}))); + + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1( + final integerTrue=3) + "Boolean to Integer conversion" + annotation (Placement(transformation(extent={{150,20},{170,40}}))); + + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gai( + final k=-1) + "Convert to heating load" + annotation (Placement(transformation(extent={{-60,90},{-40,110}}))); + + Buildings.Controls.OBC.CDL.Continuous.AddParameter addPar( + final p=273.15) + "Convert temperature to Kelvin" + annotation (Placement(transformation(extent={{-40,110},{-20,130}}))); + +equation + + connect(con3.y, boiPlaCon.uBoiAva) annotation (Line(points={{-88,0},{-60,0},{-60, + 8},{-42,8}}, color={255,0,255})); + + connect(weaDat.weaBus,weaBus) annotation (Line( + points={{-100,60},{-80,60}}, + color={255,204,51}, + thickness=0.5, + smooth=Smooth.None), Text( + textString="%second", + index=1, + extent={{6,3},{6,3}})); + + connect(weaBus.TDryBul, boiPlaCon.TOut) annotation (Line( + points={{-80,60},{-72,60},{-72,26},{-42,26}}, + color={255,204,51}, + thickness=0.5), Text( + string="%first", + index=-1, + extent={{-6,3},{-6,3}}, + horizontalAlignment=TextAlignment.Right)); + + connect(boiPla.ySupTem, boiPlaCon.TSupPri) annotation (Line(points={{62,8},{100, + 8},{100,-68},{-68,-68},{-68,23},{-42,23}}, color={0,0,127})); + + connect(boiPla.yRetTem, boiPlaCon.TRetPri) annotation (Line(points={{62,5},{104, + 5},{104,-72},{-72,-72},{-72,20},{-42,20}}, color={0,0,127})); + + connect(boiPla.yHotWatDp, boiPlaCon.dpHotWatPri_rem) annotation (Line(points={ + {62,2},{108,2},{108,-76},{-76,-76},{-76,11},{-42,11}}, color={0,0,127})); + + connect(boiPla.VHotWat_flow, boiPlaCon.VHotWatPri_flow) annotation (Line( + points={{62,-2},{112,-2},{112,-80},{-80,-80},{-80,17},{-42,17}}, color={ + 0,0,127})); + + + connect(boiPla.yBoiSta, boiPlaCon.uBoi) annotation (Line(points={{62,-5},{120, + -5},{120,-88},{-88,-88},{-88,-17},{-42,-17}}, color={255,0,255})); + + connect(boiPla.yPumSta, boiPlaCon.uPriPum) annotation (Line(points={{62,-8},{124, + -8},{124,-92},{-92,-92},{-92,-20},{-42,-20}}, color={255,0,255})); + + connect(boiPla.yHotWatIsoVal, boiPlaCon.uHotWatIsoVal) annotation (Line( + points={{62,-11},{128,-11},{128,-96},{-96,-96},{-96,-26},{-42,-26}}, + color={0,0,127})); + + connect(conPID.y, hys.u) annotation (Line(points={{72,110},{78,110}}, + color={0,0,127})); + + connect(conPID.y, hys1.u) annotation (Line(points={{72,110},{76,110},{76,30},{ + 88,30}}, + color={0,0,127})); + + connect(booToInt1.y, boiPlaCon.TSupResReq) annotation (Line(points={{172,30},{ + 184,30},{184,-104},{-54,-104},{-54,32},{-42,32}}, color={255,127,0})); + + connect(hys.y, booToInt.u) + annotation (Line(points={{102,110},{158,110}}, color={255,0,255})); + + connect(hys1.y, booToInt1.u) + annotation (Line(points={{112,30},{148,30}}, color={255,0,255})); + + connect(timTab.y[1], gai.u) + annotation (Line(points={{-79,100},{-62,100}}, color={0,0,127})); + + connect(timTab.y[2], addPar.u) annotation (Line(points={{-79,100},{-70,100},{ + -70,120},{-42,120}}, color={0,0,127})); + + connect(addPar.y, conPID.u_s) annotation (Line(points={{-18,120},{40,120},{40, + 110},{48,110}}, + color={0,0,127})); + + connect(booToInt.y, boiPlaCon.plaReq) annotation (Line(points={{182,110},{190, + 110},{190,-100},{-48,-100},{-48,29},{-42,29}}, color={255,127,0})); + connect(boiPla.port_a, zon.port_b) annotation (Line(points={{57,14},{56,14},{56, + 60},{54,60}}, color={0,127,255})); + connect(zon.TZon, conPID.u_m) annotation (Line(points={{62,70},{68,70},{68,90}, + {60,90},{60,98}}, color={0,0,127})); + connect(gai.y, zon.QFlo) annotation (Line(points={{-38,100},{30,100},{30,70},{ + 38,70}}, color={0,0,127})); + connect(boiPla.yBypValPos, boiPlaCon.uBypValPos) annotation (Line(points={{62, + 11},{116,11},{116,-84},{-84,-84},{-84,-29},{-42,-29}}, color={0,0,127})); + connect(boiPlaCon.yPla, boiPla.uPla) annotation (Line(points={{-18,18},{20,18}, + {20,12},{38,12}}, color={255,0,255})); + connect(boiPlaCon.yPriPum, boiPla.uPumSta) annotation (Line(points={{-18,-6},{ + 20,-6},{20,3},{38,3}}, color={255,0,255})); + connect(boiPlaCon.yBoi, boiPla.uBoiSta) + annotation (Line(points={{-18,10},{38,10},{38,9}}, color={255,0,255})); + connect(boiPlaCon.TPlaHotWatSupSet, boiPla.TPlaHotWatSupSet) annotation (Line( + points={{-18,14},{18,14},{18,-12},{38,-12}}, color={0,0,127})); + connect(boiPlaCon.TBoiHotWatSupSet, boiPla.TBoiHotWatSupSet) annotation (Line( + points={{-18,6},{10,6},{10,-9},{38,-9}}, color={0,0,127})); + connect(boiPlaCon.yHotWatIsoVal, boiPla.uHotIsoVal) + annotation (Line(points={{-18,2},{16,2},{16,6},{38,6}}, color={0,0,127})); + connect(boiPlaCon.yPriPumSpe, boiPla.uPumSpe) annotation (Line(points={{-18,-10}, + {14,-10},{14,0},{38,0}}, color={0,0,127})); + connect(boiPlaCon.yBypValPos, boiPla.uBypValSig) annotation (Line(points={{-18, + -2},{6,-2},{6,-3},{38,-3}}, color={0,0,127})); + connect(zon.TZon, boiPla.TZon) annotation (Line(points={{62,70},{68,70},{68,20}, + {30,20},{30,-6},{38,-6}}, color={0,0,127})); + connect(boiPla.port_b, val.port_a) + annotation (Line(points={{43,14},{44,14},{44,28}}, color={0,127,255})); + connect(val.port_b, zon.port_a) + annotation (Line(points={{44,48},{44,60},{46,60}}, color={0,127,255})); + connect(conPID.y, val.y) annotation (Line(points={{72,110},{76,110},{76,86},{20, + 86},{20,38},{32,38}}, color={0,0,127})); + annotation (Documentation(info=" +

+This model couples the boiler plant model for a primary-only, condensing boiler +plant with a headered variable pump + +Buildings.Examples.BoilerPlant.PlantModel.BoilerPlant with the boiler plant +controller +Buildings.Controls.OBC.ASHRAE.PrimarySystem.BoilerPlant.Controller developed +as per ASHRAE RP-1711, March 2020 draft. +

+", revisions=" + +"), + Diagram(coordinateSystem(preserveAspectRatio=false,extent={{-140,-140},{200, + 140}})), + __Dymola_Commands(file= + "modelica://Buildings/Resources/Scripts/Dymola/Examples/BoilerPlant/ClosedLoopTest.mos" + "Simulate and plot"), + experiment( + StartTime=518400, + StopTime=691200, + Interval=60, + Tolerance=1e-06), + Icon(coordinateSystem(extent={{-100,-100},{100,100}}))); +end ClosedLoopTest; diff --git a/Buildings/Examples/BoilerPlant/package.mo b/Buildings/Examples/BoilerPlant/package.mo new file mode 100644 index 00000000000..15350a6a88e --- /dev/null +++ b/Buildings/Examples/BoilerPlant/package.mo @@ -0,0 +1,19 @@ +within Buildings.Examples; +package BoilerPlant "Closed-loop validation model for boiler plant sequences implemented as per ASHRAE G36" + + +extends Modelica.Icons.ExamplesPackage; + + +annotation (Documentation(info=" +

System Configuration

+

This example demonstrates the implementation of a primary-only boiler plant +with condensing boilers and headered primary variable pump couped with a controller +implemented as per the sequence of operations defined in ASHRAE RP-1711. +The boiler plant schematic is as shown below. +

+

+\"image\" +

+")); +end BoilerPlant; diff --git a/Buildings/Examples/BoilerPlant/package.order b/Buildings/Examples/BoilerPlant/package.order new file mode 100644 index 00000000000..185c7a86ca8 --- /dev/null +++ b/Buildings/Examples/BoilerPlant/package.order @@ -0,0 +1,2 @@ +ClosedLoopTest +Baseclasses 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 99% rename from Buildings/Examples/ChillerPlant/BaseClasses/Controls/BatteryControl.mo rename to Buildings/Examples/ChillerPlants/DataCenter/BaseClasses/Controls/BatteryControl.mo index 6a575fbd540..1cc727b92c0 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 ( 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="