From f1607e121016b6ce7aaa15983595ce9e9028d6d8 Mon Sep 17 00:00:00 2001
From: Antoine Gautier
+This block emulates the status of an equipment, i.e.,
+the current on/off state as reported by the hardware itself.
+
+The implementation is based on
+
+Buildings.Fluid.BaseClasses.ActuatorFilter
+and the model is configured with
+This model validates
+
+Buildings.Templates.Components.Controls.MultipleCommands.
+
+This model validates
+
+Buildings.Templates.Components.Controls.StatusEmulator.
+
+This package contains validation models for the classes within
+
+Buildings.Templates.Components.Controls.
+
+This record provides the set of sizing and operating parameters for
+heat pump models that can be found within
+
+Buildings.Templates.Components.HeatPumps.
+ When using
+
+Note that this propagation does not persist when redeclaring or
+reassigning the record.
+This is because the equation fit method uses reference values that
+must match the ones used to compute the performance curve coefficients.
+
+Also note that placeholders values are assigned to the performance curves,
+the reference source temperature and the input power in
+cooling mode to avoid assigning these parameters in case of non-reversible
+heat pumps.
+These values are unrealistic and must be overwritten for reversible heat pumps, which
+is always the case when redeclaring or
+reassigning the performance record
+This record provides the set of sizing and operating parameters for
+the multiple-pump model
+
+Buildings.Templates.Components.Pumps.Multiple.
+
+A default flow characteristic is provided, which goes through
+the design operating point and spans over
+0 and twice the design flow rate at maximum speed.
+This default characteristic is based on a least squares
+polynomial fit of the characteristics from
+
+Buildings.Fluid.Movers.Data.Pumps.Wilo.
+The user may refer to the documentation of
+
+Buildings.Fluid.HydronicConfigurations.UsersGuide.ModelParameters
+for further details.
+Note that a default medium density is used to parameterize
+the pump characteristic. So models that use this record should
+overwrite this default value with the density of the medium
+in use, especially in the case of a water/glycol mix.
+
+In order to modify the default characteristic, one may use either
+of the following methods.
+
+Those various use cases are illustrated in
+
+Buildings.Templates.Components.Validation.PumpMultipleRecord.
+
+This record provides the set of sizing and operating parameters for
+the single pump model
+
+Buildings.Templates.Components.Pumps.Single.
+
+A default flow characteristic is provided and can be overwritten as
+described in the documentation of
+
+Buildings.Templates.Components.Data.PumpMultiple
+in the more generic case of multiple units.
+
+This is a model for an air-to-water heat pump where the capacity
+and input power are computed based on the equation fit method.
+The model can be configured to represent either a non-reversible heat pump
+(
+Refer to the documentation of the interface class
+
+Buildings.Templates.Components.Interfaces.PartialHeatPumpEquationFit
+for a description of the available control input and output
+variables.
+
+This model validates the models
+
+Buildings.Templates.Components.HeatPumps.AirToWater
+and
+
+Buildings.Templates.Components.HeatPumps.WaterToWater
+in a configuration in which the heat pump components are exposed
+to a constant differential pressure and a varying
+return temperature.
+
+The AWHP model is configured to represent either a non-reversible heat pump
+(suffix
+This package contains validation models.
+
+This is a model for a water-to-water heat pump where the capacity
+and input power are computed based on the equation fit method.
+The model can be configured with the parameter
+Refer to the documentation of the interface class
+
+Buildings.Templates.Components.Interfaces.PartialHeatPumpEquationFit
+for a description of the available control input and output
+variables.
+
+This package contains models for heat pumps.
+
+This partial class provides a standard interface for heat pump models.
+
+This is a model for an air-to-water heat pump where the capacity
+and drawn power are computed based on the equation fit method.
+The model can be configured with the parameter
+The following input and output points are available.
+
+This partial class provides a standard interface for pump models.
+
+This partial class provides a standard interface for models
+of multiple pumps in parallel arrangement.
+Note that the inlet and outlet manifolds are not included
+in this model. This way, the same interface can be used to model
+both headered pumps and dedicated pumps.
+
+This partial class provides a standard interface for
+single pump models.
+
diff --git a/Buildings/Templates/Components/Interfaces/package.order b/Buildings/Templates/Components/Interfaces/package.order
index 7fc811573cd..c90cefc1586 100644
--- a/Buildings/Templates/Components/Interfaces/package.order
+++ b/Buildings/Templates/Components/Interfaces/package.order
@@ -1,4 +1,9 @@
Bus
PartialCoil
PartialFan
+PartialHeatPump
+PartialHeatPumpEquationFit
+PartialPump
+PartialPumpMultiple
+PartialPumpSingle
PartialSensor
diff --git a/Buildings/Templates/Components/Pumps/Multiple.mo b/Buildings/Templates/Components/Pumps/Multiple.mo
new file mode 100644
index 00000000000..31d36eae8ea
--- /dev/null
+++ b/Buildings/Templates/Components/Pumps/Multiple.mo
@@ -0,0 +1,179 @@
+within Buildings.Templates.Components.Pumps;
+model Multiple "Multiple pumps in parallel"
+ extends Buildings.Templates.Components.Interfaces.PartialPumpMultiple(
+ final typ=Buildings.Templates.Components.Types.Pump.Multiple);
+
+ replaceable Buildings.Fluid.Movers.SpeedControlled_y pum[nPum](
+ redeclare each final package Medium=Medium,
+ final per=dat.per,
+ each final inputType=Buildings.Fluid.Types.InputType.Continuous,
+ each final addPowerToMedium=addPowerToMedium,
+ each final energyDynamics=energyDynamics,
+ each final tau=tau,
+ each final allowFlowReversal=allowFlowReversal)
+ "Pumps"
+ annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
+ Fluid.FixedResistances.CheckValve valChe[nPum](
+ redeclare each final package Medium = Medium,
+ final m_flow_nominal=m_flow_nominal,
+ final dpValve_nominal=dpValChe_nominal)
+ if have_valChe "Check valve"
+ annotation (Placement(transformation(extent={{40,10},{60,30}})));
+ Routing.PassThroughFluid pas[nPum](
+ redeclare each final package Medium = Medium) if not have_valChe
+ "Fluid pass through if no check valve"
+ annotation (Placement(transformation(extent={{40,-30},{60,-10}})));
+ Buildings.Controls.OBC.CDL.Conversions.BooleanToReal sigSta[nPum]
+ "Start/stop signal"
+ annotation (Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-60,70})));
+ Buildings.Controls.OBC.CDL.Reals.Multiply sigCon[nPum]
+ "Resulting control signal"
+ annotation (Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={0,30})));
+ Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaSpe(
+ final nout=nPum) if have_var and have_varCom
+ "Replicate signal in case of common unique commanded speed" annotation (
+ Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-20,70})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant speCst[nPum](
+ final k=fill(1, nPum)) if not have_var
+ "Constant signal in case of constant speed pump" annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={60,70})));
+ Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasSpe(
+ final nin=nPum,
+ final nout=nPum) if have_var and not have_varCom
+ "Direct pass through for dedicated speed signals" annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={20,70})));
+ Controls.StatusEmulator sta[nPum] "Emulate pump status"
+ annotation (Placement(transformation(extent={{-10,-70},{10,-50}})));
+equation
+ connect(pum.port_b,valChe. port_a)
+ annotation (Line(points={{10,0},{30,0},{30,20},{40,20}}, color={0,127,255}));
+ connect(sigSta.y, sigCon.u2)
+ annotation (Line(points={{-60,58},{-60,46},{-6,46},{-6,42}},
+ color={0,0,127}));
+ connect(sigCon.y, pum.y)
+ annotation (Line(points={{0,18},{0,15},{0,12}}, color={0,0,127}));
+ connect(valChe.port_b, ports_b)
+ annotation (Line(points={{60,20},{70,20},{70,0},{100,0}}, color={0,127,255}));
+ connect(ports_a, pum.port_a)
+ annotation (Line(points={{-100,0},{-10,0}}, color={0,127,255}));
+ connect(bus.y1, sigSta.u) annotation (Line(
+ points={{0,100},{0,88},{-60,88},{-60,82}},
+ color={255,204,51},
+ thickness=0.5), Text(
+ string="%first",
+ index=-1,
+ extent={{-3,6},{-3,6}},
+ horizontalAlignment=TextAlignment.Right));
+ connect(reaSpe.y, sigCon.u1) annotation (Line(points={{-20,58},{-20,50},{6,50},
+ {6,42}}, color={0,0,127}));
+ connect(bus.y, reaSpe.u) annotation (Line(
+ points={{0,100},{0,88},{-20,88},{-20,82}},
+ color={255,204,51},
+ thickness=0.5), Text(
+ string="%first",
+ index=-1,
+ extent={{-3,6},{-3,6}},
+ horizontalAlignment=TextAlignment.Right));
+ connect(speCst.y, sigCon.u1)
+ annotation (Line(points={{60,58},{60,50},{6,50},{6,42}}, color={0,0,127}));
+ connect(bus.y, pasSpe.u) annotation (Line(
+ points={{0,100},{0,88},{20,88},{20,82}},
+ color={255,204,51},
+ thickness=0.5), Text(
+ string="%first",
+ index=-1,
+ extent={{-6,3},{-6,3}},
+ horizontalAlignment=TextAlignment.Right));
+ connect(pasSpe.y, sigCon.u1)
+ annotation (Line(points={{20,58},{20,50},{6,50},{6,42}}, color={0,0,127}));
+ connect(pum.port_b, pas.port_a) annotation (Line(points={{10,0},{30,0},{30,-20},
+ {40,-20}}, color={0,127,255}));
+ connect(pas.port_b, ports_b) annotation (Line(points={{60,-20},{70,-20},{70,0},
+ {100,0}}, color={0,127,255}));
+ connect(sta.y1_actual, bus.y1_actual) annotation (Line(points={{12,-60},{80,
+ -60},{80,96},{0,96},{0,100}}, color={255,0,255}));
+ connect(bus.y1, sta.y1) annotation (Line(
+ points={{0,100},{0,88},{-80,88},{-80,-60},{-12,-60}},
+ color={255,204,51},
+ thickness=0.5));
+ annotation (
+ defaultComponentName="pum",
+ Documentation(info="
+
+This is a model for a parallel arrangement of
+Note that the inlet and outlet manifolds are not included in this model.
+The manifolds may be modeled with
+
+Buildings.Templates.Components.Routing.MultipleToMultiple.
+This allows representing both headered and dedicated arrangements.
+
+By default, variable speed pumps are modeled.
+Constant speed pumps can be modeled by setting the parameter
+
+The following input and output points are available.
+
+The design parameters and the pump characteristics are specified with an instance of
+
+Buildings.Templates.Components.Data.PumpMultiple.
+The documentation of this record class provides further details on how to
+properly parameterize the model.
+
+This is a model for a single pump
+with an optional check valve (depending on the value of the parameter
+
+By default, a variable speed pump is modeled.
+A constant speed pump can be modeled by setting the parameter
+
+The following input and output points are available.
+
+The design parameters and the pump characteristics are specified with an instance of
+
+Buildings.Templates.Components.Data.PumpSingle.
+The documentation of this record class provides further details on how to
+properly parameterize the model.
+
+This package contains models for pumps.
+
+This is a model of a flow junction with an optional fixed resistance
+in each flow leg and an optional mixing volume at the junction.
+This model is identical to
+
+Buildings.Fluid.FixedResistances.Junction
+except for the icon which has been changed for better integration
+into the templates.
+yLim=0.5
so that
+the delay between the on command and the on status is
+equal to the delay between the off command and the off status
+(about 2 s with the default parameter settings).
+Note that this delay may not be representative of the actual
+dynamics of certain equipment such as chillers or heat pumps.
+In addition, this block uses the equipment command signal to
+generate the status signal, which in turn can lead to inconsistencies
+with certain equipment that run cyclically at low load and
+where the status then comes and goes.
+
+
+"));
+end StatusEmulator;
diff --git a/Buildings/Templates/Components/Controls/Validation/MultipleCommands.mo b/Buildings/Templates/Components/Controls/Validation/MultipleCommands.mo
new file mode 100644
index 00000000000..697a16215f5
--- /dev/null
+++ b/Buildings/Templates/Components/Controls/Validation/MultipleCommands.mo
@@ -0,0 +1,31 @@
+within Buildings.Templates.Components.Controls.Validation;
+model MultipleCommands "Validation model for converter of multiple commands"
+ extends Modelica.Icons.Example;
+ Buildings.Controls.OBC.CDL.Logical.Sources.Pulse y1[3](
+ width={0.5,0.6,0.4},
+ each period=600,
+ shift={100,200,300})
+ "Enable command"
+ annotation (Placement(transformation(extent={{-80,-10},{-60,10}})));
+ Buildings.Templates.Components.Controls.MultipleCommands conCom(nUni=3)
+ "Converter of multiple commands"
+ annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
+equation
+ connect(y1.y, conCom.y1)
+ annotation (Line(points={{-58,0},{-12,0}}, color={255,0,255}));
+ annotation (
+ __Dymola_Commands(
+ file=
+ "modelica://Buildings/Resources/Scripts/Dymola/Templates/Components/Controls/Validation/MultipleCommands.mos"
+ "Simulate and plot"),
+ experiment(
+ Tolerance=1e-6,
+ StopTime=2000.0),
+ Documentation(info="
+
+First implementation.
+Performance data for the equation fit model
+typMod=Buildings.Templates.Components.Types.HeatPumpModel.EquationFit
,
+the design values declared at the top-level
+are propagated by default to the performance data record per
+under the assumption that the reference conditions used for assessing the
+performance data match the design conditions.
+This avoids duplicate parameter assignments when manually entering
+the performance curve coefficients.
+per
.
+Models that use this record will issue a warning if these placeholders values
+are not overwritten in case of reversible heat pumps.
+
+
+per
or
+only its component per.pressure
.
+In this case the elements per[i]
may differ one from another.
+This is the recommended approach for unequally sized units
+such as dedicated pumps.per
.
+In this case the elements per[i]
are all equal to the redeclared
+record instance.
+This is the recommended approach for equally sized units
+such as headered pumps.is_rev=false
) or a reversible heat pump (is_rev=true
).
+This model uses
+
+Buildings.Fluid.HeatPumps.EquationFitReversible,
+which the user may refer to for the modeling assumptions.
+Control points
+
+
+"));
+end AirToWater;
diff --git a/Buildings/Templates/Components/HeatPumps/Validation/HeatPumpEquationFit.mo b/Buildings/Templates/Components/HeatPumps/Validation/HeatPumpEquationFit.mo
new file mode 100644
index 00000000000..d61e7670dae
--- /dev/null
+++ b/Buildings/Templates/Components/HeatPumps/Validation/HeatPumpEquationFit.mo
@@ -0,0 +1,427 @@
+within Buildings.Templates.Components.HeatPumps.Validation;
+model HeatPumpEquationFit
+ "Validation model for heat pump component with equation fit model"
+ extends Modelica.Icons.Example;
+ replaceable package Medium=Buildings.Media.Water
+ constrainedby Modelica.Media.Interfaces.PartialMedium
+ "HW or CHW medium";
+ parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
+ "Type of energy balance: dynamic (3 initialization options) or steady state"
+ annotation (Evaluate=true,
+ Dialog(tab="Dynamics",group="Conservation equations"));
+ parameter Buildings.Templates.Components.Data.HeatPump datHpAwNrv(
+ final cpHeaWat_default=hpAwNrv.cpHeaWat_default,
+ final cpSou_default=hpAwNrv.cpSou_default,
+ final typ=hpAwNrv.typ,
+ final is_rev=hpAwNrv.is_rev,
+ final typMod=hpAwNrv.typMod,
+ mHeaWat_flow_nominal=datHpAw.capHea_nominal/abs(datHpAw.THeaWatSup_nominal -
+ Buildings.Templates.Data.Defaults.THeaWatRetMed)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
+ dpHeaWat_nominal=Buildings.Templates.Data.Defaults.dpHeaWatHp,
+ capHea_nominal=500E3,
+ THeaWatSup_nominal=Buildings.Templates.Data.Defaults.THeaWatSupMed,
+ TSouHea_nominal=Buildings.Templates.Data.Defaults.TOutHpHeaLow,
+ perFit(hea(
+ P=datHpAwNrv.capHea_nominal/Buildings.Templates.Data.Defaults.COPHpAwHea,
+ coeQ={-4.2670305442,-0.7381077035,6.0049480456,0,0},
+ coeP={-4.9107455513,5.3665308366,0.5447612754,0,0},
+ TRefLoa=Buildings.Templates.Data.Defaults.THeaWatRetMed,
+ TRefSou=Buildings.Templates.Data.Defaults.TOutHpHeaLow)))
+ "Non-reversible AWHP parameters"
+ annotation (Placement(transformation(extent={{120,100},{140,120}})));
+
+ parameter Buildings.Templates.Components.Data.HeatPump datHpAw(
+ final cpHeaWat_default=hpAw.cpHeaWat_default,
+ final cpSou_default=hpAw.cpSou_default,
+ final typ=hpAw.typ,
+ final is_rev=hpAw.is_rev,
+ final typMod=hpAw.typMod,
+ mHeaWat_flow_nominal=datHpAw.capHea_nominal/abs(datHpAw.THeaWatSup_nominal -
+ Buildings.Templates.Data.Defaults.THeaWatRetMed)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
+ dpHeaWat_nominal=Buildings.Templates.Data.Defaults.dpHeaWatHp,
+ capHea_nominal=500E3,
+ THeaWatSup_nominal=Buildings.Templates.Data.Defaults.THeaWatSupMed,
+ mChiWat_flow_nominal=datHpAw.capCoo_nominal/abs(datHpAw.TChiWatSup_nominal -
+ Buildings.Templates.Data.Defaults.TChiWatRet)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
+ capCoo_nominal=500E3,
+ TChiWatSup_nominal=Buildings.Templates.Data.Defaults.TChiWatSup,
+ TSouCoo_nominal=Buildings.Templates.Data.Defaults.TOutHpCoo,
+ TSouHea_nominal=Buildings.Templates.Data.Defaults.TOutHpHeaLow,
+ perFit(hea(
+ P=datHpAw.capHea_nominal/Buildings.Templates.Data.Defaults.COPHpAwHea,
+ coeQ={-4.2670305442,-0.7381077035,6.0049480456,0,0},
+ coeP={-4.9107455513,5.3665308366,0.5447612754,0,0},
+ TRefLoa=Buildings.Templates.Data.Defaults.THeaWatRetMed,
+ TRefSou=Buildings.Templates.Data.Defaults.TOutHpHeaLow), coo(
+ P=datHpAw.capCoo_nominal/Buildings.Templates.Data.Defaults.COPHpAwCoo,
+ coeQ={-2.2545246871,6.9089257665,-3.6548225094,0,0},
+ coeP={-5.8086010402,1.6894933858,5.1167787436,0,0},
+ TRefLoa=Buildings.Templates.Data.Defaults.TChiWatRet,
+ TRefSou=Buildings.Templates.Data.Defaults.TOutHpCoo)))
+ "Reversible AWHP parameters parameters"
+ annotation (Placement(transformation(extent={{120,22},{140,42}})));
+
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(k=datHpAw.TChiWatSup_nominal,
+ y(final unit="K", displayUnit="degC")) "CHWST setpoint" annotation (
+ Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=0,
+ origin={-80,120})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupSet(k=datHpAw.THeaWatSup_nominal,
+ y(final unit="K", displayUnit="degC")) "HW supply temperature setpoint"
+ annotation (Placement(transformation(extent={{-90,150},{-70,170}})));
+ AirToWater hpAw(
+ is_rev=true,
+ show_T=true,
+ redeclare final package MediumHeaWat = Medium,
+ final dat=datHpAw,
+ final energyDynamics=energyDynamics) "Reversible AWHP"
+ annotation (Placement(transformation(extent={{100,-10},{120,10}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Sin THeaWatRet(
+ amplitude=datHpAw.THeaWatSup_nominal - datHpAw.THeaWatRet_nominal,
+ freqHz=3/3000,
+ y(final unit="K", displayUnit="degC"),
+ offset=datHpAw.THeaWatRet_nominal,
+ startTime=0) "HW return temperature value"
+ annotation (Placement(transformation(extent={{-90,72},{-70,92}})));
+ Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1(
+ table=[
+ 0, 0;
+ 0.5, 1],
+ timeScale=1000,
+ period=3000)
+ "Heat pump Enable signal"
+ annotation (Placement(transformation(extent={{-180,130},{-160,150}})));
+ Fluid.Sensors.TemperatureTwoPort TSup(redeclare final package Medium = Medium,
+ final m_flow_nominal=datHpAw.mChiWat_flow_nominal) "Supply temperature"
+ annotation (Placement(transformation(extent={{130,-10},{150,10}})));
+ Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1Hea(
+ table=[
+ 0, 0;
+ 2, 1],
+ timeScale=1000,
+ period=3000)
+ "Heat pump heating mode signal"
+ annotation (Placement(transformation(extent={{-180,90},{-160,110}})));
+ Buildings.Controls.OBC.CDL.Reals.Switch TSetAct(
+ y(final unit="K",
+ displayUnit="degC"))
+ "Active supply temperature setpoint"
+ annotation (Placement(transformation(extent={{-40,90},{-20,110}})));
+ Fluid.Sources.Boundary_pT sup(
+ redeclare final package Medium=Medium,
+ p=Buildings.Templates.Data.Defaults.pHeaWat_rel_nominal + 101325,
+ nPorts=3)
+ "Boundary condition at distribution system supply"
+ annotation (Placement(transformation(extent={{190,30},{170,50}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet(
+ amplitude=datHpAw.TChiWatRet_nominal - datHpAw.TChiWatSup_nominal,
+ freqHz=3/3000,
+ y(final unit="K", displayUnit="degC"),
+ offset=datHpAw.TChiWatRet_nominal,
+ startTime=0) "CHW return temperature value"
+ annotation (Placement(transformation(extent={{-90,30},{-70,50}})));
+ Fluid.Sources.Boundary_pT inlHp(
+ redeclare final package Medium = Medium,
+ use_p_in=true,
+ use_T_in=true,
+ nPorts=3) "Boundary conditions of CHW/HW at HP inlet"
+ annotation (Placement(transformation(extent={{10,-10},{30,10}})));
+ Buildings.Controls.OBC.CDL.Reals.Switch TRetAct
+ "Active return temperature"
+ annotation (Placement(transformation(extent={{-40,50},{-20,70}})));
+ Buildings.Controls.OBC.CDL.Reals.Switch pInl_rel
+ "Active inlet gaupe pressure"
+ annotation (Placement(transformation(extent={{-40,-30},{-20,-10}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant pHeaWatInl(
+ k=sup.p + hpAw.dpHeaWat_nominal)
+ "HW inlet pressure"
+ annotation (Placement(transformation(extent={{-90,-10},{-70,10}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant pChiWatInl(
+ k=sup.p + hpAw.dpChiWat_nominal)
+ "CHW inlet pressure"
+ annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0,
+ origin={-80,-40})));
+ BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
+ filNam=Modelica.Utilities.Files.loadResource(
+ "modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
+ annotation (Placement(transformation(extent={{10,-10},{-10,10}},rotation=0,
+ origin={180,140})));
+ Fluid.Sensors.TemperatureTwoPort TRet(redeclare final package Medium = Medium,
+ final m_flow_nominal=datHpAw.mChiWat_flow_nominal) "Return temperature"
+ annotation (Placement(transformation(extent={{50,-10},{70,10}})));
+ AirToWater hpAwNrv(
+ is_rev=false,
+ final energyDynamics=energyDynamics,
+ final dat=datHpAwNrv) "Non reversible AWHP"
+ annotation (Placement(transformation(extent={{100,70},{120,90}})));
+ Fluid.Sensors.TemperatureTwoPort TRet1(redeclare final package Medium =
+ Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
+ "Return temperature"
+ annotation (Placement(transformation(extent={{50,70},{70,90}})));
+ Fluid.Sensors.TemperatureTwoPort TSup1(redeclare final package Medium =
+ Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
+ "Supply temperature"
+ annotation (Placement(transformation(extent={{130,70},{150,90}})));
+ WaterToWater hpWw(
+ is_rev=true,
+ show_T=true,
+ redeclare final package MediumHeaWat = Medium,
+ final dat=datHpWw,
+ final energyDynamics=energyDynamics,
+ have_preDroChiHeaWat=false,
+ have_preDroSou=false)
+ "Reversible WWHP - CHW/HW and source fluid pressure drops computed externally"
+ annotation (Placement(transformation(extent={{100,-90},{120,-70}})));
+ parameter Data.HeatPump datHpWw(
+ final cpHeaWat_default=hpWw.cpHeaWat_default,
+ final cpSou_default=hpWw.cpSou_default,
+ final typ=hpWw.typ,
+ final is_rev=hpWw.is_rev,
+ final typMod=hpWw.typMod,
+ mHeaWat_flow_nominal=datHpAw.capHea_nominal/abs(datHpAw.THeaWatSup_nominal -
+ Buildings.Templates.Data.Defaults.THeaWatRetMed)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
+ dpHeaWat_nominal=Buildings.Templates.Data.Defaults.dpHeaWatHp,
+ capHea_nominal=500E3,
+ THeaWatSup_nominal=Buildings.Templates.Data.Defaults.THeaWatSupMed,
+ mChiWat_flow_nominal=datHpAw.capCoo_nominal/abs(datHpAw.TChiWatSup_nominal -
+ Buildings.Templates.Data.Defaults.TChiWatRet)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
+ capCoo_nominal=500E3,
+ TChiWatSup_nominal=Buildings.Templates.Data.Defaults.TChiWatSup,
+ TSouCoo_nominal=Buildings.Templates.Data.Defaults.TSouHpCoo,
+ TSouHea_nominal=Buildings.Templates.Data.Defaults.TSouHpHea,
+ dpSouWwHea_nominal=Buildings.Templates.Data.Defaults.dpChiWatChi,
+ mSouWwCoo_flow_nominal=datHpWw.mSouWwHea_flow_nominal,
+ mSouWwHea_flow_nominal=datHpWw.mHeaWat_flow_nominal,
+ perFit(hea(
+ P=datHpAw.capHea_nominal/Buildings.Templates.Data.Defaults.COPHpWwHea,
+ coeQ={-4.2670305442,-0.7381077035,6.0049480456,0,0},
+ coeP={-4.9107455513,5.3665308366,0.5447612754,0,0},
+ TRefLoa=Buildings.Templates.Data.Defaults.THeaWatRetMed,
+ TRefSou=Buildings.Templates.Data.Defaults.TSouHpHea), coo(
+ P=datHpAw.capCoo_nominal/Buildings.Templates.Data.Defaults.COPHpWwCoo,
+ coeQ={-2.2545246871,6.9089257665,-3.6548225094,0,0},
+ coeP={-5.8086010402,1.6894933858,5.1167787436,0,0},
+ TRefLoa=Buildings.Templates.Data.Defaults.TChiWatRet,
+ TRefSou=Buildings.Templates.Data.Defaults.TSouHpCoo)))
+ "Reversible WWHP parameters parameters"
+ annotation (Placement(transformation(extent={{120,-60},{140,-40}})));
+
+ Fluid.Sensors.TemperatureTwoPort TRet2(redeclare final package Medium =
+ Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
+ "Return temperature"
+ annotation (Placement(transformation(extent={{50,-90},{70,-70}})));
+ Fluid.Sensors.TemperatureTwoPort TSup2(redeclare final package Medium =
+ Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
+ "Supply temperature"
+ annotation (Placement(transformation(extent={{130,-90},{150,-70}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TSouHea(
+ y(final unit="K", displayUnit="degC"),
+ height=4,
+ duration=500,
+ offset=datHpWw.TSouHea_nominal,
+ startTime=2400) "Source fluid supply temperature value"
+ annotation (Placement(transformation(extent={{-92,-90},{-72,-70}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TSouCoo(
+ y(final unit="K", displayUnit="degC"),
+ height=-4,
+ duration=500,
+ offset=datHpWw.TSouCoo_nominal,
+ startTime=1400) "Source fluid supply temperature value"
+ annotation (Placement(transformation(extent={{-92,-130},{-72,-110}})));
+ Buildings.Controls.OBC.CDL.Reals.Switch TSouAct
+ "Active source fluid supply temperature"
+ annotation (Placement(transformation(extent={{-40,-92},{-20,-72}})));
+ Buildings.Controls.OBC.CDL.Reals.Switch pInl_rel1
+ "Active inlet gaupe pressure"
+ annotation (Placement(transformation(extent={{-40,-150},{-20,-130}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant pSouInlHea(k=retSou.p +
+ hpWw.dpSouHea_nominal) "Source fluid inlet pressure"
+ annotation (Placement(transformation(extent={{-130,-130},{-110,-110}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant pSouInlCoo(k=retSou.p +
+ hpWw.dpSouCoo_nominal) "Source fluid inlet pressure" annotation (
+ Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=0,
+ origin={-120,-160})));
+ Fluid.Sources.Boundary_pT inlHpSou(
+ redeclare final package Medium = Medium,
+ use_p_in=true,
+ use_T_in=true,
+ nPorts=1) "Boundary conditions or source side fluid at HP inlet"
+ annotation (Placement(transformation(extent={{10,-110},{30,-90}})));
+ Fluid.Sources.Boundary_pT retSou(
+ redeclare final package Medium=Medium,
+ p=Buildings.Templates.Data.Defaults.pHeaWat_rel_nominal + 101325,
+ nPorts=1)
+ "Boundary condition at source system return"
+ annotation (Placement(transformation(extent={{190,-130},{170,-110}})));
+ Fluid.FixedResistances.PressureDrop res(
+ redeclare final package Medium = Medium,
+ final m_flow_nominal=datHpWw.mHeaWat_flow_nominal,
+ final dp_nominal=datHpWw.dpHeaWat_nominal)
+ "CHW/HW pressure drop computed externally"
+ annotation (Placement(transformation(extent={{70,-90},{90,-70}})));
+ Fluid.FixedResistances.PressureDrop resSou(
+ redeclare final package Medium = Medium,
+ final m_flow_nominal=datHpWw.mSouWwHea_flow_nominal,
+ final dp_nominal=datHpWw.dpSouWwHea_nominal)
+ "Source fluid pressure drop computed externally"
+ annotation (Placement(transformation(extent={{70,-110},{90,-90}})));
+protected
+ Interfaces.Bus bus "HP control bus"
+ annotation (Placement(transformation(extent={{60,20},{100,60}}),
+ iconTransformation(extent={{-276,6},{-236,46}})));
+protected
+ Interfaces.Bus bus1 "HP control bus"
+ annotation (Placement(transformation(extent={{60,100},{100,140}}),
+ iconTransformation(extent={{-276,6},{-236,46}})));
+protected
+ Interfaces.Bus bus2 "HP control bus"
+ annotation (Placement(transformation(extent={{60,-60},{100,-20}}),
+ iconTransformation(extent={{-276,6},{-236,46}})));
+equation
+ connect(y1Hea.y[1], TSetAct.u2)
+ annotation (Line(points={{-158,100},{-42,100}},color={255,0,255}));
+ connect(TChiWatSupSet.y, TSetAct.u3)
+ annotation (Line(points={{-68,120},{-64,120},{-64,92},{-42,92}},color={0,0,127}));
+ connect(THeaWatSupSet.y, TSetAct.u1)
+ annotation (Line(points={{-68,160},{-60,160},{-60,108},{-42,108}},color={0,0,127}));
+ connect(TSup.port_b, sup.ports[1])
+ annotation (Line(points={{150,0},{170,0},{170,38.6667}},color={0,127,255}));
+ connect(THeaWatRet.y, TRetAct.u1)
+ annotation (Line(points={{-68,82},{-60,82},{-60,68},{-42,68}},color={0,0,127}));
+ connect(y1Hea.y[1], TRetAct.u2)
+ annotation (Line(points={{-158,100},{-50,100},{-50,60},{-42,60}},color={255,0,255}));
+ connect(TChiWatRet.y, TRetAct.u3)
+ annotation (Line(points={{-68,40},{-50,40},{-50,52},{-42,52}},color={0,0,127}));
+ connect(hpAw.port_b, TSup.port_a)
+ annotation (Line(points={{120,0},{130,0}},color={0,127,255}));
+ connect(TRetAct.y, inlHp.T_in) annotation (Line(points={{-18,60},{-10,60},{-10,
+ 4},{8,4}}, color={0,0,127}));
+ connect(y1Hea.y[1], bus.y1Hea)
+ annotation (Line(points={{-158,100},{-50,100},{-50,120},{80,120},{80,40}},
+ color={255,0,255}));
+ connect(y1.y[1], bus.y1)
+ annotation (Line(points={{-158,140},{-50,140},{-50,120},{80,120},{80,40}},
+ color={255,0,255}));
+ connect(TSetAct.y, bus.TSet)
+ annotation (Line(points={{-18,100},{80,100},{80,40},{80,40}}, color={0,0,127}));
+ connect(pInl_rel.y, inlHp.p_in)
+ annotation (Line(points={{-18,-20},{0,-20},{0,8},{8,8}}, color={0,0,127}));
+ connect(pHeaWatInl.y, pInl_rel.u1)
+ annotation (Line(points={{-68,0},{-58,0},{-58,-12},{-42,-12}},color={0,0,127}));
+ connect(pChiWatInl.y, pInl_rel.u3)
+ annotation (Line(points={{-68,-40},{-46,-40},{-46,-28},{-42,-28}},color={0,0,127}));
+ connect(y1Hea.y[1], pInl_rel.u2)
+ annotation (Line(points={{-158,100},{-158,100.526},{-50,100.526},{-50,-20},{-42,-20}},
+ color={255,0,255}));
+ connect(bus, hpAw.bus)
+ annotation (Line(points={{80,40},{110,40},{110,10}},color={255,204,51},thickness=0.5));
+ connect(weaDat.weaBus, hpAw.busWea)
+ annotation (Line(points={{170,140},{160,140},{160,16},{104,16},{104,10}},
+ color={255,204,51},thickness=0.5));
+ connect(inlHp.ports[1], TRet.port_a) annotation (Line(points={{30,-1.33333},{
+ 40,-1.33333},{40,0},{50,0}}, color={0,127,255}));
+ connect(TRet.port_b, hpAw.port_a)
+ annotation (Line(points={{70,0},{100,0}},color={0,127,255}));
+ connect(bus1, hpAwNrv.bus)
+ annotation (Line(points={{80,120},{110,120},{110,90}},color={255,204,51},thickness=0.5));
+ connect(y1.y[1], bus1.y1)
+ annotation (Line(points={{-158,140},{-50,140},{-50,120},{80,120}},color={255,0,255}));
+ connect(hpAwNrv.port_b, TSup1.port_a)
+ annotation (Line(points={{120,80},{130,80}},color={0,127,255}));
+ connect(TRet1.port_b, hpAwNrv.port_a)
+ annotation (Line(points={{70,80},{100,80}},color={0,127,255}));
+ connect(TSup1.port_b, sup.ports[2])
+ annotation (Line(points={{150,80},{170,80},{170,40}},color={0,127,255}));
+ connect(inlHp.ports[2], TRet1.port_a) annotation (Line(points={{30,0},{40,0},
+ {40,80},{50,80}}, color={0,127,255}));
+ connect(weaDat.weaBus, hpAwNrv.busWea)
+ annotation (Line(points={{170,140},{160,140},{160,94},{104,94},{104,90}},
+ color={255,204,51},thickness=0.5));
+ connect(THeaWatSupSet.y, bus1.TSet)
+ annotation (Line(points={{-68,160},{80,160},{80,120}}, color={0,0,127}));
+ connect(hpWw.port_b, TSup2.port_a)
+ annotation (Line(points={{120,-80},{130,-80}}, color={0,127,255}));
+ connect(TSup2.port_b, sup.ports[3])
+ annotation (Line(points={{150,-80},{170,-80},{170,41.3333}},color={0,127,255}));
+ connect(inlHp.ports[3], TRet2.port_a) annotation (Line(points={{30,1.33333},{
+ 30,0},{40,0},{40,-80},{50,-80}}, color={0,127,255}));
+ connect(bus2, hpWw.bus) annotation (Line(
+ points={{80,-40},{110,-40},{110,-70}},
+ color={255,204,51},
+ thickness=0.5));
+ connect(TSouHea.y, TSouAct.u1)
+ annotation (Line(points={{-70,-80},{-56,-80},{-56,-74},{-42,-74}},color={0,0,127}));
+ connect(y1Hea.y[1], TSouAct.u2)
+ annotation (Line(points={{-158,100},{-50,100},{-50,-82},{-42,-82}},color={255,0,255}));
+ connect(TSouCoo.y, TSouAct.u3)
+ annotation (Line(points={{-70,-120},{-46,-120},{-46,-90},{-42,-90}},color={0,0,127}));
+ connect(pSouInlHea.y, pInl_rel1.u1)
+ annotation (Line(points={{-108,-120},{-102,-120},{-102,-140},{-60,-140},{-60,-132},{-42,-132}},
+ color={0,0,127}));
+ connect(pSouInlCoo.y, pInl_rel1.u3)
+ annotation (Line(points={{-108,-160},{-60,-160},{-60,-148},{-42,-148}},color={0,0,127}));
+ connect(y1Hea.y[1], pInl_rel1.u2)
+ annotation (Line(points={{-158,100},{-50,100},{-50,-140},{-42,-140}},color={255,0,255}));
+ connect(retSou.ports[1], hpWw.port_bSou) annotation (Line(points={{170,-120},{
+ 94,-120},{94,-90},{100,-90}}, color={0,127,255}));
+ connect(TSouAct.y, inlHpSou.T_in) annotation (Line(points={{-18,-82},{0,-82},
+ {0,-96},{8,-96}}, color={0,0,127}));
+ connect(pInl_rel1.y, inlHpSou.p_in) annotation (Line(points={{-18,-140},{-20,
+ -140},{-20,-92},{8,-92}}, color={0,0,127}));
+ connect(TSetAct.y, bus2.TSet)
+ annotation (Line(points={{-18,100},{80,100},{80,50},{80,50},{80,-40}},
+ color={0,0,127}));
+ connect(y1.y[1], bus2.y1)
+ annotation (Line(points={{-158,140},{-50,140},{-50,-40},{80,-40}},color={255,0,255}));
+ connect(y1Hea.y[1], bus2.y1Hea)
+ annotation (Line(points={{-158,100},{-50,100},{-50,-40},{80,-40}},color={255,0,255}));
+ connect(TRet2.port_b, res.port_a)
+ annotation (Line(points={{70,-80},{70,-80}}, color={0,127,255}));
+ connect(res.port_b, hpWw.port_a)
+ annotation (Line(points={{90,-80},{100,-80}}, color={0,127,255}));
+ connect(hpWw.port_aSou, resSou.port_b) annotation (Line(points={{120,-90},{126,
+ -90},{126,-100},{90,-100}}, color={0,127,255}));
+ connect(inlHpSou.ports[1], resSou.port_a) annotation (Line(points={{30,-100},
+ {50,-100},{50,-100},{70,-100}}, color={0,127,255}));
+ annotation (
+ Diagram(
+ coordinateSystem(
+ extent={{-200,-180},{200,180}})),
+ __Dymola_Commands(
+ file=
+ "modelica://Buildings/Resources/Scripts/Dymola/Templates/Components/HeatPumps/Validation/HeatPumpEquationFit.mos"
+ "Simulate and plot"),
+ experiment(
+ Tolerance=1e-6,
+ StartTime=10497600.0,
+ StopTime=10505600.0),
+ Documentation(
+ info="
+
+First implementation.
+Nrv
) or a reversible heat pump
+that switches between cooling and heating mode.
+
+
+"));
+end HeatPumpEquationFit;
diff --git a/Buildings/Templates/Components/HeatPumps/Validation/package.mo b/Buildings/Templates/Components/HeatPumps/Validation/package.mo
new file mode 100644
index 00000000000..393eb756c0b
--- /dev/null
+++ b/Buildings/Templates/Components/HeatPumps/Validation/package.mo
@@ -0,0 +1,9 @@
+within Buildings.Templates.Components.HeatPumps;
+package Validation "Package with validation models"
+ extends Modelica.Icons.ExamplesPackage;
+ annotation (Documentation(info="
+
+First implementation.
+is_rev
+to represent either a non-reversible heat pump (heating only) or a
+reversible heat pump.
+This model uses
+
+Buildings.Fluid.HeatPumps.EquationFitReversible,
+which the user may refer to for the modeling assumptions.
+Control points
+
+
+"));
+end WaterToWater;
diff --git a/Buildings/Templates/Components/HeatPumps/package.mo b/Buildings/Templates/Components/HeatPumps/package.mo
new file mode 100644
index 00000000000..5b1c797e920
--- /dev/null
+++ b/Buildings/Templates/Components/HeatPumps/package.mo
@@ -0,0 +1,9 @@
+within Buildings.Templates.Components;
+package HeatPumps "Heat pump models"
+ extends Modelica.Icons.VariantsPackage;
+ annotation (Documentation(info="
+
+First implementation.
+
+
+"),
+ Diagram(coordinateSystem(extent={{-100,-140},{100,160}})));
+end PartialHeatPump;
diff --git a/Buildings/Templates/Components/Interfaces/PartialHeatPumpEquationFit.mo b/Buildings/Templates/Components/Interfaces/PartialHeatPumpEquationFit.mo
new file mode 100644
index 00000000000..d96af2a33bc
--- /dev/null
+++ b/Buildings/Templates/Components/Interfaces/PartialHeatPumpEquationFit.mo
@@ -0,0 +1,196 @@
+within Buildings.Templates.Components.Interfaces;
+model PartialHeatPumpEquationFit
+ "Interface for heat pump using equation fit model"
+ extends Buildings.Templates.Components.Interfaces.PartialHeatPump(
+ final typMod=Buildings.Templates.Components.Types.HeatPumpModel.EquationFit);
+
+ final parameter Buildings.Fluid.HeatPumps.Data.EquationFitReversible.Generic datPerFit(
+ dpHeaSou_nominal = if have_preDroSou then dat.perFit.dpHeaSou_nominal else 0,
+ dpHeaLoa_nominal = if have_preDroChiHeaWat then dat.perFit.dpHeaLoa_nominal else 0,
+ hea(
+ TRefLoa = dat.perFit.hea.TRefLoa,
+ TRefSou = dat.perFit.hea.TRefSou,
+ Q_flow = dat.perFit.hea.Q_flow,
+ P = dat.perFit.hea.P,
+ mSou_flow = dat.perFit.hea.mSou_flow,
+ mLoa_flow = dat.perFit.hea.mLoa_flow,
+ coeQ = dat.perFit.hea.coeQ,
+ coeP = dat.perFit.hea.coeP),
+ coo(
+ TRefSou = dat.perFit.coo.TRefSou,
+ TRefLoa = dat.perFit.coo.TRefLoa,
+ Q_flow = dat.perFit.coo.Q_flow,
+ P = dat.perFit.coo.P,
+ coeQ = dat.perFit.coo.coeQ,
+ coeP = dat.perFit.coo.coeP))
+ "Performance data - Equation fit model";
+
+ Modelica.Blocks.Routing.BooleanPassThrough y1Hea if is_rev
+ "Operating mode command: true=heating, false=cooling"
+ annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-80,130})));
+ Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1HeaNonRev(
+ final k=true) if not is_rev
+ "Placeholder signal for non-reversible heat pumps"
+ annotation (Placement(transformation(extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-40,130})));
+ Controls.StatusEmulator y1_actual
+ "Compute heat pump status"
+ annotation (Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=90,
+ origin={40,130})));
+ Fluid.Sensors.MassFlowRate mChiHeaWat_flow(redeclare final package Medium =
+ MediumHeaWat) "CHW/HW mass flow rate"
+ annotation (Placement(transformation(extent={{-90,-10},{-70,10}})));
+ Fluid.Sensors.TemperatureTwoPort TChiHeaWatEnt(redeclare final package Medium =
+ MediumHeaWat, final m_flow_nominal=max(mChiWat_flow_nominal,
+ mHeaWat_flow_nominal)) "CHW/HW entering temperature"
+ annotation (Placement(transformation(extent={{-60,-10},{-40,10}})));
+ Fluid.Sensors.TemperatureTwoPort TChiHeaWatLvg(redeclare final package Medium =
+ MediumHeaWat, final m_flow_nominal=max(mChiWat_flow_nominal,
+ mHeaWat_flow_nominal)) "CHW/HW leaving temperature"
+ annotation (Placement(transformation(extent={{70,-10},{90,10}})));
+ Fluid.Sensors.TemperatureTwoPort TSouEnt(
+ redeclare final package Medium = MediumSou, final m_flow_nominal=
+ mSouHea_flow_nominal) "Source fluid entering temperature"
+ annotation (Placement(transformation(extent={{40,-30},{20,-10}})));
+ Fluid.Sensors.TemperatureTwoPort TSouLvg(
+ redeclare final package Medium = MediumSou,
+ final m_flow_nominal=
+ mSouHea_flow_nominal) "Source fluid leaving temperature"
+ annotation (Placement(transformation(
+ extent={{10,-10},{-10,10}},
+ rotation=0,
+ origin={-30,-20})));
+ Buildings.Fluid.HeatPumps.EquationFitReversible hp(
+ uMod(start=0),
+ redeclare final package Medium1 = MediumHeaWat,
+ redeclare final package Medium2 = MediumSou,
+ final per=datPerFit,
+ final energyDynamics=energyDynamics) "Heat pump"
+ annotation (Placement(transformation(extent={{-10,-16},{10,4}})));
+ Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger y1Int
+ "Convert on/off command into integer"
+ annotation (Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-20,90})));
+ Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger y1HeaInt(
+ y(start=0),
+ final integerTrue=1,
+ final integerFalse=-1)
+ "Convert heating mode command into integer"
+ annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-80,90})));
+ Buildings.Controls.OBC.CDL.Integers.Multiply mulInt
+ "Combine on/off and operating mode command signals"
+ annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-20,50})));
+equation
+ /* Control point connection - start */
+ /* Control point connection - stop */
+ connect(bus.y1Hea, y1Hea.u) annotation (Line(
+ points={{0,160},{0,156},{-80,156},{-80,142}},
+ color={255,204,51},
+ thickness=0.5));
+ connect(port_a, mChiHeaWat_flow.port_a)
+ annotation (Line(points={{-100,0},{-90,0}}, color={0,127,255}));
+ connect(mChiHeaWat_flow.port_b, TChiHeaWatEnt.port_a)
+ annotation (Line(points={{-70,0},{-60,0}}, color={0,127,255}));
+ connect(TChiHeaWatLvg.port_b, port_b)
+ annotation (Line(points={{90,0},{100,0}}, color={0,127,255}));
+ connect(TSouLvg.port_b, port_bSou) annotation (Line(points={{-40,-20},{-80,-20},
+ {-80,-140}}, color={0,127,255}));
+ connect(y1Hea.y, y1HeaInt.u) annotation (Line(points={{-80,119},{-80,110.5},{-80,
+ 110.5},{-80,102}}, color={255,0,255}));
+ connect(y1HeaNonRev.y, y1HeaInt.u) annotation (Line(points={{-40,118},{-40,110},
+ {-80,110},{-80,102}}, color={255,0,255}));
+ connect(y1HeaInt.y, mulInt.u2) annotation (Line(points={{-80,78},{-80,70},{-26,
+ 70},{-26,62}}, color={255,127,0}));
+ connect(y1Int.y, mulInt.u1) annotation (Line(points={{-20,78},{-20,70},{-14,70},
+ {-14,62}}, color={255,127,0}));
+ connect(TChiHeaWatEnt.port_b, hp.port_a1)
+ annotation (Line(points={{-40,0},{-10,0}}, color={0,127,255}));
+ connect(hp.port_b1, TChiHeaWatLvg.port_a)
+ annotation (Line(points={{10,0},{70,0}}, color={0,127,255}));
+ connect(TSouLvg.port_a, hp.port_b2) annotation (Line(points={{-20,-20},{-20,-12},
+ {-10,-12}}, color={0,127,255}));
+ connect(TSouEnt.port_b, hp.port_a2)
+ annotation (Line(points={{20,-20},{20,-12},{10,-12}}, color={0,127,255}));
+ connect(bus.y1, y1Int.u) annotation (Line(
+ points={{0,160},{0,110},{-20,110},{-20,102}},
+ color={255,204,51},
+ thickness=0.5));
+ connect(bus.TSet, hp.TSet) annotation (Line(
+ points={{0,160},{0,86},{0,86},{0,10},{-16,10},{-16,3},{-11.4,3}},
+ color={255,204,51},
+ thickness=0.5));
+ connect(mulInt.y, hp.uMod)
+ annotation (Line(points={{-20,38},{-20,-6},{-11,-6}}, color={255,127,0}));
+ connect(y1_actual.y1_actual, bus.y1_actual)
+ annotation (Line(points={{40,142},{40,156},{0,156},{0,160}},
+ color={255,0,255}));
+ connect(bus.y1, y1_actual.y1) annotation (Line(
+ points={{0,160},{0,110},{40,110},{40,118}},
+ color={255,204,51},
+ thickness=0.5));
+ annotation (
+ defaultComponentName="heaPum",
+ Documentation(info="
+
+First implementation.
+is_rev
+to represent either a non-reversible heat pump (heating only) or a
+reversible heat pump.
+This model uses
+
+Buildings.Fluid.HeatPumps.EquationFitReversible,
+which the user may refer to for the modeling assumptions.
+Control points
+
+
+", revisions="
+y1
:
+DO signal, with a dimensionality of zero
+is_rev=true
),
+Heat pump operating mode command signal y1Hea
:
+DO signal, with a dimensionality of zero
+(y1Hea=true
for heating mode,
+y1Hea=false
for cooling mode)
+TSet
:
+AO signal, with a dimensionality of zero
+(for reversible heat pumps, the setpoint value must be
+switched externally between HW and CHW supply temperature)
+y1_actual
:
+DI signal, with a dimensionality of zero
+
+
+"));
+end PartialHeatPumpEquationFit;
diff --git a/Buildings/Templates/Components/Interfaces/PartialPump.mo b/Buildings/Templates/Components/Interfaces/PartialPump.mo
new file mode 100644
index 00000000000..1d1ab7160c3
--- /dev/null
+++ b/Buildings/Templates/Components/Interfaces/PartialPump.mo
@@ -0,0 +1,97 @@
+within Buildings.Templates.Components.Interfaces;
+model PartialPump "Base class for all pump models"
+ parameter Buildings.Templates.Components.Types.Pump typ
+ "Equipment type"
+ annotation (Evaluate=true, Dialog(group="Configuration", enable=false));
+
+ parameter Boolean have_var=true
+ "Set to true for variable speed pump, false for constant speed pump"
+ annotation (Evaluate=true, Dialog(group="Configuration",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None));
+ parameter Boolean have_varCom=true
+ "Set to true for single common speed signal, false for dedicated signals"
+ annotation (Evaluate=true, Dialog(group="Configuration",
+ enable=typ==Buildings.Templates.Components.Types.Pump.Multiple and have_var));
+
+ parameter Boolean have_valChe=true
+ "Set to true to include a check valve in pump line"
+ annotation (Evaluate=true, Dialog(group="Configuration",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None),
+ __Linkage(enable=false));
+
+ parameter Boolean addPowerToMedium=false
+ "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)"
+ annotation(__Linkage(enable=false));
+
+ parameter Modelica.Units.SI.Time tau=1
+ "Time constant of fluid volume for nominal flow, used if energy or mass balance is dynamic"
+ annotation (Dialog(
+ tab="Dynamics",
+ group="Nominal condition",
+ enable=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState),
+ __Linkage(enable=false));
+ parameter Modelica.Fluid.Types.Dynamics energyDynamics=
+ Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
+ "Type of energy balance: dynamic (3 initialization options) or steady state"
+ annotation(Evaluate=true, Dialog(tab = "Dynamics", group="Conservation equations"),
+ __Linkage(enable=false));
+ parameter Boolean allowFlowReversal = true
+ "= false to simplify equations, assuming, but not enforcing, no flow reversal"
+ annotation(Dialog(tab="Assumptions"), Evaluate=true, __Linkage(enable=false));
+
+ parameter Integer text_rotation = 0
+ "Text rotation angle in icon layer"
+ annotation(Dialog(tab="Graphics", enable=false));
+ parameter Boolean text_flip = false
+ "True to flip text horizontally in icon layer"
+ annotation(Dialog(tab="Graphics", enable=false));
+
+ Buildings.Templates.Components.Interfaces.Bus bus
+ "Control bus"
+ annotation (
+ Placement(transformation(
+ extent={{-20,-20},{20,20}},
+ rotation=0,
+ origin={0,100}), iconTransformation(
+ extent={{-10,-10},{10,10}},
+ rotation=0,
+ origin={0,100})));
+
+ annotation ( Documentation(info="
+
+First implementation.
+
+
+"), Icon(graphics={
+ Line( points={{-100,0},{100,0}},
+ color={0,0,0},
+ thickness=5),
+ Bitmap(
+ visible=typ <> Buildings.Templates.Components.Types.Pump.None and
+ have_valChe,
+ extent={{20,-40},{100,40}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg"),
+ Bitmap(
+ visible=typ <> Buildings.Templates.Components.Types.Pump.None,
+ extent={{-100,-70},{0,30}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_var,
+ extent={{-100,60},{0,160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and not have_var,
+ extent={{-100,60},{0,160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"),
+ Line( visible=typ <> Buildings.Templates.Components.Types.Pump.None,
+ points={{-50,60},{-50,22}},
+ color={0,0,0})}));
+end PartialPump;
diff --git a/Buildings/Templates/Components/Interfaces/PartialPumpMultiple.mo b/Buildings/Templates/Components/Interfaces/PartialPumpMultiple.mo
new file mode 100644
index 00000000000..c8dd8374704
--- /dev/null
+++ b/Buildings/Templates/Components/Interfaces/PartialPumpMultiple.mo
@@ -0,0 +1,220 @@
+within Buildings.Templates.Components.Interfaces;
+partial model PartialPumpMultiple
+ "Interface class for multiple pumps in parallel arrangement"
+ extends Buildings.Templates.Components.Interfaces.PartialPump;
+
+ replaceable package Medium=Buildings.Media.Water
+ constrainedby Modelica.Media.Interfaces.PartialMedium
+ "Medium in the component"
+ annotation(__Linkage(enable=false));
+
+ parameter Integer nPum(
+ final min=0,
+ start=1)
+ "Number of pumps"
+ annotation (Dialog(group="Configuration",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None));
+
+ parameter Buildings.Templates.Components.Data.PumpMultiple dat(
+ final nPum=nPum,
+ final typ=typ)
+ "Design and operating parameters"
+ annotation(__Linkage(enable=false));
+
+ final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal[nPum](
+ each final min=0)=dat.m_flow_nominal
+ "Nominal mass flow rate"
+ annotation (Dialog(group="Nominal condition",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None));
+ final parameter Modelica.Units.SI.PressureDifference dp_nominal[nPum](
+ each final min=0,
+ each displayUnit="Pa")=dat.dp_nominal
+ "Pump head at design conditions"
+ annotation (Dialog(group="Nominal condition",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None));
+ // This parameter is declared outside the parameter record dat as
+ // it is considered to be an advanced parameter for which a default
+ // value can probably be used.
+ parameter Modelica.Units.SI.PressureDifference dpValChe_nominal[nPum](
+ each final min=0,
+ each start=Buildings.Templates.Data.Defaults.dpValChe,
+ each displayUnit="Pa")=fill(Buildings.Templates.Data.Defaults.dpValChe, nPum)
+ "Check valve pressure drop at design conditions"
+ annotation (Dialog(group="Nominal condition",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None
+ and have_valChe));
+ Modelica.Fluid.Interfaces.FluidPorts_a ports_a[nPum](
+ redeclare each final package Medium = Medium,
+ each m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
+ each h_outflow(start = Medium.h_default, nominal = Medium.h_default),
+ each p(start=Medium.p_default))
+ "Vectorized fluid connector a (positive design flow direction is from port(s)_a to port(s)_b)"
+ annotation (Placement(
+ transformation(extent={{-110,-40},{-90,40}}), iconTransformation(extent={{-110,
+ -40},{-90,40}})));
+ Modelica.Fluid.Interfaces.FluidPorts_b ports_b[nPum](
+ redeclare each final package Medium = Medium,
+ each m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
+ each h_outflow(start = Medium.h_default, nominal = Medium.h_default),
+ each p(start=Medium.p_default))
+ "Vectorized fluid connector b (positive design flow direction is from port(s)_a to port(s)_b)"
+ annotation (Placement(
+ transformation(extent={{90,-40},{110,40}}), iconTransformation(extent={{90,-40},
+ {110,40}})));
+
+ parameter Integer icon_dy = 300
+ "Distance in y-direction between each unit in icon layer"
+ annotation(Dialog(tab="Graphics", enable=false));
+
+ annotation (Documentation(info="
+
+First implementation.
+
+
+"), Icon(graphics={
+ Text(
+ extent={{-149,-114},{151,-154}},
+ textColor={0,0,255},
+ textString="%name"),
+ Line( visible=typ <> Buildings.Templates.Components.Types.Pump.None and
+ nPum >= 2,
+ points={{-100,icon_dy},{100,icon_dy}},
+ color={0,0,0},
+ thickness=5),
+ Line( visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=2,
+ points={{-50,icon_dy+60},{-50,icon_dy+22}},
+ color={0,0,0}),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=2,
+ extent={{-100,icon_dy-70},{0,icon_dy+30}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_valChe and nPum>=2,
+ extent={{20,icon_dy-40},{100,icon_dy+40}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_var and nPum>=2,
+ extent={{-100,icon_dy+60},{0,icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and not have_var and nPum>=2,
+ extent={{-100,icon_dy+60},{0,icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"),
+ Line(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=3,
+ points={{-100,2*icon_dy},{100,2*icon_dy}},
+ color={0,0,0},
+ thickness=5),
+ Line( visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=3,
+ points={{-50,2*icon_dy+60},{-50,2*icon_dy+22}},
+ color={0,0,0}),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=3,
+ extent={{-100,2*icon_dy-70},{0,2*icon_dy+30}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_valChe and nPum>=3,
+ extent={{20, 2*icon_dy-40},{100, 2*icon_dy+40}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_var and nPum>=3,
+ extent={{-100, 2*icon_dy+60},{0, 2*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and not have_var and nPum>=3,
+ extent={{-100, 2*icon_dy+60},{0, 2*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"),
+ Line(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=4,
+ points={{-100, 3*icon_dy},{100, 3*icon_dy}},
+ color={0,0,0},
+ thickness=5),
+ Line( visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=4,
+ points={{-50, 3*icon_dy+60},{-50, 3*icon_dy+22}},
+ color={0,0,0}),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=4,
+ extent={{-100, 3*icon_dy-70},{0, 3*icon_dy+30}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_valChe and nPum>=4,
+ extent={{20, 3*icon_dy-40},{100, 3*icon_dy+40}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_var and nPum>=4,
+ extent={{-100, 3*icon_dy+60},{0, 3*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and not have_var and nPum>=4,
+ extent={{-100, 3*icon_dy+60},{0, 3*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"),
+ Line(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=5,
+ points={{-100, 4*icon_dy},{100, 4*icon_dy}},
+ color={0,0,0},
+ thickness=5),
+ Line( visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=5,
+ points={{-50, 4*icon_dy+60},{-50, 4*icon_dy+22}},
+ color={0,0,0}),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=5,
+ extent={{-100, 4*icon_dy-70},{0, 4*icon_dy+30}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_valChe and nPum>=5,
+ extent={{20, 4*icon_dy-40},{100, 4*icon_dy+40}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_var and nPum>=5,
+ extent={{-100, 4*icon_dy+60},{0, 4*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and not have_var and nPum>=5,
+ extent={{-100, 4*icon_dy+60},{0, 4*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"),
+ Line(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=6,
+ points={{-100, 5*icon_dy},{100, 5*icon_dy}},
+ color={0,0,0},
+ thickness=5),
+ Line( visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=6,
+ points={{-50, 5*icon_dy+60},{-50, 5*icon_dy+22}},
+ color={0,0,0}),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and nPum>=6,
+ extent={{-100, 5*icon_dy-70},{0, 5*icon_dy+30}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_valChe and nPum>=6,
+ extent={{20, 5*icon_dy-40},{100, 5*icon_dy+40}},
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and have_var and nPum>=6,
+ extent={{-100, 5*icon_dy+60},{0, 5*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"),
+ Bitmap(
+ visible=typ<>Buildings.Templates.Components.Types.Pump.None and not have_var and nPum>=6,
+ extent={{-100, 5*icon_dy+60},{0, 5*icon_dy+160}},
+ rotation=text_rotation,
+ fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg")}));
+
+end PartialPumpMultiple;
diff --git a/Buildings/Templates/Components/Interfaces/PartialPumpSingle.mo b/Buildings/Templates/Components/Interfaces/PartialPumpSingle.mo
new file mode 100644
index 00000000000..6b210d8825a
--- /dev/null
+++ b/Buildings/Templates/Components/Interfaces/PartialPumpSingle.mo
@@ -0,0 +1,48 @@
+within Buildings.Templates.Components.Interfaces;
+partial model PartialPumpSingle "Interface class for single pump"
+ extends Buildings.Templates.Components.Interfaces.PartialPump;
+ extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
+ redeclare replaceable package Medium=Buildings.Media.Water,
+ final m_flow_nominal(min=0)=dat.m_flow_nominal)
+ annotation(__Linkage(enable=false));
+
+ parameter Buildings.Templates.Components.Data.PumpSingle dat(
+ final typ=typ)
+ "Design and operating parameters"
+ annotation(__Linkage(enable=false));
+
+ final parameter Modelica.Units.SI.PressureDifference dp_nominal(
+ final min=0,
+ displayUnit="Pa")=dat.dp_nominal
+ "Pump head at design conditions"
+ annotation (Dialog(group="Nominal condition",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None));
+
+ // This parameter is declared outside the parameter record dat as
+ // it is considered to be an advanced parameter for which a default
+ // value can probably be used.
+ parameter Modelica.Units.SI.PressureDifference dpValChe_nominal(
+ final min=0,
+ start=Buildings.Templates.Data.Defaults.dpValChe,
+ displayUnit="Pa")=Buildings.Templates.Data.Defaults.dpValChe
+ "Check valve pressure drop at design conditions"
+ annotation (Dialog(group="Nominal condition",
+ enable=typ<>Buildings.Templates.Components.Types.Pump.None
+ and have_valChe));
+
+ annotation (
+ Icon(coordinateSystem(preserveAspectRatio=false)),
+ Documentation(info="
+
+First implementation.
+
+
+"));
+end PartialPumpSingle;
diff --git a/Buildings/Templates/Components/Interfaces/PartialSensor.mo b/Buildings/Templates/Components/Interfaces/PartialSensor.mo
index a714f4d78a3..bc8a979f99b 100644
--- a/Buildings/Templates/Components/Interfaces/PartialSensor.mo
+++ b/Buildings/Templates/Components/Interfaces/PartialSensor.mo
@@ -1,7 +1,7 @@
within Buildings.Templates.Components.Interfaces;
partial model PartialSensor "Interface class for sensor"
extends Buildings.Fluid.Interfaces.PartialTwoPortInterface
- annotation(__ctrlFlow(enable=false));
+ annotation(__Linkage(enable=false));
parameter Boolean have_sen=true
"Set to true for sensor, false for direct pass through"
@@ -16,6 +16,10 @@ partial model PartialSensor "Interface class for sensor"
parameter Boolean text_flip = false
"True to flip text horizontally in icon layer"
annotation(Dialog(tab="Graphics", enable=false));
+ parameter Buildings.Templates.Components.Types.IconPipe icon_pipe =
+ Buildings.Templates.Components.Types.IconPipe.None
+ "Pipe symbol"
+ annotation(Dialog(tab="Graphics", enable=false));
Buildings.Controls.OBC.CDL.Interfaces.RealOutput y if have_sen
"Connector for measured value"
@@ -42,12 +46,16 @@ equation
annotation (
Icon(coordinateSystem(preserveAspectRatio=false),
- graphics={
- Line(
- visible=(not have_sen) and (not isDifPreSen),
- points={{-100,0},{100,0}},
- color={28,108,200},
- thickness=1)}),
+ graphics={Line(
+ visible=icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None
+ or (not have_sen) and (not isDifPreSen),
+ points={{-100,0},{100,0}},
+ color=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.None
+ then {28,108,200} else {0,0,0},
+ thickness=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.None
+ then 1 else 5,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Return
+ then LinePattern.Dash else LinePattern.Solid)}),
Diagram(coordinateSystem(preserveAspectRatio=false)),
Documentation(info="
+First implementation.
+nPum
pumps
+with optional check valves (depending on the value of the parameter
+have_valChe
).
+have_var
to false
.
+Control points
+
+
+y1
:
+DO signal dedicated to each unit, with a dimensionality of one
+y
for variable speed pumps only:
+
+
+have_varCom
: AO signal common to all units,
+with a dimensionality of zero
+not have_varCom
: AO signal dedicated to each unit,
+with a dimensionality of one
+y1_actual
:
+DI signal dedicated to each unit, with a dimensionality of one
+Model parameters
+
+
+"));
+end Multiple;
diff --git a/Buildings/Templates/Components/Pumps/Single.mo b/Buildings/Templates/Components/Pumps/Single.mo
new file mode 100644
index 00000000000..1a524680de3
--- /dev/null
+++ b/Buildings/Templates/Components/Pumps/Single.mo
@@ -0,0 +1,148 @@
+within Buildings.Templates.Components.Pumps;
+model Single "Single pump"
+ extends Buildings.Templates.Components.Interfaces.PartialPumpSingle(
+ final typ=Buildings.Templates.Components.Types.Pump.Single);
+
+ replaceable Buildings.Fluid.Movers.SpeedControlled_y pum(
+ redeclare final package Medium=Medium,
+ final per=dat.per,
+ final inputType=Buildings.Fluid.Types.InputType.Continuous,
+ final addPowerToMedium=addPowerToMedium,
+ final energyDynamics=energyDynamics,
+ final tau=tau,
+ final allowFlowReversal=allowFlowReversal)
+ "Pump"
+ annotation (
+ Placement(transformation(extent={{-10,-10},{10,10}})));
+ Buildings.Controls.OBC.CDL.Conversions.BooleanToReal sigSta
+ "Start/stop signal"
+ annotation (Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={-60,70})));
+ Buildings.Controls.OBC.CDL.Reals.Multiply sigCon
+ "Resulting control signal"
+ annotation (Placement(transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={0,30})));
+ Fluid.FixedResistances.CheckValve valChe(
+ redeclare final package Medium = Medium,
+ final m_flow_nominal=dat.m_flow_nominal,
+ final dpValve_nominal=dpValChe_nominal)
+ if have_valChe
+ "Check valve"
+ annotation (Placement(transformation(extent={{40,10},{60,30}})));
+ Routing.PassThroughFluid pas(
+ redeclare final package Medium=Medium) if not have_valChe
+ "Fluid pass through if no check valve"
+ annotation (Placement(transformation(extent={{40,-30},{60,-10}})));
+ Buildings.Controls.OBC.CDL.Reals.Sources.Constant speCst(
+ final k=1) if not have_var
+ "Constant signal in case of constant speed pump"
+ annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={60,70})));
+ Modelica.Blocks.Routing.RealPassThrough pasSpe if have_var
+ "Direct pass through for variable speed signal"
+ annotation (Placement(
+ transformation(
+ extent={{-10,-10},{10,10}},
+ rotation=-90,
+ origin={0,70})));
+ Controls.StatusEmulator sta "Emulate pump status"
+ annotation (Placement(transformation(extent={{-10,-70},{10,-50}})));
+equation
+ connect(sigSta.y, sigCon.u2)
+ annotation (Line(points={{-60,58},{-60,50},{-6,50},{-6,42}},
+ color={0,0,127}));
+ connect(sigCon.y, pum.y)
+ annotation (Line(points={{0,18},{0,15},{0,12}}, color={0,0,127}));
+ connect(port_a, pum.port_a)
+ annotation (Line(points={{-100,0},{-10,0}}, color={0,127,255}));
+ connect(bus.y, pasSpe.u) annotation (Line(
+ points={{0,100},{2.22045e-15,100},{2.22045e-15,82}},
+ color={255,204,51},
+ thickness=0.5), Text(
+ string="%first",
+ index=-1,
+ extent={{-3,6},{-3,6}},
+ horizontalAlignment=TextAlignment.Right));
+ connect(pasSpe.y, sigCon.u1)
+ annotation (Line(points={{0,59},{0,50},{6,50},{6,42}}, color={0,0,127}));
+ connect(speCst.y, sigCon.u1)
+ annotation (Line(points={{60,58},{60,50},{6,50},{6,42}}, color={0,0,127}));
+ connect(bus.y1, sigSta.u) annotation (Line(
+ points={{0,100},{0,88},{-60,88},{-60,82}},
+ color={255,204,51},
+ thickness=0.5), Text(
+ string="%first",
+ index=-1,
+ extent={{6,3},{6,3}},
+ horizontalAlignment=TextAlignment.Left));
+ connect(pum.port_b, valChe.port_a) annotation (Line(points={{10,0},{28,0},{28,
+ 20},{40,20}}, color={0,127,255}));
+ connect(valChe.port_b, port_b) annotation (Line(points={{60,20},{70,20},{70,0},
+ {100,0}}, color={0,127,255}));
+ connect(pum.port_b, pas.port_a) annotation (Line(points={{10,0},{28,0},{28,-20},
+ {40,-20}}, color={0,127,255}));
+ connect(pas.port_b, port_b) annotation (Line(points={{60,-20},{70,-20},{70,0},
+ {100,0}}, color={0,127,255}));
+ connect(bus.y1, sta.y1) annotation (Line(
+ points={{0,100},{0,88},{-80,88},{-80,-60},{-12,-60}},
+ color={255,204,51},
+ thickness=0.5));
+ connect(sta.y1_actual, bus.y1_actual) annotation (Line(points={{12,-60},{80,
+ -60},{80,96},{0,96},{0,100}}, color={255,0,255}));
+ annotation (
+ defaultComponentName="pum",
+ Documentation(info="
+
+First implementation.
+have_valChe
).
+have_var
to false
.
+Control points
+
+
+y1
:
+DO signal
+y
for variable speed pumps only:
+AO signal
+y1_actual
:
+DI signal
+Model parameters
+
+
+"));
+end Single;
diff --git a/Buildings/Templates/Components/Pumps/package.mo b/Buildings/Templates/Components/Pumps/package.mo
new file mode 100644
index 00000000000..d1f4ec5215f
--- /dev/null
+++ b/Buildings/Templates/Components/Pumps/package.mo
@@ -0,0 +1,15 @@
+within Buildings.Templates.Components;
+package Pumps "Pump models"
+ extends Modelica.Icons.VariantsPackage;
+
+
+
+
+
+
+annotation (Documentation(info="
+
+First implementation.
+
+
+"));
+end Junction;
diff --git a/Buildings/Templates/Components/Routing/MultipleToMultiple.mo b/Buildings/Templates/Components/Routing/MultipleToMultiple.mo
index e23e8ac3d7c..c94efade48e 100644
--- a/Buildings/Templates/Components/Routing/MultipleToMultiple.mo
+++ b/Buildings/Templates/Components/Routing/MultipleToMultiple.mo
@@ -42,16 +42,17 @@ model MultipleToMultiple
annotation (
Dialog(tab="Advanced", group="Diagnostics"), HideResult=true);
- parameter Integer icon_extend = 0
- "Extend lines by this amount in x-direction in icon layer: >0 at outlet, <0 at inlet"
- annotation(Dialog(tab="Graphics", enable=false));
- parameter Integer icon_dy = 100
- "Distance in y-direction between each branch in icon layer"
- annotation(Dialog(tab="Graphics", enable=false));
- parameter Buildings.Templates.Components.Types.IconPipe icon_pipe =
+ constant Integer icon_xinl = -100
+ "Minimum x-coordinate of inlet connection lines";
+ constant Integer icon_xout = 100
+ "Maximum x-coordinate of outlet connection lines";
+ constant Integer icon_offset = 0
+ "Offset in y-direction between inlet and outlet in icon layer";
+ constant Integer icon_dy = 100
+ "Distance in y-direction between each branch in icon layer";
+ constant Buildings.Templates.Components.Types.IconPipe icon_pipe =
Buildings.Templates.Components.Types.IconPipe.Supply
- "Pipe symbol"
- annotation(Dialog(tab="Graphics", enable=false));
+ "Pipe symbol";
Modelica.Fluid.Interfaces.FluidPorts_a ports_a[nPorts_a](
redeclare each final package Medium = Medium,
@@ -160,49 +161,84 @@ equation
Text( extent={{-149,-114},{151,-154}},
textColor={0,0,255},
textString="%name"),
- Line( points={{-100 + min(0,icon_extend), 0}, {100 + max(0, icon_extend),0}},
+ Line( points={{-100, 0}, {100, 0}},
+ color={0,127,255},
+ visible=icon_pipe==Buildings.Templates.Components.Types.IconPipe.None),
+ Line( points={{icon_xinl, 0}, {0,0}},
color={0,0,0},
thickness=5,
+ visible=icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
then LinePattern.Solid else LinePattern.Dash),
- Line( visible=nPorts_a>=2,
- points=if have_comLeg then
- {{-100 + min(0,icon_extend), icon_dy}, {-40,icon_dy}, {-40, 0}}
- else {{-100 + min(0,icon_extend),icon_dy}, {100 + max(0, icon_extend),icon_dy}},
+ Line( visible=nPorts_a>=2 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{icon_xinl, icon_dy}, {0,icon_dy}},
color={0,0,0},
thickness=5,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
then LinePattern.Solid else LinePattern.Dash),
- Line( visible=nPorts_a>=3,
- points=if have_comLeg then
- {{-100 + min(0,icon_extend), 2*icon_dy}, {-40, 2*icon_dy}, {-40, icon_dy}}
- else {{-100 + min(0,icon_extend),2*icon_dy}, {100 + max(0, icon_extend),2*icon_dy}},
+ Line( visible=nPorts_a>=3 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{icon_xinl, 2*icon_dy}, {0, 2*icon_dy}},
color={0,0,0},
thickness=5,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
then LinePattern.Solid else LinePattern.Dash),
- Line( visible=nPorts_a>=4,
- points=if have_comLeg then
- {{-100 + min(0,icon_extend), 3*icon_dy}, {-40, 3*icon_dy}, {-40, 2*icon_dy}}
- else {{-100 + min(0,icon_extend),3*icon_dy}, {100 + max(0, icon_extend),3*icon_dy}},
+ Line( visible=nPorts_a>=4 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{icon_xinl, 3*icon_dy}, {0, 3*icon_dy}},
color={0,0,0},
thickness=5,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
then LinePattern.Solid else LinePattern.Dash),
- Line( visible=nPorts_b>=2 and have_comLeg,
- points={{40, 0}, {40, icon_dy}, {100 + max(0, icon_extend), icon_dy}},
+ Line( visible=nPorts_a>=5 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{icon_xinl, 4*icon_dy}, {0, 4*icon_dy}},
color={0,0,0},
thickness=5,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
then LinePattern.Solid else LinePattern.Dash),
- Line( visible=nPorts_b>=3 and have_comLeg,
- points={{40, icon_dy}, {40, 2*icon_dy}, {100 + max(0, icon_extend), 2*icon_dy}},
+ Line( visible=nPorts_a>=6 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{icon_xinl, 5*icon_dy}, {0, 5*icon_dy}},
color={0,0,0},
thickness=5,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
then LinePattern.Solid else LinePattern.Dash),
- Line( visible=nPorts_b>=4 and have_comLeg,
- points={{40, 2*icon_dy}, {40, 3*icon_dy}, {100 + max(0, icon_extend), 3*icon_dy}},
+ Line( points={{0, icon_offset}, {icon_xout,icon_offset}},
+ color={0,0,0},
+ thickness=5,
+ visible=icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
+ then LinePattern.Solid else LinePattern.Dash),
+ Line( visible=nPorts_b>=2 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{0, icon_offset + 1*icon_dy}, {icon_xout,icon_offset + 1*icon_dy}},
+ color={0,0,0},
+ thickness=5,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
+ then LinePattern.Solid else LinePattern.Dash),
+ Line( visible=nPorts_b>=3 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{0, icon_offset + 2*icon_dy}, {icon_xout,icon_offset + 2*icon_dy}},
+ color={0,0,0},
+ thickness=5,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
+ then LinePattern.Solid else LinePattern.Dash),
+ Line( visible=nPorts_b>=4 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{0, icon_offset + 3*icon_dy}, {icon_xout,icon_offset + 3*icon_dy}},
+ color={0,0,0},
+ thickness=5,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
+ then LinePattern.Solid else LinePattern.Dash),
+ Line( visible=nPorts_b>=5 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{0, icon_offset + 4*icon_dy}, {icon_xout,icon_offset + 4*icon_dy}},
+ color={0,0,0},
+ thickness=5,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
+ then LinePattern.Solid else LinePattern.Dash),
+ Line( visible=nPorts_b>=6 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None,
+ points={{0, icon_offset + 5*icon_dy}, {icon_xout,icon_offset + 5*icon_dy}},
+ color={0,0,0},
+ thickness=5,
+ pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
+ then LinePattern.Solid else LinePattern.Dash),
+ Line( visible=icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None and
+ max(nPorts_a, nPorts_b)>=2 and have_comLeg,
+ points={{0, 0}, {0, icon_offset + (max(nPorts_a, nPorts_b)-1)*icon_dy}},
color={0,0,0},
thickness=5,
pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply
@@ -221,7 +257,7 @@ First implementation.
This is a model of a many-to-many fluid connector with an
optional control volume, and an optional mixing port (common leg).
It is typically used to connect parallel pumps with parallel
-chillers or boilers.
+chillers or boilers.
Selecting a mixing port allows modeling a headered pumping arrangement.
Without any mixing port, a dedicated pumping arrangement is modeled.
+First implementation.
+
This is a model of a direct fluid pass-through used for diff --git a/Buildings/Templates/Components/Routing/SingleToMultiple.mo b/Buildings/Templates/Components/Routing/SingleToMultiple.mo index 0c8996d1449..6bfd895ae96 100644 --- a/Buildings/Templates/Components/Routing/SingleToMultiple.mo +++ b/Buildings/Templates/Components/Routing/SingleToMultiple.mo @@ -35,16 +35,13 @@ model SingleToMultiple "Single inlet port, multiple outlet ports" Dialog(tab="Advanced", group="Diagnostics"), HideResult=true); - parameter Integer icon_offset = 0 - "Offset in y-direction between inlet and outlet in icon layer" - annotation(Dialog(tab="Graphics", enable=false)); - parameter Integer icon_dy = 100 - "Distance in y-direction between each branch in icon layer" - annotation(Dialog(tab="Graphics", enable=false)); - parameter Buildings.Templates.Components.Types.IconPipe icon_pipe = - Buildings.Templates.Components.Types.IconPipe.Supply - "Pipe symbol" - annotation(Dialog(tab="Graphics", enable=false)); + constant Integer icon_offset = 0 + "Offset in y-direction between inlet and outlet in icon layer"; + constant Integer icon_dy = 100 + "Distance in y-direction between each branch in icon layer"; + constant Buildings.Templates.Components.Types.IconPipe icon_pipe = + Buildings.Templates.Components.Types.IconPipe.None + "Pipe symbol"; Modelica.Fluid.Interfaces.FluidPort_a port_a( redeclare final package Medium = Medium, @@ -114,12 +111,16 @@ equation Text( extent={{-149,-114},{151,-154}}, textColor={0,0,255}, textString="%name"), + Line( points={{-100, 0}, {100, 0}}, + color={0,127,255}, + visible=icon_pipe==Buildings.Templates.Components.Types.IconPipe.None), Line( points={{-100,0},{0,0},{0,icon_offset},{100,icon_offset}}, color={0,0,0}, thickness=5, + visible=icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None, pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply then LinePattern.Solid else LinePattern.Dash), - Line( visible=nPorts>=2, + Line( visible=nPorts>=2 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None, points=if icon_offset*icon_dy>=0 then {{0, icon_offset}, {0,icon_offset+icon_dy}, {100,icon_offset+icon_dy}} elseif icon_offset>0 and icon_offset+icon_dy<0 or icon_offset<0 and icon_offset+icon_dy>0 then @@ -129,7 +130,7 @@ equation pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply then LinePattern.Solid else LinePattern.Dash, thickness=5), - Line( visible=nPorts>=3, + Line( visible=nPorts>=3 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None, points=if icon_offset*icon_dy>=0 then {{0, icon_offset+icon_dy},{0, icon_offset+2*icon_dy},{100, icon_offset+2*icon_dy}} elseif icon_offset>0 and icon_offset+2*icon_dy<0 or icon_offset<0 and icon_offset+2*icon_dy>0 then @@ -139,7 +140,7 @@ equation pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply then LinePattern.Solid else LinePattern.Dash, thickness=5), - Line( visible=nPorts>=4, + Line( visible=nPorts>=4 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None, points=if icon_offset*icon_dy>=0 then {{0, icon_offset+2*icon_dy},{0, icon_offset+3*icon_dy},{100, icon_offset+3*icon_dy}} elseif icon_offset>0 and icon_offset+3*icon_dy<0 or icon_offset<0 and icon_offset+3*icon_dy>0 then @@ -148,6 +149,26 @@ equation color={0,0,0}, pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply then LinePattern.Solid else LinePattern.Dash, + thickness=5), + Line( visible=nPorts>=5 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None, + points=if icon_offset*icon_dy>=0 then + {{0, icon_offset+3*icon_dy},{0, icon_offset+4*icon_dy},{100, icon_offset+4*icon_dy}} + elseif icon_offset>0 and icon_offset+4*icon_dy<0 or icon_offset<0 and icon_offset+4*icon_dy>0 then + {{0, 0},{0, icon_offset+4*icon_dy},{100, icon_offset+4*icon_dy}} + else {{0, icon_offset+4*icon_dy},{100, icon_offset+4*icon_dy}}, + color={0,0,0}, + pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply + then LinePattern.Solid else LinePattern.Dash, + thickness=5), + Line( visible=nPorts>=6 and icon_pipe<>Buildings.Templates.Components.Types.IconPipe.None, + points=if icon_offset*icon_dy>=0 then + {{0, icon_offset+4*icon_dy},{0, icon_offset+5*icon_dy},{100, icon_offset+5*icon_dy}} + elseif icon_offset>0 and icon_offset+5*icon_dy<0 or icon_offset<0 and icon_offset+5*icon_dy>0 then + {{0, 0},{0, icon_offset+5*icon_dy},{100, icon_offset+5*icon_dy}} + else {{0, icon_offset+5*icon_dy},{100, icon_offset+5*icon_dy}}, + color={0,0,0}, + pattern=if icon_pipe==Buildings.Templates.Components.Types.IconPipe.Supply + then LinePattern.Solid else LinePattern.Dash, thickness=5)}), Diagram( coordinateSystem(preserveAspectRatio=false)), diff --git a/Buildings/Templates/Components/Routing/package.order b/Buildings/Templates/Components/Routing/package.order index cb417ce6c69..3aed6c23d3f 100644 --- a/Buildings/Templates/Components/Routing/package.order +++ b/Buildings/Templates/Components/Routing/package.order @@ -1,3 +1,4 @@ +Junction MultipleToMultiple MultipleToSingle PassThroughFluid diff --git a/Buildings/Templates/Components/Sensors/Temperature.mo b/Buildings/Templates/Components/Sensors/Temperature.mo index 812a4f07e1e..f1265a767a2 100644 --- a/Buildings/Templates/Components/Sensors/Temperature.mo +++ b/Buildings/Templates/Components/Sensors/Temperature.mo @@ -11,13 +11,11 @@ model Temperature "Temperature sensor" Buildings.Fluid.Sensors.TemperatureTwoPort senTem( redeclare final package Medium=Medium, - final m_flow_nominal=m_flow_nominal, - final allowFlowReversal=allowFlowReversal) if have_sen + final m_flow_nominal=m_flow_nominal) if have_sen "Temperature sensor" annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); - Buildings.Templates.Components.Routing.PassThroughFluid pas( - redeclare final package Medium = Medium, - final allowFlowReversal=allowFlowReversal) if not have_sen "Pass through" + Buildings.Templates.Components.Routing.PassThroughFluid pas(redeclare final + package Medium = Medium) if not have_sen "Pass through" annotation (Placement(transformation(extent={{-10,-50},{10,-30}}))); equation @@ -45,12 +43,12 @@ equation Bitmap(extent={{-100,-160},{100,40}}, visible=have_sen and typ==Buildings.Templates.Components.Types.SensorTemperature.Averaging, fileName="modelica://Buildings/Resources/Images/Templates/Components/Sensors/ProbeAveraging.svg"), - Bitmap(extent={{-100,-160},{100,40}}, - visible=have_sen and typ==Buildings.Templates.Components.Types.SensorTemperature.Standard, - fileName="modelica://Buildings/Resources/Images/Templates/Components/Sensors/ProbeStandard.svg"), Bitmap(extent={{-100,-40},{100,160}}, visible=have_sen and typ==Buildings.Templates.Components.Types.SensorTemperature.InWell, - fileName="modelica://Buildings/Resources/Images/Templates/Components/Sensors/ProbeInWell.svg")}), + fileName="modelica://Buildings/Resources/Images/Templates/Components/Sensors/ProbeInWell.svg"), + Bitmap(extent={{-100,-160},{100,40}}, + visible=have_sen and typ==Buildings.Templates.Components.Types.SensorTemperature.Standard, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Sensors/ProbeStandard.svg")}), Diagram(coordinateSystem(preserveAspectRatio=false)), Documentation(info="
diff --git a/Buildings/Templates/Components/Sensors/VolumeFlowRate.mo b/Buildings/Templates/Components/Sensors/VolumeFlowRate.mo index 4f4ed3158d0..a69f91cecf4 100644 --- a/Buildings/Templates/Components/Sensors/VolumeFlowRate.mo +++ b/Buildings/Templates/Components/Sensors/VolumeFlowRate.mo @@ -10,13 +10,11 @@ model VolumeFlowRate "Volume flow rate sensor" Buildings.Fluid.Sensors.VolumeFlowRate senVolFlo( redeclare final package Medium=Medium, - final m_flow_nominal=m_flow_nominal, - final allowFlowReversal=allowFlowReversal) if have_sen + final m_flow_nominal=m_flow_nominal) if have_sen "Volume flow rate sensor" annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); - Buildings.Templates.Components.Routing.PassThroughFluid pas( - redeclare final package Medium = Medium, - final allowFlowReversal=allowFlowReversal) if not have_sen "Pass through" + Buildings.Templates.Components.Routing.PassThroughFluid pas(redeclare final + package Medium = Medium) if not have_sen "Pass through" annotation (Placement(transformation(extent={{-10,-50},{10,-30}}))); equation diff --git a/Buildings/Templates/Components/Types.mo b/Buildings/Templates/Components/Types.mo index abcc68c0f20..b2e5f8e32c1 100644 --- a/Buildings/Templates/Components/Types.mo +++ b/Buildings/Templates/Components/Types.mo @@ -67,6 +67,16 @@ package Types "Package with type definitions" Propeller "Propeller fan") "Enumeration to specify the type of single fan"; + type HeatPump = enumeration( + AirToWater + "Air-to-water heat pump", + WaterToWater + "Water(or brine)-to-water heat pump") + "Enumeration to specify the type of heat pump"; + type HeatPumpModel = enumeration( + EquationFit + "Heat pump model based on the equation fit method") + "Enumeration to specify the heat pump model"; type IconPipe = enumeration( None "No line", @@ -75,6 +85,17 @@ package Types "Package with type definitions" Supply "Supply pipe - Solid line") "Enumeration to specify the pipe symbol"; + type Pump = enumeration( + None + "No pump", + Single + "Single pump", + Multiple + "Multiple pumps in parallel") + "Enumeration to configure the pump"; + type PumpArrangement = enumeration( + Dedicated "Dedicated pumps", + Headered "Headered pumps") "Enumeration to specify the pump arrangement"; type Sensor = enumeration( DifferentialPressure "Differential pressure", diff --git a/Buildings/Templates/Components/Validation/Coils.mo b/Buildings/Templates/Components/Validation/Coils.mo index 437d93b1f9f..14a59d07332 100644 --- a/Buildings/Templates/Components/Validation/Coils.mo +++ b/Buildings/Templates/Components/Validation/Coils.mo @@ -129,9 +129,8 @@ model Coils "Validation model for coil components" Buildings.Controls.OBC.CDL.Reals.Sources.Constant XOut(k=0.015) "Water mass fraction in outdoor air" annotation (Placement(transformation(extent={{-130,-150},{-110,-130}}))); - Utilities.Psychrometrics.TWetBul_TDryBulXi wetBul( - redeclare final package Medium = MediumAir) - "Compute wet bulb temperature" + Buildings.Utilities.Psychrometrics.TWetBul_TDryBulXi wetBul(redeclare final + package Medium = MediumAir) "Compute wet bulb temperature" annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); Buildings.Controls.OBC.CDL.Reals.Sources.Constant pOut(k=101325) "Outdoor pressure" @@ -143,7 +142,7 @@ model Coils "Validation model for coil components" T=coiEva.dat.datCoi.sta[1].nomVal.TEvaIn_nominal, nPorts=2) "Boundary conditions for entering air" annotation (Placement(transformation(extent={{-90,-70},{-70,-50}}))); - Utilities.Psychrometrics.X_pTphi x_pTphi(use_p_in=false) + Buildings.Utilities.Psychrometrics.X_pTphi x_pTphi(use_p_in=false) "Compute wet bulb temperature" annotation (Placement(transformation(extent={{-88,-10},{-68,10}}))); Buildings.Controls.OBC.CDL.Reals.Sources.Constant TAirEnt(k=coiEva.dat.datCoi.sta[ diff --git a/Buildings/Templates/Components/Validation/PumpMultipleRecord.mo b/Buildings/Templates/Components/Validation/PumpMultipleRecord.mo new file mode 100644 index 00000000000..21f723c721b --- /dev/null +++ b/Buildings/Templates/Components/Validation/PumpMultipleRecord.mo @@ -0,0 +1,96 @@ +within Buildings.Templates.Components.Validation; +model PumpMultipleRecord "Validation model for parameter propagation with the multiple-pump record" + extends Modelica.Icons.Example; + + replaceable package Medium=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "Fluid medium"; + + parameter Integer nPum( + final min=0, + start=1)=2 + "Number of pumps" + annotation (Dialog(group="Configuration", enable=false)); + + parameter Modelica.Units.SI.MassFlowRate m_flow_nominal[nPum]( + each start=1, + each final min=0)={1, 2} + "Mass flow rate - Each pump"; + final parameter Modelica.Units.SI.VolumeFlowRate V_flow_nominal[nPum]= + m_flow_nominal ./ datDef.rho_default + "Mass flow rate - Each pump"; + parameter Modelica.Units.SI.PressureDifference dp_nominal[nPum]( + each start=0, + each final min=0)={1, 2} .* 1E4 + "Total pressure rise - Each pump"; + + parameter Buildings.Templates.Components.Data.PumpMultiple datDef( + final typ=Buildings.Templates.Components.Types.Pump.Multiple, + final nPum=nPum, + final m_flow_nominal=m_flow_nominal, + final dp_nominal=dp_nominal) + "Parameter record - Default bindings for subrecord per" + annotation (Placement(transformation(extent={{-10,50},{10,70}}))); + + parameter Buildings.Templates.Components.Data.PumpMultiple datRed( + final typ=Buildings.Templates.Components.Types.Pump.Multiple, + final nPum=nPum, + final m_flow_nominal=m_flow_nominal, + final dp_nominal=dp_nominal, + redeclare Buildings.Fluid.Movers.Data.Pumps.Wilo.Stratos80slash1to12 per) + "Parameter record - Redeclaration of subrecord per" + annotation (Placement(transformation(extent={{-10,10},{10,30}}))); + + parameter Buildings.Fluid.Movers.Data.Pumps.Wilo.Stratos80slash1to12 per1; + parameter Buildings.Fluid.Movers.Data.Pumps.Wilo.Stratos50slash1to12 per2; + + parameter Buildings.Templates.Components.Data.PumpMultiple datAss( + final typ=Buildings.Templates.Components.Types.Pump.Multiple, + final nPum=nPum, + final m_flow_nominal=m_flow_nominal, + final dp_nominal=dp_nominal, + per={per1, per2}) + "Parameter record - Assignment of subrecord per" + annotation (Placement(transformation(extent={{-10,-30},{10,-10}}))); + + parameter Buildings.Templates.Components.Data.PumpMultiple datPre( + final typ=Buildings.Templates.Components.Types.Pump.Multiple, + final nPum=nPum, + final m_flow_nominal=m_flow_nominal, + final dp_nominal=dp_nominal, + per(pressure( + V_flow={{0, 2, 4} * m_flow_nominal[i] / datPre.rho_default for i in 1:nPum}, + dp={{2, 1.5, 0.8} * dp_nominal[i] for i in 1:nPum}))) + "Parameter record - Assignment of pressure inside the subrecord per" + annotation (Placement(transformation(extent={{-10,-70},{10,-50}}))); + + annotation ( + experiment( + StopTime=1, + Tolerance=1e-06), + __Dymola_Commands(file= + "modelica://Buildings/Resources/Scripts/Dymola/Templates/Components/Validation/PumpMultipleRecord.mos" + "Simulate and plot"), + Documentation(info=" +
+This model validates the parameter propagation within the record class + +Buildings.Templates.Components.Data.PumpMultiple. +
+
+The instance datDef
illustrates the default pressure curve
+assignment based on the design parameters.
+
+The instance datRed
illustrates the modification of the
+pressure curve by redeclaring the subrecord per
.
+In this case, all elements per[i]
are equal.
+
+The instances datAss
and datPre
illustrate
+the modification of the pressure curve by assigning either the whole
+subrecord per
or its component per.pressure
.
+This allows assigning different pressure curves to the elements per[i]
.
+
+This model validates the models within
+
+Buildings.Templates.Components.Pumps
+by connecting each pump component to a water loop with a
+fixed flow resistance, which
+is sized based on the pump's nominal operating point.
+Two identical parallel pumps are modeled with either
+one instance of
+
+Buildings.Templates.Components.Pumps.Multiple
+or two instances of
+
+Buildings.Templates.Components.Pumps.Single.
+The multiple pump component is configured to represent
+variable speed pumps with dedicated speed command signals
+(component pumMulDed
),
+variable speed pumps with common speed command
+signal (component pumMul
) or constant speed pumps
+(component pumMulCst
).
+The single pump components (pum1
and pum2
)
+are configured to represent variable speed pumps.
+
+This package defines some constants that are either +
+
+The plant is enabled when it has been disabled for at least the duration dtRun
and:
+
nReqIgn
, and
+TOutLck
, and
+TOutLck
, and
+
+The plant is disabled when it has been enabled for at least the duration
+dtRun
and:
+
nReqIgn
+for at least the duration dtReq
, or
+TOutLck
minus hysteresis dTOutLck
, or
+TOutLck
plus hysteresis dTOutLck
, or
+
+This model validates
+
+Buildings.Templates.Plants.Controls.Enable.Enable
+in a heating configuration, in a cooling configuration, and in
+a cooling configuration with the enable schedule provided via
+an input point.
+All these configurations have the same setting for the minimum number
+of ignored requests: nReqIgn=1
.
+
+This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/Enabling/Validation/package.order b/Buildings/Templates/Plants/Controls/Enabling/Validation/package.order new file mode 100644 index 00000000000..bc0ba0e9217 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Enabling/Validation/package.order @@ -0,0 +1 @@ +Enable diff --git a/Buildings/Templates/Plants/Controls/Enabling/package.mo b/Buildings/Templates/Plants/Controls/Enabling/package.mo new file mode 100644 index 00000000000..0b50ad9137f --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Enabling/package.mo @@ -0,0 +1,44 @@ +within Buildings.Templates.Plants.Controls; +package Enabling "Plant enable/disable" + 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), + 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)}), Documentation(info=" ++This package contains control sequences to enable or disable +chilled water or hot water plants. +
+")); +end Enabling; diff --git a/Buildings/Templates/Plants/Controls/Enabling/package.order b/Buildings/Templates/Plants/Controls/Enabling/package.order new file mode 100644 index 00000000000..ff54e1e7178 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Enabling/package.order @@ -0,0 +1,2 @@ +Enable +Validation diff --git a/Buildings/Templates/Plants/Controls/HeatPumps/AirToWater.mo b/Buildings/Templates/Plants/Controls/HeatPumps/AirToWater.mo new file mode 100644 index 00000000000..2048e9d1a06 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/HeatPumps/AirToWater.mo @@ -0,0 +1,1582 @@ +within Buildings.Templates.Plants.Controls.HeatPumps; +block AirToWater + "Controller for AWHP plant" + parameter Boolean have_heaWat + "Set to true for plants that provide HW" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Boolean have_chiWat + "Set to true for plants that provide CHW" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Boolean have_valHpInlIso + "Set to true for plants with isolation valves at heat pump inlet" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Boolean have_valHpOutIso + "Set to true for plants with isolation valves at heat pump outlet" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + final parameter Boolean have_pumHeaWatPri=have_heaWat + "Set to true for plants with primary HW pumps" + annotation (Evaluate=true); + parameter Boolean have_pumChiWatPriDed_select(start=false)=false + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true, + Dialog(enable=have_chiWat and not have_pumPriHdr, group="Plant configuration")); + final parameter Boolean have_pumChiWatPriDed= + if have_chiWat and not have_pumPriHdr then have_pumChiWatPriDed_select else false + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true); + final parameter Boolean have_pumChiWatPri= + have_chiWat and (have_pumPriHdr or have_pumChiWatPriDed) + "Set to true for plants with separate primary CHW pumps" + annotation (Evaluate=true); + parameter Boolean have_pumPriHdr + "Set to true for headered primary pumps, false for dedicated pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Boolean have_pumHeaWatPriVar(start=true)=true + "Set to true for variable speed primary HW pumps, false for constant speed pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", enable=have_heaWat)); + parameter Boolean have_pumChiWatPriVar(start=true)=true + "Set to true for variable speed primary CHW pumps, false for constant speed pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", enable=have_chiWat and + (have_pumPriHdr or have_pumChiWatPriDed))); + // Only constant primary is supported for AWHP. + final parameter Boolean have_pumPriCtlDp=false + "Set to true for primary headered variable speed pumps using ∆p pump speed control" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Boolean have_pumHeaWatSec_select(start=false) + "Set to true for plants with secondary HW pumps" + annotation (Evaluate=true, + Dialog(enable=have_heaWat,group="Plant configuration")); + final parameter Boolean have_pumHeaWatSec= + if have_heaWat then have_pumHeaWatSec_select else false + "Set to true for plants with secondary HW pumps" + annotation (Evaluate=true); + parameter Boolean have_pumChiWatSec_select(start=false) + "Set to true for plants with secondary CHW pumps" + annotation (Evaluate=true, + Dialog(enable=have_chiWat,group="Plant configuration")); + final parameter Boolean have_pumChiWatSec= + if have_chiWat then have_pumChiWatSec_select else false + "Set to true for plants with secondary CHW pumps" + annotation (Evaluate=true); + // Only headered arrangements are supported for secondary pumps. + final parameter Boolean have_pumSecHdr=true + "Set to true for headered secondary pumps, false for dedicated pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + // Only ∆p controlled variable speed pumps are supported for secondary pumps. + final parameter Boolean have_pumSecCtlDp=have_pumHeaWatSec or have_pumChiWatSec + "Set to true for secondary headered variable speed pumps using ∆p pump speed control" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + // RFE(AntoineGautier): Add option for sidestream HRC. Always excluded for now. + final parameter Boolean have_hrc( + start=false)=false + "Set to true for plants with a sidestream heat recovery chiller" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_heaWat and have_chiWat)); + parameter Boolean have_senVHeaWatPri_select(start=false) + "Set to true for plants with primary HW flow sensor" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_heaWat and not have_hrc and have_senVHeaWatSec)); + final parameter Boolean have_senVHeaWatPri=have_heaWat and + (if have_hrc or not have_senVHeaWatSec then true else have_senVHeaWatPri_select) + "Set to true for plants with primary HW flow sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + // Secondary flow sensor required for secondary HW pump staging. + final parameter Boolean have_senVHeaWatSec=have_pumHeaWatSec + "Set to true for plants with secondary HW flow sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + parameter Boolean have_senVChiWatPri_select(start=false) + "Set to true for plants with primary CHW flow sensor" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_chiWat and not have_hrc and have_senVChiWatSec)); + final parameter Boolean have_senVChiWatPri=have_chiWat and + (if have_hrc or not have_senVChiWatSec then true + else have_senVChiWatPri_select) + "Set to true for plants with primary CHW flow sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + // Secondary flow sensor required for secondary CHW pump staging. + final parameter Boolean have_senVChiWatSec(start=false)=have_pumChiWatSec + "Set to true for plants with secondary CHW flow sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + parameter Boolean have_senTHeaWatPriRet_select(start=false) + "Set to true for plants with primary HW return temperature sensor" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_heaWat and not have_hrc and have_senTHeaWatSecRet)); + final parameter Boolean have_senTHeaWatPriRet=have_heaWat and + (if have_hrc or not have_senTHeaWatSecRet then true else have_senTHeaWatPriRet_select) + "Set to true for plants with primary HW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + parameter Boolean have_senTChiWatPriRet_select(start=false) + "Set to true for plants with primary CHW return temperature sensor" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_chiWat and not have_hrc and have_senTChiWatSecRet)); + final parameter Boolean have_senTChiWatPriRet=have_chiWat and + (if have_hrc or not have_senTChiWatSecRet then true else have_senTChiWatPriRet_select) + "Set to true for plants with primary CHW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + // For primary-secondary plants, SHWST sensor is required for plant staging. + final parameter Boolean have_senTHeaWatSecSup=have_pumHeaWatSec + "Set to true for plants with secondary HW supply temperature sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + // For primary-secondary plants, SCHWST sensor is required for plant staging. + final parameter Boolean have_senTChiWatSecSup=have_pumChiWatSec + "Set to true for plants with secondary CHW supply temperature sensor" + annotation (Evaluate=true, Dialog(group="Sensors")); + parameter Boolean have_senTHeaWatSecRet(start=false) + "Set to true for plants with secondary HW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Sensors", enable=have_pumHeaWatSec)); + parameter Boolean have_senTChiWatSecRet(start=false) + "Set to true for plants with secondary CHW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Sensors", enable=have_pumChiWatSec)); + parameter Integer nHp(final min=1) + "Number of heat pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Integer nPumHeaWatPri( + final min=if have_pumHeaWatPri then 1 else 0, + start=0)=nHp + "Number of primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_pumHeaWatPri)); + parameter Integer nPumChiWatPri( + final min=if have_pumChiWatPri then 1 else 0, + start=if have_pumChiWatPri then nHp else 0)=if have_pumChiWatPri then nHp + else 0 + "Number of primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_pumChiWatPri)); + parameter Integer nPumHeaWatSec( + final min=if have_pumHeaWatSec then 1 else 0, + start=0)=nHp + "Number of secondary HW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_pumHeaWatSec)); + parameter Integer nPumChiWatSec( + final min=if have_pumChiWatSec then 1 else 0, + start=0)=nHp + "Number of secondary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_pumChiWatSec)); + parameter Boolean have_senDpHeaWatRemWir(start=true)=true + "Set to true for remote HW differential pressure sensor(s) hardwired to plant or pump controller" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Integer nSenDpHeaWatRem(final min=if have_heaWat and have_pumHeaWatSec + then 1 else 0, start=0) + "Number of remote HW differential pressure sensors used for HW pump speed control" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Boolean have_senDpChiWatRemWir(start=true)=true + "Set to true for remote CHW differential pressure sensor(s) hardwired to plant or pump controller" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_chiWat and have_pumChiWatSec)); + parameter Integer nSenDpChiWatRem(final min=if have_chiWat and have_pumChiWatSec + then 1 else 0, start=0) + "Number of remote CHW differential pressure sensors used for CHW pump speed control" + annotation (Evaluate=true, + Dialog(group="Sensors", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real THeaWatSup_nominal( + final min=273.15, + start=50 + 273.15, + final unit="K", + displayUnit="degC") + "Design HW supply temperature (maximum setpoint)" + annotation (Dialog(group="Information provided by designer", + enable=have_heaWat)); + parameter Real THeaWatSupSet_min( + final min=273.15, + start=25 + 273.15, + final unit="K", + displayUnit="degC") + "Minimum value to which the HW supply temperature can be reset" + annotation (Dialog(group="Information provided by designer", + enable=have_heaWat)); + parameter Real TOutHeaWatLck( + final min=273.15, + start=21 + 273.15, + final unit="K", + displayUnit="degC")=294.15 + "Outdoor air lockout temperature above which the HW loop is prevented from operating" + annotation (Dialog(group="Information provided by designer", + enable=have_heaWat)); + parameter Real capHeaHp_nominal[nHp]( + final min=fill(0, nHp), + start=fill(1, nHp), + final unit=fill("W", nHp)) + "Design heating capacity - Each heat pump" + annotation (Dialog(group="Information provided by designer", + enable=have_heaWat)); + parameter Real VHeaWatSec_flow_nominal( + final min=0, + start=1E-6, + final unit="m3/s") + "Design secondary HW volume flow rate" + annotation (Evaluate=true, + Dialog(group="Information provided by designer", + enable=have_heaWat and have_pumHeaWatSec and have_pumSecCtlDp)); + parameter Real dpHeaWatRemSet_max[nSenDpHeaWatRem]( + final min=fill(0, nSenDpHeaWatRem), + start=fill(5E4, nSenDpHeaWatRem), + final unit=fill("Pa", nSenDpHeaWatRem)) + "Maximum HW differential pressure setpoint - Remote sensor" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real dpHeaWatRemSet_min( + final min=0, + start=5*6894, + final unit="Pa")=5*6894 + "Minimum value to which the HW differential pressure can be reset - Remote sensor" + annotation (Dialog(group= + "Information provided by designer", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real yPumHeaWatPriSet( + final max=1, + final min=0, + start=1, + final unit="1") + "Primary pump speed providing design heat pump flow in heating mode" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=have_heaWat and have_pumHeaWatPriVar)); + parameter Real TChiWatSup_nominal( + final min=273.15, + start=7 + 273.15, + final unit="K", + displayUnit="degC") + "Design CHW supply temperature (minimum setpoint)" + annotation (Dialog(group="Information provided by designer", + enable=have_chiWat)); + parameter Real TChiWatSupSet_max( + final min=273.15, + start=15 + 273.15, + final unit="K", + displayUnit="degC") + "Maximum value to which the CHW supply temperature can be reset" + annotation (Dialog(group="Information provided by designer", + enable=have_chiWat)); + parameter Real TOutChiWatLck( + final min=273.15, + start=16 + 273.15, + final unit="K", + displayUnit="degC")=289.15 + "Outdoor air lockout temperature below which the CHW loop is prevented from operating" + annotation (Dialog(group="Information provided by designer", + enable=have_chiWat)); + parameter Real capCooHp_nominal[nHp]( + final min=fill(0, nHp), + start=fill(1, nHp), + final unit=fill("W", nHp)) + "Design cooling capacity - Each heat pump" + annotation (Dialog(group="Information provided by designer", + enable=have_chiWat)); + parameter Real VChiWatSec_flow_nominal( + final min=0, + start=1E-6, + final unit="m3/s") + "Design secondary CHW volume flow rate" + annotation (Evaluate=true, + Dialog(group="Information provided by designer", + enable=have_chiWat and have_pumChiWatSec and have_pumSecCtlDp)); + parameter Real dpChiWatRemSet_max[nSenDpChiWatRem]( + final min=fill(0, nSenDpChiWatRem), + start=fill(5E4, nSenDpChiWatRem), + final unit=fill("Pa", nSenDpChiWatRem)) + "Maximum CHW differential pressure setpoint - Remote sensor" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real dpChiWatRemSet_min( + final min=0, + start=5*6894, + final unit="Pa")=5*6894 + "Minimum value to which the CHW differential pressure can be reset - Remote sensor" + annotation (Dialog(group= + "Information provided by designer", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real yPumChiWatPriSet( + final max=1, + final min=0, + start=1, + final unit="1") + "Primary pump speed providing design heat pump flow in cooling mode" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=have_chiWat and have_pumChiWatPriVar)); + parameter Real cp_default( + final min=0, + final unit="J/(kg.K)")=4184 + "Default specific heat capacity used to compute required capacity" + annotation (Evaluate=true, + Dialog(group="Information provided by designer")); + parameter Real rho_default( + final min=0, + final unit="kg/m3")=996 + "Default density used to compute required capacity" + annotation (Evaluate=true, + Dialog(group="Information provided by designer")); + parameter Boolean have_inpSch=false + "Set to true to provide schedule via software input point" + annotation (Dialog(group="Plant enable"), + Evaluate=true); + parameter Real schHea[:, 2](start=[0,1; 24*3600,1])=[0,1; 24*3600,1] + "Heating mode enable schedule" + annotation (Dialog(enable=not have_inpSch,group="Plant enable")); + parameter Real schCoo[:, 2](start=[0,1; 24*3600,1])=[0,1; 24*3600,1] + "Cooling mode enable schedule" + annotation (Dialog(enable=not have_inpSch,group="Plant enable")); + parameter Integer nReqIgnHeaWat(final min=0)=0 + "Number of ignored HW plant requests" + annotation (Dialog(tab="Advanced",group="Plant enable")); + parameter Integer nReqIgnChiWat(final min=0)=0 + "Number of ignored CHW plant requests" + annotation (Dialog(tab="Advanced",group="Plant enable")); + parameter Real dTOutLck( + final min=0, + final unit="K")=0.5 + "Hysteresis for outdoor air lockout temperature" + annotation (Dialog(tab="Advanced",group="Plant enable")); + parameter Real dtRunEna( + final min=0, + final unit="s")=15*60 + "Minimum runtime of enable and disable states" + annotation (Dialog(tab="Advanced",group="Plant enable")); + parameter Real dtReqDis( + final min=0, + final unit="s")=3*60 + "Runtime with low number of request before disabling" + annotation (Dialog(tab="Advanced",group="Plant enable")); + parameter Real staEqu[:, nHp]( + each final max=1, + each final min=0, + each final unit="1") + "Staging matrix – Equipment required for each stage" + annotation (Dialog(group="Equipment staging and rotation")); + final parameter Integer nSta( + final min=1)=size(staEqu, 1) + "Number of stages" + annotation (Evaluate=true); + final parameter Integer nEquAlt( + final min=0)=max({sum({(if staEqu[i, j] > 0 and staEqu[i, j] < 1 then 1 else 0) for j in 1:nHp}) for i in 1:nSta}) + "Number of lead/lag alternate equipment" + annotation (Evaluate=true); + parameter Integer idxEquAlt[nEquAlt]( + each final min=1) + "Indices of lead/lag alternate equipment" + annotation (Evaluate=true, + Dialog(group="Equipment staging and rotation")); + parameter Real dtVal( + final min=0, + start=90, + final unit="s")=90 + "Nominal valve timing" + annotation (Dialog(tab="Advanced",group="Equipment staging and rotation", + enable=have_valHpInlIso or have_valHpOutIso)); + parameter Real dtHp( + final min=0, + final unit="s")=180 + annotation (Dialog(tab="Advanced",group="Equipment staging and rotation")); + parameter Real plrSta( + final max=1, + final min=0, + start=0.9, + final unit="1")=0.9 + "Staging part load ratio" + annotation (Dialog(group="Equipment staging and rotation")); + parameter Real dtRunSta( + final min=0, + final unit="s", + displayUnit="min")=900 + "Minimum runtime of each stage" + annotation (Dialog(tab="Advanced",group="Equipment staging and rotation")); + parameter Real dtOff( + final min=0, + final unit="s")=900 + "Off time required before equipment is deemed available again" + annotation (Dialog(tab="Advanced",group="Equipment staging and rotation")); + parameter Real dtRunPumSta( + final min=0, + start=600, + final unit="s")=600 + "Runtime before triggering stage command" + annotation (Dialog(tab="Advanced",group="Pump staging", + enable=have_pumPriHdr and have_pumPriCtlDp or have_pumSecHdr and have_pumSecCtlDp)); + parameter Real dVOffUpPumSta( + final max=1, + final min=0, + start=0.03, + final unit="1")=0.03 + "Stage up flow point offset" + annotation (Dialog(tab="Advanced",group="Pump staging", + enable=have_pumPriHdr and have_pumPriCtlDp or have_pumSecHdr and have_pumSecCtlDp)); + parameter Real dVOffDowPumSta( + final max=1, + final min=0, + start=0.03, + final unit="1")=dVOffUpPumSta + "Stage down flow point offset" + annotation (Dialog(tab="Advanced",group="Pump staging", + enable=have_pumPriHdr and have_pumPriCtlDp or have_pumSecHdr and have_pumSecCtlDp)); + parameter Real dtHol( + final min=0, + final unit="s")=900 + "Minimum hold time during stage change" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec or have_chiWat and have_pumChiWatSec)); + parameter Real resDpHeaWat_max( + final max=1, + final min=0, + final unit="1")=0.5 + "Upper limit of plant reset interval for HW differential pressure reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real resTHeaWatSup_min( + final max=1, + final min=0, + final unit="1")=resDpHeaWat_max + "Lower limit of plant reset interval for HW supply temperature reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real resDpChiWat_max( + final max=1, + final min=0, + final unit="1")=0.5 + "Upper limit of plant reset interval for CHW differential pressure reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real resTChiWatSup_min( + final max=1, + final min=0, + final unit="1")=resDpChiWat_max + "Lower limit of plant reset interval for CHW supply temperature reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real res_init( + final max=1, + final min=0, + final unit="1")=1 + "Initial reset value" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec or have_chiWat and have_pumChiWatSec)); + parameter Real res_min( + final max=1, + final min=0, + final unit="1")=0 + "Minimum reset value" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec or have_chiWat and have_pumChiWatSec)); + parameter Real res_max( + final max=1, + final min=0, + final unit="1")=1 + "Maximum reset value" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec or have_chiWat and have_pumChiWatSec)); + parameter Real dtDel( + final min=100*1E-15, + final unit="s")=900 + "Delay time before the reset begins" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec or have_chiWat and have_pumChiWatSec)); + parameter Real dtResHeaWat( + final min=1E-3, + final unit="s")=300 + "Reset period for HW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Integer nReqResIgnHeaWat(final min=0)=2 + "Number of ignored requests for HW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real triHeaWat( + final max=0, + final unit="1")=-0.02 + "Trim amount for HW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real rspHeaWat( + final min=0, + final unit="1")=0.03 + "Respond amount for HW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real rspHeaWat_max( + final min=0, + final unit="1")=0.07 + "Maximum response per reset period for HW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_heaWat and have_pumHeaWatSec)); + parameter Real dtResChiWat( + final min=1E-3, + final unit="s")=300 + "Reset period for CHW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Integer nReqResIgnChiWat(final min=0)=2 + "Number of ignored requests for CHW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real triChiWat( + final max=0, + final unit="1")=-0.02 + "Trim amount for CHW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real rspChiWat( + final min=0, + final unit="1")=0.03 + "Respond amount for CHW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real rspChiWat_max( + final min=0, + final unit="1")=0.07 + "Maximum response per reset period for CHW plant reset" + annotation (Dialog(tab="Advanced",group="Plant reset", + enable=have_chiWat and have_pumChiWatSec)); + parameter Real yPumHeaWatSec_min( + final max=1, + final min=0, + start=0.1, + final unit="1")=0.1 + "Minimum pump speed" + annotation (Dialog(tab="Advanced",group="Secondary HW pumps", + enable=have_pumHeaWatSec)); + parameter Real kPumHeaWatSec( + final min=100*Buildings.Controls.OBC.CDL.Constants.eps, + start=1)=1 + "Gain of controller" + annotation (Dialog(tab="Advanced",group="Secondary HW pumps", + enable=have_pumHeaWatSec)); + parameter Real TiPumHeaWatSec( + final min=100*Buildings.Controls.OBC.CDL.Constants.eps, + start=60, + final unit="s")=60 + "Time constant of integrator block" + annotation (Dialog(tab="Advanced",group="Secondary HW pumps", + enable=have_pumHeaWatSec)); + parameter Real yPumChiWatSec_min( + final max=1, + final min=0, + start=0.1, + final unit="1")=0.1 + "Minimum pump speed" + annotation (Dialog(tab="Advanced",group="Secondary CHW pumps", + enable=have_pumChiWatSec)); + parameter Real kPumChiWatSec( + final min=100*Buildings.Controls.OBC.CDL.Constants.eps, + start=1)=1 + "Gain of controller" + annotation (Dialog(tab="Advanced",group="Secondary CHW pumps", + enable=have_pumChiWatSec)); + parameter Real TiPumChiWatSec( + final min=100*Buildings.Controls.OBC.CDL.Constants.eps, + start=60, + final unit="s")=60 + "Time constant of integrator block" + annotation (Dialog(tab="Advanced",group="Secondary CHW pumps", + enable=have_pumChiWatSec)); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant u1AvaHp[nHp](each k=true) + "Heat pump available signal – Block does not handle faulted equipment yet" + annotation (Placement(transformation(extent={{-250,250},{-230,270}}), + iconTransformation(extent={{-240,220},{-200,260}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqPlaHeaWat + if have_heaWat + "Number of HW plant requests" annotation (Placement(transformation(extent={ + {-300,320},{-260,360}}), iconTransformation(extent={{-240,120},{-200, + 160}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut( + final unit="K", + final quantity="ThermodynamicTemperature", + displayUnit="degC") + "Outdoor air temperature" + annotation (Placement(transformation(extent={{-300,60},{-260,100}}), + iconTransformation(extent={{-240,20},{-200,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SchHea + if have_heaWat and have_inpSch + "Heating mode enable via schedule" + annotation (Placement(transformation(extent={{-300,360},{-260,400}}), + iconTransformation(extent={{-240,300},{-200,340}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqPlaChiWat + if have_chiWat + "Number of CHW plant requests" annotation (Placement(transformation(extent= + {{-300,300},{-260,340}}), iconTransformation(extent={{-240,100},{-200, + 140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SchCoo + if have_chiWat and have_inpSch + "Cooling mode enable via schedule" + annotation (Placement(transformation(extent={{-300,340},{-260,380}}), + iconTransformation(extent={{-240,280},{-200,320}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqResHeaWat + if have_heaWat + "Sum of HW reset requests of all heating loads served" + annotation (Placement(transformation(extent={{-300,-360},{-260,-320}}), + iconTransformation(extent={{-240,80},{-200,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqResChiWat + if have_chiWat + "Sum of CHW reset requests of all heating loads served" + annotation (Placement(transformation(extent={{-300,-380},{-260,-340}}), + iconTransformation(extent={{-240,60},{-200,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatPri_actual[nPumHeaWatPri] + if have_heaWat and have_pumHeaWatPri + "Primary HW pump status" + annotation (Placement(transformation(extent={{-300,180},{-260,220}}), + iconTransformation(extent={{-240,220},{-200,260}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatPri_actual[nPumChiWatPri] + if have_chiWat and have_pumChiWatPri + "Primary CHW pump status" + annotation (Placement(transformation(extent={{-300,160},{-260,200}}), + iconTransformation(extent={{-240,200},{-200,240}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatSec_actual[nPumHeaWatSec] + if have_heaWat and have_pumHeaWatSec + "Secondary HW pump status" + annotation (Placement(transformation(extent={{-300,140},{-260,180}}), + iconTransformation(extent={{-240,180},{-200,220}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatSec_actual[nPumChiWatSec] + if have_chiWat and have_pumChiWatSec + "Secondary CHW pump status" + annotation (Placement(transformation(extent={{-300,120},{-260,160}}), + iconTransformation(extent={{-240,160},{-200,200}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatPriRet( + final unit="K", + displayUnit="degC") if have_heaWat and have_senTHeaWatPriRet + "Primary HW return temperature" + annotation (Placement(transformation(extent={{-300,20},{-260,60}}), + iconTransformation(extent={{-240,-20},{-200,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHeaWatPri_flow( + final unit="m3/s") if have_heaWat and have_senVHeaWatPri + "Primary HW volume flow rate" + annotation (Placement(transformation(extent={{-300,0},{-260,40}}), + iconTransformation(extent={{-240,-40},{-200,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatLoc( + final unit="Pa") + if have_heaWat and not have_senDpHeaWatRemWir + "Local HW differential pressure" + annotation (Placement(transformation(extent={{-300,-260},{-260,-220}}), + iconTransformation(extent={{-240,-280},{-200,-240}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatLocSet[nSenDpHeaWatRem]( + each final unit="Pa") + if have_heaWat and not have_senDpHeaWatRemWir + "Local HW differential pressure setpoint output from each of the remote loops" + annotation (Placement(transformation(extent={{-300,-240},{-260,-200}}), + iconTransformation(extent={{-240,-260},{-200,-220}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatRem[nSenDpHeaWatRem]( + each final unit="Pa") + if have_heaWat and have_senDpHeaWatRemWir + "Remote HW differential pressure" + annotation (Placement(transformation(extent={{-300,-220},{-260,-180}}), + iconTransformation(extent={{-240,-240},{-200,-200}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatLoc( + final unit="Pa") + if have_chiWat and not have_senDpChiWatRemWir + "Local CHW differential pressure" + annotation (Placement(transformation(extent={{-300,-320},{-260,-280}}), + iconTransformation(extent={{-240,-340},{-200,-300}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatLocSet[nSenDpChiWatRem]( + each final unit="Pa") + if have_chiWat and not have_senDpChiWatRemWir + "Local CHW differential pressure setpoint output from each of the remote loops" + annotation (Placement(transformation(extent={{-300,-300},{-260,-260}}), + iconTransformation(extent={{-240,-320},{-200,-280}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatRem[nSenDpChiWatRem]( + each final unit="Pa") + if have_chiWat and have_senDpChiWatRemWir + "Remote CHW differential pressure" + annotation (Placement(transformation(extent={{-300,-280},{-260,-240}}), + iconTransformation(extent={{-240,-300},{-200,-260}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValHeaWatHpInlIso[nHp] + if have_heaWat and have_valHpInlIso + "Heat pump inlet HW inlet isolation valve command" annotation (Placement( + transformation(extent={{260,300},{300,340}}), iconTransformation(extent + ={{200,180},{240,220}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValHeaWatHpOutIso[nHp] + if have_heaWat and have_valHpOutIso + "Heat pump outlet HW isolation valve command" annotation (Placement( + transformation(extent={{260,280},{300,320}}), iconTransformation(extent + ={{200,160},{240,200}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValChiWatHpInlIso[nHp] + if have_chiWat and have_valHpInlIso + "Heat pump inlet CHW isolation valve command" annotation (Placement( + transformation(extent={{260,260},{300,300}}), iconTransformation(extent + ={{200,140},{240,180}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValChiWatHpOutIso[nHp] + if have_chiWat and have_valHpOutIso + "Heat pump outlet CHW isolation valve command" annotation (Placement( + transformation(extent={{260,240},{300,280}}), iconTransformation(extent + ={{200,120},{240,160}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWatPri[nPumHeaWatPri] + if have_pumHeaWatPri + "Primary HW pump start command" + annotation (Placement(transformation(extent={{260,180},{300,220}}), + iconTransformation(extent={{200,80},{240,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWatPri[nPumChiWatPri] + if have_pumChiWatPri and have_chiWat + "Primary CHW pump start command" + annotation (Placement(transformation(extent={{260,160},{300,200}}), + iconTransformation(extent={{200,60},{240,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWatSec[nPumHeaWatSec] + if have_pumHeaWatSec + "Secondary HW pump start command" + annotation (Placement(transformation(extent={{260,140},{300,180}}), + iconTransformation(extent={{200,20},{240,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWatSec[nPumChiWatSec] + if have_pumChiWatSec and have_chiWat + "Secondary CHW pump start command" + annotation (Placement(transformation(extent={{260,120},{300,160}}), + iconTransformation(extent={{200,0},{240,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Hp[nHp] + "Heat pump enable command" + annotation (Placement(transformation(extent={{260,360},{300,400}}), + iconTransformation(extent={{200,240},{240,280}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1HeaHp[nHp] + if have_heaWat and have_chiWat + "Heat pump heating/cooling mode command: true=heating, false=cooling" + annotation (Placement(transformation(extent={{260,340},{300,380}}), + iconTransformation(extent={{200,220},{240,260}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpHeaWatRemSet[nSenDpHeaWatRem]( + each final min=0, + each final unit="Pa") if have_heaWat + "HW differential pressure setpoint" + annotation (Placement(transformation(extent={{260,-80},{300,-40}}), + iconTransformation(extent={{200,-180},{240,-140}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpChiWatRemSet[nSenDpChiWatRem]( + each final min=0, + each final unit="Pa") if have_chiWat + "CHW differential pressure setpoint" + annotation (Placement(transformation(extent={{260,-100},{300,-60}}), + iconTransformation(extent={{200,-200},{240,-160}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatPriHdr( + final unit="1") + if have_heaWat and have_pumHeaWatPriVar and have_pumPriHdr + "Primary headered HW pump speed command" + annotation (Placement(transformation(extent={{260,80},{300,120}}), + iconTransformation(extent={{200,-40},{240,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatPriHdr( + final unit="1") if have_chiWat and have_pumChiWatPri and + have_pumChiWatPriVar and have_pumPriHdr + "Primary headered CHW pump speed command" + annotation (Placement(transformation(extent={{260,60},{300,100}}), + iconTransformation(extent={{200,-60},{240,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatSec( + final unit="1") + if have_heaWat and have_pumHeaWatSec + "Primary HW pump speed command" + annotation (Placement(transformation(extent={{260,-20},{300,20}}), + iconTransformation(extent={{200,-120},{240,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatSec( + final unit="1") + if have_chiWat and have_pumChiWatSec + "Primary CHW pump speed command" + annotation (Placement(transformation(extent={{260,-40},{300,0}}), + iconTransformation(extent={{200,-140},{240,-100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TChiWatSupSet( + final unit="K", + displayUnit="degC") if have_chiWat + "CHW supply temperature setpoint" + annotation (Placement(transformation(extent={{260,-200},{300,-160}}), + iconTransformation(extent={{200,-280},{240,-240}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput THeaWatSupSet( + final unit="K", + displayUnit="degC") if have_heaWat + "HW supply temperature setpoint" + annotation (Placement(transformation(extent={{260,-180},{300,-140}}), + iconTransformation(extent={{200,-260},{240,-220}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatPriRet( + final unit="K", + displayUnit="degC") if have_chiWat and have_senTChiWatPriRet + "Primary CHW return temperature" + annotation (Placement(transformation(extent={{-300,-40},{-260,0}}), + iconTransformation(extent={{-240,-80},{-200,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWatPri_flow( + final unit="m3/s") if have_chiWat and have_senVChiWatPri + "Primary CHW volume flow rate" + annotation (Placement(transformation(extent={{-300,-60},{-260,-20}}), + iconTransformation(extent={{-240,-100},{-200,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hp_actual[nHp] + "Heat pump status" + annotation (Placement(transformation(extent={{-300,280},{-260,320}}), + iconTransformation(extent={{-240,240},{-200,280}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatPriDed[nPumHeaWatPri]( + each final unit="1") + if have_heaWat and have_pumHeaWatPriVar and not have_pumPriHdr + "Primary dedicated HW pump speed command" + annotation (Placement(transformation(extent={{260,40},{300,80}}), + iconTransformation(extent={{200,-80},{240,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatPriDed[nPumChiWatPri]( + each final unit="1") + if have_chiWat and have_pumChiWatPriDed and have_pumChiWatPriVar + "Primary dedicated CHW pump speed command" + annotation (Placement(transformation(extent={{260,20},{300,60}}), + iconTransformation(extent={{200,-100},{240,-60}}))); + Enabling.Enable enaHea( + final typ=Buildings.Templates.Plants.Controls.Types.Application.Heating, + final TOutLck=TOutHeaWatLck, + final dTOutLck=dTOutLck, + final dtReq=dtReqDis, + final dtRun=dtRunEna, + final have_inpSch=have_inpSch, + final nReqIgn=nReqIgnHeaWat, + final sch=schHea) + if have_heaWat + "Heating mode enable" + annotation (Placement(transformation(extent={{-110,350},{-90,370}}))); + Utilities.StageIndex idxStaHea( + final nSta=nSta, + final dtRun=dtRunSta) + if have_heaWat + "Compute heating stage index" + annotation (Placement(transformation(extent={{-10,350},{10,370}}))); + StagingRotation.StageAvailability avaStaHea( + final staEqu=staEqu) + if have_heaWat + "Evaluate heating stage availability" + annotation (Placement(transformation(extent={{-110,320},{-90,340}}))); + StagingRotation.EquipmentEnable enaEquHea( + final staEqu=staEqu) + if have_heaWat + "Compute enable command for equipment in heating mode" + annotation (Placement(transformation(extent={{40,350},{60,370}}))); + StagingRotation.EventSequencing seqEve[nHp]( + each final have_heaWat=have_heaWat, + each final have_chiWat=have_chiWat, + each final have_valInlIso=have_valHpInlIso, + each final have_valOutIso=have_valHpOutIso, + each final have_pumHeaWatPri=have_pumHeaWatPri, + each final have_pumChiWatPri=have_pumChiWatPri, + each final have_pumHeaWatSec=have_pumHeaWatSec, + each final have_pumChiWatSec=have_pumChiWatSec, + each final dtVal=dtVal, + each final dtOff=dtHp) "Event sequencing" + annotation (Placement(transformation(extent={{140,284},{160,312}}))); + StagingRotation.StageAvailability avaStaCoo( + final staEqu=staEqu) + if have_chiWat + "Evaluate cooling stage availability" + annotation (Placement(transformation(extent={{-110,60},{-90,80}}))); + StagingRotation.StageChangeCommand chaStaHea( + final have_inpPlrSta=false, + final plrSta=plrSta, + final staEqu=staEqu, + final capEqu=capHeaHp_nominal, + final dtRun=dtRunSta, + final cp_default=cp_default, + final rho_default=rho_default) + if have_heaWat + "Generate heating stage transition command" + annotation (Placement(transformation(extent={{-40,308},{-20,332}}))); + StagingRotation.SortRuntime sorRunTimHea( + idxEquAlt=idxEquAlt, + nin=nHp) + if have_heaWat + "Sort lead/lag alternate equipment by staging runtime – Heating mode" + annotation (Placement(transformation(extent={{-40,280},{-20,300}}))); + Enabling.Enable enaCoo( + final typ=Buildings.Templates.Plants.Controls.Types.Application.Cooling, + final TOutLck=TOutChiWatLck, + final dTOutLck=dTOutLck, + final dtReq=dtReqDis, + final dtRun=dtRunEna, + final have_inpSch=have_inpSch, + final nReqIgn=nReqIgnChiWat, + final sch=schCoo) + if have_chiWat + "Cooling mode enable" + annotation (Placement(transformation(extent={{-110,90},{-90,110}}))); + StagingRotation.StageChangeCommand chaStaCoo( + final have_inpPlrSta=false, + final plrSta=plrSta, + final staEqu=staEqu, + final capEqu=capCooHp_nominal, + final dtRun=dtRunSta, + final cp_default=cp_default, + final rho_default=rho_default) + if have_chiWat + "Generate cooling stage transition command" + annotation (Placement(transformation(extent={{-40,50},{-20,74}}))); + Utilities.StageIndex idxStaCoo( + final nSta=nSta, + final dtRun=dtRunSta) + if have_chiWat + "Compute cooling stage index" + annotation (Placement(transformation(extent={{-10,90},{10,110}}))); + StagingRotation.EquipmentEnable enaEquCoo( + final staEqu=staEqu) + if have_chiWat + "Compute enable command for equipment in cooling mode" + annotation (Placement(transformation(extent={{40,90},{60,110}}))); + StagingRotation.EquipmentAvailability avaEquHeaCoo[nHp]( + each final have_heaWat=have_heaWat, + each final have_chiWat=have_chiWat, + each final dtOff=dtOff) + "Evaluate equipment availability in heating or cooling mode" + annotation (Placement(transformation(extent={{-152,210},{-132,230}}))); + Buildings.Controls.OBC.CDL.Logical.Pre y1HeaPre[nHp] + if have_heaWat and have_chiWat + "Left-limit of command signal to break algebraic loop" + annotation (Placement(transformation(extent={{230,350},{210,370}}))); + StagingRotation.SortRuntime sorRunTimCoo( + final idxEquAlt=idxEquAlt, + nin=nHp) + if have_chiWat + "Sort lead/lag alternate equipment by staging runtime – Cooling mode" + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + Pumps.Generic.StagingHeadered staPumHeaWatPri( + final is_pri=true, + final have_valInlIso=have_valHpInlIso, + final have_valOutIso=have_valHpOutIso, + final nEqu=nHp, + final nPum=nPumHeaWatPri, + final is_hdr=have_pumPriHdr, + final is_ctlDp=have_pumPriCtlDp, + final dtRun=dtRunPumSta, + final dVOffUp=dVOffUpPumSta, + final dVOffDow=dVOffDowPumSta) if have_pumHeaWatPri + "Primary HW pump staging" + annotation (Placement(transformation(extent={{140,190},{160,210}}))); + Pumps.Generic.StagingHeadered staPumChiWatPri( + final is_pri=true, + final have_valInlIso=have_valHpInlIso, + final have_valOutIso=have_valHpOutIso, + final nEqu=nHp, + final nPum=nPumChiWatPri, + final is_hdr=have_pumPriHdr, + final is_ctlDp=have_pumPriCtlDp, + final dtRun=dtRunPumSta, + final dVOffUp=dVOffUpPumSta, + final dVOffDow=dVOffDowPumSta) if have_pumChiWatPri and have_chiWat + "Primary CHW pump staging" + annotation (Placement(transformation(extent={{190,170},{210,190}}))); + Pumps.Generic.StagingHeadered staPumChiWatSec( + final is_pri=false, + final nEqu=nHp, + final nPum=nPumChiWatSec, + final is_hdr=have_pumSecHdr, + final is_ctlDp=have_pumSecCtlDp, + final V_flow_nominal=VChiWatSec_flow_nominal, + final dtRun=dtRunPumSta, + final dVOffUp=dVOffUpPumSta, + final dVOffDow=dVOffDowPumSta) if have_pumChiWatSec and have_chiWat + "Secondary CHW pump staging" + annotation (Placement(transformation(extent={{190,130},{210,150}}))); + Pumps.Generic.StagingHeadered staPumHeaWatSec( + final is_pri=false, + final nEqu=nHp, + final nPum=nPumHeaWatSec, + final is_hdr=have_pumSecHdr, + final is_ctlDp=have_pumSecCtlDp, + final V_flow_nominal=VHeaWatSec_flow_nominal, + final dtRun=dtRunPumSta, + final dVOffUp=dVOffUpPumSta, + final dVOffDow=dVOffDowPumSta) if have_pumHeaWatSec + "Secondary HW pump staging" + annotation (Placement(transformation(extent={{140,150},{160,170}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSecRet( + final unit="K", + displayUnit="degC") if have_heaWat and have_senTHeaWatSecRet + "Secondary HW return temperature" + annotation (Placement(transformation(extent={{-300,-100},{-260,-60}}), + iconTransformation(extent={{-240,-140},{-200,-100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VHeaWatSec_flow( + final unit="m3/s") if have_heaWat and have_senVHeaWatSec + "Secondary HW volume flow rate" + annotation (Placement(transformation(extent={{-300,-120},{-260,-80}}), + iconTransformation(extent={{-240,-160},{-200,-120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSecRet( + final unit="K", + displayUnit="degC") if have_chiWat and have_senTChiWatSecRet + "Secondary CHW return temperature" + annotation (Placement(transformation(extent={{-300,-160},{-260,-120}}), + iconTransformation(extent={{-240,-200},{-200,-160}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWatSec_flow( + final unit="m3/s") if have_chiWat and have_senVChiWatSec + "Secondary CHW volume flow rate" + annotation (Placement(transformation(extent={{-300,-180},{-260,-140}}), + iconTransformation(extent={{-240,-220},{-200,-180}}))); + Utilities.PlaceholderReal THeaWatRet(have_inp=have_heaWat and + have_senTHeaWatPriRet, + have_inpPh=true) if have_heaWat "Select HW return temperature sensor" + annotation (Placement(transformation(extent={{-230,30},{-210,50}}))); + Utilities.PlaceholderReal VHeaWat_flow(have_inp=have_heaWat and + have_senVHeaWatPri, + have_inpPh=true) if have_heaWat "Select HW flow sensor" + annotation (Placement(transformation(extent={{-200,10},{-180,30}}))); + Utilities.PlaceholderReal TChiWatRet(have_inp=have_chiWat and + have_senTChiWatPriRet, + have_inpPh=true) if have_chiWat "Select CHW return temperature sensor" + annotation (Placement(transformation(extent={{-230,-30},{-210,-10}}))); + Utilities.PlaceholderReal VChiWat_flow(have_inp=have_chiWat and + have_senVChiWatPri, + have_inpPh=true) if have_chiWat "Select CHW flow sensor" + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Pre y1HpPre[nHp] + "Left-limit of command signal to break algebraic loop" + annotation (Placement(transformation(extent={{200,370},{180,390}}))); + StagingRotation.StageCompletion comStaCoo( + nin=nHp) + if have_chiWat + "Check successful completion of cooling stage change" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + StagingRotation.StageCompletion comStaHea( + nin=nHp) + if have_heaWat + "Check successful completion of heating stage change" + annotation (Placement(transformation(extent={{-40,250},{-20,270}}))); + Setpoints.PlantReset resHeaWat( + final TSup_nominal=THeaWatSup_nominal, + final TSupSetLim=THeaWatSupSet_min, + final dpSet_max=dpHeaWatRemSet_max, + final dpSet_min=dpHeaWatRemSet_min, + final dtDel=dtDel, + final dtHol=dtHol, + final dtRes=dtResHeaWat, + final nReqResIgn=nReqResIgnHeaWat, + final nSenDpRem=nSenDpHeaWatRem, + final resDp_max=resDpHeaWat_max, + final resTSup_min=resTHeaWatSup_min, + final res_init=res_init, + final res_max=res_max, + final res_min=res_min, + final rsp=rspHeaWat, + final rsp_max=rspHeaWat_max, + final tri=triHeaWat) if have_heaWat "HW plant reset" + annotation (Placement(transformation(extent={{90,230},{110,250}}))); + Setpoints.PlantReset resChiWat( + final TSup_nominal=TChiWatSup_nominal, + final TSupSetLim=TChiWatSupSet_max, + final dpSet_max=dpChiWatRemSet_max, + final dpSet_min=dpChiWatRemSet_min, + final dtDel=dtDel, + final dtHol=dtHol, + final dtRes=dtResChiWat, + final nReqResIgn=nReqResIgnChiWat, + final nSenDpRem=nSenDpChiWatRem, + final resDp_max=resDpChiWat_max, + final resTSup_min=resTChiWatSup_min, + final res_init=res_init, + final res_max=res_max, + final res_min=res_min, + final rsp=rspChiWat, + final rsp_max=rspChiWat_max, + final tri=triChiWat) if have_chiWat "CHW plant reset" + annotation (Placement(transformation(extent={{90,-50},{110,-30}}))); + Pumps.Primary.VariableSpeedNoDpControl ctlPumPri( + final have_heaWat=have_heaWat, + final have_chiWat=have_chiWat, + final have_pumChiWatPriDed=have_pumChiWatPriDed, + final have_pumPriHdr=have_pumPriHdr, + final nEqu=nHp, + final nPumHeaWatPri=nPumHeaWatPri, + final nPumChiWatPri=nPumChiWatPri, + final yPumHeaWatPriSet=yPumHeaWatPriSet, + final yPumChiWatPriSet=yPumChiWatPriSet) + "Primary pump speed control" + annotation (Placement(transformation(extent={{190,70},{210,90}}))); + Pumps.Generic.ControlDifferentialPressure ctlPumHeaWatSec( + final have_senDpRemWir=have_senDpHeaWatRemWir, + nPum=nPumHeaWatSec, + final nSenDpRem=nSenDpHeaWatRem, + final y_min=yPumHeaWatSec_min, + final k=kPumHeaWatSec, + final Ti=TiPumHeaWatSec) + if have_pumHeaWatSec + "Secondary HW pump speed control" + annotation (Placement(transformation(extent={{140,-10},{160,10}}))); + Pumps.Generic.ControlDifferentialPressure ctlPumChiWatSec( + final have_senDpRemWir=have_senDpChiWatRemWir, + final nPum=nPumChiWatSec, + final nSenDpRem=nSenDpChiWatRem, + final y_min=yPumChiWatSec_min, + final k=kPumChiWatSec, + final Ti=TiPumChiWatSec) if have_chiWat and have_pumChiWatSec + "Secondary CHW pump speed control" + annotation (Placement(transformation(extent={{190,-30},{210,-10}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSet[nHp]( + each final unit="K", + each final quantity="ThermodynamicTemperature", + each displayUnit="degC") + "Active HP supply temperature setpoint" + annotation (Placement(transformation(extent={{260,-140},{300,-100}}), + iconTransformation(extent={{200,-240},{240,-200}}))); + Buildings.Controls.OBC.CDL.Reals.Switch swiTSupSet[nHp] + if have_heaWat and have_chiWat + "Select supply temperature setpoint based on operating mode" + annotation (Placement(transformation(extent={{190,-130},{210,-110}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator repTChiWatSupSet(final + nout=nHp) if have_chiWat "Replicate CHWST setpoint" + annotation (Placement(transformation(extent={{150,-150},{170,-130}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator repTHeaWatSupSet(final + nout=nHp) if have_heaWat "Replicate HWST setpoint" + annotation (Placement(transformation(extent={{150,-110},{170,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatPriSup(final unit="K", + displayUnit="degC") if have_heaWat "Primary HW supply temperature" + annotation (Placement(transformation(extent={{-300,40},{-260,80}}), + iconTransformation(extent={{-240,0},{-200,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatPriSup(final unit="K", + displayUnit="degC") if have_chiWat "Primary CHW return temperature" + annotation (Placement(transformation(extent={{-300,-20},{-260,20}}), + iconTransformation(extent={{-240,-60},{-200,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSecSup(final unit="K", + displayUnit="degC") if have_chiWat and have_senTHeaWatSecSup + "Secondary HW supply temperature" annotation (Placement(transformation( + extent={{-300,-80},{-260,-40}}), iconTransformation(extent={{-240,-120}, + {-200,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSecSup(final unit="K", + displayUnit="degC") if have_chiWat and have_senTChiWatSecSup + "Secondary CHW return temperature" annotation (Placement(transformation( + extent={{-300,-140},{-260,-100}}), iconTransformation(extent={{-240,-180}, + {-200,-140}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasTHeaWatSupSet(final nin + =nHp, final + nout=nHp) if have_heaWat and not have_chiWat + "Direct pass through for HWST setpoint" + annotation (Placement(transformation(extent={{220,-110},{240,-90}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasTChiWatSupSet(final nin + =nHp, final nout=nHp) if have_chiWat and not have_heaWat + "Direct pass through for CHWST setpoint" + annotation (Placement(transformation(extent={{220,-150},{240,-130}}))); +equation + connect(u1SchHea, enaHea.u1Sch) + annotation (Line(points={{-280,380},{-180,380},{-180,364},{-112,364}},color={255,0,255})); + connect(nReqPlaHeaWat, enaHea.nReqPla) annotation (Line(points={{-280,340},{-178, + 340},{-178,360},{-112,360}}, color={255,127,0})); + connect(TOut, enaHea.TOut) + annotation (Line(points={{-280,80},{-170,80},{-170,356},{-112,356}},color={0,0,127})); + connect(enaHea.y1, idxStaHea.u1Lea) + annotation (Line(points={{-88,360},{-56,360},{-56,366},{-12,366}},color={255,0,255})); + connect(avaStaHea.y1, idxStaHea.u1AvaSta) + annotation (Line(points={{-88,330},{-56,330},{-56,354},{-12,354}},color={255,0,255})); + connect(idxStaHea.y, enaEquHea.uSta) + annotation (Line(points={{12,360},{38,360}},color={255,127,0})); + connect(seqEve.y1, y1Hp) annotation (Line(points={{162,310},{238,310},{238, + 380},{280,380}}, color={255,0,255})); + connect(seqEve.y1Hea, y1HeaHp) annotation (Line(points={{162,308},{240,308},{ + 240,360},{280,360}}, color={255,0,255})); + connect(seqEve.y1ValHeaWatOutIso, y1ValHeaWatHpOutIso) annotation (Line( + points={{162,298},{240,298},{240,300},{280,300}}, color={255,0,255})); + connect(seqEve.y1ValHeaWatInlIso, y1ValHeaWatHpInlIso) annotation (Line( + points={{162,300},{242,300},{242,320},{280,320}}, color={255,0,255})); + connect(seqEve.y1ValChiWatInlIso, y1ValChiWatHpInlIso) annotation (Line( + points={{162,296},{238,296},{238,280},{280,280}}, color={255,0,255})); + connect(seqEve.y1ValChiWatOutIso, y1ValChiWatHpOutIso) annotation (Line( + points={{162,294},{236,294},{236,260},{280,260}}, color={255,0,255})); + connect(idxStaHea.y, chaStaHea.uSta) + annotation (Line(points={{12,360},{20,360},{20,340},{-50,340},{-50,330},{-42,330}}, + color={255,127,0})); + connect(chaStaHea.y1Dow, idxStaHea.u1Dow) + annotation (Line(points={{-18,316},{-14,316},{-14,358},{-12,358}},color={255,0,255})); + connect(chaStaHea.y1Up, idxStaHea.u1Up) + annotation (Line(points={{-18,324},{-16,324},{-16,362},{-12,362}},color={255,0,255})); + connect(avaStaHea.y1, chaStaHea.u1AvaSta) + annotation (Line(points={{-88,330},{-56,330},{-56,326},{-42,326}},color={255,0,255})); + connect(sorRunTimHea.yIdx, enaEquHea.uIdxAltSor) + annotation (Line(points={{-18,284},{32,284},{32,366},{38,366}},color={255,127,0})); + connect(nReqPlaChiWat, enaCoo.nReqPla) annotation (Line(points={{-280,320},{-182, + 320},{-182,100},{-112,100}}, color={255,127,0})); + connect(TOut, enaCoo.TOut) + annotation (Line(points={{-280,80},{-170,80},{-170,96},{-112,96}},color={0,0,127})); + connect(u1SchCoo, enaCoo.u1Sch) + annotation (Line(points={{-280,360},{-180,360},{-180,104},{-112,104}},color={255,0,255})); + connect(avaStaCoo.y1, chaStaCoo.u1AvaSta) + annotation (Line(points={{-88,70},{-56,70},{-56,68},{-42,68}},color={255,0,255})); + connect(enaCoo.y1, idxStaCoo.u1Lea) + annotation (Line(points={{-88,100},{-56,100},{-56,106},{-12,106}},color={255,0,255})); + connect(chaStaCoo.y1Up, idxStaCoo.u1Up) + annotation (Line(points={{-18,66},{-16,66},{-16,102},{-12,102}},color={255,0,255})); + connect(chaStaCoo.y1Dow, idxStaCoo.u1Dow) + annotation (Line(points={{-18,58},{-14,58},{-14,98},{-12,98}},color={255,0,255})); + connect(idxStaCoo.y, enaEquCoo.uSta) + annotation (Line(points={{12,100},{38,100}},color={255,127,0})); + connect(enaEquHea.y1, seqEve.u1Hea) annotation (Line(points={{62,360},{80,360}, + {80,310},{138,310}}, color={255,0,255})); + connect(enaEquCoo.y1, seqEve.u1Coo) annotation (Line(points={{62,100},{80,100}, + {80,306},{138,306}}, color={255,0,255})); + connect(y1HeaHp, y1HeaPre.u) + annotation (Line(points={{280,360},{232,360}},color={255,0,255})); + connect(y1HeaPre.y, avaEquHeaCoo.u1Hea) + annotation (Line(points={{208,360},{160,360},{160,378},{-156,378},{-156,214},{-154,214}}, + color={255,0,255})); + connect(avaEquHeaCoo.y1Hea, avaStaHea.u1Ava) + annotation (Line(points={{-130,226},{-120,226},{-120,330},{-112,330}},color={255,0,255})); + connect(avaEquHeaCoo.y1Coo, avaStaCoo.u1Ava) + annotation (Line(points={{-130,214},{-120,214},{-120,70},{-112,70}},color={255,0,255})); + connect(avaStaCoo.y1, idxStaCoo.u1AvaSta) + annotation (Line(points={{-88,70},{-56,70},{-56,94},{-12,94}},color={255,0,255})); + connect(avaEquHeaCoo.y1Hea, enaEquHea.u1Ava) + annotation (Line(points={{-130,226},{36,226},{36,354},{38,354}},color={255,0,255})); + connect(avaEquHeaCoo.y1Coo, enaEquCoo.u1Ava) + annotation (Line(points={{-130,214},{36,214},{36,94},{38,94}},color={255,0,255})); + connect(sorRunTimCoo.yIdx, enaEquCoo.uIdxAltSor) + annotation (Line(points={{-18,24},{32,24},{32,106},{38,106}},color={255,127,0})); + connect(idxStaCoo.y, chaStaCoo.uSta) + annotation (Line(points={{12,100},{20,100},{20,80},{-48,80},{-48,72},{-42,72}}, + color={255,127,0})); + connect(avaEquHeaCoo.y1Hea, sorRunTimHea.u1Ava) + annotation (Line(points={{-130,226},{-120,226},{-120,284},{-42,284}},color={255,0,255})); + connect(avaEquHeaCoo.y1Coo, sorRunTimCoo.u1Ava) + annotation (Line(points={{-130,214},{-120,214},{-120,24},{-42,24}},color={255,0,255})); + connect(staPumChiWatPri.y1, y1PumChiWatPri) + annotation (Line(points={{212,180},{280,180}},color={255,0,255})); + connect(staPumChiWatPri.y1_actual, seqEve.u1PumChiWatPri_actual) annotation ( + Line(points={{212,186},{220,186},{220,262},{122,262},{122,296},{138,296}}, + color={255,0,255})); + connect(seqEve.y1PumChiWatPri, staPumChiWatPri.u1Pum) annotation (Line(points + ={{162,288},{178,288},{178,178},{188,178}}, color={255,0,255})); + connect(u1PumChiWatPri_actual, staPumChiWatPri.u1Pum_actual) + annotation (Line(points={{-280,180},{170,180},{170,176},{188,176}},color={255,0,255})); + connect(u1PumHeaWatPri_actual, staPumHeaWatPri.u1Pum_actual) + annotation (Line(points={{-280,200},{128,200},{128,196},{138,196}},color={255,0,255})); + connect(staPumHeaWatPri.y1_actual, seqEve.u1PumHeaWatPri_actual) annotation ( + Line(points={{162,206},{164,206},{164,260},{120,260},{120,298},{138,298}}, + color={255,0,255})); + connect(staPumHeaWatSec.y1, y1PumHeaWatSec) + annotation (Line(points={{162,160},{280,160}},color={255,0,255})); + connect(staPumChiWatSec.y1, y1PumChiWatSec) + annotation (Line(points={{212,140},{280,140}},color={255,0,255})); + connect(u1PumHeaWatSec_actual, staPumHeaWatSec.u1Pum_actual) + annotation (Line(points={{-280,160},{120,160},{120,156},{138,156}},color={255,0,255})); + connect(u1PumChiWatSec_actual, staPumChiWatSec.u1Pum_actual) + annotation (Line(points={{-280,140},{180,140},{180,136},{188,136}},color={255,0,255})); + connect(staPumHeaWatPri.y1, y1PumHeaWatPri) + annotation (Line(points={{162,200},{216,200},{216,200},{280,200}},color={255,0,255})); + connect(staPumChiWatSec.y1_actual, seqEve.u1PumChiWatSec_actual) annotation ( + Line(points={{212,146},{222,146},{222,266},{126,266},{126,290},{138,290}}, + color={255,0,255})); + connect(seqEve.y1PumHeaWatPri, staPumHeaWatPri.u1Pum) annotation (Line(points + ={{162,290},{162,220},{130,220},{130,198},{138,198}}, color={255,0,255})); + connect(staPumHeaWatSec.y1_actual, seqEve.u1PumHeaWatSec_actual) annotation ( + Line(points={{162,166},{166,166},{166,264},{124,264},{124,292},{138,292}}, + color={255,0,255})); + connect(VHeaWatSec_flow, staPumHeaWatSec.V_flow) + annotation (Line(points={{-280,-100},{-156,-100},{-156,152},{138,152}},color={0,0,127})); + connect(VChiWatSec_flow, staPumChiWatSec.V_flow) + annotation (Line(points={{-280,-160},{-154,-160},{-154,132},{188,132}},color={0,0,127})); + connect(THeaWatPriRet, THeaWatRet.u) + annotation (Line(points={{-280,40},{-232,40}},color={0,0,127})); + connect(THeaWatRet.y, chaStaHea.TRet) + annotation (Line(points={{-208,40},{-168,40},{-168,306},{-50,306},{-50,314},{-42,314}}, + color={0,0,127})); + connect(THeaWatSecRet, THeaWatRet.uPh) annotation (Line(points={{-280,-80},{-240, + -80},{-240,34},{-232,34}}, color={0,0,127})); + connect(VHeaWatPri_flow, VHeaWat_flow.u) + annotation (Line(points={{-280,20},{-202,20}},color={0,0,127})); + connect(VHeaWat_flow.y, chaStaHea.V_flow) + annotation (Line(points={{-178,20},{-166,20},{-166,304},{-48,304},{-48,312},{-42,312}}, + color={0,0,127})); + connect(VHeaWatSec_flow, VHeaWat_flow.uPh) annotation (Line(points={{-280,-100}, + {-206,-100},{-206,14},{-202,14}}, color={0,0,127})); + connect(TChiWatPriRet, TChiWatRet.u) + annotation (Line(points={{-280,-20},{-232,-20}},color={0,0,127})); + connect(TChiWatRet.y, chaStaCoo.TRet) + annotation (Line(points={{-208,-20},{-164,-20},{-164,48},{-50,48},{-50,56},{-42,56}}, + color={0,0,127})); + connect(TChiWatSecRet, TChiWatRet.uPh) annotation (Line(points={{-280,-140},{-238, + -140},{-238,-26},{-232,-26}}, color={0,0,127})); + connect(VChiWatPri_flow, VChiWat_flow.u) + annotation (Line(points={{-280,-40},{-202,-40}},color={0,0,127})); + connect(VChiWat_flow.y, chaStaCoo.V_flow) + annotation (Line(points={{-178,-40},{-162,-40},{-162,38},{-48,38},{-48,54},{-42,54}}, + color={0,0,127})); + connect(VChiWatSec_flow, VChiWat_flow.uPh) annotation (Line(points={{-280,-160}, + {-204,-160},{-204,-46},{-202,-46}}, color={0,0,127})); + connect(enaHea.y1, staPumHeaWatSec.u1Pla) + annotation (Line(points={{-88,360},{-80,360},{-80,162},{128,162},{128,168}, + {138,168}}, + color={255,0,255})); + connect(enaCoo.y1, staPumChiWatSec.u1Pla) + annotation (Line(points={{-88,100},{-80,100},{-80,138},{186,138},{186,148}, + {188,148}}, + color={255,0,255})); + connect(seqEve.y1ValHeaWatInlIso, staPumHeaWatPri.u1ValInlIso) annotation ( + Line(points={{162,300},{170,300},{170,216},{134,216},{134,204},{138,204}}, + color={255,0,255})); + connect(seqEve.y1ValHeaWatOutIso, staPumHeaWatPri.u1ValOutIso) annotation ( + Line(points={{162,298},{168,298},{168,218},{132,218},{132,202},{138,202}}, + color={255,0,255})); + connect(seqEve.y1ValChiWatInlIso, staPumChiWatPri.u1ValInlIso) annotation ( + Line(points={{162,296},{182,296},{182,184},{188,184}}, color={255,0,255})); + connect(seqEve.y1ValChiWatOutIso, staPumChiWatPri.u1ValOutIso) annotation ( + Line(points={{162,294},{180,294},{180,182},{188,182}}, color={255,0,255})); + connect(u1Hp_actual, sorRunTimHea.u1Run) + annotation (Line(points={{-280,300},{-60,300},{-60,296},{-42,296}},color={255,0,255})); + connect(u1Hp_actual, sorRunTimCoo.u1Run) + annotation (Line(points={{-280,300},{-60,300},{-60,36},{-42,36}},color={255,0,255})); + connect(y1Hp, y1HpPre.u) + annotation (Line(points={{280,380},{202,380}},color={255,0,255})); + connect(y1HpPre.y, avaEquHeaCoo.u1) + annotation (Line(points={{178,380},{-158,380},{-158,226},{-154,226}},color={255,0,255})); + connect(idxStaCoo.y, comStaCoo.uSta) + annotation (Line(points={{12,100},{20,100},{20,-12},{-46,-12},{-46,4},{-42,4}}, + color={255,127,0})); + connect(comStaCoo.y1, chaStaCoo.u1StaPro) + annotation (Line(points={{-18,-6},{-10,-6},{-10,48},{-46,48},{-46,64},{-42,64}}, + color={255,0,255})); + connect(u1Hp_actual, comStaCoo.u1_actual) + annotation (Line(points={{-280,300},{-60,300},{-60,-4},{-42,-4}},color={255,0,255})); + connect(y1HpPre.y, comStaCoo.u1) + annotation (Line(points={{178,380},{-158,380},{-158,0},{-42,0}},color={255,0,255})); + connect(idxStaHea.y, comStaHea.uSta) + annotation (Line(points={{12,360},{20,360},{20,248},{-44,248},{-44,264},{-42,264}}, + color={255,127,0})); + connect(u1Hp_actual, comStaHea.u1_actual) + annotation (Line(points={{-280,300},{-60,300},{-60,256},{-42,256}},color={255,0,255})); + connect(y1HpPre.y, comStaHea.u1) + annotation (Line(points={{178,380},{-60,380},{-60,260},{-42,260}},color={255,0,255})); + connect(comStaHea.y1, chaStaHea.u1StaPro) + annotation (Line(points={{-18,254},{-10,254},{-10,306},{-44,306},{-44,322},{-42,322}}, + color={255,0,255})); + connect(resHeaWat.dpSet, dpHeaWatRemSet) + annotation (Line(points={{112,246},{242,246},{242,-60},{280,-60}},color={0,0,127})); + connect(resChiWat.dpSet, dpChiWatRemSet) + annotation (Line(points={{112,-34},{238,-34},{238,-80},{280,-80}},color={0,0,127})); + connect(nReqResHeaWat,resHeaWat.nReqRes) + annotation (Line(points={{-280,-340},{76,-340},{76,246},{88,246}},color={255,127,0})); + connect(nReqResChiWat,resChiWat.nReqRes) + annotation (Line(points={{-280,-360},{80,-360},{80,-34},{88,-34}},color={255,127,0})); + connect(enaCoo.y1, resChiWat.u1Ena) + annotation (Line(points={{-88,100},{-80,100},{-80,-40},{88,-40}},color={255,0,255})); + connect(enaHea.y1, resHeaWat.u1Ena) + annotation (Line(points={{-88,360},{-80,360},{-80,240},{88,240}},color={255,0,255})); + connect(comStaHea.y1, resHeaWat.u1StaPro) + annotation (Line(points={{-18,254},{-10,254},{-10,234},{88,234}},color={255,0,255})); + connect(comStaCoo.y1, resChiWat.u1StaPro) + annotation (Line(points={{-18,-6},{-10,-6},{-10,-46},{88,-46}},color={255,0,255})); + connect(resChiWat.TSupSet, chaStaCoo.TSupSet) + annotation (Line(points={{112,-46},{116,-46},{116,-20},{-52,-20},{-52,58},{-42, + 58}}, + color={0,0,127})); + connect(resHeaWat.TSupSet, chaStaHea.TSupSet) + annotation (Line(points={{112,234},{118,234},{118,220},{-52,220},{-52,316},{ + -42,316}}, + color={0,0,127})); + connect(ctlPumPri.yPumHeaWatPriHdr, yPumHeaWatPriHdr) + annotation (Line(points={{212,86},{222,86},{222,100},{280,100}},color={0,0,127})); + connect(ctlPumPri.yPumChiWatPriHdr, yPumChiWatPriHdr) + annotation (Line(points={{212,82},{220,82},{220,80},{280,80}},color={0,0,127})); + connect(ctlPumPri.yPumHeaWatPriDed, yPumHeaWatPriDed) + annotation (Line(points={{212,78},{220,78},{220,60},{280,60},{280,60}},color={0,0,127})); + connect(ctlPumPri.yPumChiWatPriDed, yPumChiWatPriDed) + annotation (Line(points={{212,74},{216,74},{216,40},{280,40}},color={0,0,127})); + connect(staPumHeaWatPri.y1, ctlPumPri.u1PumHeaWatPri) + annotation (Line(points={{162,200},{172,200},{172,86},{188,86}},color={255,0,255})); + connect(staPumChiWatPri.y1, ctlPumPri.u1PumChiWatPri) + annotation (Line(points={{212,180},{220,180},{220,100},{184,100},{184,80},{188, + 80}}, + color={255,0,255})); + connect(seqEve.y1Hea, ctlPumPri.u1Hea) annotation (Line(points={{162,308},{ + 174,308},{174,74},{188,74}}, color={255,0,255})); + connect(ctlPumHeaWatSec.y, yPumHeaWatSec) + annotation (Line(points={{161.8,0},{280,0}}, color={0,0,127})); + connect(ctlPumChiWatSec.y, yPumChiWatSec) + annotation (Line(points={{211.8,-20},{280,-20}}, color={0,0,127})); + connect(u1PumHeaWatSec_actual, ctlPumHeaWatSec.y1_actual) + annotation (Line(points={{-280,160},{120,160},{120,8},{138,8}}, color={255,0,255})); + connect(u1PumChiWatSec_actual, ctlPumChiWatSec.y1_actual) + annotation (Line(points={{-280,140},{180,140},{180,-12},{188,-12}}, + color={255,0,255})); + connect(resChiWat.dpSet, ctlPumChiWatSec.dpRemSet) + annotation (Line(points={{112,-34},{178,-34},{178,-16},{188,-16}}, + color={0,0,127})); + connect(dpHeaWatRem, ctlPumHeaWatSec.dpRem) + annotation (Line(points={{-280,-200},{130,-200},{130,0},{138,0}}, color={0,0,127})); + connect(resHeaWat.dpSet, ctlPumHeaWatSec.dpRemSet) + annotation (Line(points={{112,246},{122,246},{122,4},{138,4}}, color={0,0,127})); + connect(dpHeaWatLoc, ctlPumHeaWatSec.dpLoc) + annotation (Line(points={{-280,-240},{134,-240},{134,-8},{138,-8}},color={0,0,127})); + connect(dpHeaWatLocSet, ctlPumHeaWatSec.dpLocSet) + annotation (Line(points={{-280,-220},{132,-220},{132,-4},{138,-4}},color={0,0,127})); + connect(dpChiWatRem, ctlPumChiWatSec.dpRem) + annotation (Line(points={{-280,-260},{180,-260},{180,-20},{188,-20}}, + color={0,0,127})); + connect(dpChiWatLocSet, ctlPumChiWatSec.dpLocSet) + annotation (Line(points={{-280,-280},{182,-280},{182,-24},{188,-24}}, + color={0,0,127})); + connect(dpChiWatLoc, ctlPumChiWatSec.dpLoc) + annotation (Line(points={{-280,-300},{184,-300},{184,-28},{188,-28}}, + color={0,0,127})); + connect(u1AvaHp.y, avaEquHeaCoo.u1Ava) annotation (Line(points={{-228,260},{ + -200,260},{-200,220},{-154,220}}, color={255,0,255})); + connect(repTChiWatSupSet.y, swiTSupSet.u3) annotation (Line(points={{172,-140}, + {178,-140},{178,-128},{188,-128}}, color={0,0,127})); + connect(repTHeaWatSupSet.y, swiTSupSet.u1) annotation (Line(points={{172,-100}, + {178,-100},{178,-112},{188,-112}}, color={0,0,127})); + connect(resChiWat.TSupSet, repTChiWatSupSet.u) annotation (Line(points={{112,-46}, + {116,-46},{116,-140},{148,-140}}, color={0,0,127})); + connect(resHeaWat.TSupSet, repTHeaWatSupSet.u) annotation (Line(points={{112,234}, + {118,234},{118,-100},{148,-100}}, color={0,0,127})); + connect(seqEve.y1Hea, swiTSupSet.u2) annotation (Line(points={{162,308},{176, + 308},{176,-120},{188,-120}}, color={255,0,255})); + connect(swiTSupSet.y, TSupSet) annotation (Line(points={{212,-120},{242,-120}, + {242,-120},{280,-120}}, color={0,0,127})); + connect(pasTChiWatSupSet.y, TSupSet) annotation (Line(points={{242,-140},{250, + -140},{250,-120},{280,-120}}, color={0,0,127})); + connect(pasTHeaWatSupSet.y, TSupSet) annotation (Line(points={{242,-100},{250, + -100},{250,-120},{280,-120}}, color={0,0,127})); + connect(repTChiWatSupSet.y, pasTChiWatSupSet.u) + annotation (Line(points={{172,-140},{218,-140}}, color={0,0,127})); + connect(repTHeaWatSupSet.y, pasTHeaWatSupSet.u) + annotation (Line(points={{172,-100},{218,-100}}, color={0,0,127})); + connect(resChiWat.TSupSet, TChiWatSupSet) annotation (Line(points={{112,-46}, + {116,-46},{116,-180},{280,-180}}, color={0,0,127})); + connect(resHeaWat.TSupSet, THeaWatSupSet) annotation (Line(points={{112,234}, + {118,234},{118,-160},{280,-160}}, color={0,0,127})); + annotation ( + defaultComponentName="ctl", + Icon( + coordinateSystem( + preserveAspectRatio=true, + extent={{-200,-340},{200,340}}), + graphics={ + Rectangle( + extent={{-200,340},{200,-340}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-150,390},{150,350}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + extent={{-260,-400},{260,400}})), + Documentation( + info=" ++This block implements the sequence of operation for plants with +air-to-water heat pumps. +Most parts of the sequence of operation are similar to that +described in ASHRAE, 2021 for chiller plants. +
+
+The supported plant configurations are enumerated in the table below.
+
Configuration parameter | Options | Notes |
---|---|---|
Function | +
+Heating and cooling +Heating-only +Cooling-only + |
++ | +
Type of distribution | ++Constant primary-variable secondary centralized + | +
+\"Centralized secondary pumps\" refers to configurations with a single
+group of secondary pumps that is typically integrated into the plant. +Distributed secondary pumps with multiple secondary loops served +by dedicated secondary pumps are currently not supported. +Options are limited to constant primary distributions because most +AWHPs on the market use a reverse cycle for defrosting. +This requires maximum primary flow during defrost cycles and hinders +variable primary distributions. +An option for constant primary-only distributions with ∆p-controlled +variable speed pumps will be added in a next release. + |
+
Type of primary pump arrangement | +
+Dedicated +Headered + |
+It is assumed that the HW and the CHW loops have the +same type of primary pump arrangement, as specified by this parameter. + | +
Separate dedicated primary CHW pumps | +
+False +True + |
+This option is only available for heating and cooling plants +with dedicated primary pumps. +If this option is not selected, each AWHP uses +a common dedicated primary pump for HW and CHW. +Otherwise, each AWHP relies on a separate dedicated HW pump +and a separate dedicated CHW pump. + | +
Type of primary HW pumps | +
+Variable speed +Constant speed + |
++For constant primary-variable secondary distributions, the variable +speed primary pumps are commanded at fixed speeds, determined during the +Testing, Adjusting and Balancing phase to provide design AWHP flow in +heating and cooling modes. +The same intent is achieved with constant speed primary pumps through the +use of balancing valves. + | +
Type of primary CHW pumps | +
+Variable speed +Constant speed + |
+See the note above on primary HW pumps. | +
+A staging matrix staEqu
is required as a parameter.
+See the documentation of
+
+Buildings.Templates.Plants.Controls.StagingRotation.EquipmentEnable
+for the associated definition and requirements.
+
+Depending on the plant configuration, the term \"primary HW pumps\"
+(and the corresponding variables containing *pumHeaWatPri*
)
+refers either to primary HW pumps for plants with separate primary
+HW and CHW pumps (either headered or dedicated)
+or to dedicated primary pumps for plants with common primary pumps
+serving both the HW and CHW loops.
+
+At its current stage of development, this controller contains no +logic for handling faulted equipment. +It is therefore assumed that any equipment is available at all times. +
++This model validates + +Buildings.Templates.Plants.Controls.HeatPumps.AirToWater +in a configuration with three equally sized lead/lag alternate +heat pumps. +
++Simulating this model shows how the controller responds to a varying load by +
++This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/HeatPumps/Validation/package.order b/Buildings/Templates/Plants/Controls/HeatPumps/Validation/package.order new file mode 100644 index 00000000000..971b641363f --- /dev/null +++ b/Buildings/Templates/Plants/Controls/HeatPumps/Validation/package.order @@ -0,0 +1 @@ +AirToWater diff --git a/Buildings/Templates/Plants/Controls/HeatPumps/package.mo b/Buildings/Templates/Plants/Controls/HeatPumps/package.mo new file mode 100644 index 00000000000..af3c9fb29f4 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/HeatPumps/package.mo @@ -0,0 +1,8 @@ +within Buildings.Templates.Plants.Controls; +package HeatPumps + annotation (Documentation(info=" ++This package contains control sequences for heat pump plants. +
+")); +end HeatPumps; diff --git a/Buildings/Templates/Plants/Controls/HeatPumps/package.order b/Buildings/Templates/Plants/Controls/HeatPumps/package.order new file mode 100644 index 00000000000..8df76113296 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/HeatPumps/package.order @@ -0,0 +1,2 @@ +AirToWater +Validation diff --git a/Buildings/Templates/Plants/Controls/Pumps/Generic/ControlDifferentialPressure.mo b/Buildings/Templates/Plants/Controls/Pumps/Generic/ControlDifferentialPressure.mo new file mode 100644 index 00000000000..f731cf30b09 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Generic/ControlDifferentialPressure.mo @@ -0,0 +1,233 @@ +within Buildings.Templates.Plants.Controls.Pumps.Generic; +block ControlDifferentialPressure + "Differential pressure control for variable speed pumps" + parameter Boolean have_senDpRemWir + "Set to true for remote differential pressure sensor(s) hardwired to controller" + annotation (Evaluate=true); + parameter Integer nPum( + min=1) + "Number of pumps that operate at design conditions" + annotation (Evaluate=true); + parameter Integer nSenDpRem( + min=1) + "Number of remote loop differential pressure sensors used for pump speed control" + annotation (Evaluate=true); + parameter Real y_min( + max=1, + min=0, + unit="1")=0.1 + "Minimum pump speed"; + final parameter Real y_max( + final unit="1", + final min=0, + final max=1)=1 + "Maximum pump speed"; + parameter Real k( + min=100 * Buildings.Controls.OBC.CDL.Constants.eps)=1 + "Gain of controller" + annotation (Dialog(group="Control gains")); + parameter Real Ti( + min=100 * Buildings.Controls.OBC.CDL.Constants.eps, + unit="s")=60 + "Time constant of integrator block" + annotation (Dialog(group="Control gains")); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput y1_actual[nPum] + "Pump status" + annotation (Placement(transformation(extent={{-140,60},{-100,100}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpRemSet[nSenDpRem]( + each final unit="Pa") + if have_senDpRemWir + "Remote differential pressure setpoint" + annotation (Placement(transformation(extent={{-140,20},{-100,60}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpLoc( + final unit="Pa") + if not have_senDpRemWir + "Loop differential pressure local to the plant" + annotation (Placement(transformation(extent={{-140,-100},{-100,-60}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpRem[nSenDpRem]( + each final unit="Pa") + if have_senDpRemWir + "Remote loop differential pressure" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput dpLocSet[nSenDpRem]( + each final unit="Pa") + if not have_senDpRemWir + "Local differential pressure setpoint" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput y( + final unit="1") + "Pump speed command" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{98,-20},{138,20}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyOn( + final nin=nPum) + "Return true when any pump is proven on" + annotation (Placement(transformation(extent={{-90,70},{-70,90}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator repEna( + final nout=nSenDpRem) + "Replicate" + annotation (Placement(transformation(extent={{-50,70},{-30,90}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax maxSet( + nin=nSenDpRem) + if not have_senDpRemWir + "Maximum DP setpoint" + annotation (Placement(transformation(extent={{-90,-50},{-70,-30}}))); + Utilities.PIDWithEnable ctlDpRem[nSenDpRem]( + each final k=k, + each final Ti=Ti, + each r=dpSca, + each final yMin=y_min, + each final yMax=y_max, + each final y_reset=y_min, + each final y_neutral=0) + if have_senDpRemWir + "Remote differential pressure control" + annotation (Placement(transformation(extent={{-10,30},{10,50}}))); + Utilities.PIDWithEnable ctlDpLoc( + final k=k, + final Ti=Ti, + final r=dpSca, + final yMin=y_min, + final yMax=y_max, + final y_reset=y_min, + final y_neutral=0) + if not have_senDpRemWir + "Local differential pressure control" + annotation (Placement(transformation(extent={{-10,-50},{10,-30}}))); + Buildings.Controls.OBC.CDL.Reals.MultiMax maxY( + nin=nSenDpRem) + if have_senDpRemWir + "Maximum control loop output" + annotation (Placement(transformation(extent={{40,30},{60,50}}))); +protected + parameter Real dpSca( + final unit="Pa", + final min=0)=1E4 + "Differential pressure used as a scaling factor for PI control"; +equation + connect(y1_actual, anyOn.u) + annotation (Line(points={{-120,80},{-92,80}},color={255,0,255})); + connect(anyOn.y, repEna.u) + annotation (Line(points={{-68,80},{-52,80}},color={255,0,255})); + connect(dpLocSet, maxSet.u) + annotation (Line(points={{-120,-40},{-92,-40}},color={0,0,127})); + connect(dpRemSet, ctlDpRem.u_s) + annotation (Line(points={{-120,40},{-12,40}},color={0,0,127})); + connect(maxSet.y, ctlDpLoc.u_s) + annotation (Line(points={{-68,-40},{-12,-40}},color={0,0,127})); + connect(dpRem, ctlDpRem.u_m) + annotation (Line(points={{-120,0},{0,0},{0,28}},color={0,0,127})); + connect(repEna.y, ctlDpRem.uEna) + annotation (Line(points={{-28,80},{-20,80},{-20,20},{-4,20},{-4,28}},color={255,0,255})); + connect(dpLoc, ctlDpLoc.u_m) + annotation (Line(points={{-120,-80},{0,-80},{0,-52}},color={0,0,127})); + connect(anyOn.y, ctlDpLoc.uEna) + annotation (Line(points={{-68,80},{-60,80},{-60,-60},{-4,-60},{-4,-52}}, + color={255,0,255})); + connect(ctlDpRem.y, maxY.u) + annotation (Line(points={{12,40},{38,40}},color={0,0,127})); + connect(ctlDpLoc.y, y) + annotation (Line(points={{12,-40},{80,-40},{80,0},{120,0}},color={0,0,127})); + connect(maxY.y, y) + annotation (Line(points={{62,40},{80,40},{80,0},{120,0}},color={0,0,127})); + annotation ( + defaultComponentName="ctlDp", + Icon( + coordinateSystem( + preserveAspectRatio=true, + 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={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Documentation( + info=" +
+For plants where a remote DP sensor(s) is hardwired to the pump controller
+(have_senDpRemHar=true
):
+
+For plants where the remote DP sensor(s) is not hardwired to the plant controller, but
+a local DP sensor is hardwired to the plant controller
+(have_senDpRemHar=false
):
+
This logic is prescribed in ASHRAE, 2021 for: +
++For plants where the remote DP sensor(s) is not hardwired to the plant controller, but +a local DP sensor is hardwired to the plant controller, +remote DP is maintained at setpoint by a reverse acting PI loop running in the controller +to which the remote sensor is wired. +
++The loop output is a DP setpoint for the local primary loop DP sensor hardwired to the +plant controller. +
+
+The local DP setpoint is reset from dpLocSet_min
at 0 % loop output
+to dpLocSet_max
at 100 % loop output.
+
+The minimum local differential pressure setpoint dpLocSet_min
is
+dictated by minimum flow control in primary-only plants but has no lower
+limit in primary-secondary plants.
+In primary-only plants, the minimum setpoint needs to be high enough to drive design
+minimum flow for the largest equipment through the minimum flow bypass valve.
+
This logic is prescribed in ASHRAE, 2021 for: +
++Primary pumps are lead/lag alternated as described in + +Buildings.Templates.Plants.Controls.StagingRotation.SortRuntime. +
++The lead primary pump is enabled as described in + +Buildings.Templates.Plants.Controls.Pumps.Primary.EnableLeadHeadered. +
++The number of operating primary pumps matches the number of operating +equipment. +
++Primary pumps are lead/lag alternated as described in + +Buildings.Templates.Plants.Controls.StagingRotation.SortRuntime. +
++The lead primary pump is enabled as described in + +Buildings.Templates.Plants.Controls.Pumps.Primary.EnableLeadHeadered. +
+Primary pumps are staged as described in + +Buildings.Templates.Plants.Controls.Pumps.Generic.StagingHeaderedDeltaP. +
++Secondary pumps are lead/lag alternated as described in + +Buildings.Templates.Plants.Controls.StagingRotation.SortRuntime. +
++The lead secondary pump is enabled when the plant is enabled. +Otherwise, the lead secondary pump is disabled. +
+Secondary pumps are staged as described in + +Buildings.Templates.Plants.Controls.Pumps.Generic.StagingHeaderedDeltaP. +
++At its current stage of development, this block contains no +logic for handling faulted equipment. +It is therefore assumed that all pumps are available at all times. +
++To simplify integration into the plant controller this block also +serves as a pass-through for the dedicated primary pump command signal +that is generated in + +Buildings.Templates.Plants.Controls.StagingRotation.EventSequencing. +
+", revisions=" ++Pumps are staged as a function of the ratio ratV_flow +of current volume flow rate V_flow to design volume +flow rate V_flow_nominal, +the number of operating pumps nPum_actual +and the number of pumps that operate at design conditions +nPum. +Pumps are assumed to be equally sized. +
+FR = V_flow / V_flow_nominal +
+
+The next lag pump is enabled whenever the following is true for
+dtRun
:
+
+FR > nPum_actual / nPum − dVOffUp +
+
+The last lag pump is disabled whenever the following is true for
+dtRun
:
+
+FR < (nPum_actual - 1) / nPum − dVOffDow +
+
+If desired, the stage down flow point dVOffDow
can be
+offset slightly below the stage up point dVOffUp
to
+prevent cycling between pump stages in applications with highly variable loads.
+
+The timers are reset to zero when the status of a pump changes. +This is necessary to ensure the minimum pump runtime with rapidly changing loads. +
+This logic is prescribed in ASHRAE, 2021 for:
++For other plant configurations, the pumps are staged with the equipment, +i.e., the number of pumps matches the number of chillers or boilers. +The actual logic for generating the pump enable commands is part of the +staging event sequencing. +
+
+A \"if\" condition is used to generate the stage up and down command as opposed
+to a \"when\" condition. This means that the command remains true as long as the
+condition is verified. This is necessary, for example, if no higher stage is
+available when a stage up command is triggered. Using a \"when\" condition –
+which is only valid at the point in time at which the condition becomes true –
+would prevent the plant from staging when a higher stage becomes available again.
+To avoid multiple consecutive stage changes, the block that receives the stage up
+and down command and computes the stage index must enforce a minimum stage runtime
+of dtRun
.
+
+This model validates
+
+Buildings.Templates.Plants.Controls.Pumps.Generic.ControlDifferentialPressure
+in a configuration with two pumps and two remote DP sensors that either are
+hardwired to the controller (component ctlDpRem
)
+or are not hardwired to the controller, which uses a local DP sensor instead
+(component ctlDpLoc
).
+
+The simulation of this model shows that when any pump is proven on,
+the controller is enabled and its output is
+initially set to the minimum pump speed y_min
.
+The minimum pump speed sets the lower limit of the controller output
+for the entire time that the controller is enabled.
+The output of the controller ctlDpRem
is driven by the most
+demanding remote DP control loop, e.g.,
+the controller output only drops when both loop input measurements are
+above setpoints.
+Without remote sensors hardwired to the controller, the pump speed is
+driven by the highest local DP setpoint.
+
+When no pump is proven on, the controller is disabled and its output +is set to 0 %. +
+", + revisions=" ++This model validates + +Buildings.Templates.Plants.Controls.Pumps.Generic.ResetLocalDifferentialPressure. +
+
+The simulation of this model shows how the local DP
+setpoint is reset by the controller resDpLoc
+based on the variation of the remote differential pressure
+around its setpoint.
+The local DP setpoint remains bounded by
+resDpLoc.dpLocSet_min
and resDpLoc.dpLocSet_max
.
+
+This model validates + +Buildings.Templates.Plants.Controls.Pumps.Generic.StagingHeadered +with three plant equipment and three pumps and for the following configurations. +
+staPumPriDed
):
+the number of pumps commanded on matches the number of operating
+equipment with a one-to-one relationship.
+staPumPriNoDp
):
+the number of pumps commanded on matches the number of operating
+equipment without a one-to-one relationship.
+staPumPriDp
):
+the number of pumps commanded on does not match the number of operating
+equipment but is rather related to the fractional flow rate.
+The simulation also exhibits the lead/lag rotation of the primary pumps.
+staPumSecDp
):
+the number of pumps commanded on does not match the number of operating
+equipment but is rather related to the fractional flow rate.
+All pumps are disabled when the plant is disabled.
++This model validates + +Buildings.Templates.Plants.Controls.Pumps.Generic.StagingHeaderedDeltaP +in a configuration with four pumps. +
++The simulation of this model shows that when the lead pump is enabled, +the output of the staging controller is greater than or equal to one. +The number of enabled pumps increases and decreases with the varying +flow rate and under the condition of a minimum runtime of 10 min. +It remains greater than or equal to one as long as the lead pump remains +enabled. +
++When the lead pump is disabled, the number of enabled pumps is set +to 0. This transition is not subject to the minimum runtime. +
+", + revisions=" ++This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/Pumps/Generic/Validation/package.order b/Buildings/Templates/Plants/Controls/Pumps/Generic/Validation/package.order new file mode 100644 index 00000000000..6071ceab043 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Generic/Validation/package.order @@ -0,0 +1,4 @@ +ControlDifferentialPressure +ResetLocalDifferentialPressure +StagingHeadered +StagingHeaderedDeltaP diff --git a/Buildings/Templates/Plants/Controls/Pumps/Generic/package.mo b/Buildings/Templates/Plants/Controls/Pumps/Generic/package.mo new file mode 100644 index 00000000000..6d707adf50c --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Generic/package.mo @@ -0,0 +1,8 @@ +within Buildings.Templates.Plants.Controls.Pumps; +package Generic + annotation (Documentation(info=" ++This package contains control sequences for primary or secondary pumps. +
+")); +end Generic; diff --git a/Buildings/Templates/Plants/Controls/Pumps/Generic/package.order b/Buildings/Templates/Plants/Controls/Pumps/Generic/package.order new file mode 100644 index 00000000000..530b96ee682 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Generic/package.order @@ -0,0 +1,5 @@ +ControlDifferentialPressure +ResetLocalDifferentialPressure +StagingHeadered +StagingHeaderedDeltaP +Validation diff --git a/Buildings/Templates/Plants/Controls/Pumps/Primary/EnableLeadHeadered.mo b/Buildings/Templates/Plants/Controls/Pumps/Primary/EnableLeadHeadered.mo new file mode 100644 index 00000000000..ed16681af43 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Primary/EnableLeadHeadered.mo @@ -0,0 +1,199 @@ +within Buildings.Templates.Plants.Controls.Pumps.Primary; +block EnableLeadHeadered + "Lead primary pump enable/disable for plants with headered primary pumps" + parameter Buildings.Templates.Plants.Controls.Types.EquipmentConnection typCon + "Type of connection between equipment and primary loop" + annotation (Evaluate=true); + parameter Buildings.Templates.Plants.Controls.Types.Actuator typValIso= + Buildings.Templates.Plants.Controls.Types.Actuator.TwoPosition + "Type of isolation valve" + annotation (Evaluate=true); + parameter Integer nValIso( + final min=1) + "Number of isolation valves" + annotation (Evaluate=true); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ValIso[nValIso] + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.TwoPosition + "Isolation valve command" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uValIso[nValIso] + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.Modulating + "Isolation valve command" + annotation (Placement(transformation(extent={{-140,-60},{-100,-20}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1 + "Lead pump enable signal" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyOpePar( + nin=nValIso) + if typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Parallel + "Return true if any valve is commanded open - Parallel piped equipment" + annotation (Placement(transformation(extent={{10,-10},{30,10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd allCloPar( + nin=nValIso) + if typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Parallel + "Return true if all valves are commanded closed - Parallel piped equipment" + annotation (Placement(transformation(extent={{10,-50},{30,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Not cloParMod[nValIso] + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.Modulating + and typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Parallel + "Return true if valve is commanded closed" + annotation (Placement(transformation(extent={{-30,-50},{-10,-30}}))); + Buildings.Controls.OBC.CDL.Reals.GreaterThreshold opeParMod[nValIso]( + each final t=0) + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.Modulating + and typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Parallel + "Return true if valve commanded > 0 % open" + annotation (Placement(transformation(extent={{-80,-50},{-60,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Latch lat + "Clear enable signal if disable conditions are met" + annotation (Placement(transformation(extent={{70,-10},{90,10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyCloSer( + nin=nValIso) + if typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Series + "Return true if any valve is commanded closed - Series piped equipment" + annotation (Placement(transformation(extent={{10,70},{30,90}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd allOpeSer( + nin=nValIso) + if typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Series + "Return true if all valves are commanded open - Series piped equipment" + annotation (Placement(transformation(extent={{10,30},{30,50}}))); + Buildings.Controls.OBC.CDL.Reals.LessThreshold cloSerMod[nValIso]( + each final t=0.99) + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.Modulating + and typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Series + "Return true if valve commanded < 99 % open" + annotation (Placement(transformation(extent={{-80,-90},{-60,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not opeSerMod[nValIso] + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.Modulating + and typCon == Buildings.Templates.Plants.Controls.Types.EquipmentConnection.Series + "Return true if valve is commanded open" + annotation (Placement(transformation(extent={{-30,-90},{-10,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Not cloTwo[nValIso] + if typValIso == Buildings.Templates.Plants.Controls.Types.Actuator.TwoPosition + "Return true if valve is commanded closed" + annotation (Placement(transformation(extent={{-30,10},{-10,30}}))); +equation + connect(uValIso, opeParMod.u) + annotation (Line(points={{-120,-40},{-82,-40}},color={0,0,127})); + connect(opeParMod.y, cloParMod.u) + annotation (Line(points={{-58,-40},{-32,-40}},color={255,0,255})); + connect(lat.y, y1) + annotation (Line(points={{92,0},{120,0}},color={255,0,255})); + connect(anyOpePar.y, lat.u) + annotation (Line(points={{32,0},{68,0}},color={255,0,255})); + connect(allCloPar.y, lat.clr) + annotation (Line(points={{32,-40},{50,-40},{50,-6},{68,-6}},color={255,0,255})); + connect(allOpeSer.y, lat.clr) + annotation (Line(points={{32,40},{50,40},{50,-6},{68,-6}},color={255,0,255})); + connect(anyCloSer.y, lat.u) + annotation (Line(points={{32,80},{60,80},{60,0},{68,0}},color={255,0,255})); + connect(uValIso, cloSerMod.u) + annotation (Line(points={{-120,-40},{-90,-40},{-90,-80},{-82,-80}},color={0,0,127})); + connect(cloSerMod.y, opeSerMod.u) + annotation (Line(points={{-58,-80},{-32,-80}},color={255,0,255})); + connect(u1ValIso, cloTwo.u) + annotation (Line(points={{-120,0},{-60,0},{-60,20},{-32,20}},color={255,0,255})); + connect(cloTwo.y, anyCloSer.u) + annotation (Line(points={{-8,20},{0,20},{0,80},{8,80}},color={255,0,255})); + connect(u1ValIso, anyOpePar.u) + annotation (Line(points={{-120,0},{8,0}},color={255,0,255})); + connect(cloTwo.y, allCloPar.u) + annotation (Line(points={{-8,20},{0,20},{0,-40},{8,-40}},color={255,0,255})); + connect(u1ValIso, allOpeSer.u) + annotation (Line(points={{-120,0},{0,0},{0,40},{8,40}},color={255,0,255})); + connect(cloParMod.y, allCloPar.u) + annotation (Line(points={{-8,-40},{0,-40},{0,-40},{8,-40}},color={255,0,255})); + connect(cloSerMod.y, anyCloSer.u) + annotation (Line(points={{-58,-80},{-40,-80},{-40,80},{8,80}},color={255,0,255})); + connect(opeSerMod.y, allOpeSer.u) + annotation (Line(points={{-8,-80},{0,-80},{0,40},{8,40}},color={255,0,255})); + connect(opeParMod.y, anyOpePar.u) + annotation (Line(points={{-58,-40},{-40,-40},{-40,0},{8,0}},color={255,0,255})); + annotation ( + defaultComponentName="enaLea", + Icon( + coordinateSystem( + preserveAspectRatio=true, + 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={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Documentation( + info=" ++The lead primary pump is enabled when any equipment isolation valve is commanded open. +
++The lead primary pump is disabled when all equipment isolation valves are commanded closed. +
++For modulating valves, the \"valve commanded open\" +condition is evaluated based on a command signal > 0 %. +The \"valve commanded closed\" condition is evaluated as the negation of the previous condition. +
++The lead primary pump is enabled when any equipment isolation valve is commanded closed. +
++The lead primary pump is disabled when all equipment isolation valves are commanded open. +
++For modulating valves, the \"valve commanded closed\" +condition is evaluated based on a command signal < 100 %. +The \"valve commanded open\" condition is evaluated as the negation of the previous condition. +
+This logic is prescribed in ASHRAE, 2021 for: +
++The valve command is used in contrast to the feedback of the +valve position or the end switch status, as prescribed by Guideline 36. +This is for the sake of simplicity, as there is no harm in deadheading the pump +for a couple seconds and it simplifies the programming. +
++For modulating valves, the \"valve commanded open/closed\" condition is +evaluated without hysteresis because the +valve command signal is generated by the +enabling or staging logic and both use minimum runtime conditions. +Therefore, the valve command signal is not subject to any oscillatory +behavior. +
++This model validates + +Buildings.Templates.Plants.Controls.Pumps.Primary.EnableLeadHeadered +in a configuration with two production units, either parallel piped +or series piped, with either two-position or modulating isolation valves. +
+", + revisions=" ++This model validates + +Buildings.Templates.Plants.Controls.Pumps.Primary.VariableSpeedNoDpControl +with two plant equipment and two primary pumps and for the following configurations. +
+ctlPumPriHdrHea
)
+ctlPumPriHdr
)
+ctlPumPriDedCom
)
+ctlPumPriDedSep
)
++This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/Pumps/Primary/Validation/package.order b/Buildings/Templates/Plants/Controls/Pumps/Primary/Validation/package.order new file mode 100644 index 00000000000..7de919ee9d0 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Primary/Validation/package.order @@ -0,0 +1,2 @@ +EnableLeadHeadered +VariableSpeedNoDpControl diff --git a/Buildings/Templates/Plants/Controls/Pumps/Primary/VariableSpeedNoDpControl.mo b/Buildings/Templates/Plants/Controls/Pumps/Primary/VariableSpeedNoDpControl.mo new file mode 100644 index 00000000000..6001958af8c --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Primary/VariableSpeedNoDpControl.mo @@ -0,0 +1,281 @@ +within Buildings.Templates.Plants.Controls.Pumps.Primary; +block VariableSpeedNoDpControl + "Variable speed primary pumps without differential pressure control" + parameter Boolean have_heaWat + "Set to true for plants that provide HW" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Boolean have_chiWat + "Set to true for plants that provide CHW" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + final parameter Boolean have_pumHeaWatPri=have_heaWat + "Set to true for plants with primary HW pumps" + annotation (Evaluate=true); + parameter Boolean have_pumChiWatPriDed(start=false) + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_chiWat and not have_pumPriHdr)); + final parameter Boolean have_pumChiWatPri= + have_chiWat and (have_pumPriHdr or have_pumChiWatPriDed) + "Set to true for plants with separate primary CHW pumps" + annotation (Evaluate=true); + parameter Boolean have_pumPriHdr + "Set to true for headered primary pumps, false for dedicated pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Integer nEqu(start=0) + "Number of equipment" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_heaWat and have_chiWat)); + parameter Integer nPumHeaWatPri + "Number of primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration")); + parameter Integer nPumChiWatPri(start=if have_chiWat and have_pumChiWatPri + then nEqu else 0) + "Number of primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Plant configuration", + enable=have_pumChiWatPri)); + parameter Real yPumHeaWatPriSet( + max=1, + min=0, + start=1, + unit="1") + "Primary pump speed providing design heat pump flow in heating mode" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=have_heaWat)); + parameter Real yPumChiWatPriSet( + max=1, + min=0, + start=1, + unit="1") + "Primary pump speed providing design heat pump flow in cooling mode" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=have_chiWat)); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatPri[nPumHeaWatPri] + if have_heaWat and have_pumHeaWatPri + "Primary HW pump start command" + annotation (Placement(transformation(extent={{-180,40},{-140,80}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatPriHdr + if have_heaWat and have_pumHeaWatPri and have_pumPriHdr + "Headered primary HW pump speed command" + annotation (Placement(transformation(extent={{140,80},{180,120}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatPri[nPumChiWatPri] + if have_chiWat and have_pumChiWatPri + "Primary CHW pump start command" + annotation (Placement(transformation(extent={{-180,-20},{-140,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatPriHdr + if have_chiWat and have_pumChiWatPri and have_pumPriHdr + "Headered primary CHW pump speed command" + annotation (Placement(transformation(extent={{140,40},{180,80}}), + iconTransformation(extent={{100,0},{140,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatPriDed[nPumHeaWatPri] + if have_heaWat and have_pumHeaWatPri and not have_pumPriHdr + "Dedicated primary HW pump speed command" + annotation (Placement(transformation(extent={{140,-80},{180,-40}}), + iconTransformation(extent={{100,-40},{140,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatPriDed[nPumChiWatPri] + if have_chiWat and have_pumChiWatPri and not have_pumPriHdr + "Dedicated primary CHW pump speed command" + annotation (Placement(transformation(extent={{140,-120},{180,-80}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea[nEqu] if have_heaWat + and have_chiWat and not have_pumChiWatPriDed and not have_pumPriHdr + "Heating/cooling mode command" + annotation (Placement(transformation(extent={{-180,-80},{-140,-40}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Reals.Switch setPumChiWatPriDed[nPumChiWatPri] + if have_chiWat and have_pumChiWatPri and not have_pumPriHdr + "Set prescribed speed when pump is enabled" + annotation (Placement(transformation(extent={{110,-110},{130,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) + "Constant" + annotation (Placement(transformation(extent={{-110,-90},{-90,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant spePumChiWatPri( + final k=yPumChiWatPriSet) + if have_chiWat + "Constant" + annotation (Placement(transformation(extent={{-110,-130},{-90,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch setPumHeaWatPriDed[nPumHeaWatPri] + if have_heaWat and have_pumHeaWatPri and not have_pumPriHdr + "Set prescribed speed when pump is enabled" + annotation (Placement(transformation(extent={{110,-70},{130,-50}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep( + nout=nPumHeaWatPri) + if have_heaWat and have_pumHeaWatPri + "Replicate signal" + annotation (Placement(transformation(extent={{-60,-30},{-40,-10}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep1( + nout=nPumChiWatPri) + if have_chiWat and have_pumChiWatPri + "Replicate signal" + annotation (Placement(transformation(extent={{-60,-130},{-40,-110}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep2( + nout=nPumChiWatPri) + if have_chiWat and have_pumChiWatPri + "Replicate signal" + annotation (Placement(transformation(extent={{-60,-90},{-40,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant spePumHeaWatPri( + final k=yPumHeaWatPriSet) + if have_heaWat and have_pumHeaWatPri + "Constant" + annotation (Placement(transformation(extent={{-110,110},{-90,130}}))); + Buildings.Controls.OBC.CDL.Reals.Switch setPumChiWatPriHdr + if have_chiWat and have_pumChiWatPri and have_pumPriHdr + "Set prescribed speed when pump is enabled" + annotation (Placement(transformation(extent={{110,50},{130,70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch setPumHeaWatPriHdr + if have_heaWat and have_pumHeaWatPri and have_pumPriHdr + "Set prescribed speed when pump is enabled" + annotation (Placement(transformation(extent={{110,90},{130,110}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyPumChiWatPri( + nin=nPumChiWatPri) + if have_chiWat and have_pumChiWatPri + "Return true if any pump is enabled" + annotation (Placement(transformation(extent={{-110,-10},{-90,10}}))); + Buildings.Controls.OBC.CDL.Logical.MultiOr anyPumHeaWatPri( + nin=nPumHeaWatPri) + if have_heaWat and have_pumHeaWatPri + "Return true if any pump is enabled" + annotation (Placement(transformation(extent={{-110,50},{-90,70}}))); + Buildings.Controls.OBC.CDL.Reals.Switch selSpeHea[nPumHeaWatPri] if + have_heaWat and have_chiWat and not have_pumChiWatPri and not + have_pumPriHdr + "Select prescribed pump speed depending on heating/cooling mode – Case with common CHW and HW dedicated pumps" + annotation (Placement(transformation(extent={{40,-50},{60,-30}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep3( + nout=nPumHeaWatPri) + if have_heaWat and have_pumHeaWatPri + "Replicate signal" + annotation (Placement(transformation(extent={{-60,20},{-40,40}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep4( + nout=nPumHeaWatPri) if have_heaWat and have_chiWat and not + have_pumChiWatPri and not have_pumPriHdr + "Replicate signal" + annotation (Placement(transformation(extent={{-30,2},{-10,22}}))); + Utilities.PlaceholderReal ph[nPumHeaWatPri]( + each final have_inp=have_heaWat and have_chiWat and not have_pumChiWatPri + and not have_pumPriHdr, + each final have_inpPh=false, + each final u_internal=yPumHeaWatPriSet) + if have_heaWat and have_pumHeaWatPri and not have_pumPriHdr + "Always use HW pump speed in case of separate dedicated CHW pumps " + annotation (Placement(transformation(extent={{70,-50},{90,-30}}))); +equation + connect(u1PumChiWatPri, setPumChiWatPriDed.u2) + annotation (Line(points={{-160,0},{-126,0},{-126,-100},{108,-100}},color={255,0,255})); + connect(setPumChiWatPriDed.y, yPumChiWatPriDed) + annotation (Line(points={{132,-100},{160,-100}},color={0,0,127})); + connect(setPumHeaWatPriDed.y, yPumHeaWatPriDed) + annotation (Line(points={{132,-60},{160,-60}},color={0,0,127})); + connect(zer.y, rep.u) + annotation (Line(points={{-88,-80},{-70,-80},{-70,-20},{-62,-20}},color={0,0,127})); + connect(spePumChiWatPri.y, rep1.u) + annotation (Line(points={{-88,-120},{-62,-120}},color={0,0,127})); + connect(zer.y, rep2.u) + annotation (Line(points={{-88,-80},{-62,-80}},color={0,0,127})); + connect(setPumHeaWatPriHdr.y, yPumHeaWatPriHdr) + annotation (Line(points={{132,100},{160,100}},color={0,0,127})); + connect(setPumChiWatPriHdr.y, yPumChiWatPriHdr) + annotation (Line(points={{132,60},{160,60}},color={0,0,127})); + connect(rep2.y, setPumChiWatPriDed.u3) + annotation (Line(points={{-38,-80},{-20,-80},{-20,-108},{108,-108}},color={0,0,127})); + connect(rep1.y, setPumChiWatPriDed.u1) + annotation (Line(points={{-38,-120},{80,-120},{80,-92},{108,-92}},color={0,0,127})); + connect(zer.y, setPumChiWatPriHdr.u3) + annotation (Line(points={{-88,-80},{-70,-80},{-70,52},{108,52}},color={0,0,127})); + connect(rep.y, setPumHeaWatPriDed.u3) + annotation (Line(points={{-38,-20},{-20,-20},{-20,-68},{108,-68}},color={0,0,127})); + connect(zer.y, setPumHeaWatPriHdr.u3) + annotation (Line(points={{-88,-80},{-70,-80},{-70,92},{108,92}},color={0,0,127})); + connect(spePumChiWatPri.y, setPumChiWatPriHdr.u1) + annotation (Line(points={{-88,-120},{-80,-120},{-80,68},{108,68}},color={0,0,127})); + connect(u1PumChiWatPri, anyPumChiWatPri.u) + annotation (Line(points={{-160,0},{-112,0}},color={255,0,255})); + connect(u1PumHeaWatPri, anyPumHeaWatPri.u) + annotation (Line(points={{-160,60},{-136,60},{-136,60},{-112,60}},color={255,0,255})); + connect(anyPumHeaWatPri.y, setPumHeaWatPriHdr.u2) + annotation (Line(points={{-88,60},{60,60},{60,100},{108,100}},color={255,0,255})); + connect(spePumHeaWatPri.y, setPumHeaWatPriHdr.u1) + annotation (Line(points={{-88,120},{40,120},{40,108},{108,108}},color={0,0,127})); + connect(anyPumChiWatPri.y, setPumChiWatPriHdr.u2) + annotation (Line(points={{-88,0},{80,0},{80,60},{108,60}},color={255,0,255})); + connect(u1PumHeaWatPri, setPumHeaWatPriDed.u2) + annotation (Line(points={{-160,60},{-120,60},{-120,-60},{108,-60}},color={255,0,255})); + connect(u1Hea, selSpeHea.u2) + annotation (Line(points={{-160,-60},{-132,-60},{-132,-40},{38,-40}},color={255,0,255})); + connect(spePumHeaWatPri.y, rep3.u) + annotation (Line(points={{-88,120},{-84,120},{-84,30},{-62,30}}, + color={0,0,127})); + connect(rep3.y, selSpeHea.u1) + annotation (Line(points={{-38,30},{30,30},{30,-32},{38,-32}},color={0,0,127})); + connect(rep4.y, selSpeHea.u3) + annotation (Line(points={{-8,12},{20,12},{20,-48},{38,-48}},color={0,0,127})); + connect(spePumChiWatPri.y, rep4.u) + annotation (Line(points={{-88,-120},{-80,-120},{-80,12},{-32,12}},color={0,0,127})); + connect(ph.y, setPumHeaWatPriDed.u1) annotation (Line(points={{92,-40},{100,-40}, + {100,-52},{108,-52}}, color={0,0,127})); + connect(selSpeHea.y, ph.u) + annotation (Line(points={{62,-40},{68,-40}}, color={0,0,127})); + annotation ( + defaultComponentName="ctlPumPri", + Icon( + coordinateSystem( + preserveAspectRatio=true, + 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={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + extent={{-140,-140},{140,140}})), + Documentation(info=" +
+When commanded on, the primary HW pumps are commanded at a fixed
+speed yPumHeaWatPriSet
, as determined during the Testing, Adjusting,
+and Balancing phase to provide the design heat pump flow.
+
+When commanded on, the primary pumps are commanded at a fixed
+speed yPumHeaWatPriSet
in heating mode or
+yPumChiWatPriSet
in cooling mode, as determined during the
+Testing, Adjusting, and Balancing phase to provide the design heat pump flow
+in heating mode or cooling mode.
+
+When commanded on, the primary HW pumps are commanded at a fixed
+speed yPumHeaWatPriSet
.
+When commanded on, the primary CHW pumps are commanded at a fixed
+speed yPumChiWatPriSet
.
+The pump speed yPumHeaWatPriSet
or yPumChiWatPriSet
+is determined during the Testing, Adjusting, and Balancing phase to provide
+the design heat pump flow in heating mode or cooling mode.
+
+This package contains control sequences for primary pumps. +
+")); +end Primary; diff --git a/Buildings/Templates/Plants/Controls/Pumps/Primary/package.order b/Buildings/Templates/Plants/Controls/Pumps/Primary/package.order new file mode 100644 index 00000000000..f1ce062b461 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/Primary/package.order @@ -0,0 +1,3 @@ +EnableLeadHeadered +VariableSpeedNoDpControl +Validation diff --git a/Buildings/Templates/Plants/Controls/Pumps/package.mo b/Buildings/Templates/Plants/Controls/Pumps/package.mo new file mode 100644 index 00000000000..c0a653e65ea --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/package.mo @@ -0,0 +1,43 @@ +within Buildings.Templates.Plants.Controls; +package Pumps "Package of sequences for primary and secondary pumps" + 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), + 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)}), Documentation(info=" ++This package contains control sequences for HW and CHW pumps. +
+")); +end Pumps; diff --git a/Buildings/Templates/Plants/Controls/Pumps/package.order b/Buildings/Templates/Plants/Controls/Pumps/package.order new file mode 100644 index 00000000000..67246907683 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Pumps/package.order @@ -0,0 +1,2 @@ +Generic +Primary diff --git a/Buildings/Templates/Plants/Controls/Setpoints/PlantReset.mo b/Buildings/Templates/Plants/Controls/Setpoints/PlantReset.mo new file mode 100644 index 00000000000..b62059f874e --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Setpoints/PlantReset.mo @@ -0,0 +1,261 @@ +within Buildings.Templates.Plants.Controls.Setpoints; +block PlantReset + "Plant reset logic" + parameter Integer nSenDpRem(final min=1) + "Number of remote loop differential pressure sensors used for pump speed control" + annotation (Evaluate=true); + parameter Real dpSet_max[nSenDpRem]( + each final min=5*6894, + each unit="Pa") + "Maximum differential pressure setpoint"; + parameter Real dpSet_min( + final min=0, + final unit="Pa")=5*6894 + "Minimum value to which the differential pressure can be reset"; + parameter Real TSup_nominal( + final min=273.15, + final unit="K", + displayUnit="degC") + "Design supply temperature"; + parameter Real TSupSetLim( + final min=273.15, + final unit="K", + displayUnit="degC") + "Limit value to which the supply temperature can be reset"; + parameter Real dtHol( + final min=0, + final unit="s")=900 + "Minimum hold time during stage change" + annotation (Dialog(tab="Advanced")); + parameter Real resDp_max( + final max=1, + final min=0, + final unit="1")=0.5 + "Upper limit of plant reset interval for differential pressure reset" + annotation (Dialog(tab="Advanced")); + parameter Real resTSup_min( + final max=1, + final min=0, + final unit="1")=resDp_max + "Lower limit of plant reset interval for supply temperature reset" + annotation (Dialog(tab="Advanced")); + parameter Real res_init( + final max=1, + final min=0, + final unit="1")=1 + "Initial reset value" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real res_min( + final max=1, + final min=0, + final unit="1")=0 + "Minimum reset value" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real res_max( + final max=1, + final min=0, + final unit="1")=1 + "Maximum reset value" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real dtDel( + final min=100*1E-15, + final unit="s")=900 + "Delay time before the reset begins" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real dtRes( + final min=1E-3, + final unit="s")=300 + "Sample period of component" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Integer nReqResIgn(min=0)=2 + "Number of ignored requests" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real tri( + final max=0, + final unit="1")=-0.02 + "Trim amount" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real rsp( + final min=0, + final unit="1")=0.03 + "Respond amount (must have opposite sign of trim amount)" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + parameter Real rsp_max( + final min=0, + final unit="1")=0.07 + "Maximum response per reset period (must have same sign as respond amount)" + annotation (Dialog(tab="Advanced",group="Trim and respond")); + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqRes + "Sum of reset requests of all loads served" + annotation (Placement(transformation(extent={{-200,120},{-160,160}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Ena + "Plant enable" + annotation (Placement(transformation(extent={{-200,80},{-160,120}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1StaPro + "Staging process in progress" + annotation (Placement(transformation(extent={{-200,20},{-160,60}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSet( + final unit="K", + displayUnit="degC") + "Supply temperature setpoint" + annotation (Placement(transformation(extent={{160,-120},{200,-80}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpSet[nSenDpRem]( + each final min=0, + each final unit="Pa") + "Differential pressure setpoint" + annotation (Placement(transformation(extent={{160,-40},{200,0}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond triRes( + final delTim=dtDel, + final iniSet=res_init, + final maxRes=rsp_max, + final maxSet=res_max, + final minSet=res_min, + final numIgnReq=nReqResIgn, + final resAmo=rsp, + final samplePeriod=dtRes, + final triAmo=tri) + "Compute plant reset with trim and respond logic " + annotation (Placement(transformation(extent={{-50,90},{-30,110}}))); + Buildings.Controls.OBC.CDL.Logical.TrueHold truHol( + final duration=dtHol) + "Hold true value of input signal for given time" + annotation (Placement(transformation(extent={{-130,30},{-110,50}}))); + Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler triSam + "Fixed value at stage change" + annotation (Placement(transformation(extent={{-10,90},{10,110}}))); + Buildings.Controls.OBC.CDL.Reals.Switch res + "Switch between actual and fixed value to compute actual reset" + annotation (Placement(transformation(extent={{30,50},{50,70}}))); + Buildings.Controls.OBC.CDL.Reals.Line resTSup + "Supply temperature reset" + annotation (Placement(transformation(extent={{120,-110},{140,-90}}))); + Buildings.Controls.OBC.CDL.Reals.Line resDp[nSenDpRem] + "Differential pressure reset" + annotation (Placement(transformation(extent={{120,-30},{140,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer( + final k=0) + "Constant" + annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant one( + final k=1) + "Constant" + annotation (Placement(transformation(extent={{-10,-130},{10,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant resDpMax( + final k=resDp_max) + "Constant" + annotation (Placement(transformation(extent={{-10,-50},{10,-30}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep( + final nout=nSenDpRem) + "Replicate signal" + annotation (Placement(transformation(extent={{30,-10},{50,10}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep1( + final nout=nSenDpRem) + "Replicate signal" + annotation (Placement(transformation(extent={{70,30},{90,50}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep2( + final nout=nSenDpRem) + "Replicate signal" + annotation (Placement(transformation(extent={{30,-50},{50,-30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpSetMax[nSenDpRem]( + final k=dpSet_max) + "Constant" + annotation (Placement(transformation(extent={{-90,-70},{-70,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant resTSupMin( + final k=resTSup_min) + "Constant" + annotation (Placement(transformation(extent={{-10,-90},{10,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupSetNom( + final k=TSup_nominal) + "Constant" + annotation (Placement(transformation(extent={{-90,-150},{-70,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpSetMin( + final k=dpSet_min) + "Constant" + annotation (Placement(transformation(extent={{-90,10},{-70,30}}))); + Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep3( + final nout=nSenDpRem) + "Replicate signal" + annotation (Placement(transformation(extent={{-50,10},{-30,30}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupSetMinMax(final k= + TSupSetLim) "Constant" + annotation (Placement(transformation(extent={{-90,-110},{-70,-90}}))); +equation + connect(u1StaPro, truHol.u) + annotation (Line(points={{-180,40},{-132,40}},color={255,0,255})); + connect(triRes.y, triSam.u) + annotation (Line(points={{-28,100},{-12,100}},color={0,0,127})); + connect(u1StaPro, triSam.trigger) + annotation (Line(points={{-180,40},{-140,40},{-140,80},{0,80},{0,88}},color={255,0,255})); + connect(truHol.y, res.u2) + annotation (Line(points={{-108,40},{20,40},{20,60},{28,60}},color={255,0,255})); + connect(triSam.y, res.u1) + annotation (Line(points={{12,100},{20,100},{20,68},{28,68}},color={0,0,127})); + connect(triRes.y, res.u3) + annotation (Line(points={{-28,100},{-20,100},{-20,52},{28,52}},color={0,0,127})); + connect(nReqRes, triRes.numOfReq) + annotation (Line(points={{-180,140},{-80,140},{-80,92},{-52,92}},color={255,127,0})); + connect(resTSup.y, TSupSet) + annotation (Line(points={{142,-100},{180,-100}},color={0,0,127})); + connect(resDp.y, dpSet) + annotation (Line(points={{142,-20},{180,-20}},color={0,0,127})); + connect(one.y, resTSup.x2) + annotation (Line(points={{12,-120},{100,-120},{100,-104},{118,-104}},color={0,0,127})); + connect(res.y, resTSup.u) + annotation (Line(points={{52,60},{104,60},{104,-100},{118,-100}},color={0,0,127})); + connect(zer.y, rep.u) + annotation (Line(points={{12,0},{28,0}},color={0,0,127})); + connect(rep.y, resDp.x1) + annotation (Line(points={{52,0},{80,0},{80,-12},{118,-12}},color={0,0,127})); + connect(res.y, rep1.u) + annotation (Line(points={{52,60},{60,60},{60,40},{68,40}},color={0,0,127})); + connect(rep1.y, resDp.u) + annotation (Line(points={{92,40},{100,40},{100,-20},{118,-20}},color={0,0,127})); + connect(rep2.y, resDp.x2) + annotation (Line(points={{52,-40},{80,-40},{80,-24},{118,-24}},color={0,0,127})); + connect(dpSetMax.y, resDp.f2) + annotation (Line(points={{-68,-60},{100,-60},{100,-28},{118,-28}},color={0,0,127})); + connect(TSupSetNom.y, resTSup.f2) + annotation (Line(points={{-68,-140},{104,-140},{104,-108},{118,-108}},color={0,0,127})); + connect(dpSetMin.y, rep3.u) + annotation (Line(points={{-68,20},{-52,20}},color={0,0,127})); + connect(rep3.y, resDp.f1) + annotation (Line(points={{-28,20},{76,20},{76,-16},{118,-16}},color={0,0,127})); + connect(TSupSetMinMax.y, resTSup.f1) + annotation (Line(points={{-68,-100},{80,-100},{80,-96},{118,-96}},color={0,0,127})); + connect(resTSupMin.y, resTSup.x1) + annotation (Line(points={{12,-80},{80,-80},{80,-92},{118,-92}},color={0,0,127})); + connect(resDpMax.y, rep2.u) + annotation (Line(points={{12,-40},{28,-40}},color={0,0,127})); + connect(u1Ena, triRes.uDevSta) annotation (Line(points={{-180,100},{-60,100}, + {-60,108},{-52,108}}, color={255,0,255})); + annotation ( + defaultComponentName="res", + Icon( + graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + extent={{-160,-160},{160,160}})), + Documentation(info=" +", revisions=" ++This model validates + +Buildings.Templates.Plants.Controls.Setpoints.PlantReset. +
+", + revisions=" ++This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/Setpoints/Validation/package.order b/Buildings/Templates/Plants/Controls/Setpoints/Validation/package.order new file mode 100644 index 00000000000..f8522085d40 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Setpoints/Validation/package.order @@ -0,0 +1 @@ +PlantReset diff --git a/Buildings/Templates/Plants/Controls/Setpoints/package.mo b/Buildings/Templates/Plants/Controls/Setpoints/package.mo new file mode 100644 index 00000000000..8e7dcd0d270 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Setpoints/package.mo @@ -0,0 +1,27 @@ +within Buildings.Templates.Plants.Controls; +package Setpoints "Plant reset logic" + annotation ( + preferredView="info", + Documentation( + info=" ++This package contains plant reset 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), + Text( + extent={{-100,100},{100,-100}}, + textColor={0,0,0}, + textString="S")})); +end Setpoints; diff --git a/Buildings/Templates/Plants/Controls/Setpoints/package.order b/Buildings/Templates/Plants/Controls/Setpoints/package.order new file mode 100644 index 00000000000..e6f148a661f --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Setpoints/package.order @@ -0,0 +1,2 @@ +PlantReset +Validation diff --git a/Buildings/Templates/Plants/Controls/StagingRotation/EquipmentAvailability.mo b/Buildings/Templates/Plants/Controls/StagingRotation/EquipmentAvailability.mo new file mode 100644 index 00000000000..c22062208e8 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/StagingRotation/EquipmentAvailability.mo @@ -0,0 +1,239 @@ +within Buildings.Templates.Plants.Controls.StagingRotation; +block EquipmentAvailability + "Equipment availability for heating and cooling applications" + parameter Boolean have_heaWat + "Set to true for plants that provide HW" + annotation (Evaluate=true); + parameter Boolean have_chiWat + "Set to true for plants that provide CHW" + annotation (Evaluate=true); + parameter Real dtOff( + final min=0, + final unit="s")=900 + "Off time required before equipment is deemed available again"; + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1 + "Equipment enable command" + annotation (Placement(transformation(extent={{-240,-20},{-200,20}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Hea + if have_heaWat + "Equipment available for heating" + annotation (Placement(transformation(extent={{200,-20},{240,20}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea + if have_heaWat and have_chiWat + "Equipment operating mode command" + annotation (Placement(transformation(extent={{-240,-140},{-200,-100}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Coo + if have_chiWat + "Equipment available for cooling" + annotation (Placement(transformation(extent={{200,-140},{240,-100}}), + iconTransformation(extent={{100,-80},{140,-40}}))); + Buildings.Controls.OBC.CDL.Logical.And onAndHea + "Return true if equipment on and in heating mode" + annotation (Placement(transformation(extent={{-110,-150},{-90,-130}}))); + Buildings.Controls.OBC.CDL.Logical.And onAndCoo + "Return true if equipment on and in cooling mode" + annotation (Placement(transformation(extent={{-110,-10},{-90,10}}))); + Buildings.Controls.OBC.CDL.Logical.Not coo + "Return true if equipment in cooling mode" + annotation (Placement(transformation(extent={{-150,-110},{-130,-90}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Ava + "Equipment available signal" + annotation (Placement(transformation(extent={{-240,-80},{-200,-40}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Utilities.PlaceholderLogical phHea(final have_inp=have_heaWat and have_chiWat, + final u_internal=have_heaWat or not have_chiWat) + "Placeholder value if signal is not available" + annotation (Placement(transformation(extent={{-190,-130},{-170,-110}}))); + Buildings.Controls.OBC.CDL.Logical.Not off + "Return true if equipment is off" + annotation (Placement(transformation(extent={{-150,-50},{-130,-30}}))); + inner Modelica.StateGraph.StateGraphRoot stateGraphRoot + annotation (Placement(transformation(extent={{-160,160},{-140,180}}))); + Modelica.StateGraph.StepWithSignal onHea( + nOut=2, + nIn=1) + annotation (Placement(transformation(extent={{10,150},{30,170}}))); + Modelica.StateGraph.InitialStepWithSignal avaMod( + nOut=3, + nIn=2) + "Initial state – Equipment available for all modes" + annotation (Placement(transformation(extent={{-70,150},{-50,170}}))); + Modelica.StateGraph.TransitionWithSignal trnToOff + "Transition to off state" + annotation (Placement(transformation(extent={{50,150},{70,170}}))); + Modelica.StateGraph.StepWithSignal onCoo( + nOut=2, + nIn=1) + annotation (Placement(transformation(extent={{70,110},{90,130}}))); + Modelica.StateGraph.TransitionWithSignal trnToCoo + "Transition to cooling mode" + annotation (Placement(transformation(extent={{-10,110},{10,130}}))); + Modelica.StateGraph.TransitionWithSignal trnToHea + "Transition to heating mode" + annotation (Placement(transformation(extent={{-30,150},{-10,170}}))); + Modelica.StateGraph.TransitionWithSignal trnToOff1 + "Transition to off state" + annotation (Placement(transformation(extent={{110,110},{130,130}}))); + Buildings.Controls.OBC.CDL.Logical.Or avaAllHea + "Return true if equipment available for all modes or in heating mode" + annotation (Placement(transformation(extent={{150,-10},{170,10}}))); + Buildings.Controls.OBC.CDL.Logical.Or avaAllCoo + "Return true if equipment available for all modes or in cooling mode" + annotation (Placement(transformation(extent={{170,-130},{190,-110}}))); + Modelica.StateGraph.Step offSta( + nOut=1, + nIn=2) + "Off state" + annotation (Placement(transformation(extent={{140,130},{160,150}}))); + Modelica.StateGraph.Transition trnToAvaTim( + enableTimer=true, + final waitTime=dtOff) + "Transition back to available state after off time elapsed" + annotation (Placement(transformation(extent={{160,170},{140,190}}))); + Modelica.StateGraph.Step unaSta( + nOut=1, + nIn=3) + "Unavailable state" + annotation (Placement(transformation(extent={{140,90},{160,110}}))); + Modelica.StateGraph.TransitionWithSignal trnToUna + "Transition to unavailable state" + annotation (Placement(transformation(extent={{-36,70},{-16,90}}))); + Buildings.Controls.OBC.CDL.Logical.Not una + "Return true if equipment is unavailable" + annotation (Placement(transformation(extent={{-110,-90},{-90,-70}}))); + Modelica.StateGraph.TransitionWithSignal trnToAva + "Transition back to available state" + annotation (Placement(transformation(extent={{170,90},{190,110}}))); + Modelica.StateGraph.TransitionWithSignal trnToUna2 + "Transition to unavailable state" + annotation (Placement(transformation(extent={{30,90},{50,110}}))); + Modelica.StateGraph.TransitionWithSignal trnToUna3 + "Transition to unavailable state" + annotation (Placement(transformation(extent={{90,70},{110,90}}))); +equation + connect(coo.y, onAndCoo.u2) + annotation (Line(points={{-128,-100},{-116,-100},{-116,-8},{-112,-8}},color={255,0,255})); + connect(u1, onAndHea.u1) + annotation (Line(points={{-220,0},{-120,0},{-120,-140},{-112,-140}},color={255,0,255})); + connect(u1, onAndCoo.u1) + annotation (Line(points={{-220,0},{-112,0}},color={255,0,255})); + connect(u1Hea, phHea.u) + annotation (Line(points={{-220,-120},{-192,-120}}, color={255,0,255})); + connect(phHea.y, onAndHea.u2) annotation (Line(points={{-168,-120},{-140,-120}, + {-140,-148},{-112,-148}}, color={255,0,255})); + connect(phHea.y, coo.u) annotation (Line(points={{-168,-120},{-160,-120},{-160, + -100},{-152,-100}}, color={255,0,255})); + connect(u1, off.u) + annotation (Line(points={{-220,0},{-160,0},{-160,-40},{-152,-40}},color={255,0,255})); + connect(avaMod.outPort[1], trnToCoo.inPort) + annotation (Line(points={{-49.5,159.833},{-40,159.833},{-40,120},{-4,120}}, + color={0,0,0})); + connect(onAndCoo.y, trnToCoo.condition) + annotation (Line(points={{-88,0},{-80,0},{-80,40},{0,40},{0,108}},color={255,0,255})); + connect(onHea.outPort[1], trnToOff.inPort) + annotation (Line(points={{30.5,159.875},{44,159.875},{44,160},{56,160}}, + color={0,0,0})); + connect(off.y, trnToOff.condition) + annotation (Line(points={{-128,-40},{60,-40},{60,148}},color={255,0,255})); + connect(onCoo.outPort[1], trnToOff1.inPort) + annotation (Line(points={{90.5,119.875},{104,119.875},{104,120},{116,120}}, + color={0,0,0})); + connect(trnToCoo.outPort, onCoo.inPort[1]) + annotation (Line(points={{1.5,120},{69,120}},color={0,0,0})); + connect(onAndHea.y, trnToHea.condition) + annotation (Line(points={{-88,-140},{-20,-140},{-20,148}},color={255,0,255})); + connect(avaMod.outPort[2], trnToHea.inPort) + annotation (Line(points={{-49.5,160},{-24,160}},color={0,0,0})); + connect(avaMod.active, avaAllHea.u1) + annotation (Line(points={{-60,149},{-60,0},{148,0}},color={255,0,255})); + connect(onHea.active, avaAllHea.u2) + annotation (Line(points={{20,149},{20,-8},{148,-8}},color={255,0,255})); + connect(avaAllHea.y, y1Hea) + annotation (Line(points={{172,0},{220,0}},color={255,0,255})); + connect(avaAllCoo.y, y1Coo) + annotation (Line(points={{192,-120},{220,-120}},color={255,0,255})); + connect(off.y, trnToOff1.condition) + annotation (Line(points={{-128,-40},{120,-40},{120,108}},color={255,0,255})); + connect(trnToHea.outPort, onHea.inPort[1]) + annotation (Line(points={{-18.5,160},{9,160}},color={0,0,0})); + connect(offSta.outPort[1], trnToAvaTim.inPort) + annotation (Line(points={{160.5,140},{170,140},{170,180},{154,180}},color={0,0,0})); + connect(trnToOff.outPort, offSta.inPort[1]) + annotation (Line(points={{61.5,160},{130,160},{130,139.75},{139,139.75}}, + color={0,0,0})); + connect(trnToOff1.outPort, offSta.inPort[2]) + annotation (Line(points={{121.5,120},{130,120},{130,140},{134,140},{134,140.25},{139,140.25}}, + color={0,0,0})); + connect(trnToAvaTim.outPort, avaMod.inPort[1]) + annotation (Line(points={{148.5,180},{-80,180},{-80,159.75},{-71,159.75}}, + color={0,0,0})); + connect(u1Ava, una.u) + annotation (Line(points={{-220,-60},{-140,-60},{-140,-80},{-112,-80}},color={255,0,255})); + connect(avaMod.outPort[3], trnToUna.inPort) + annotation (Line(points={{-49.5,160.167},{-49.5,160},{-40,160},{-40,80},{ + -30,80}}, + color={0,0,0})); + connect(una.y, trnToUna.condition) + annotation (Line(points={{-88,-80},{-26,-80},{-26,68}},color={255,0,255})); + connect(trnToUna.outPort, unaSta.inPort[1]) + annotation (Line(points={{-24.5,80},{50,80},{50,99.6667},{139,99.6667}}, + color={0,0,0})); + connect(unaSta.outPort[1], trnToAva.inPort) + annotation (Line(points={{160.5,100},{176,100}},color={0,0,0})); + connect(u1Ava, trnToAva.condition) + annotation (Line(points={{-220,-60},{180,-60},{180,88}},color={255,0,255})); + connect(trnToAva.outPort, avaMod.inPort[2]) + annotation (Line(points={{181.5,100},{190,100},{190,190},{-90,190},{-90,160.25},{-71,160.25}}, + color={0,0,0})); + connect(avaMod.active, avaAllCoo.u1) + annotation (Line(points={{-60,149},{-60,-120},{168,-120}},color={255,0,255})); + connect(onCoo.active, avaAllCoo.u2) + annotation (Line(points={{80,109},{80,-128},{168,-128}},color={255,0,255})); + connect(onHea.outPort[2], trnToUna2.inPort) + annotation (Line(points={{30.5,160.125},{32,160.125},{32,100},{36,100}}, + color={0,0,0})); + connect(trnToUna2.outPort, unaSta.inPort[2]) + annotation (Line(points={{41.5,100},{90,100},{90,100},{139,100}},color={0,0,0})); + connect(una.y, trnToUna2.condition) + annotation (Line(points={{-88,-80},{40,-80},{40,88}},color={255,0,255})); + connect(onCoo.outPort[2], trnToUna3.inPort) + annotation (Line(points={{90.5,120.125},{92,120.125},{92,80},{96,80}},color={0,0,0})); + connect(trnToUna3.outPort, unaSta.inPort[3]) + annotation (Line(points={{101.5,80},{130,80},{130,100.333},{139,100.333}}, + color={0,0,0})); + connect(una.y, trnToUna3.condition) + annotation (Line(points={{-88,-80},{100,-80},{100,68}},color={255,0,255})); + annotation ( + __cdl( + extensionBlock=true), + defaultComponentName="avaHeaCoo", + Icon( + coordinateSystem( + preserveAspectRatio=true, + 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={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + preserveAspectRatio=false, + extent={{-200,-200},{200,200}})), + Documentation( + info=" +
+If a heat pump is commanded enabled in either heating or cooling mode,
+it is removed from the staging order of the opposite mode until it has
+been off for dtOff
.
+
+This block generates the equipment enable commands based on the
+active stage index uSta
, the equipment available
+signal u1Ava
and the indices of lead/lag alternate
+equipment, sorted by increasing staging runtime.
+
+A staging matrix staEqu
is required as a parameter.
+
staEqu[i, j]
equal to 0
+means that equipment j
shall not be enabled at
+stage i
.staEqu[i, j]
equal to 1
+means that equipment j
is required at stage i
.
+If equipment j
is unavailable, stage i
is
+deemed unavailable.
+staEqu[i, j]
strictly lower than 1
+and strictly greater than 0 means that equipment j
+may be enabled at stage i
as a lead/lag alternate equipment.
+If equipment j
is unavailable but another lead/lag alternate
+equipment is available, then the latter equipment is enabled.
+Stage i
is only deemed unavailable if all
+lead/lag alternate equipment specified for stage i
+are unavailable.
+∑_j staEqu[i, j]
+gives the number of equipment required at stage i
.
+If this number cannot be achieved with the available equipment,
+stage i
is deemed unavailable.
+∑_j staEqu[i+1, j] ≥ ∑_j staEqu[i, j]
+is required for all i < size(staEqu, 1)
.
++The state of the enable signals is only updated at stage change, or +if the number of previously enabled equipment that is available is +strictly less than the number of equipment required to run. +This avoids hot swapping equipment, e.g., an equipment would not be started +and another stopped during operation just to fulfill the priority order. +However, when a lead/lag alternate equipment becomes unavailable and another +lead/lag alternate equipment can be enabled to meet the number of required +equipment, then the state of the enable signals is updated. +
+")); +end EquipmentEnable; diff --git a/Buildings/Templates/Plants/Controls/StagingRotation/EventSequencing.mo b/Buildings/Templates/Plants/Controls/StagingRotation/EventSequencing.mo new file mode 100644 index 00000000000..33aeb99a775 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/StagingRotation/EventSequencing.mo @@ -0,0 +1,405 @@ +within Buildings.Templates.Plants.Controls.StagingRotation; +block EventSequencing "Staging event sequencing" + parameter Boolean have_heaWat + "Set to true for plants that provide HW" + annotation (Evaluate=true); + parameter Boolean have_chiWat + "Set to true for plants that provide CHW" + annotation (Evaluate=true); + parameter Boolean have_valInlIso + "Set to true if the system as inlet isolation valves" + annotation (Evaluate=true); + parameter Boolean have_valOutIso + "Set to true if the system as outlet isolation valves" + annotation (Evaluate=true); + parameter Boolean have_pumHeaWatPri(start=false) + "Set to true for plants with primary HW pumps" + annotation (Evaluate=true, + Dialog(enable=have_heaWat)); + parameter Boolean have_pumChiWatPri( + start=false) + "Set to true for plants with separate primary CHW pumps" + annotation (Evaluate=true, + Dialog(enable=have_chiWat)); + parameter Boolean have_pumHeaWatSec(start=false) + "Set to true for plants with secondary HW pumps" + annotation (Evaluate=true, + Dialog(enable=have_heaWat)); + parameter Boolean have_pumChiWatSec(start=false) + "Set to true for plants with secondary CHW pumps" + annotation (Evaluate=true, + Dialog(enable=have_chiWat)); + parameter Real dtVal( + min=0, + start=90, + unit="s")=90 + "Nominal valve timing" + annotation (Dialog(enable=have_valInlIso or have_valOutIso)); + parameter Real dtOff( + min=0, + unit="s") = 180 + "Heat pump internal shutdown cycle timing"; + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea + if have_heaWat + "Enable command from heating mode sequence" + annotation (Placement(transformation(extent={{-200,120},{-160,160}}), + iconTransformation(extent={{-140,100},{-100,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatPri_actual + if have_heaWat and have_pumHeaWatPri + "Primary HW pump status (dedicated or lead headered pump)" + annotation (Placement(transformation(extent={{-200,-30},{-160,10}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatPri_actual + if have_chiWat and have_pumChiWatPri + "Primary CHW pump status – Dedicated or lead headered pump" + annotation (Placement(transformation(extent={{-200,-70},{-160,-30}}), + iconTransformation(extent={{-140,-40},{-100,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatSec_actual + if have_heaWat and have_pumHeaWatSec + "Lead headered secondary HW pump status" + annotation (Placement(transformation(extent={{-200,-110},{-160,-70}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatSec_actual + if have_chiWat and have_pumChiWatSec + "Lead headered secondary CHW pump status" + annotation (Placement(transformation(extent={{-200,-150},{-160,-110}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValHeaWatInlIso + if have_heaWat and have_valInlIso + "Inlet HW inlet isolation valve command" + annotation (Placement(transformation(extent={{160,20},{200,60}}), + iconTransformation(extent={{100,0},{140,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValHeaWatOutIso + if have_heaWat and have_valOutIso + "Outlet HW isolation valve command" + annotation (Placement(transformation(extent={{160,0},{200,40}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValChiWatInlIso + if have_chiWat and have_valInlIso + "Inlet CHW isolation valve command" + annotation (Placement(transformation(extent={{160,-20},{200,20}}), + iconTransformation(extent={{100,-40},{140,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValChiWatOutIso + if have_chiWat and have_valOutIso + "Outlet CHW isolation valve command" + annotation (Placement(transformation(extent={{160,-40},{200,0}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWatPri + if have_heaWat and have_pumHeaWatPri + "Primary HW pump start command – Dedicated or lead headered pump" + annotation (Placement(transformation(extent={{160,-80},{200,-40}}), + iconTransformation(extent={{100,-100},{140,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWatPri + if have_chiWat and have_pumChiWatPri + "Primary CHW pump start command – Dedicated or lead headered pump" + annotation (Placement(transformation(extent={{160,-120},{200,-80}}), + iconTransformation(extent={{100,-120},{140,-80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1 + "Equipment enable command" + annotation (Placement(transformation(extent={{160,120},{200,160}}), + iconTransformation(extent={{100,100},{140,140}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Hea + if have_heaWat and have_chiWat + "Heating/cooling mode command: true=heating, false=cooling" + annotation (Placement(transformation(extent={{160,100},{200,140}}), + iconTransformation(extent={{100,80},{140,120}}))); + Buildings.Controls.OBC.CDL.Logical.Timer timVal( + final t=dtVal) + "Return true when nominal valve timing elapsed" + annotation (Placement(transformation(extent={{-50,90},{-30,110}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd heaValPum( + nin=3) + "Return true if heating AND valve timing elapsed AND lead HW pumps on" + annotation (Placement(transformation(extent={{60,110},{80,130}}))); + Buildings.Controls.OBC.CDL.Logical.Or ena + "Return true if enabled" + annotation (Placement(transformation(extent={{90,90},{110,110}}))); + Buildings.Controls.OBC.CDL.Logical.MultiAnd cooValPum( + nin=4) + "Return true if cooling AND valve timing elapsed AND lead CHW pumps on" + annotation (Placement(transformation(extent={{60,70},{80,90}}))); + Utilities.PlaceholderLogical u1PumChiWatSec_internal( + final have_inp=have_chiWat and have_pumChiWatSec, + final have_inpPh=false, + final u_internal=true) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-150,-140},{-130,-120}}))); + Utilities.PlaceholderLogical timVal_internal( + final have_inp=have_valInlIso or have_valOutIso, + final have_inpPh=true, + final u_internal=true) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-10,90},{10,110}}))); + Utilities.PlaceholderLogical u1PumHeaWatSec_internal( + final have_inp=have_heaWat and have_pumHeaWatSec, + final have_inpPh=false, + final u_internal=true) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-150,-100},{-130,-80}}))); + Utilities.PlaceholderLogical u1PumChiWatPri_internal( + final have_inp=have_chiWat and have_pumChiWatPri, + final have_inpPh=false, + final u_internal=true) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-150,-60},{-130,-40}}))); + Utilities.PlaceholderLogical u1PumHeaWatPri_internal( + final have_inp=have_heaWat and have_pumHeaWatPri, + final have_inpPh=false, + final u_internal=true) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-150,-20},{-130,0}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Coo + if have_chiWat + "Enable command from cooling mode sequence" + annotation (Placement(transformation(extent={{-200,60},{-160,100}}), + iconTransformation(extent={{-140,60},{-100,100}}))); + Utilities.PlaceholderLogical u1Coo_internal( + final have_inp=have_chiWat, + final have_inpPh=false, + final u_internal=false) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-150,70},{-130,90}}))); + Buildings.Controls.OBC.CDL.Logical.Or u1HeaOrCoo + "Return true if enabled from heating or cooling mode sequence" + annotation (Placement(transformation(extent={{-90,110},{-70,130}}))); + Utilities.PlaceholderLogical u1Hea_internal( + final have_inp=have_heaWat, + final have_inpPh=false, + final u_internal=false) + "Replace with placeholder value if input signal is not available" + annotation (Placement(transformation(extent={{-150,130},{-130,150}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1AndHea + if have_heaWat + "Equipment commanded on in heating mode" + annotation (Placement(transformation(extent={{160,80},{200,120}}), + iconTransformation(extent={{100,60},{140,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1AndCoo + if have_chiWat + "Equipment commanded on in cooling mode" + annotation (Placement(transformation(extent={{160,60},{200,100}}), + iconTransformation(extent={{100,40},{140,80}}))); + Buildings.Controls.OBC.CDL.Logical.And enaAndHea + "Return true if enabled in heating mode" + annotation (Placement(transformation(extent={{130,90},{150,110}}))); + Buildings.Controls.OBC.CDL.Logical.And enaAndCoo + "Return true if enabled in cooling mode" + annotation (Placement(transformation(extent={{130,60},{150,80}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rou( + final nout=1) + if have_pumChiWatPri + "Signal routing for plants with dedicated primary CHW pumps" + annotation (Placement(transformation(extent={{60,-76},{80,-56}}))); + Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rou1( + final nout=1) + if not have_pumChiWatPri + "Signal routing for plants without dedicated primary CHW pumps" + annotation (Placement(transformation(extent={{60,-50},{80,-30}}))); + Buildings.Controls.OBC.CDL.Logical.Nor off + "Return true if disabled from heating and cooling mode sequence" + annotation (Placement(transformation(extent={{-52,10},{-32,30}}))); + Buildings.Controls.OBC.CDL.Logical.Timer timHp(final t=dtOff) + "Return true when heat pump internal shutdown cycle times out" + annotation (Placement(transformation(extent={{-10,10},{10,30}}))); + Buildings.Controls.OBC.CDL.Logical.Latch latValHeaWatIso + if have_heaWat + "Keep valve open until heat pump internal shutdown cycle times out" + annotation (Placement(transformation(extent={{100,30},{120,50}}))); + Buildings.Controls.OBC.CDL.Logical.Latch latValChiWatIso + if have_chiWat + "Keep valve open until heat pump internal shutdown cycle times out" + annotation (Placement(transformation(extent={{100,-10},{120,10}}))); + Buildings.Controls.OBC.CDL.Logical.Latch latPumHeaWatPri + if have_heaWat + "Keep pump running until heat pump internal shutdown cycle times out" + annotation (Placement(transformation(extent={{110,-70},{130,-50}}))); + Buildings.Controls.OBC.CDL.Logical.Latch latPumChiWatPri + if have_chiWat and have_pumChiWatPri + "Keep pump running until heat pump internal shutdown cycle times out" + annotation (Placement(transformation(extent={{110,-110},{130,-90}}))); +equation + connect(heaValPum.y, ena.u1) + annotation (Line(points={{82,120},{84,120},{84,100},{88,100}},color={255,0,255})); + connect(cooValPum.y, ena.u2) + annotation (Line(points={{82,80},{84,80},{84,92},{88,92}},color={255,0,255})); + connect(timVal.passed, timVal_internal.u) + annotation (Line(points={{-28,92},{-16,92},{-16,100},{-12,100}},color={255,0,255})); + connect(timVal_internal.y, heaValPum.u[1]) + annotation (Line(points={{12,100},{52,100},{52,117.667},{58,117.667}},color={255,0,255})); + connect(u1PumChiWatSec_actual, u1PumChiWatSec_internal.u) + annotation (Line(points={{-180,-130},{-152,-130}},color={255,0,255})); + connect(u1PumHeaWatPri_actual, u1PumHeaWatPri_internal.u) + annotation (Line(points={{-180,-10},{-152,-10}},color={255,0,255})); + connect(u1PumChiWatPri_actual, u1PumChiWatPri_internal.u) + annotation (Line(points={{-180,-50},{-152,-50}},color={255,0,255})); + connect(u1PumHeaWatSec_actual, u1PumHeaWatSec_internal.u) + annotation (Line(points={{-180,-90},{-152,-90}},color={255,0,255})); + connect(u1PumHeaWatPri_internal.y, heaValPum.u[2]) + annotation (Line(points={{-128,-10},{46,-10},{46,120},{58,120}},color={255,0,255})); + connect(u1PumHeaWatSec_internal.y, heaValPum.u[3]) + annotation (Line(points={{-128,-90},{50,-90},{50,122},{56,122},{56,122.333}, + {58,122.333}}, + color={255,0,255})); + connect(timVal_internal.y, cooValPum.u[1]) + annotation (Line(points={{12,100},{48,100},{48,77.375},{58,77.375}},color={255,0,255})); + connect(u1PumChiWatPri_internal.y, cooValPum.u[2]) + annotation (Line(points={{-128,-50},{48,-50},{48,79.125},{58,79.125}},color={255,0,255})); + connect(u1PumChiWatSec_internal.y, cooValPum.u[3]) + annotation (Line(points={{-128,-130},{52,-130},{52,80.875},{58,80.875}}, + color={255,0,255})); + connect(ena.y, y1) + annotation (Line(points={{112,100},{124,100},{124,140},{180,140}},color={255,0,255})); + connect(u1Hea, u1Hea_internal.u) + annotation (Line(points={{-180,140},{-152,140}},color={255,0,255})); + connect(u1Coo_internal.y, u1HeaOrCoo.u2) + annotation (Line(points={{-128,80},{-100,80},{-100,112},{-92,112}},color={255,0,255})); + connect(u1Hea_internal.y, u1HeaOrCoo.u1) + annotation (Line(points={{-128,140},{-120,140},{-120,120},{-92,120}},color={255,0,255})); + connect(u1HeaOrCoo.y, timVal.u) + annotation (Line(points={{-68,120},{-60,120},{-60,100},{-52,100}},color={255,0,255})); + connect(u1HeaOrCoo.y, timVal_internal.uPh) annotation (Line(points={{-68,120}, + {-20,120},{-20,94},{-12,94}}, color={255,0,255})); + connect(u1Coo, u1Coo_internal.u) + annotation (Line(points={{-180,80},{-152,80}},color={255,0,255})); + connect(u1Coo_internal.y, cooValPum.u[4]) + annotation (Line(points={{-128,80},{58,80},{58,82.625}},color={255,0,255})); + connect(u1Hea_internal.y, y1Hea) + annotation (Line(points={{-128,140},{120,140},{120,120},{180,120}},color={255,0,255})); + connect(ena.y, enaAndHea.u1) + annotation (Line(points={{112,100},{128,100}},color={255,0,255})); + connect(u1Hea_internal.y, enaAndHea.u2) + annotation (Line(points={{-128,140},{120,140},{120,92},{128,92}},color={255,0,255})); + connect(enaAndHea.y, y1AndHea) + annotation (Line(points={{152,100},{180,100}},color={255,0,255})); + connect(ena.y, enaAndCoo.u1) + annotation (Line(points={{112,100},{124,100},{124,70},{128,70}},color={255,0,255})); + connect(u1Coo_internal.y, enaAndCoo.u2) + annotation (Line(points={{-128,80},{-100,80},{-100,48},{60,48},{60,62},{128,62}}, + color={255,0,255})); + connect(enaAndCoo.y, y1AndCoo) + annotation (Line(points={{152,70},{156,70},{156,80},{180,80}},color={255,0,255})); + connect(u1Hea_internal.y, rou.u) + annotation (Line(points={{-128,140},{-120,140},{-120,-66},{58,-66}},color={255,0,255})); + connect(u1HeaOrCoo.y, rou1.u) + annotation (Line(points={{-68,120},{44,120},{44,-40},{58,-40}}, color={255,0,255})); + connect(u1Hea_internal.y, off.u1) + annotation (Line(points={{-128,140},{-120,140},{-120,20},{-54,20}},color={255,0,255})); + connect(u1Coo_internal.y, off.u2) + annotation (Line(points={{-128,80},{-100,80},{-100,12},{-54,12}},color={255,0,255})); + connect(off.y, timHp.u) + annotation (Line(points={{-30,20},{-12,20}},color={255,0,255})); + connect(timHp.passed, latValHeaWatIso.clr) + annotation (Line(points={{12,12},{40,12},{40,34},{98,34}}, color={255,0,255})); + connect(latValHeaWatIso.y, y1ValHeaWatInlIso) + annotation (Line(points={{122,40},{180,40}},color={255,0,255})); + connect(u1Hea_internal.y, latValHeaWatIso.u) + annotation (Line(points={{-128,140},{-120,140},{-120,40},{98,40}},color={255,0,255})); + connect(latValChiWatIso.y, y1ValChiWatInlIso) + annotation (Line(points={{122,0},{180,0}},color={255,0,255})); + connect(timHp.passed, latValChiWatIso.clr) + annotation (Line(points={{12,12},{40,12},{40,-6},{98,-6}}, color={255,0,255})); + connect(latValHeaWatIso.y, y1ValHeaWatOutIso) + annotation (Line(points={{122,40},{140,40},{140,20},{180,20}},color={255,0,255})); + connect(latValChiWatIso.y, y1ValChiWatOutIso) + annotation (Line(points={{122,0},{140,0},{140,-20},{180,-20}},color={255,0,255})); + connect(rou1.y[1], latPumHeaWatPri.u) + annotation (Line(points={{82,-40},{90,-40},{90,-60},{108,-60}}, + color={255,0,255})); + connect(rou.y[1], latPumHeaWatPri.u) + annotation (Line(points={{82,-66},{90,-66},{90,-60},{108,-60}}, + color={255,0,255})); + connect(timHp.passed, latPumHeaWatPri.clr) + annotation (Line(points={{12,12},{40,12},{40,-20},{100,-20},{100,-66},{108, + -66}}, + color={255,0,255})); + connect(latPumHeaWatPri.y, y1PumHeaWatPri) + annotation (Line(points={{132,-60},{180,-60}}, color={255,0,255})); + connect(latPumChiWatPri.y, y1PumChiWatPri) + annotation (Line(points={{132,-100},{180,-100}}, + color={255,0,255})); + connect(timHp.passed, latPumChiWatPri.clr) + annotation (Line(points={{12,12},{40,12},{40,-106},{108,-106}}, + color={255,0,255})); + connect(u1Coo_internal.y, latPumChiWatPri.u) + annotation (Line(points={{-128,80},{-100,80},{-100,-100},{108,-100}}, + color={255,0,255})); + connect(u1Coo_internal.y, latValChiWatIso.u) + annotation (Line(points={{-128,80},{-100,80},{-100,0},{98,0}},color={255,0,255})); + annotation ( + defaultComponentName="seqEve", + Icon( + coordinateSystem( + preserveAspectRatio=true, + extent={{-100,-140},{100,140}}), + graphics={ + Rectangle( + extent={{-100,140},{100,-142}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-150,190},{150,150}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + extent={{-160,-160},{160,160}})), + Documentation( + info=" ++If a heat pump is commanded on in a desired heating or cooling mode: +
+dtVal
)
+and the lead pumps are proven on, the heat pump is enabled in heating or cooling
+mode.
++If a heat pump is commanded off: +
+dtOff
to be determined empirically, defaulting to 3 min),
+all isolation valves are commanded closed.
++This block implements the rotation logic for identical parallel +staged equipment that are lead/lag alternated. +
++Two runtime points are defined for each equipment. +The Lifetime Runtime is the cumulative runtime of the equipment +since equipment start-up. This point is not readily resettable by operators. +Lifetime Runtime should be stored to a software point on the control +system server so the recorded value is not lost due to controller reset, +loss of power, programming file update, etc. +The Staging Runtime is an operator resettable runtime point that stores +cumulative runtime since the last operator reset. +
++In the case of available equipment, +when more than one equipment is off or more than one is on, +the equipment with the most operating hours as determined by +Staging Runtime is made the last stage equipment and the one +with the least number of hours is made the lead stage equipment. +
++In the case of unavailable equipment, +the equipment that alarmed most recently is sent to the last position. +The equipment in alarm automatically moves up in the staging order +only if another equipment goes into alarm. +
+
+When the controller is initialized, the choice of the first equipment to run
+is random since all runtimes are equal to zero.
+So, before this first equipment reports status, all equipment will be
+considered off and only this first equipment will increase runtime and be
+queued in the staging order.
+At next stage change, another equipment will then be staged on instead,
+resulting in the first running equipment being \"hot swapped\".
+To avoid this behavior, the vector parameter runTim_start
is used
+to initialize the staging runtime, which will be fixed at this parameter
+value until it becomes higher.
+The parameter runTim_start
should be set to a vector of
+strictly increasing values, where the minimum value is greater than
+the time needed for the equipment to report status.
+
+The sorting logic is implemented using the following method. +
+
+This is effectively the same as sorting the units within
+the three following subsets: units that are on and available,
+units that are off and available, units that are unavailable.
+In particular, the order index of a given unit remains unchanged
+if it is the only element of a given subset.
+Note that the staging runtime and the time elapsed since an equipment became unavailable
+are both computed from Boolean signals (u1Run
and u1Ava
).
+These are discrete-time, piecewise constant variables,
+which is why the caveat in the documentation of
+
+Buildings.Templates.Plants.Controls.Utilities.SortWithIndices
+for purely continuous time-varying variables does not apply here.
+Therefore, no sampling is performed before sorting the equipment runtimes.
+
+To facilitate integration into the plant controller, the input vectors +cover the full set of equipment, including equipment that may not be +lead/lag alternate. +The output vectors cover only the subset of lead/lag alternate equipment, +and the vector of sorted equipment provides indices with respect +to the input vectors (full set of equipment). +
+", revisions=" ++A stage is deemed available if both the following are true: +
++Otherwise, the stage is deemed unavailable. +
+")); +end StageAvailability; diff --git a/Buildings/Templates/Plants/Controls/StagingRotation/StageChangeCommand.mo b/Buildings/Templates/Plants/Controls/StagingRotation/StageChangeCommand.mo new file mode 100644 index 00000000000..3eef5577daf --- /dev/null +++ b/Buildings/Templates/Plants/Controls/StagingRotation/StageChangeCommand.mo @@ -0,0 +1,458 @@ +within Buildings.Templates.Plants.Controls.StagingRotation; +block StageChangeCommand + "Generate stage change command" + parameter Boolean have_inpPlrSta=false + "Set to true to use an input signal for SPLR, false to use a parameter" + annotation (Evaluate=true); + parameter Real plrSta( + final max=1, + final min=0, + start=0.9, + final unit="1")=0.9 + "Staging part load ratio" + annotation (Dialog(enable=not have_inpPlrSta)); + final parameter Real traStaEqu[nEqu, nSta]={{staEqu[i, j] for i in 1:nSta} for j in 1:nEqu} + "Transpose of staging matrix"; + parameter Real staEqu[:,:]( + each final max=1, + each final min=0, + each final unit="1") + "Staging matrix – Equipment required for each stage"; + final parameter Integer nSta=size(staEqu, 1) + "Number of stages" + annotation (Evaluate=true); + final parameter Integer nEqu=size(staEqu, 2) + "Number of equipment" + annotation (Evaluate=true); + parameter Real capEqu[nEqu]( + each final min=0, + each final unit="W") + "Design capacity of each equipment"; + parameter Real dtRun( + final min=0, + final unit="s")=900 + "Runtime with exceeded staging part load ratio before staging event is triggered"; + parameter Real dtMea( + final min=0, + final unit="s")=300 + "Duration used to compute the moving average of required capacity"; + parameter Real cp_default( + final min=0, + final unit="J/(kg.K)") + "Default specific heat capacity used to compute required capacity"; + parameter Real rho_default( + final min=0, + final unit="kg/m3") + "Default density used to compute required capacity"; + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1AvaSta[nSta] + "Stage available signal" + annotation (Placement(transformation(extent={{-240,60},{-200,100}}), + iconTransformation(extent={{-140,40},{-100,80}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1StaPro + "Staging process in progress" + annotation (Placement(transformation(extent={{-240,-40},{-200,0}}), + iconTransformation(extent={{-140,0},{-100,40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput uPlrSta( + final unit="1", + final min=0, + final max=1) + if have_inpPlrSta + "Input signal for staging part load ratio" + annotation (Placement(transformation(extent={{-240,-200},{-200,-160}}), + iconTransformation(extent={{-140,-120},{-100,-80}}))); + // We allow the stage index to be zero, e.g., when the plant is disabled. + Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uSta( + final min=0, + final max=nSta) + "Stage index" + annotation (Placement(transformation(extent={{-240,160},{-200,200}}), + iconTransformation(extent={{-140,80},{-100,120}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TRet( + final unit="K", + displayUnit="degC") + "Return temperature used to compute required capacity" + annotation (Placement(transformation(extent={{-240,-120},{-200,-80}}), + iconTransformation(extent={{-140,-80},{-100,-40}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupSet( + final unit="K", + displayUnit="degC") + "Active supply temperature setpoint used to compute required capacity" + annotation (Placement(transformation(extent={{-240,-80},{-200,-40}}), + iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput V_flow( + final unit="m3/s") + "Volume flow rate used to compute required capacity" + annotation (Placement(transformation(extent={{-240,-160},{-200,-120}}), + iconTransformation(extent={{-140,-100},{-100,-60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Up + "Stage up command" + annotation (Placement(transformation(extent={{200,60},{240,100}}), + iconTransformation(extent={{100,20},{140,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Dow + "Stage down command" + annotation (Placement(transformation(extent={{200,-100},{240,-60}}), + iconTransformation(extent={{100,-60},{140,-20}}))); + Buildings.Controls.OBC.CDL.Reals.Subtract delT( + y(final unit="K")) + "Compute ∆T" + annotation (Placement(transformation(extent={{-170,-90},{-150,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Abs absDelT( + y(final unit="K")) + "Compute absolute value of ∆T" + annotation (Placement(transformation(extent={{-130,-90},{-110,-70}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter capFlo( + y(final unit="W/K"), + final k=rho_default * cp_default) + "Compute capacity flow rate" + annotation (Placement(transformation(extent={{-130,-150},{-110,-130}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply capReq + "Compute required capacity" + annotation (Placement(transformation(extent={{-90,-90},{-70,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant traMatStaEqu[nEqu, nSta]( + final k=traStaEqu) + "Transpose of staging matrix" + annotation (Placement(transformation(extent={{-70,210},{-50,230}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor reqEquSta[nEqu]( + each final nin=nSta) + "Extract equipment required at given stage" + annotation (Placement(transformation(extent={{-10,210},{10,230}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intScaRep( + final nout=nEqu) + "Replicate signal" + annotation (Placement(transformation(extent={{-104,190},{-84,210}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply capEquSta[nEqu] + "Capacity of each equipment required at given stage" + annotation (Placement(transformation(extent={{30,210},{50,230}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant capEquPar[nEqu]( + final k=capEqu) + "Capacity of each equipment" + annotation (Placement(transformation(extent={{-70,150},{-50,170}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum capSta( + nin=nEqu) + "Compute nominal capacity of active stage" + annotation (Placement(transformation(extent={{70,210},{90,230}}))); + Buildings.Controls.OBC.CDL.Reals.Greater gre(h=1E-4*min(capEqu)) + "Compare OPLR to SPLR (hysteresis is to avoid chattering with some simulators)" + annotation (Placement(transformation(extent={{60,-70},{80,-50}}))); + Buildings.Controls.OBC.CDL.Reals.MovingAverage movAve( + delta=dtMea) + "Compute moving average" + annotation (Placement(transformation(extent={{-50,-90},{-30,-70}}))); + Buildings.Templates.Plants.Controls.Utilities.TimerWithReset timUp( + final t=dtRun) + "Timer" + annotation (Placement(transformation(extent={{110,-70},{130,-50}}))); + Buildings.Controls.OBC.CDL.Reals.Less les(h=1E-4*min(capEqu)) + "Compare OPLR to SPLR (hysteresis is to avoid chattering with some simulators)" + annotation (Placement(transformation(extent={{60,-130},{80,-110}}))); + Buildings.Templates.Plants.Controls.Utilities.TimerWithReset timDow( + final t=dtRun) + "Timer" + annotation (Placement(transformation(extent={{110,-130},{130,-110}}))); + Utilities.HoldReal hol(final dtHol=dtRun) + "Hold value of required capacity at stage change" + annotation (Placement(transformation(extent={{20,-70},{40,-50}}))); + Buildings.Controls.OBC.CDL.Integers.Max maxInt + "Maximum between stage index and 1" + annotation (Placement(transformation(extent={{-140,190},{-120,210}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant one( + final k=1) + "Constant" + annotation (Placement(transformation(extent={{-180,170},{-160,190}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant idxSta[nSta]( + final k={i for i in 1:nSta}) + "Stage index" + annotation (Placement(transformation(extent={{-180,130},{-160,150}}))); + Buildings.Controls.OBC.CDL.Integers.Less idxStaLesAct[nSta] + "Return true if stage index lower than active stage index" + annotation (Placement(transformation(extent={{-150,90},{-130,110}}))); + Buildings.Controls.OBC.CDL.Logical.And idxStaLesActAva[nSta] + annotation (Placement(transformation(extent={{-110,70},{-90,90}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intScaRep1( + final nout=nSta) + "Replicate signal" + annotation (Placement(transformation(extent={{-180,90},{-160,110}}))); + Utilities.LastTrueIndex idxLasTru( + nin=nSta) + "Index of next available lower stage" + annotation (Placement(transformation(extent={{-70,70},{-50,90}}))); + Buildings.Controls.OBC.CDL.Integers.Max maxInt1 + "Maximum between stage index and 1" + annotation (Placement(transformation(extent={{-30,110},{-10,130}}))); + Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator intScaRep2( + final nout=nEqu) + "Replicate signal" + annotation (Placement(transformation(extent={{10,110},{30,130}}))); + Buildings.Controls.OBC.CDL.Routing.RealExtractor reqEquStaLow[nEqu]( + each final nin=nSta) + "Extract equipment required at next available lower stage" + annotation (Placement(transformation(extent={{-10,170},{10,190}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply capEquStaLow[nEqu] + "Capacity of each equipment required at next available lower stage" + annotation (Placement(transformation(extent={{30,170},{50,190}}))); + Buildings.Controls.OBC.CDL.Reals.MultiSum capStaLow( + nin=nEqu) + "Compute nominal capacity of next available lower stage" + annotation (Placement(transformation(extent={{70,170},{90,190}}))); + Buildings.Controls.OBC.CDL.Integers.Min minInt + "Minimum between stage index and 1" + annotation (Placement(transformation(extent={{-30,70},{-10,90}}))); + Buildings.Controls.OBC.CDL.Conversions.IntegerToReal intToRea + "Convert to real value" + annotation (Placement(transformation(extent={{10,70},{30,90}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply setZer + "Set nominal capacity to zero if no lower available stage" + annotation (Placement(transformation(extent={{110,170},{130,190}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply splTimCapSta + "SPLR times capacity of active stage" + annotation (Placement(transformation(extent={{20,-130},{40,-110}}))); + Buildings.Controls.OBC.CDL.Reals.Multiply splTimCapStaLow + "SPLR times capacity of next available lower stage" + annotation (Placement(transformation(extent={{20,-170},{40,-150}}))); + Utilities.PlaceholderReal parPlrSta( + final have_inp=have_inpPlrSta, + final have_inpPh=false, + final u_internal=plrSta) "Parameter value for SPLR" + annotation (Placement(transformation(extent={{-180,-190},{-160,-170}}))); + Buildings.Controls.OBC.CDL.Logical.FallingEdge endStaPro + "True when staging process terminates" + annotation (Placement(transformation(extent={{20,-30},{40,-10}}))); +equation + connect(delT.y, absDelT.u) + annotation (Line(points={{-148,-80},{-132,-80}},color={0,0,127})); + connect(absDelT.y, capReq.u1) + annotation (Line(points={{-108,-80},{-100,-80},{-100,-74},{-92,-74}}, color={0,0,127})); + connect(capFlo.y, capReq.u2) + annotation (Line(points={{-108,-140},{-100,-140},{-100,-86},{-92,-86}}, + color={0,0,127})); + connect(intScaRep.y, reqEquSta.index) + annotation (Line(points={{-82,200},{0,200},{0,208}},color={255,127,0})); + connect(traMatStaEqu.y, reqEquSta.u) + annotation (Line(points={{-48,220},{-12,220}},color={0,0,127})); + connect(reqEquSta.y, capEquSta.u1) + annotation (Line(points={{12,220},{20,220},{20,226},{28,226}},color={0,0,127})); + connect(capEquPar.y, capEquSta.u2) + annotation (Line(points={{-48,160},{20,160},{20,214},{28,214}},color={0,0,127})); + connect(capEquSta.y, capSta.u) + annotation (Line(points={{52,220},{68,220}},color={0,0,127})); + connect(movAve.y, hol.u) + annotation (Line(points={{-28,-80},{-10,-80},{-10,-66},{18,-66}}, color={0,0,127})); + connect(intScaRep.u, maxInt.y) + annotation (Line(points={{-106,200},{-118,200}},color={255,127,0})); + connect(idxSta.y, idxStaLesAct.u1) + annotation (Line(points={{-158,140},{-154,140},{-154,100},{-152,100}},color={255,127,0})); + connect(uSta, intScaRep1.u) + annotation (Line(points={{-220,180},{-190,180},{-190,100},{-182,100}},color={255,127,0})); + connect(intScaRep1.y, idxStaLesAct.u2) + annotation (Line(points={{-158,100},{-156,100},{-156,92},{-152,92}},color={255,127,0})); + connect(idxStaLesAct.y, idxStaLesActAva.u1) + annotation (Line(points={{-128,100},{-120,100},{-120,80},{-112,80}},color={255,0,255})); + connect(u1AvaSta, idxStaLesActAva.u2) + annotation (Line(points={{-220,80},{-126,80},{-126,72},{-112,72}},color={255,0,255})); + connect(idxStaLesActAva.y, idxLasTru.u1) + annotation (Line(points={{-88,80},{-72,80}},color={255,0,255})); + connect(idxLasTru.y, maxInt1.u2) + annotation (Line(points={{-48,80},{-44,80},{-44,114},{-32,114}},color={255,127,0})); + connect(one.y, maxInt1.u1) + annotation (Line(points={{-158,180},{-40,180},{-40,126},{-32,126}},color={255,127,0})); + connect(maxInt1.y, intScaRep2.u) + annotation (Line(points={{-8,120},{8,120}},color={255,127,0})); + connect(uSta, maxInt.u1) + annotation (Line(points={{-220,180},{-190,180},{-190,206},{-142,206}},color={255,127,0})); + connect(one.y, maxInt.u2) + annotation (Line(points={{-158,180},{-150,180},{-150,194},{-142,194}},color={255,127,0})); + connect(intScaRep2.y, reqEquStaLow.index) + annotation (Line(points={{32,120},{40,120},{40,140},{0,140},{0,168}},color={255,127,0})); + connect(traMatStaEqu.y, reqEquStaLow.u) + annotation (Line(points={{-48,220},{-20,220},{-20,180},{-12,180}},color={0,0,127})); + connect(reqEquStaLow.y, capEquStaLow.u2) + annotation (Line(points={{12,180},{16,180},{16,174},{28,174}},color={0,0,127})); + connect(capEquPar.y, capEquStaLow.u1) + annotation (Line(points={{-48,160},{20,160},{20,186},{28,186}},color={0,0,127})); + connect(capEquStaLow.y, capStaLow.u) + annotation (Line(points={{52,180},{68,180}},color={0,0,127})); + connect(idxLasTru.y, minInt.u2) + annotation (Line(points={{-48,80},{-44,80},{-44,74},{-32,74}},color={255,127,0})); + connect(one.y, minInt.u1) + annotation (Line(points={{-158,180},{-40,180},{-40,86},{-32,86}},color={255,127,0})); + connect(minInt.y, intToRea.u) + annotation (Line(points={{-8,80},{8,80}},color={255,127,0})); + connect(capStaLow.y, setZer.u1) + annotation (Line(points={{92,180},{100,180},{100,186},{108,186}},color={0,0,127})); + connect(intToRea.y, setZer.u2) + annotation (Line(points={{32,80},{100,80},{100,174},{108,174}},color={0,0,127})); + connect(hol.y, gre.u1) + annotation (Line(points={{42,-60},{58,-60}},color={0,0,127})); + connect(splTimCapSta.y, gre.u2) + annotation (Line(points={{42,-120},{44,-120},{44,-68},{58,-68}},color={0,0,127})); + connect(capSta.y, splTimCapSta.u2) + annotation (Line(points={{92,220},{184,220},{184,-140},{10,-140},{10,-126}, + {18,-126}}, + color={0,0,127})); + connect(setZer.y, splTimCapStaLow.u2) + annotation (Line(points={{132,180},{180,180},{180,-180},{10,-180},{10,-166}, + {18,-166}}, + color={0,0,127})); + connect(splTimCapStaLow.y, les.u2) + annotation (Line(points={{42,-160},{50,-160},{50,-128},{58,-128}},color={0,0,127})); + connect(hol.y, les.u1) + annotation (Line(points={{42,-60},{50,-60},{50,-120},{58,-120}},color={0,0,127})); + connect(gre.y, timUp.u) + annotation (Line(points={{82,-60},{108,-60}}, + color={255,0,255})); + connect(les.y, timDow.u) + annotation (Line(points={{82,-120},{108,-120}}, + color={255,0,255})); + connect(uPlrSta, parPlrSta.u) + annotation (Line(points={{-220,-180},{-182,-180}}, color={0,0,127})); + connect(parPlrSta.y, splTimCapSta.u1) annotation (Line(points={{-158,-180},{ + -40,-180},{-40,-114},{18,-114}}, + color={0,0,127})); + connect(parPlrSta.y, splTimCapStaLow.u1) annotation (Line(points={{-158,-180}, + {-40,-180},{-40,-154},{18,-154}}, color={0,0,127})); + connect(u1StaPro, hol.u1) + annotation (Line(points={{-220,-20},{-10,-20},{-10,-60},{18,-60}}, color={255,0,255})); + connect(u1StaPro, endStaPro.u) + annotation (Line(points={{-220,-20},{18,-20}}, color={255,0,255})); + connect(endStaPro.y, timUp.reset) + annotation (Line(points={{42,-20},{90,-20},{90,-68},{108,-68}}, + color={255,0,255})); + connect(endStaPro.y, timDow.reset) + annotation (Line(points={{42,-20},{90,-20},{90,-128},{108,-128}}, + color={255,0,255})); + connect(timUp.passed, y1Up) annotation (Line(points={{132,-68},{140,-68},{140, + 80},{220,80}}, color={255,0,255})); + connect(timDow.passed, y1Dow) annotation (Line(points={{132,-128},{140,-128}, + {140,-80},{220,-80}},color={255,0,255})); + connect(TSupSet, delT.u1) annotation (Line(points={{-220,-60},{-180,-60},{ + -180,-74},{-172,-74}}, color={0,0,127})); + connect(TRet, delT.u2) annotation (Line(points={{-220,-100},{-180,-100},{-180, + -86},{-172,-86}}, color={0,0,127})); + connect(V_flow, capFlo.u) annotation (Line(points={{-220,-140},{-132,-140}}, + color={0,0,127})); + connect(capReq.y, movAve.u) + annotation (Line(points={{-68,-80},{-52,-80}}, color={0,0,127})); + annotation ( + defaultComponentName="chaSta", + Icon( + coordinateSystem( + preserveAspectRatio=false, + extent={{-100,-120},{100,120}}), + graphics={ + Rectangle( + extent={{-100,120},{100,-120}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-150,170},{150,130}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + preserveAspectRatio=false, + extent={{-200,-240},{200,240}})), + Documentation( + info=" ++The plant equipment is staged in part based on required capacity, Qrequired, +relative to nominal capacity of a given stage, Qstage. +This ratio is the operative part load ratio, OPLR. +
++OPLR = Qrequired / Qstage +
++If both primary and secondary hot water temperatures and flow rates are available, +the sensors in the primary loop are used for calculating Qrequired. +If a heat recovery chiller is piped into the secondary return, the sensors in the +primary loop are used. +(These conditions are implemented in + +Buildings.Templates.Plants.Controls.HeatPumps.AirToWater.) +
++The required capacity is calculated based on return temperature, +active supply temperature setpoint and measured flow through the +associated circuit flow meter. +
+
+The required capacity used in logic is a rolling average over a period
+of dtMea
+of instantaneous values sampled at minimum once every 30 s.
+
+When a stage up or stage down transition is initiated,
+Qrequired is held fixed at its last value until the longer of
+the successful completion of the stage change
+and the duration dtRun
.
+
+The nominal capacity of a given stage, Qstage, is calculated +as the sum of the design capacities of all units enabled in a given stage. +
++Staging is executed per the conditions below subject to the following requirements. +
+dtRun
.
+(This condition is implemented in
+
+Buildings.Templates.Plants.Controls.Utilities.StageIndex.)
++A stage up command is triggered if any of the following is true: +
+dtRun
.
++A stage down command is triggered if the following is true: +
+dtRun
.
+
+A staging matrix staEqu
is required as a parameter.
+See the documentation of
+
+Buildings.Templates.Plants.Controls.StagingRotation.EquipmentEnable
+for the associated definition and requirements.
+
+An \"if\" condition is used to generate the stage up and down command as opposed
+to a \"when\" condition. This means that the command remains true as long as the
+condition is verified. This is necessary, for example, if no higher stage is
+available when a stage up command is triggered. Using a \"when\" condition –
+which is only valid at the point in time at which the condition becomes true –
+would prevent the plant from staging when a higher stage becomes available again.
+To avoid multiple consecutive stage changes, the block that receives the stage up
+and down command and computes the stage index must enforce a minimum stage runtime
+of dtRun
.
+
+Block that detects a stage change and evaluates whether the stage +transition is completed. +
++The completion of a stage change is considered successful when +both of the following conditions have been verified. +
+
+The output signal y1End
is true exactly at the time when
+the successful completion of the stage change is confirmed.
+The output signal y1
is true during the entire time in which
+the stage change is in progress.
+
+This model validates
+
+Buildings.Templates.Plants.Controls.StagingRotation.EquipmentAvailability
+for heating-only applications (component avaHeaCoo
) and heating and cooling
+applications (component avaHea
).
+
+This model validates
+
+Buildings.Templates.Plants.Controls.StagingRotation.EquipmentEnable
+in a configuration with three equally sized units (component equEnaEqu
)
+and in a configuration with one small unit and two large equally sized
+units (component equEnaOneTwo
).
+Only the units of the same size are lead/lag alternated.
+
+This model validates + +Buildings.Templates.Plants.Controls.StagingRotation.EventSequencing +for the following configurations. +
+seqEveHea
)
+seqEveHeaCoo
)
++The simulation shows that even wear is achieved among available equipment. +When it becomes unavailable, equipment #1 is sent to last position, +and automatically moves up in the staging order only if another +equipment (#3) becomes unavailable. +
++We can verify that no equipment gets \"hot swapped\". +
+", revisions=" +
+This model validates
+
+Buildings.Templates.Plants.Controls.StagingRotation.StageAvailability
+in a configuration with three equally sized units (component avaStaEqu
)
+and in a configuration with one small unit and two large equally sized
+units (component avaStaOneTwo
).
+Only the units of the same size are lead/lag alternated.
+
+This model validates
+
+Buildings.Templates.Plants.Controls.StagingRotation.StageChangeCommand
+in a configuration with one small unit and two large equally sized
+units (component avaStaOneTwo
).
+In response to a varying flow rate, the variation of the
+required capacity chaSta.capReq.y
triggers stage change
+events.
+The block
+
+Buildings.Templates.Plants.Controls.Utilities.StageIndex
+is used to illustrate how these events translate into
+a varying plant stage index idxSta.y
.
+
+This model validates
+
+Buildings.Templates.Plants.Controls.StagingRotation.StageCompletion
+in a configuration with one small unit and two large equally sized
+units (component avaStaOneTwo
).
+In response to a varying flow rate, the variation of the
+required capacity chaSta.capReq.y
triggers stage change
+events.
+The block
+
+Buildings.Templates.Plants.Controls.Utilities.StageIndex
+is used to illustrate how these events translate into
+a varying plant stage index idxSta.y
.
+
+This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/StagingRotation/Validation/package.order b/Buildings/Templates/Plants/Controls/StagingRotation/Validation/package.order new file mode 100644 index 00000000000..fb6e2c8e0f6 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/StagingRotation/Validation/package.order @@ -0,0 +1,7 @@ +EquipmentAvailability +EquipmentEnable +EventSequencing +SortRuntime +StageAvailability +StageChangeCommand +StageCompletion diff --git a/Buildings/Templates/Plants/Controls/StagingRotation/package.mo b/Buildings/Templates/Plants/Controls/StagingRotation/package.mo new file mode 100644 index 00000000000..34a7cfdbcf1 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/StagingRotation/package.mo @@ -0,0 +1,43 @@ +within Buildings.Templates.Plants.Controls; +package StagingRotation "Package of sequences for equipment staging and rotation" + 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), + 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)}), Documentation(info=" ++This package contains equipment staging and rotation sequences. +
+")); +end StagingRotation; diff --git a/Buildings/Templates/Plants/Controls/StagingRotation/package.order b/Buildings/Templates/Plants/Controls/StagingRotation/package.order new file mode 100644 index 00000000000..b55032749c8 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/StagingRotation/package.order @@ -0,0 +1,8 @@ +EquipmentAvailability +EquipmentEnable +EventSequencing +SortRuntime +StageAvailability +StageChangeCommand +StageCompletion +Validation diff --git a/Buildings/Templates/Plants/Controls/Types.mo b/Buildings/Templates/Plants/Controls/Types.mo new file mode 100644 index 00000000000..fd911f43f50 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Types.mo @@ -0,0 +1,28 @@ +within Buildings.Templates.Plants.Controls; +package Types + "Package with type definitions" + extends Modelica.Icons.TypesPackage; + type Application = enumeration( + Cooling + "Cooling system", + Heating + "Heating system") + "Enumeration to specify the type of application"; + type Actuator = enumeration( + Modulating + "Modulating", + TwoPosition + "Two-position") + "Enumeration to specify the type of actuator"; + type EquipmentConnection = enumeration( + Parallel + "Parallel piped", + Series + "Series piped") + "Enumeration to specify the type of connection between equipment and primary loop"; + annotation (Documentation(info=" ++This package provides type definitions. +
+")); +end Types; diff --git a/Buildings/Templates/Plants/Controls/Utilities/CountTrue.mo b/Buildings/Templates/Plants/Controls/Utilities/CountTrue.mo new file mode 100644 index 00000000000..8290098d308 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Utilities/CountTrue.mo @@ -0,0 +1,62 @@ +within Buildings.Templates.Plants.Controls.Utilities; +block CountTrue + "Output the number of true elements in a Boolean array" + parameter Integer nin( + min=0)=0 + "Size of input array" + annotation (Evaluate=true, + Dialog(connectorSizing=true),HideResult=true); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1[nin] + "Array of Boolean signals" + annotation (Placement(transformation(extent={{-140,-20},{-100,20}}), + iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput y + "Index of first element being true" + annotation (Placement(transformation(extent={{100,-20},{140,20}}), + iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nin]( + each final integerTrue=1, + each final integerFalse=0) + "Cast to integer" + annotation (Placement(transformation(extent={{-40,-10},{-20,10}}))); + Buildings.Controls.OBC.CDL.Integers.MultiSum sumMul( + final nin=nin) + "Sum over array elements" + annotation (Placement(transformation(extent={{20,-10},{40,10}}))); +equation + connect(u1, booToInt.u) + annotation (Line(points={{-120,0},{-42,0}},color={255,0,255})); + connect(sumMul.y, y) + annotation (Line(points={{42,0},{120,0}},color={255,127,0})); + connect(booToInt.y, sumMul.u) + annotation (Line(points={{-18,0},{18,0}},color={255,127,0})); + annotation ( + defaultComponentName="couTru", + Icon( + coordinateSystem( + preserveAspectRatio=true, + 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={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Documentation(info=" +
+Counts the number of true
elements in the Boolean
+input vector.
+
+Returns the index of the first true
element of the Boolean
+input vector.
+If no element is true
, the block returns 0.
+
+Holds input value fixed at its last value while the Boolean signal
+u1
is true, and for at least the hold time dtHol
.
+
+Returns the index of the last true
element of the Boolean
+input vector.
+If no element is true
, the block returns 0.
+
+Outputs the maximum element of the input vector. +
+", revisions=" ++Outputs the minimum element of the input vector. +
+", revisions=" ++This is an update of + +Buildings.Controls.OBC.CDL.Reals.PIDWithReset +with an additional enable signal provided as a Boolean input. +
+y_reset
at
+enable time.
+y_neutral
+and the setpoint is overridden by the measurement signal in order to avoid
+time integration of the control error.
++This block enables replacing a variable that is conditionally +removed with either a parameter or another input variable. +
+have_inp
is true, the output variable
+y
is equal to the input variable u
.
+have_inp
is false and the
+parameter have_inpPh
is true, the output variable
+y
is equal to the input variable uPh
.
+have_inp
is false and the
+parameter have_inpPh
is false, the output variable
+y
is equal to the parameter u_internal
.
++This block enables replacing a variable that is conditionally +removed with either a parameter or another input variable. +
+have_inp
is true, the output variable
+y
is equal to the input variable u
.
+have_inp
is false and the
+parameter have_inpPh
is true, the output variable
+y
is equal to the input variable uPh
.
+have_inp
is false and the
+parameter have_inpPh
is false, the output variable
+y
is equal to the parameter u_internal
.
++This block enables replacing a variable that is conditionally +removed with either a parameter or another input variable. +
+have_inp
is true, the output variable
+y
is equal to the input variable u
.
+have_inp
is false and the
+parameter have_inpPh
is true, the output variable
+y
is equal to the input variable uPh
.
+have_inp
is false and the
+parameter have_inpPh
is false, the output variable
+y
is equal to the parameter u_internal
.
+
+Block that sorts the elements of the input signal u.
+If the parameter ascending = true
, then the output signal y satisfies
+yi <= yi+1 for all i ∈ {1, ..., n-1}.
+Otherwise, it satisfies
+yi >= yi+1 for all i ∈ {1, ..., n-1}.
+The output signal yIdx contains the indices of the sorted elements,
+with respect to the input vector u.
+
+Note that this block shall only be used for input signals u
that are
+time sampled.
+Otherwise, in simulation, numerical noise from a nonlinear solver or from an
+implicit time integration algorithm may cause the simulation to stall.
+Numerical noise can be present if an input depends
+on a state variable or a quantity that requires an iterative solution,
+such as a temperature or a mass flow rate of an HVAC system.
+In real controllers, measurement noise may cause the output to change frequently.
+
+This block may for example be used in a variable air volume flow +controller to access the position of the dampers that are most open. +
+", + revisions=" +assert
statement.
++This block is used to compute the stage index for a group of +multiple equipment such as CHW pumps or chillers. +
+0
is active –
+all units are disabled.
+0
, the transition to the next higher available
+stage is triggered when the lead unit is enabled (u1Lea = true
)
+and if at least one stage is available.
+i
(1 ≤ i ≤ nSta
), the transition
+to the next higher or lower available stage j
+(1 ≤ j ≤ nSta
, j ≠ i
)
+is triggered when stage i
has been active for the minimum runtime
+and there is a stage up command u1Up
or stage down command u1Dow
, respectively.
+i
(1 ≤ i ≤ nSta
), the transition
+to stage 0
is triggered when stage i
has been active
+for the minimum runtime and the lead unit is disabled (u1Lea = false
).
++Unavailable stages are handled by the following requirements. +
+u1Ava[i] = false
) is skipped during
+staging events.
+
+The only way to transition to stage 0
is by disabling the lead unit
+(u1Lea = false
).
+The stage down command u1Dow
cannot be used to transition
+below stage 1
.
+
+When the current stage becomes unavailable, the transition to the next +higher available stage is triggered. +However, it can happen that equipment that is enabled at the current +stage is no longer available while the current stage is not deemed +unavailable – for example if a lead/lag alternate equipment remains available. +In this case, the equipment rotation logic must stage on the +lead/lag alternate equipment to replace the faulty equipment. +
+", + revisions=" +
+This block is similar to
+
+Buildings.Controls.OBC.CDL.Logical.Timer,
+but introduces an additional Boolean input signal reset
,
+which resets the timer.
+When reset
becomes true:
+y=0
and passed=false
.
+
+Accepts indices of true elements that may not be within the +range of indices of the output vector. +In this, the number of true elements will not be met. +
+", revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.CountTrue. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.FirstTrueIndex. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.HoldValue. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.FirstTrueIndex. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.MultiMaxInteger. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.MultiMinInteger. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.PlaceholderLogical. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.PlaceholderReal. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.SortWithIndices. +
+
+The input u1
varies from -2 to +2, input u2
varies from -1 to +2,
+input u3
varies from +2 to -2, input u4
varies from +3 to +2,
+input u5
varies from 0 to +4,
+
+Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.StageIndex. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.TimerWithReset. +
+", + revisions=" ++Validation model for the block + +Buildings.Templates.Plants.Controls.Utilities.TrueArrayConditional. +
+", + revisions=" ++This package contains validation models. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/Controls/Utilities/Validation/package.order b/Buildings/Templates/Plants/Controls/Utilities/Validation/package.order new file mode 100644 index 00000000000..caa1e43ad37 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Utilities/Validation/package.order @@ -0,0 +1,13 @@ +CountTrue +FirstTrueIndex +HoldReal +LastTrueIndex +MultiMaxInteger +MultiMinInteger +PlaceholderInteger +PlaceholderLogical +PlaceholderReal +SortWithIndices +StageIndex +TimerWithReset +TrueArrayConditional diff --git a/Buildings/Templates/Plants/Controls/Utilities/package.mo b/Buildings/Templates/Plants/Controls/Utilities/package.mo new file mode 100644 index 00000000000..bf3ce309a24 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Utilities/package.mo @@ -0,0 +1,48 @@ +within Buildings.Templates.Plants.Controls; +package Utilities "Package with utility blocks" + annotation ( + Documentation( + info=" ++This package contains utility blocks that are used to implement +the control sequences within + +Buildings.Templates.Plants.Controls. +
+"), + 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 Utilities; diff --git a/Buildings/Templates/Plants/Controls/Utilities/package.order b/Buildings/Templates/Plants/Controls/Utilities/package.order new file mode 100644 index 00000000000..7e02dab8af1 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/Utilities/package.order @@ -0,0 +1,15 @@ +CountTrue +FirstTrueIndex +HoldReal +LastTrueIndex +MultiMaxInteger +MultiMinInteger +PIDWithEnable +PlaceholderInteger +PlaceholderLogical +PlaceholderReal +SortWithIndices +StageIndex +TimerWithReset +TrueArrayConditional +Validation diff --git a/Buildings/Templates/Plants/Controls/package.mo b/Buildings/Templates/Plants/Controls/package.mo new file mode 100644 index 00000000000..35798c237e9 --- /dev/null +++ b/Buildings/Templates/Plants/Controls/package.mo @@ -0,0 +1,47 @@ +within Buildings.Templates.Plants; +package Controls "Control blocks" + annotation ( + Documentation( + info=" ++This package contains control blocks that comply with the CDL specification: + +https://obc.lbl.gov/specification/cdl.html. +
+"), + 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 Controls; diff --git a/Buildings/Templates/Plants/Controls/package.order b/Buildings/Templates/Plants/Controls/package.order new file mode 100644 index 00000000000..07c7d33a37e --- /dev/null +++ b/Buildings/Templates/Plants/Controls/package.order @@ -0,0 +1,7 @@ +Enabling +HeatPumps +Pumps +Setpoints +StagingRotation +Utilities +Types diff --git a/Buildings/Templates/Plants/HeatPumps/AirToWater.mo b/Buildings/Templates/Plants/HeatPumps/AirToWater.mo new file mode 100644 index 00000000000..39702ac659d --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/AirToWater.mo @@ -0,0 +1,766 @@ +within Buildings.Templates.Plants.HeatPumps; +model AirToWater + "Air-to-water heat pump plant" + extends Buildings.Templates.Plants.HeatPumps.Interfaces.PartialHeatPumpPlant( + redeclare final package MediumChiWat=MediumHeaWat, + redeclare final package MediumSou=MediumAir, + redeclare Buildings.Templates.Plants.HeatPumps.Components.Controls.AirToWater ctl, + final typ=Buildings.Templates.Components.Types.HeatPump.AirToWater, + final is_rev=have_chiWat, + final cfg( + final typMod=hp.typMod)); + // Heat pumps, dedicated primary pumps and isolation valves + Buildings.Templates.Plants.HeatPumps.Components.HeatPumpGroups.AirToWater hp( + redeclare final package MediumHeaWat=MediumHeaWat, + redeclare final package MediumAir=MediumAir, + final nHp=nHp, + final is_rev=is_rev, + final energyDynamics=energyDynamics, + final have_preDroChiHeaWat=false, + final have_preDroSou=false, + final dat=dat.hp, + final allowFlowReversal=allowFlowReversal, + final allowFlowReversalSou=false) + "Heat pump group" + annotation (Placement(transformation(extent={{-540,-210},{-60,-130}}))); + Components.PumpsPrimaryDedicated pumPri( + redeclare final package Medium=MediumHeaWat, + final nHp=nHp, + final typArrPumPri=typArrPumPri, + final have_pumChiWatPriDed=have_pumChiWatPriDed, + final have_pumHeaWatPriVar=have_pumHeaWatPriVar, + final have_pumChiWatPriVar=have_pumChiWatPriVar, + final datPumHeaWat=dat.pumHeaWatPri, + final datPumChiWat=dat.pumChiWatPri, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal) + "Dedicated primary pumps" + annotation (Placement(transformation(extent={{-540,-130},{-60,-50}}))); + Components.ValvesIsolation valIso( + redeclare final package Medium=MediumHeaWat, + final nHp=nHp, + final have_chiWat=have_chiWat, + final have_valHpInlIso=have_valHpInlIso, + final have_valHpOutIso=have_valHpOutIso, + final have_pumChiWatPriDed=have_pumChiWatPriDed, + final mHeaWatHp_flow_nominal=fill(dat.hp.mHeaWatHp_flow_nominal, nHp), + final dpHeaWatHp_nominal=fill(dat.hp.dpHeaWatHp_nominal, nHp), + final mChiWatHp_flow_nominal=fill(dat.hp.mChiWatHp_flow_nominal, nHp), + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal) + "Heat pump isolation valves" + annotation (Placement(transformation(extent={{-540,-50},{-60,90}}))); + // Primary CHW loop + Buildings.Templates.Components.Pumps.Multiple pumChiWatPri( + final energyDynamics=energyDynamics, + redeclare final package Medium=MediumChiWat, + final dat=dat.pumChiWatPri, + final nPum=nPumChiWatPri, + final have_var=have_pumChiWatPriVar, + final have_varCom=true, + final allowFlowReversal=allowFlowReversal) + if have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + "Headered primary CHW pumps" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + Buildings.Templates.Components.Routing.SingleToMultiple inlPumChiWatPri( + redeclare final package Medium=MediumChiWat, + final nPorts=nPumChiWatPri, + final m_flow_nominal=mChiWatPri_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) + if have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + "Primary CHW pumps inlet manifold" + annotation (Placement(transformation(extent={{-40,70},{-20,90}}))); + Buildings.Templates.Components.Routing.MultipleToSingle outPumChiWatPri( + redeclare final package Medium=MediumChiWat, + final nPorts=nPumChiWatPri, + final m_flow_nominal=mChiWatPri_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) + if have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + "Primary CHW pumps outlet manifold" + annotation (Placement(transformation(extent={{0,70},{20,90}}))); + Buildings.Templates.Components.Routing.PassThroughFluid supChiWatPri( + redeclare final package Medium=MediumChiWat, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) if have_chiWat and typArrPumPri + == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + "Primary CHW supply pipe - Plant with dedicated primary CHW pumps" + annotation (Placement(transformation(extent={{-20,70},{0,90}}))); + Buildings.Templates.Components.Sensors.VolumeFlowRate VChiWatPri_flow( + redeclare final package Medium=MediumChiWat, + final m_flow_nominal=mChiWatPri_flow_nominal, + final allowFlowReversal=allowFlowReversal, + final have_sen=ctl.have_senVChiWatPri, + final text_flip=false, + final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter, + icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply) + if have_chiWat + "Primary CHW volume flow rate" + annotation (Placement(transformation(extent={{20,70},{40,90}}))); + Buildings.Templates.Components.Routing.Junction junChiWatBypSup( + redeclare final package Medium=MediumChiWat, + final tau=tau, + final m_flow_nominal=mChiWatPri_flow_nominal * {1, - 1, - 1}, + final energyDynamics=energyDynamics, + dp_nominal=fill(0, 3), + final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Entering, + final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Leaving, + final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Leaving) if have_chiWat + "Fluid junction" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={100,80}))); + Buildings.Templates.Components.Sensors.Temperature TChiWatPriSup( + redeclare final package Medium=MediumChiWat, + final have_sen=true, + final m_flow_nominal=mChiWatPri_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) if have_chiWat + "Primary CHW supply temperature" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=0, + origin={60,80}))); + Buildings.Templates.Components.Routing.Junction junChiWatBypRet( + redeclare final package Medium=MediumChiWat, + final tau=tau, + final m_flow_nominal=mChiWatPri_flow_nominal * {1, - 1, 1}, + final energyDynamics=energyDynamics, + dp_nominal=fill(0, 3), + final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Entering, + final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Leaving, + final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Entering, + icon_pipe1=Buildings.Templates.Components.Types.IconPipe.Return, + icon_pipe3=Buildings.Templates.Components.Types.IconPipe.Supply) + if have_chiWat + "Fluid junction" + annotation (Placement(transformation(extent={{10,10},{-10,-10}},rotation=0, + origin={100,0}))); + Buildings.Templates.Components.Sensors.Temperature TChiWatPriRet( + redeclare final package Medium=MediumChiWat, + final have_sen=ctl.have_senTChiWatPriRet, + final m_flow_nominal=mChiWatPri_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Return, + final allowFlowReversal=allowFlowReversal) if have_chiWat + "Primary CHW return temperature" + annotation (Placement(transformation(extent={{10,-10},{-10,10}},rotation=0, + origin={60,0}))); + // Secondary CHW loop + Buildings.Templates.Components.Pumps.Multiple pumChiWatSec( + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + redeclare final package Medium=MediumChiWat, + final nPum=nPumChiWatSec, + final have_var=true, + final have_varCom=true, + final dat=dat.pumChiWatSec) if have_chiWat and typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary CHW pumps" + annotation (Placement(transformation(extent={{170,70},{190,90}}))); + Buildings.Templates.Components.Routing.SingleToMultiple inlPumChiWatSec( + redeclare final package Medium=MediumChiWat, + final nPorts=nPumChiWatSec, + final m_flow_nominal=mChiWat_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) if + have_chiWat and typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary CHW pumps inlet manifold" + annotation (Placement(transformation(extent={{150,70},{170,90}}))); + Buildings.Templates.Components.Routing.MultipleToSingle outPumChiWatSec( + redeclare final package Medium=MediumChiWat, + final nPorts=nPumChiWatSec, + final m_flow_nominal=mChiWat_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) if + have_chiWat and typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary CHW pumps outlet manifold" + annotation (Placement(transformation(extent={{190,70},{210,90}}))); + Buildings.Templates.Components.Routing.PassThroughFluid supChiWatSec( + redeclare final package Medium=MediumChiWat, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) if have_chiWat and + typPumChiWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary CHW supply pipe - Plant without secondary CHW pumps" + annotation (Placement(transformation(extent={{170,70},{190,90}}))); + Buildings.Templates.Components.Sensors.VolumeFlowRate VChiWatSec_flow( + redeclare final package Medium=MediumChiWat, + final m_flow_nominal=mChiWat_flow_nominal, + final allowFlowReversal=allowFlowReversal, + final have_sen=ctl.have_senVChiWatSec, + final text_flip=false, + final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply) + if have_chiWat + "Secondary CHW volume flow rate" + annotation (Placement(transformation(extent={{208,70},{228,90}}))); + Buildings.Templates.Components.Sensors.Temperature TChiWatSecSup( + redeclare final package Medium=MediumChiWat, + final have_sen=ctl.have_senTChiWatSecSup, + final m_flow_nominal=mChiWat_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) if have_chiWat + "Secondary CHW supply temperature" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={140,80}))); + Buildings.Templates.Components.Sensors.Temperature TChiWatSecRet( + redeclare final package Medium=MediumChiWat, + final have_sen=ctl.have_senTChiWatSecRet, + final m_flow_nominal=mChiWat_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Return, + final allowFlowReversal=allowFlowReversal) if have_chiWat + "Secondary CHW return temperature" + annotation (Placement(transformation(extent={{10,-10},{-10,10}},rotation=0, + origin={140,0}))); + // Primary HW loop + Buildings.Templates.Components.Routing.SingleToMultiple inlPumHeaWatPri( + redeclare final package Medium=MediumHeaWat, + final nPorts=nPumHeaWatPri, + final m_flow_nominal=mHeaWatPri_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) + if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + "Primary HW pumps inlet manifold" + annotation (Placement(transformation(extent={{-40,-290},{-20,-270}}))); + Buildings.Templates.Components.Pumps.Multiple pumHeaWatPri( + final energyDynamics=energyDynamics, + redeclare final package Medium=MediumHeaWat, + final dat=dat.pumHeaWatPri, + final nPum=nPumHeaWatPri, + final have_var=have_pumHeaWatPriVar, + final have_varCom=true, + final allowFlowReversal=allowFlowReversal) + if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + "Headered primary HW pumps" + annotation (Placement(transformation(extent={{-20,-290},{0,-270}}))); + Buildings.Templates.Components.Routing.MultipleToSingle outPumHeaWatPri( + redeclare final package Medium=MediumHeaWat, + final nPorts=nPumHeaWatPri, + final m_flow_nominal=mHeaWatPri_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) + if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + "Primary HW pumps outlet manifold" + annotation (Placement(transformation(extent={{0,-290},{20,-270}}))); + Buildings.Templates.Components.Routing.PassThroughFluid supHeaWatPri( + redeclare final package Medium=MediumHeaWat, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) if have_heaWat and typArrPumPri + == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + "Primary HW supply pipe - Plant with dedicated primary HW pumps" + annotation (Placement(transformation(extent={{-20,-290},{0,-270}}))); + Buildings.Templates.Components.Sensors.VolumeFlowRate VHeaWatPri_flow( + redeclare final package Medium=MediumHeaWat, + final m_flow_nominal=mHeaWatPri_flow_nominal, + final allowFlowReversal=allowFlowReversal, + final have_sen=ctl.have_senVHeaWatPri, + final text_flip=false, + final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter, + icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply) + "Primary HW volume flow rate" + annotation (Placement(transformation(extent={{20,-290},{40,-270}}))); + Buildings.Templates.Components.Routing.Junction junHeaWatBypSup( + redeclare final package Medium=MediumHeaWat, + final tau=tau, + final m_flow_nominal=mHeaWatPri_flow_nominal * {1, - 1, - 1}, + final energyDynamics=energyDynamics, + dp_nominal=fill(0, 3), + final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Entering, + final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Leaving, + final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Leaving) if have_heaWat + "Fluid junction" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={100,-280}))); + Buildings.Templates.Components.Sensors.Temperature THeaWatPriSup( + redeclare final package Medium=MediumHeaWat, + final have_sen=true, + final m_flow_nominal=mHeaWatPri_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) + "Primary HW supply temperature" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={60,-280}))); + Buildings.Templates.Components.Sensors.Temperature THeaWatPriRet( + redeclare final package Medium = MediumHeaWat, + final have_sen=ctl.have_senTHeaWatPriRet, + final m_flow_nominal=mHeaWatPri_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Return, + final allowFlowReversal=allowFlowReversal) + "Primary HW return temperature" + annotation (Placement(transformation(extent={{10,-10},{-10,10}},rotation=0, + origin={60,-360}))); + Buildings.Templates.Components.Routing.Junction junHeaWatBypRet( + redeclare final package Medium=MediumHeaWat, + final tau=tau, + final m_flow_nominal=mHeaWatPri_flow_nominal * {1, - 1, 1}, + final energyDynamics=energyDynamics, + dp_nominal=fill(0, 3), + final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Entering, + final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Leaving, + final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional + else Modelica.Fluid.Types.PortFlowDirection.Entering, + icon_pipe1=Buildings.Templates.Components.Types.IconPipe.Return, + icon_pipe3=Buildings.Templates.Components.Types.IconPipe.Supply) + if have_heaWat + "Fluid junction" + annotation (Placement(transformation(extent={{10,10},{-10,-10}},rotation=0, + origin={100,-360}))); + Buildings.Fluid.Sources.Boundary_pT bouHeaWat( + redeclare final package Medium=MediumHeaWat, + p=Buildings.Templates.Data.Defaults.pHeaWat_rel_nominal + 101325, + nPorts=1) if have_heaWat + "Pressure boundary condition to mimic expansion tank" + annotation (Placement(transformation(extent={{10,-10},{-10,10}},rotation=90, + origin={20,-340}))); + // Secondary HW loop + Buildings.Templates.Components.Pumps.Multiple pumHeaWatSec( + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + redeclare final package Medium=MediumHeaWat, + final nPum=nPumHeaWatSec, + final have_var=true, + final have_varCom=true, + final dat=dat.pumHeaWatSec) + if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary HW pumps" + annotation (Placement(transformation(extent={{170,-290},{190,-270}}))); + Buildings.Templates.Components.Routing.SingleToMultiple inlPumHeaWatSec( + redeclare final package Medium=MediumHeaWat, + final nPorts=nPumHeaWatSec, + final m_flow_nominal=mHeaWat_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) + if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary HW pumps inlet manifold" + annotation (Placement(transformation(extent={{150,-290},{170,-270}}))); + Buildings.Templates.Components.Routing.MultipleToSingle outPumHeaWatSec( + redeclare final package Medium=MediumHeaWat, + final nPorts=nPumHeaWatSec, + final m_flow_nominal=mHeaWat_flow_nominal, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final icon_dy=300) + if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary HW pumps outlet manifold" + annotation (Placement(transformation(extent={{190,-290},{210,-270}}))); + Buildings.Templates.Components.Routing.PassThroughFluid supHeaWatSec( + redeclare final package Medium=MediumHeaWat, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) if have_heaWat and + typPumHeaWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary HW supply pipe - Plant without secondary HW pumps" + annotation (Placement(transformation(extent={{170,-290},{190,-270}}))); + Buildings.Templates.Components.Sensors.VolumeFlowRate VHeaWatSec_flow( + redeclare final package Medium=MediumHeaWat, + final m_flow_nominal=mHeaWat_flow_nominal, + final allowFlowReversal=allowFlowReversal, + final have_sen=ctl.have_senVHeaWatSec, + final text_flip=false, + final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply) + "Secondary HW volume flow rate" + annotation (Placement(transformation(extent={{210,-290},{230,-270}}))); + Buildings.Templates.Components.Sensors.Temperature THeaWatSecSup( + redeclare final package Medium=MediumHeaWat, + final have_sen=ctl.have_senTHeaWatSecSup, + final m_flow_nominal=mHeaWat_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Supply, + final allowFlowReversal=allowFlowReversal) + "Secondary HW supply temperature" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={140,-280}))); + Buildings.Templates.Components.Sensors.Temperature THeaWatSecRet( + redeclare final package Medium=MediumHeaWat, + final have_sen=ctl.have_senTHeaWatSecRet, + final m_flow_nominal=mHeaWat_flow_nominal, + final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell, + final icon_pipe=Buildings.Templates.Components.Types.IconPipe.Return, + final allowFlowReversal=allowFlowReversal) + "Secondary HW return temperature" + annotation (Placement(transformation(extent={{10,-10},{-10,10}},rotation=0, + origin={140,-360}))); +equation + /* Control point connection - start */ + connect(bus, hp.bus); + connect(busWea, hp.busWea); + connect(bus, pumPri.bus); + connect(bus, valIso.bus); + connect(bus.pumChiWatPri, pumChiWatPri.bus); + connect(bus.pumHeaWatPri, pumHeaWatPri.bus); + connect(bus.pumChiWatSec, pumChiWatSec.bus); + connect(bus.pumHeaWatSec, pumHeaWatSec.bus); + connect(VChiWatPri_flow.y, bus.VChiWatPri_flow); + connect(VHeaWatPri_flow.y, bus.VHeaWatPri_flow); + connect(VChiWatSec_flow.y, bus.VChiWatSec_flow); + connect(VHeaWatSec_flow.y, bus.VHeaWatSec_flow); + connect(TChiWatPriSup.y, bus.TChiWatPriSup); + connect(THeaWatPriSup.y, bus.THeaWatPriSup); + connect(TChiWatPriRet.y, bus.TChiWatPriRet); + connect(THeaWatPriRet.y, bus.THeaWatPriRet); + connect(TChiWatSecSup.y, bus.TChiWatSecSup); + connect(THeaWatSecSup.y, bus.THeaWatSecSup); + connect(TChiWatSecRet.y, bus.TChiWatSecRet); + connect(THeaWatSecRet.y, bus.THeaWatSecRet); + /* Control point connection - stop */ + connect(pumChiWatPri.ports_b, outPumChiWatPri.ports_a) + annotation (Line(points={{0,80},{0,80}}, color={0,127,255})); + connect(inlPumChiWatPri.ports_b, pumChiWatPri.ports_a) + annotation (Line(points={{-20,80},{-20,80}}, + color={0,127,255})); + connect(valIso.port_bChiWat, inlPumChiWatPri.port_a) + annotation (Line( + points={{-60,80},{-60,80},{-40,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered)); + connect(hp.ports_bChiHeaWat, pumPri.ports_aChiHeaWatHp) + annotation (Line(points={{-350,-130},{-350,-130}},color={0,127,255})); + connect(pumPri.ports_bChiHeaWat, valIso.ports_aChiHeaWatHp) + annotation (Line(points={{-350,-50},{-350,-50}},color={0,127,255})); + connect(pumPri.ports_bHeaWat, valIso.ports_aHeaWatHp) + annotation (Line(points={{-366,-50},{-366,-50}},color={0,127,255})); + connect(pumPri.ports_bChiWat, valIso.ports_aChiWatHp) + annotation (Line(points={{-334,-50},{-334,-50}}, color={0,127,255})); + connect(outPumChiWatPri.port_b, VChiWatPri_flow.port_a) + annotation (Line(points={{20,80},{20,80}},color={0,127,255})); + connect(VChiWatPri_flow.port_b, TChiWatPriSup.port_a) + annotation (Line( + points={{40,80},{50,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat)); + connect(TChiWatPriSup.port_b, junChiWatBypSup.port_1) + annotation (Line( + points={{70,80},{90,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat)); + connect(pumChiWatSec.ports_b, outPumChiWatSec.ports_a) + annotation (Line(points={{190,80},{190,80}},color={0,127,255})); + connect(inlPumChiWatSec.ports_b, pumChiWatSec.ports_a) + annotation (Line(points={{170,80},{170,80}},color={0,127,255})); + connect(valIso.port_bChiWat, supChiWatPri.port_a) + annotation (Line( + points={{-60,80},{-60,80},{-20,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + connect(supChiWatPri.port_b, VChiWatPri_flow.port_a) + annotation (Line( + points={{0,80},{20,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + connect(valIso.ports_bChiHeaWatHp, pumPri.ports_aChiHeaWat) + annotation (Line(points={{-250,-50},{-250,-50}}, + color={0,127,255})); + connect(pumPri.ports_bChiHeaWatHp, hp.ports_aChiHeaWat) + annotation (Line(points={{-250,-130},{-250,-130}}, + color={0,127,255})); + connect(VChiWatSec_flow.port_b, port_bChiWat) + annotation (Line( + points={{228,80},{600,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat)); + connect(supChiWatSec.port_b, VChiWatSec_flow.port_a) + annotation (Line( + points={{190,80},{208,80}}, + color={0,0,0}, + visible=have_chiWat and typPumChiWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized, + thickness=0.5)); + + connect(pumHeaWatPri.ports_b, outPumHeaWatPri.ports_a) + annotation (Line(points={{0,-280},{0,-280}}, color={0,127,255})); + connect(inlPumHeaWatPri.ports_b, pumHeaWatPri.ports_a) + annotation (Line(points={{-20,-280},{-20,-280}}, + color={0,127,255})); + connect(outPumHeaWatPri.port_b, VHeaWatPri_flow.port_a) + annotation (Line(points={{20,-280},{20,-280}},color={0,127,255})); + connect(VHeaWatPri_flow.port_b, THeaWatPriSup.port_a) + annotation (Line(points={{40,-280},{50,-280}}, color={0,0,0}, + thickness=0.5)); + connect(THeaWatPriSup.port_b, junHeaWatBypSup.port_1) + annotation (Line(points={{70,-280},{90,-280}}, color={0,0,0}, + thickness=0.5)); + connect(pumHeaWatSec.ports_b, outPumHeaWatSec.ports_a) + annotation (Line(points={{190,-280},{190,-280}},color={0,127,255})); + connect(inlPumHeaWatSec.ports_b, pumHeaWatSec.ports_a) + annotation (Line(points={{170,-280},{170,-280}},color={0,127,255})); + connect(supHeaWatPri.port_b, VHeaWatPri_flow.port_a) + annotation (Line( + points={{0,-280},{20,-280}}, + color={0,0,0}, + thickness=0.5, + visible=have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + connect(supHeaWatSec.port_b, VHeaWatSec_flow.port_a) + annotation (Line( + points={{190,-280},{210,-280}}, + color={0,0,0}, + thickness=0.5, + visible=have_heaWat and typPumHeaWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized)); + connect(outPumHeaWatSec.port_b, VHeaWatSec_flow.port_a) + annotation (Line(points={{210,-280},{210,-280}},color={0,0,0}, + thickness=0.5)); + connect(valIso.port_bHeaWat, inlPumHeaWatPri.port_a) + annotation (Line( + points={{-540,20},{-540,-280},{-40,-280}}, + color={0,0,0}, + thickness=0.5, + visible=have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered)); + connect(VHeaWatSec_flow.port_b, port_bHeaWat) + annotation (Line(points={{230,-280},{600,-280}},color={0,0,0}, + thickness=0.5)); + connect(valIso.port_bHeaWat, supHeaWatPri.port_a) + annotation (Line( + points={{-540,20},{-540,-280},{-20,-280}}, + color={0,0,0}, + thickness=0.5, + visible=have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + connect(junHeaWatBypSup.port_3, junHeaWatBypRet.port_3) + annotation (Line(points={{100,-290},{100,-350}}, color={0,0,0}, + thickness=0.5)); + connect(junChiWatBypSup.port_3, junChiWatBypRet.port_3) + annotation (Line( + points={{100,70},{100,10}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat)); + connect(junChiWatBypSup.port_2, TChiWatSecSup.port_a) + annotation (Line( + points={{110,80},{130,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat)); + connect(TChiWatSecSup.port_b, inlPumChiWatSec.port_a) + annotation (Line(points={{150,80},{150,80}}, + color={0,0,0}, + thickness=0.5)); + connect(junChiWatBypRet.port_1, TChiWatSecRet.port_b) + annotation (Line( + points={{110,0},{130,0}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=0.5, + visible=have_chiWat)); + connect(port_aChiWat, TChiWatSecRet.port_a) + annotation (Line( + points={{600,0},{150,0}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=0.5, + visible=have_chiWat)); + connect(junChiWatBypRet.port_2, TChiWatPriRet.port_a) + annotation (Line( + points={{90,0},{70,0}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=0.5, + visible=have_chiWat)); + connect(port_aHeaWat, THeaWatSecRet.port_a) + annotation (Line(points={{600,-360},{150,-360}},color={0,0,0}, + thickness=0.5, + pattern=LinePattern.Dash)); + connect(junHeaWatBypSup.port_2, THeaWatSecSup.port_a) + annotation (Line(points={{110,-280},{130,-280}}, + color={0,0,0}, + thickness=0.5)); + connect(THeaWatSecSup.port_b, inlPumHeaWatSec.port_a) + annotation (Line(points={{150,-280},{150,-280}}, + color={0,0,0}, + thickness=0.5)); + connect(THeaWatSecSup.port_b, supHeaWatSec.port_a) annotation (Line( + points={{150,-280},{158,-280},{158,-232},{166,-232},{166,-280},{170,-280}}, + color={0,0,0}, + thickness=0.5, + visible=have_heaWat and typPumHeaWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized)); + connect(TChiWatSecSup.port_b, supChiWatSec.port_a) annotation (Line( + points={{150,80},{158,80},{158,60},{166,60},{166,80},{170,80}}, + color={0,0,0}, + thickness=0.5, + visible=have_chiWat and typPumChiWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized)); + connect(bouHeaWat.ports[1], THeaWatPriRet.port_b) + annotation (Line(points={{20,-350},{20,-360},{50,-360}}, + color={0,127,255})); + connect(junHeaWatBypRet.port_1, THeaWatSecRet.port_b) + annotation (Line(points={{110,-360},{130,-360}}, color={0,0,0}, + thickness=0.5, + pattern=LinePattern.Dash)); + connect(junHeaWatBypRet.port_2, THeaWatPriRet.port_a) annotation (Line( + points={{90,-360},{70,-360}}, + color={0,0,0}, + thickness=0.5, + pattern=LinePattern.Dash)); + connect(THeaWatPriRet.port_b, valIso.port_aHeaWat) annotation (Line( + points={{50,-360},{-584,-360},{-584,60},{-540,60}}, + color={0,0,0}, + thickness=0.5, + pattern=LinePattern.Dash)); + connect(outPumChiWatSec.port_b, VChiWatSec_flow.port_a) annotation (Line( + points={{210,80},{208,80}}, + color={0,0,0}, + thickness=1)); + connect(TChiWatPriRet.port_b, valIso.port_aChiWat) annotation (Line( + points={{50,0},{0,0},{0,40},{-60,40}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=0.5, + visible=have_chiWat)); + annotation ( + defaultComponentName="pla", + Documentation( + info=" ++This template represents an air-to-water heat pump plant +with closed-loop controls. +
++Only identical heat pumps are currently supported. +
+
+The supported plant configurations are enumerated in the table below.
+The first option displayed in bold characters corresponds to the default
+configuration.
+
Configuration parameter | Options | Notes |
---|---|---|
Function | +
+Heating and cooling +Heating-only + |
+
+The plant always provides heating hot water. +Setting the parameter have_chiWat to true (default setting) allows
+modeling a plant that provides both heating hot water and chilled water.
+ |
+
Type of distribution | ++Constant primary-variable secondary centralized + | +
+It is assumed that the HW and the CHW loops have the
+same type of distribution, as specified by this parameter. +\"Centralized secondary pumps\" refers to configurations with a single +group of secondary pumps that is typically integrated into the plant. +Distributed secondary pumps with multiple secondary loops served +by dedicated secondary pumps are currently not supported. +Options are limited to constant primary distributions because most +AWHPs on the market use a reverse cycle for defrosting. +This requires maximum primary flow during defrost cycles and hinders +variable primary distributions. +An option for constant primary-only distributions with ∆p-controlled +variable speed pumps will be added in a next release. + |
+
Type of primary pump arrangement | +
+Dedicated +Headered + |
+It is assumed that the HW and the CHW loops have the +same type of primary pump arrangement, as specified by this parameter. + | +
Separate dedicated primary CHW pumps | +
+False +True + |
+This option is only available for heating and cooling plants +with dedicated primary pumps. +If this option is not selected (default setting), each AWHP uses +a common dedicated primary pump for HW and CHW. +Otherwise, each AWHP relies on a separate dedicated HW pump +and a separate dedicated CHW pump. + | +
Type of primary HW pumps | +
+Variable speed +Constant speed + |
++For constant primary-variable secondary distributions, the variable +speed primary pumps are commanded at fixed speeds, determined during the +Testing, Adjusting and Balancing phase to provide design AWHP flow in +heating and cooling modes. +The same intent is achieved with constant speed primary pumps through the +use of balancing valves. + | +
Type of primary CHW pumps | +
+Variable speed +Constant speed + |
+See the note above on primary HW pumps. | +
Controller | +
+Closed-loop controls with supply temperature and differential pressure reset + |
+
+Most parts of the sequence of operation are similar to that
+described in ASHRAE, 2021 for chiller plants. +See the documentation of +Buildings.Templates.Plants.Controls.HeatPumps.AirToWater +for more details. +An open loop controller is also available for validation purposes. + |
+
+The control sequence implemented in this template requires the +external input points specified in the documentation of the controller + +Buildings.Templates.Plants.HeatPumps.Components.Controls.AirToWater. +
+The pressure drops of the heat pump CHW and HW heat exchangers are calculated
+within the isolation valve component valIso
based on lumped flow
+coefficients for the sake of computational efficiency.
+
+This class implements the sequence of operation for plants with +air-to-water heat pumps. +It is based on the controller + +Buildings.Templates.Plants.Controls.HeatPumps.AirToWater. +
++The control sequence requires the following external input points in +addition to those already included in the HP plant template. +
+TOut
:
+AI signal with a dimensionality of zerodpHeaWatRem
:
+AI signal with a dimensionality of one, the number of remote
+sensors is specified by the parameter nSenDpHeaWatRem
.dpChiWatRem
–
+only for heating and cooling plants:
+AI signal with a dimensionality of one, the number of remote
+sensors is specified by the parameter nSenDpChiWatRem
.busAirHan[:]
or busEquZon[:]
,
+with a dimensionality of one
+bus(AirHan|EquZon)[:].reqPlaHeaWat
:
+AI signal (Integer), with a dimensionality of one
+bus(AirHan|EquZon)[:].reqResHeaWat
:
+AI signal (Integer), with a dimensionality of one
+bus(AirHan|EquZon)[:].reqPlaChiWat
:
+AI signal (Integer), with a dimensionality of one
+bus(AirHan|EquZon)[:].reqResChiWat
:
+AI signal (Integer), with a dimensionality of one
++This is an open loop controller providing control inputs +for the plant model + +Buildings.Templates.Plants.HeatPumps.AirToWater. +It is only used for testing purposes. +
+")); +end OpenLoop; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Controls/package.mo b/Buildings/Templates/Plants/HeatPumps/Components/Controls/package.mo new file mode 100644 index 00000000000..9e7d14a9162 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Controls/package.mo @@ -0,0 +1,13 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +package Controls "Controllers" + extends Modelica.Icons.VariantsPackage; + annotation ( + Documentation( + info=" ++All control blocks that form the control sequence of a system are instantiated +into one single class, a so-called control section. +This package contains such control sections for heat pump plant models. +
+")); +end Controls; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Controls/package.order b/Buildings/Templates/Plants/HeatPumps/Components/Controls/package.order new file mode 100644 index 00000000000..c1d5525102f --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Controls/package.order @@ -0,0 +1,2 @@ +AirToWater +OpenLoop diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Data/Controller.mo b/Buildings/Templates/Plants/HeatPumps/Components/Data/Controller.mo new file mode 100644 index 00000000000..a577b627f97 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Data/Controller.mo @@ -0,0 +1,229 @@ +within Buildings.Templates.Plants.HeatPumps.Components.Data; +record Controller + "Record for plant controller" + extends Modelica.Icons.Record; + parameter Buildings.Templates.Plants.HeatPumps.Configuration.HeatPumpPlant cfg + "Plant configuration parameters"; + // HW loop + // RFE: Declare array parameters for unequally sized units. + // The current implementation only supports equally sized units. + parameter Modelica.Units.SI.Temperature THeaWatSup_nominal( + displayUnit="degC", + start=Buildings.Templates.Data.Defaults.THeaWatSupMed, + final min=273.15) + "Maximum HW supply temperature setpoint (design HW supply temperature)" + annotation (Dialog(group="Temperature setpoints", + enable=cfg.have_heaWat)); + parameter Real THeaWatSupSet_min( + final min=273.15, + start=25 + 273.15, + final unit="K", + displayUnit="degC") + "Minimum value to which the HW supply temperature can be reset" + annotation (Dialog(group="Temperature setpoints", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.Temperature TOutHeaWatLck( + displayUnit="degC", + final min=273.15)=Buildings.Templates.Data.Defaults.TOutHeaWatLck + "Outdoor air lockout temperature above which the HW loop is prevented from operating" + annotation (Dialog(group="Temperature setpoints", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.VolumeFlowRate VHeaWatHp_flow_nominal( + start=0.1, + displayUnit="L/s", + final min=0) + "Design HW volume flow rate - Each heat pump" + annotation (Evaluate=true, + Dialog(group="Heat pump flow setpoints", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.HeatFlowRate capHeaHp_nominal( + start=1, + final min=0) + "Design heating capacity - Each heat pump" + annotation (Dialog(group="Capacity", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.VolumeFlowRate VHeaWatSec_flow_nominal( + start=0.01, + displayUnit="L/s", + final min=0) + "Design secondary HW volume flow rate" + annotation (Evaluate=true, + Dialog(group="Capacity", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None)); + parameter Modelica.Units.SI.PressureDifference dpHeaWatRemSet_min( + final min=0, + start=5 * 6894)=5 * 6894 + "Minimum value to which the HW differential pressure can be reset - Remote sensor" + annotation (Dialog(group= + "Information provided by designer", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and (cfg.typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + or cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None))); + // HACK(AntoineGautier): + // Using cfg.nSenDpHeaWatRem for size(dpHeaWatRemSet_max, 1) is not supported by Dymola which fails to "evaluate and check the size declaration". + // So the size is kept unassigned. + // This requires explicitely providing a value with OCT, even if enable=false. + parameter Modelica.Units.SI.PressureDifference dpHeaWatRemSet_max[:]( + start=fill(Buildings.Templates.Data.Defaults.dpHeaWatRemSet_max, cfg.nSenDpHeaWatRem), + final min=fill(0, cfg.nSenDpHeaWatRem)) + "Maximum HW differential pressure setpoint - Remote sensor" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and (cfg.typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + or cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None))); + parameter Real yPumHeaWatPriSet( + final max=1, + final min=0, + start=1, + final unit="1") + "Primary pump speed providing design heat pump flow in heating mode" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater and + cfg.have_heaWat and cfg.have_pumHeaWatPriVar)); + parameter Real yPumHeaWatSec_min( + final unit="1", + final min=0, + final max=1)=0.1 + "Secondary HW pump minimum speed" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=cfg.have_heaWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None)); + // CHW loop + parameter Modelica.Units.SI.Temperature TChiWatSup_nominal( + displayUnit="degC", + start=Buildings.Templates.Data.Defaults.TChiWatSup, + final min=273.15) + "Minimum CHW supply temperature setpoint (design CHW supply temperature)" + annotation (Dialog(group="Temperature setpoints", + enable=cfg.have_chiWat)); + parameter Modelica.Units.SI.Temperature TChiWatSupSet_max( + final min=273.15, + start=15 + 273.15, + displayUnit="degC") + "Maximum value to which the CHW supply temperature can be reset" + annotation (Dialog(group="Temperature setpoints", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.Temperature TOutChiWatLck( + displayUnit="degC", + final min=273.15)=Buildings.Templates.Data.Defaults.TOutChiWatLck + "Outdoor air lockout temperature below which the CHW loop is prevented from operating" + annotation (Dialog(group="Temperature setpoints", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.VolumeFlowRate VChiWatHp_flow_nominal( + start=0.1, + displayUnit="L/s", + final min=0) + "Design CHW volume flow rate - Each heat pump" + annotation (Evaluate=true, + Dialog(group="Heat pump flow setpoints", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.HeatFlowRate capCooHp_nominal( + start=1, + final min=0) + "Design cooling capacity - Each heat pump" + annotation (Dialog(group="Capacity", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + parameter Modelica.Units.SI.VolumeFlowRate VChiWatSec_flow_nominal( + start=0.01, + displayUnit="L/s", + final min=0) + "Design secondary CHW volume flow rate" + annotation (Evaluate=true, + Dialog(group="Capacity", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None)); + parameter Modelica.Units.SI.PressureDifference dpChiWatRemSet_min( + final min=0, + start=5 * 6894)=5 * 6894 + "Minimum value to which the CHW differential pressure can be reset - Remote sensor" + annotation (Dialog(group= + "Information provided by designer", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and (cfg.typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + or cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None))); + // HACK(AntoineGautier): + // Using cfg.nSenDpChiWatRem for size(dpChiWatRemSet_max, 1) is not supported by Dymola which fails to "evaluate and check the size declaration". + // So the size is kept unassigned. + // This requires explicitely providing a value with OCT, even if enable=false. + parameter Modelica.Units.SI.PressureDifference dpChiWatRemSet_max[:]( + start=fill(Buildings.Templates.Data.Defaults.dpChiWatRemSet_max, cfg.nSenDpChiWatRem), + final min=fill(0, cfg.nSenDpChiWatRem)) + "Maximum CHW differential pressure setpoint - Remote sensor" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and (cfg.typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + or cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None))); + parameter Real yPumChiWatPriSet( + final max=1, + final min=0, + start=1, + final unit="1") + "Primary pump speed providing design heat pump flow in cooling mode" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and cfg.have_pumChiWatPriVar)); + parameter Real yPumChiWatSec_min( + final unit="1", + final min=0, + final max=1)=0.1 + "Secondary CHW pump minimum speed" + annotation (Dialog(group= + "Information provided by testing, adjusting, and balancing contractor", + enable=cfg.have_chiWat and cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater + and cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None)); + parameter Real schHea[:, 2](start=[ + 0, 1; + 24 * 3600, 1])=[ + 0, 1; + 24 * 3600, 1] + "Heating mode enable schedule" + annotation (Dialog(enable=not cfg.have_inpSch and + cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater, + group="Plant enable")); + parameter Real schCoo[:, 2](start=[ + 0, 1; + 24 * 3600, 1])=[ + 0, 1; + 24 * 3600, 1] + "Cooling mode enable schedule" + annotation (Dialog(enable=not cfg.have_inpSch and + cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater, + group="Plant enable")); + // HACK(AntoineGautier): + // Using cfg.nHp for size(staEqu, 2) is not supported by Dymola which fails to "evaluate and check the size declaration". + // So the size is kept unassigned and a check is performed at initialization. + // Furthermore, a start value cannot be provided as the number of plant stages is not known beforehand. + // If provided, there will likely be a mismatch between assigned value and start value. + // Therefore, no enable annotation can be used. + parameter Real staEqu[:, :]( + each final max=1, + each final min=0, + each final unit="1") + "Staging matrix – Equipment required for each stage" + annotation (Dialog(group="Equipment staging and rotation")); + parameter Real plrSta( + final max=1, + final min=0, + start=0.9, + final unit="1")=0.9 + "Staging part load ratio" + annotation (Dialog(group="Equipment staging and rotation", + enable=cfg.typCtl==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater)); + annotation ( + defaultComponentName="datCtl", + Documentation( + info=" ++This record provides the set of parameters for +heat pump plant controllers that can be found within + +Buildings.Templates.Plants.HeatPumps.Components.Controls. +
+")); +end Controller; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Data/HeatPumpGroup.mo b/Buildings/Templates/Plants/HeatPumps/Components/Data/HeatPumpGroup.mo new file mode 100644 index 00000000000..61b988302c3 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Data/HeatPumpGroup.mo @@ -0,0 +1,185 @@ +within Buildings.Templates.Plants.HeatPumps.Components.Data; +record HeatPumpGroup + extends Modelica.Icons.Record; + parameter Integer nHp( + final min=1) + "Number of heat pumps" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=false)); + parameter Buildings.Templates.Components.Types.HeatPump typ + "Equipment type" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=false)); + parameter Boolean is_rev + "Set to true for reversible heat pumps, false for heating only" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=false)); + parameter Buildings.Templates.Components.Types.HeatPumpModel typMod + "Type of heat pump model" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=false)); + // Default fluid properties + parameter Modelica.Units.SI.SpecificHeatCapacity cpHeaWat_default=Buildings.Utilities.Psychrometrics.Constants.cpWatLiq + "HW default specific heat capacity" + annotation (Dialog(group="Configuration", + enable=false)); + /* + cpChiWat_default is for internal use only. + It is the same as cpChiWat_default for reversible HP. + Non-reversible HP that can be controlled to produce either HW or CHW + shall be modeled with chiller components (as a chiller/heater). + */ + final parameter Modelica.Units.SI.SpecificHeatCapacity cpChiWat_default= + cpHeaWat_default + "CHW default specific heat capacity"; + parameter Modelica.Units.SI.SpecificHeatCapacity cpSou_default=if typ == + Buildings.Templates.Components.Types.HeatPump.AirToWater then Buildings.Utilities.Psychrometrics.Constants.cpAir + else Buildings.Utilities.Psychrometrics.Constants.cpWatLiq + "Source fluid default specific heat capacity" + annotation (Dialog(group="Configuration", + enable=false)); + // RFE: Declare array parameters for unequally sized units. + // The current implementation only supports equally sized units. + parameter Modelica.Units.SI.MassFlowRate mHeaWatHp_flow_nominal( + final min=0) + "HW mass flow rate - Each heat pump" + annotation (Evaluate=true, + Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.PressureDifference dpHeaWatHp_nominal( + min=0, + start=Buildings.Templates.Data.Defaults.dpChiWatChi) + "Pressure drop at design HW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.HeatFlowRate capHeaHp_nominal + "Heating capacity - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.Temperature THeaWatSupHp_nominal( + final min=273.15) + "(Highest) HW supply temperature - Each heat pump" + annotation (Dialog(group="Nominal condition")); + final parameter Modelica.Units.SI.Temperature THeaWatRetHp_nominal= + THeaWatSupHp_nominal - abs(capHeaHp_nominal) / cpHeaWat_default / + mHeaWatHp_flow_nominal + "HW return temperature - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.MassFlowRate mChiWatHp_flow_nominal( + start=0, + final min=0) + "CHW mass flow rate - Each heat pump" + annotation (Evaluate=true, + Dialog(group="Nominal condition", + enable=is_rev)); + final parameter Modelica.Units.SI.PressureDifference dpChiWatHp_nominal= + dpHeaWatHp_nominal *(mChiWatHp_flow_nominal / mHeaWatHp_flow_nominal) ^ 2 + "Pressure drop at design CHW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.HeatFlowRate capCooHp_nominal( + start=0) + "Cooling capacity - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=is_rev)); + parameter Modelica.Units.SI.Temperature TChiWatSupHp_nominal( + start=Buildings.Templates.Data.Defaults.TChiWatSup, + final min=253.15) + "(Lowest) CHW supply temperature - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=is_rev)); + final parameter Modelica.Units.SI.Temperature TChiWatRetHp_nominal=if is_rev + then TChiWatSupHp_nominal + abs(capCooHp_nominal) / cpChiWat_default / + mChiWatHp_flow_nominal else Buildings.Templates.Data.Defaults.TChiWatRet + "CHW return temperature - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=is_rev)); + parameter Modelica.Units.SI.Temperature TSouHeaHp_nominal( + start=Buildings.Templates.Data.Defaults.TOutHpHeaLow, + final min=220) + "OAT or source fluid supply temperature (evaporator entering) in heating mode - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.MassFlowRate mSouWwHeaHp_flow_nominal( + start=mHeaWatHp_flow_nominal, + final min=0) + "Source fluid mass flow rate in heating mode - Each heat pump" + annotation (Evaluate=true, + Dialog(group="Nominal condition", + enable=typ==Buildings.Templates.Components.Types.HeatPump.WaterToWater)); + parameter Modelica.Units.SI.PressureDifference dpSouWwHeaHp_nominal( + min=0, + start=Buildings.Templates.Data.Defaults.dpChiWatChi) + "Source fluid pressure drop in heating mode - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=typ==Buildings.Templates.Components.Types.HeatPump.WaterToWater)); + final parameter Modelica.Units.SI.MassFlowRate mSouHeaHp_flow_nominal=if typ == + Buildings.Templates.Components.Types.HeatPump.WaterToWater then mSouWwHeaHp_flow_nominal + else Buildings.Templates.Data.Defaults.mAirFloByCapChi * abs(capHeaHp_nominal) + "Source fluid mass flow rate in heating mode - Each heat pump" + annotation (Evaluate=true); + final parameter Modelica.Units.SI.PressureDifference dpSouHeaHp_nominal=if typ == + Buildings.Templates.Components.Types.HeatPump.WaterToWater then dpSouWwHeaHp_nominal + else Buildings.Templates.Data.Defaults.dpAirChi + "Source fluid pressure drop in heating mode - Each heat pump"; + parameter Modelica.Units.SI.Temperature TSouCooHp_nominal( + start=Buildings.Templates.Data.Defaults.TOutHpCoo, + final min=273.15) + "OAT or source fluid supply temperature (condenser entering) in cooling mode - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=is_rev)); + parameter Modelica.Units.SI.MassFlowRate mSouWwCooHp_flow_nominal( + start=mChiWatHp_flow_nominal, + final min=0) + "Source fluid mass flow rate in cooling mode - Each heat pump" + annotation (Evaluate=true, + Dialog(group="Nominal condition", + enable=typ==Buildings.Templates.Components.Types.HeatPump.WaterToWater and is_rev)); + final parameter Modelica.Units.SI.MassFlowRate mSouCooHp_flow_nominal=if typ == + Buildings.Templates.Components.Types.HeatPump.WaterToWater then mSouWwCooHp_flow_nominal + else Buildings.Templates.Data.Defaults.mAirFloByCapChi * abs(capCooHp_nominal) + "Source fluid mass flow rate in cooling mode - Each heat pump" + annotation (Evaluate=true); + final parameter Modelica.Units.SI.PressureDifference dpSouCooHp_nominal= + dpSouHeaHp_nominal *(mSouCooHp_flow_nominal / mSouHeaHp_flow_nominal) ^ 2 + "Source fluid pressure drop in cooling mode - Each heat pump"; + replaceable parameter Buildings.Fluid.HeatPumps.Data.EquationFitReversible.Generic perFitHp( + dpHeaLoa_nominal=dpHeaWatHp_nominal, + dpHeaSou_nominal=dpSouHeaHp_nominal, + hea( + Q_flow=abs(capHeaHp_nominal), + P=0, + mLoa_flow=mHeaWatHp_flow_nominal, + mSou_flow=mSouHeaHp_flow_nominal, + coeQ={1, 0, 0, 0, 0}, + coeP={1, 0, 0, 0, 0}, + TRefLoa=THeaWatRetHp_nominal, + TRefSou=TSouHeaHp_nominal), + coo( + Q_flow=if is_rev then - abs(capCooHp_nominal) else - 1, + P=0, + mLoa_flow=mChiWatHp_flow_nominal, + mSou_flow=mSouCooHp_flow_nominal, + coeQ={1, 0, 0, 0, 0}, + coeP={1, 0, 0, 0, 0}, + TRefLoa=TChiWatRetHp_nominal, + TRefSou=TSouCooHp_nominal)) + constrainedby Buildings.Fluid.HeatPumps.Data.EquationFitReversible.Generic + "Performance data - Equation fit model - Each heat pump" + annotation (Dialog(enable=typMod==Buildings.Templates.Components.Types.HeatPumpModel.EquationFit), + choicesAllMatching=true, + Placement(transformation(extent={{-8,-40},{8,-24}}))); + annotation ( + defaultComponentPrefixes="parameter", + defaultComponentName="datHp", + Documentation(info=" ++This record provides the set of parameters for heat pump group models +that can be found within + +Buildings.Templates.Plants.HeatPumps.Components.HeatPumpGroups. +
++Only identical heat pumps are currently supported. +
+")); +end HeatPumpGroup; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Data/package.mo b/Buildings/Templates/Plants/HeatPumps/Components/Data/package.mo new file mode 100644 index 00000000000..0c219b8eb9e --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Data/package.mo @@ -0,0 +1,11 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +package Data "Records for design and operating parameters" + extends Modelica.Icons.MaterialPropertiesPackage; + annotation ( + Documentation( + info=" ++This package provides records for design and operating parameters. +
+")); +end Data; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Data/package.order b/Buildings/Templates/Plants/HeatPumps/Components/Data/package.order new file mode 100644 index 00000000000..62f5cba34cf --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Data/package.order @@ -0,0 +1,2 @@ +Controller +HeatPumpGroup diff --git a/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/AirToWater.mo b/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/AirToWater.mo new file mode 100644 index 00000000000..533afb57ce9 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/AirToWater.mo @@ -0,0 +1,40 @@ +within Buildings.Templates.Plants.HeatPumps.Components.HeatPumpGroups; +model AirToWater + "Air-to-water heat pump group" + extends Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialHeatPumpGroup( + redeclare final package MediumSou=MediumAir, + final typ=Buildings.Templates.Components.Types.HeatPump.AirToWater, + final typMod=Buildings.Templates.Components.Types.HeatPumpModel.EquationFit); + Buildings.Templates.Components.HeatPumps.AirToWater hp[nHp]( + redeclare each final package MediumHeaWat=MediumHeaWat, + redeclare each final package MediumAir=MediumAir, + each final is_rev=is_rev, + final dat=datHp, + each final allowFlowReversal=allowFlowReversal, + each final energyDynamics=energyDynamics, + each final have_preDroChiHeaWat=have_preDroChiHeaWat, + each final have_preDroSou=have_preDroSou) + "Heat pump unit" + annotation (Placement(transformation(extent={{10,-10},{-10,10}}))); +equation + for i in 1:nHp loop + connect(busWea, hp[i].busWea) + annotation (Line(points={{40,200},{40,10},{6,10}},color={255,204,51},thickness=0.5)); + end for; + connect(ports_aChiHeaWat, hp.port_a) + annotation (Line(points={{120,200},{120,0},{10,0}},color={0,127,255})); + connect(hp.port_b, ports_bChiHeaWat) + annotation (Line(points={{-10,0},{-120,0},{-120,200}},color={0,127,255})); + connect(busHp, hp.bus) + annotation (Line(points={{0,160},{0,10}},color={255,204,51},thickness=0.5)); + connect(ports_aSou, hp.port_aSou) + annotation (Line(points={{-120,-200},{-120,-10},{-10,-10}},color={0,127,255})); + connect(ports_bSou, hp.port_bSou) + annotation (Line(points={{120,-200},{120,-10},{10,-10}},color={0,127,255})); + annotation ( + defaultComponentName="hp", Documentation(info=" ++This model represents a group of heat pumps. +
+")); +end AirToWater; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/package.mo b/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/package.mo new file mode 100644 index 00000000000..49ae155ba9d --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/package.mo @@ -0,0 +1,11 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +package HeatPumpGroups "Models for heat pump groups" + extends Modelica.Icons.VariantsPackage; + annotation ( + Documentation( + info=" ++This package contains models of heat pump groups. +
+")); +end HeatPumpGroups; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/package.order b/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/package.order new file mode 100644 index 00000000000..971b641363f --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/HeatPumpGroups/package.order @@ -0,0 +1 @@ +AirToWater diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/PartialController.mo b/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/PartialController.mo new file mode 100644 index 00000000000..aacd12b97cb --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/PartialController.mo @@ -0,0 +1,264 @@ +within Buildings.Templates.Plants.HeatPumps.Components.Interfaces; +block PartialController "Interface for heat pump plant controller" + /* + The following bindings are for parameters that are propagated *up* + from the controller to the plant configuration record. + All other configuration parameters (e.g. nHp) are propagated *down* + from the plant configuration record to the controller. + */ + parameter Buildings.Templates.Plants.HeatPumps.Configuration.HeatPumpPlant cfg( + typCtl=typ, + nAirHan=nAirHan, + nEquZon=nEquZon, + have_senDpHeaWatRemWir=have_senDpHeaWatRemWir, + nSenDpHeaWatRem=nSenDpHeaWatRem, + have_senDpChiWatRemWir=have_senDpChiWatRemWir, + nSenDpChiWatRem=nSenDpChiWatRem) + "Plant configuration parameters" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=false)); + parameter Buildings.Templates.Plants.HeatPumps.Components.Data.Controller dat( + cfg=cfg) + "Parameter record for controller"; + final parameter Integer nHp=cfg.nHp + "Number of heat pumps" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Buildings.Templates.Plants.HeatPumps.Types.Controller typ + "Type of controller" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Integer nAirHan( + final min=if typ <> Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop + and nEquZon == 0 then 1 else 0, + start=0) + "Number of air handling units served by the plant" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop)); + parameter Integer nEquZon( + final min=if typ <> Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop + and nAirHan == 0 then 1 else 0, + start=0) + "Number of terminal units (zone equipment) served by the plant" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop)); + parameter Boolean have_senVHeaWatPri_select(start=false) + "Set to true for plants with primary HW flow sensor" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop and + cfg.have_heaWat and not cfg.have_hrc and have_senVHeaWatSec)); + final parameter Boolean have_senVHeaWatPri=cfg.have_heaWat and + (if cfg.have_hrc or not have_senVHeaWatSec then true else have_senVHeaWatPri_select) + "Set to true for plants with primary HW flow sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + // Secondary flow sensor required for secondary HW pump staging. + final parameter Boolean have_senVHeaWatSec= + cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + "Set to true for plants with secondary HW flow sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + parameter Boolean have_senVChiWatPri_select(start=false) + "Set to true for plants with primary CHW flow sensor" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop and + cfg.have_chiWat and not cfg.have_hrc and have_senVChiWatSec)); + final parameter Boolean have_senVChiWatPri=cfg.have_chiWat and + (if cfg.have_hrc or not have_senVChiWatSec then true + else have_senVChiWatPri_select) + "Set to true for plants with primary CHW flow sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + // Secondary flow sensor required for secondary CHW pump staging. + final parameter Boolean have_senVChiWatSec= + cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + "Set to true for plants with secondary CHW flow sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + parameter Boolean have_senTHeaWatPriRet_select(start=false) + "Set to true for plants with primary HW return temperature sensor" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop and + cfg.have_heaWat and not cfg.have_hrc and have_senTHeaWatSecRet)); + final parameter Boolean have_senTHeaWatPriRet=cfg.have_heaWat and + (if cfg.have_hrc or not have_senTHeaWatSecRet then true else have_senTHeaWatPriRet_select) + "Set to true for plants with primary HW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + parameter Boolean have_senTChiWatPriRet_select(start=false) + "Set to true for plants with primary CHW return temperature sensor" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop and + cfg.have_chiWat and not cfg.have_hrc and have_senTChiWatSecRet)); + final parameter Boolean have_senTChiWatPriRet=cfg.have_chiWat and + (if cfg.have_hrc or not have_senTChiWatSecRet then true else have_senTChiWatPriRet_select) + "Set to true for plants with primary CHW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + // For primary-secondary plants, SHWST sensor is required for plant staging. + final parameter Boolean have_senTHeaWatSecSup= + cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + "Set to true for plants with secondary HW supply temperature sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + // For primary-secondary plants, SCHWST sensor is required for plant staging. + final parameter Boolean have_senTChiWatSecSup= + cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + "Set to true for plants with secondary CHW supply temperature sensor" + annotation (Evaluate=true, Dialog(group="Configuration")); + parameter Boolean have_senTHeaWatSecRet(start=false) + "Set to true for plants with secondary HW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop and + cfg.typPumHeaWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None)); + parameter Boolean have_senTChiWatSecRet(start=false) + "Set to true for plants with secondary CHW return temperature sensor" + annotation (Evaluate=true, Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop and + cfg.typPumChiWatSec<>Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None)); + parameter Boolean have_senDpHeaWatRemWir=false + "Set to true for remote HW differential pressure sensor(s) hardwired to plant or pump controller" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop)); + parameter Integer nSenDpHeaWatRem( + final min=if typ <> Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop + then 1 else 0)=1 + "Number of remote HW differential pressure sensors used for HW pump speed control" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop)); + parameter Boolean have_senDpChiWatRemWir=have_senDpHeaWatRemWir + "Set to true for remote CHW differential pressure sensor(s) hardwired to plant or pump controller" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=cfg.have_chiWat and typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop)); + parameter Integer nSenDpChiWatRem( + final min=if typ <> Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop + then 1 else 0)=1 + "Number of remote CHW differential pressure sensors used for CHW pump speed control" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=cfg.have_chiWat and typ<>Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop)); + parameter Boolean have_inpSch(start=false)=false + "Set to true to provide schedule via software input point" + annotation (Dialog(group="Plant enable", + enable=typ==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater), + Evaluate=true); + final parameter Real schHea[:, 2]=dat.schHea + "Heating mode enable schedule" + annotation (Dialog(enable=not have_inpSch and + typ==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater, + group="Plant enable")); + final parameter Real schCoo[:, 2]=dat.schCoo + "Cooling mode enable schedule" + annotation (Dialog(enable=not have_inpSch and + typ==Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater, + group="Plant enable")); + Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus + "Plant control bus" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=90, + origin={-260,0}), + iconTransformation(extent={{-20,-20},{20,20}},rotation=90,origin={-100,0}))); + Buildings.Templates.AirHandlersFans.Interfaces.Bus busAirHan[nAirHan] + if nAirHan > 0 + "Air handling unit control bus" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=-90, + origin={260,140}), + iconTransformation(extent={{-20,-20},{20,20}},rotation=-90,origin={100,60}))); + Buildings.Templates.ZoneEquipment.Interfaces.Bus busEquZon[nEquZon] + if nEquZon > 0 + "Terminal unit control bus" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=-90, + origin={260,-140}), + iconTransformation(extent={{-20,-20},{20,20}},rotation=-90,origin={100,-60}))); +protected + Buildings.Templates.Components.Interfaces.Bus busHp[nHp] + "Heat pump control bus" + annotation (Placement(transformation(extent={{-260,320},{-220,360}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busPumHeaWatPri + if cfg.typPumHeaWatPri<>Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None + "Primary HW pump control bus" + annotation (Placement(transformation(extent={{-260,160},{-220,200}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busPumHeaWatSec + if cfg.typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary HW pump control bus" + annotation (Placement(transformation(extent={{-260,120},{-220,160}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busPumChiWatPri + if cfg.typPumChiWatPri<>Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None + "Primary CHW pump control bus" + annotation (Placement(transformation(extent={{-260,-220},{-220,-180}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busPumChiWatSec + if cfg.typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + "Secondary CHW pump control bus" + annotation (Placement(transformation(extent={{-260,-260},{-220,-220}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValHeaWatHpInlIso[nHp] + if cfg.have_heaWat and cfg.have_valHpInlIso + "Heat pump inlet HW isolation valve control bus" + annotation (Placement(transformation(extent={{-260,280},{-220,320}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValHeaWatHpOutIso[nHp] + if cfg.have_heaWat and cfg.have_valHpOutIso + "Heat pump outlet HW isolation valve control bus" + annotation (Placement(transformation(extent={{-260,240},{-220,280}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValChiWatHpInlIso[nHp] + if cfg.have_chiWat and cfg.have_valHpInlIso + "Heat pump inlet CHW isolation valve control bus" + annotation (Placement(transformation(extent={{-260,-100},{-220,-60}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValChiWatHpOutIso[nHp] + if cfg.have_chiWat and cfg.have_valHpOutIso + "Heat pump outlet CHW isolation valve control bus" + annotation (Placement(transformation(extent={{-260,-140},{-220,-100}}), + iconTransformation(extent={{-466,50},{-426,90}}))); +equation + /* Control point connection - start */ + connect(busPumHeaWatPri, bus.pumHeaWatPri); + connect(busPumChiWatPri, bus.pumChiWatPri); + connect(busPumChiWatSec, bus.pumChiWatSec); + connect(busPumHeaWatSec, bus.pumHeaWatSec); + connect(busHp, bus.hp); + connect(busValHeaWatHpInlIso, bus.valHeaWatHpInlIso); + connect(busValHeaWatHpOutIso, bus.valHeaWatHpOutIso); + connect(busValChiWatHpInlIso, bus.valChiWatHpInlIso); + connect(busValChiWatHpOutIso, bus.valChiWatHpOutIso); + /* Control point connection - stop */ + annotation ( + Icon( + coordinateSystem( + preserveAspectRatio=false), + graphics={ + Rectangle( + extent={{-100,100},{100,-100}}, + lineColor={0,0,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255})}), + Diagram( + coordinateSystem( + preserveAspectRatio=false, + extent={{-260,-380},{260,380}})), + Documentation( + info=" ++This partial class provides a standard interface for heat pump plant controllers. +
+", + revisions=" ++This partial class provides a standard interface for heat pump +group models. +
+")); +end PartialHeatPumpGroup; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/package.mo b/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/package.mo new file mode 100644 index 00000000000..15254aed0fd --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/package.mo @@ -0,0 +1,11 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +package Interfaces "Interface classes" + extends Modelica.Icons.InterfacesPackage; + annotation ( + Documentation( + info=" ++This package contains interface classes. +
+")); +end Interfaces; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/package.order b/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/package.order new file mode 100644 index 00000000000..6112600b18a --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Interfaces/package.order @@ -0,0 +1,2 @@ +PartialController +PartialHeatPumpGroup diff --git a/Buildings/Templates/Plants/HeatPumps/Components/PumpsPrimaryDedicated.mo b/Buildings/Templates/Plants/HeatPumps/Components/PumpsPrimaryDedicated.mo new file mode 100644 index 00000000000..5721bb03f62 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/PumpsPrimaryDedicated.mo @@ -0,0 +1,868 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +model PumpsPrimaryDedicated + "Dedicated primary pumps" + replaceable package Medium=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "Medium model" + annotation (__ctrlFlow(enable=false)); + parameter Integer nHp(min=1) + "Number of heat pumps" + annotation (Evaluate=true, + Dialog(group="Configuration")); + /* RFE(AntoineGautier): Add support for multiple pumps for each heat pump. + Currently, only one dedicated CHW or HW pump for each HP is supported. + */ + final parameter Integer nPum=if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + then nHp else 0 + "Number of primary pumps" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Buildings.Templates.Components.Types.PumpArrangement typArrPumPri + "Type of primary pump arrangement" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Boolean have_pumChiWatPriDed(start=false) + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + parameter Boolean have_pumHeaWatPriVar(start=false) + "Set to true for variable speed primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + parameter Boolean have_pumChiWatPriVar(start=false) + "Set to true for variable speed primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumChiWatPriDed)); + parameter Buildings.Templates.Components.Data.PumpMultiple datPumHeaWat( + typ=if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + then Buildings.Templates.Components.Types.Pump.Multiple else Buildings.Templates.Components.Types.Pump.None, + nPum=nPum) + "HW pump parameters" + annotation (Dialog(enable=typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated), + Placement(transformation(extent={{170,170},{190,190}}))); + parameter Buildings.Templates.Components.Data.PumpMultiple datPumChiWat( + typ=if have_pumChiWatPriDed then Buildings.Templates.Components.Types.Pump.Multiple + else Buildings.Templates.Components.Types.Pump.None, + nPum=if have_pumChiWatPriDed then nPum else 0) + "CHW pump parameters" + annotation (Dialog(enable=typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumChiWatPriDed), + Placement(transformation(extent={{170,130},{190,150}}))); + parameter Modelica.Units.SI.PressureDifference dpValCheHeaWat_nominal[nPum]( + each final min=0, + start=fill(if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + then Buildings.Templates.Data.Defaults.dpValChe else 0, nPum))=fill( + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + then Buildings.Templates.Data.Defaults.dpValChe else 0, nPum) + "HW pump check valve pressure drop at design HW pump flow rate" + annotation (Dialog(group="Nominal condition", + enable=typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + parameter Modelica.Units.SI.PressureDifference dpValCheChiWat_nominal[if have_pumChiWatPriDed then nPum else 0]( + each final min=0, + start=fill(if have_pumChiWatPriDed then Buildings.Templates.Data.Defaults.dpValChe + else 0, if have_pumChiWatPriDed then nPum else 0))=fill(if + have_pumChiWatPriDed then Buildings.Templates.Data.Defaults.dpValChe else 0, + if have_pumChiWatPriDed then nPum else 0) + "CHW pump check valve pressure drop at design CHW pump flow rate" + annotation (Dialog(group="Nominal condition", enable=have_pumChiWatPriDed)); + parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial + "Type of energy balance: dynamic (3 initialization options) or steady state" + annotation (Evaluate=true, + Dialog(tab="Dynamics",group="Conservation equations")); + parameter Modelica.Units.SI.Time tau=1 + "Time constant at nominal flow" + annotation (Dialog(tab="Dynamics",group="Nominal condition", + enable=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState), + __ctrlFlow(enable=false)); + parameter Boolean allowFlowReversal=true + "Set to false to simplify equations, assuming, but not enforcing, no flow reversal" + annotation (Dialog(tab="Assumptions"), + Evaluate=true); + Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiHeaWat[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + or typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumChiWatPriDed + "CHW/HW supply (to primary loop)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={-100,200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=270,origin={-500,400}))); + Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiHeaWat[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + "CHW/HW return (from primary loop)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={100,200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=270,origin={500,400}))); + Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiHeaWatHp[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + "CHW/HW return (HP entering)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={100,-200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=90,origin={500,-400}))); + Modelica.Fluid.Interfaces.FluidPorts_b ports_bHeaWat[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumChiWatPriDed + "HW supply (to primary loop)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={-180,200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=90,origin={-660,400}))); + Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiWat[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumChiWatPriDed + "CHW supply (to primary loop)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={-20,200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=90,origin={-340,400}))); + Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiHeaWatHp[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + "CHW/HW supply (HP leaving)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={-100,-200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=90,origin={-500,-400}))); + Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus + "Plant control bus" + annotation (Placement(transformation(extent={{20,180},{60,220}}), + iconTransformation(extent={{-20,380},{20,420}}))); + Buildings.Templates.Components.Pumps.Multiple pumHeaWat( + redeclare final package Medium=Medium, + final have_var=have_pumHeaWatPriVar, + final have_varCom=false, + final nPum=nPum, + final dat=datPumHeaWat, + final dpValChe_nominal=dpValCheHeaWat_nominal, + final allowFlowReversal=allowFlowReversal, + final tau=tau, + final energyDynamics=energyDynamics) + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + "Dedicated primary (HW) Pumps" + annotation (Placement(transformation(extent={{-130,-70},{-150,-50}}))); + Buildings.Templates.Components.Pumps.Multiple pumChiWat( + redeclare final package Medium=Medium, + final have_var=have_pumChiWatPriVar, + final have_varCom=false, + final nPum=if have_pumChiWatPriDed then nPum else 0, + final dat=datPumChiWat, + final dpValChe_nominal=dpValCheChiWat_nominal, + final allowFlowReversal=allowFlowReversal, + final tau=tau, + final energyDynamics=energyDynamics) + if have_pumChiWatPriDed + "Dedicated primary CHW pumps - Optional" + annotation (Placement(transformation(extent={{-48,-70},{-28,-50}}))); + Buildings.Templates.Components.Routing.PassThroughFluid pasHdr[nHp]( + redeclare each final package Medium = Medium) if typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Headered + "Direct fluid pass-through for headered primary pumps" annotation ( + Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={-100,-140}))); + Fluid.FixedResistances.Junction junDedSep[nPum]( + redeclare each final package Medium =Medium, + final m_flow_nominal={{ + max(datPumHeaWat.m_flow_nominal[i], datPumChiWat.m_flow_nominal[i]), + -datPumHeaWat.m_flow_nominal[i], + -datPumChiWat.m_flow_nominal[i]} for i in 1:nPum}, + dp_nominal=fill(fill(0, 3), nPum), + each final energyDynamics=energyDynamics, + each final portFlowDirection_1=if allowFlowReversal then + Modelica.Fluid.Types.PortFlowDirection.Bidirectional else + Modelica.Fluid.Types.PortFlowDirection.Entering, + each final portFlowDirection_2=if allowFlowReversal then + Modelica.Fluid.Types.PortFlowDirection.Bidirectional else + Modelica.Fluid.Types.PortFlowDirection.Leaving, + each final portFlowDirection_3=if allowFlowReversal then + Modelica.Fluid.Types.PortFlowDirection.Bidirectional else + Modelica.Fluid.Types.PortFlowDirection.Leaving) + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumChiWatPriDed + "Fluid junction for separate dedicated primary pumps" annotation (Placement( + transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={-80,-140}))); + Buildings.Templates.Components.Routing.PassThroughFluid pasDedCom[nHp]( + redeclare each final package Medium = Medium) if typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Dedicated and not + have_pumChiWatPriDed + "Direct fluid pass-through for common dedicated primary pumps" annotation ( + Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={-120,-140}))); +protected + Buildings.Templates.Components.Interfaces.Bus busPumHeaWatPri + "Primary HW pump control bus" + annotation (Placement(transformation(extent={{-20,-120},{20,-80}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busPumChiWatPri + if have_pumChiWatPriDed + "Primary CHW pump control bus" + annotation (Placement(transformation(extent={{-20,-70},{20,-30}}), + iconTransformation(extent={{-466,50},{-426,90}}))); +equation + connect(bus.pumHeaWatPri, busPumHeaWatPri) + annotation (Line(points={{40,200},{40,-100},{0,-100}}, + color={255,204,51},thickness=0.5)); + connect(bus.pumChiWatPri, busPumChiWatPri) + annotation (Line(points={{40,200},{40,-50},{0,-50}},color={255,204,51},thickness=0.5)); + connect(pumHeaWat.ports_b, ports_bHeaWat) + annotation (Line(points={{-150,-60},{-180,-60},{-180,200}}, + color={0,127,255})); + connect(pumHeaWat.ports_b, ports_bChiHeaWat) + annotation (Line(points={{-150,-60},{-160,-60},{-160,180},{-100,180},{-100, + 200}}, + color={0,127,255})); + connect(pumChiWat.ports_b, ports_bChiWat) + annotation (Line(points={{-28,-60},{-20,-60},{-20,200}}, + color={0,127,255})); + connect(busPumHeaWatPri, pumHeaWat.bus) + annotation (Line(points={{0,-100},{-140,-100},{-140,-50}}, color={255,204,51},thickness=0.5)); + connect(busPumChiWatPri, pumChiWat.bus) + annotation (Line(points={{0,-50},{-38,-50}},color={255,204,51},thickness=0.5)); + connect(ports_aChiHeaWat, ports_bChiHeaWatHp) + annotation (Line(points={{100,200},{100,-200}},color={0,127,255})); + connect(ports_aChiHeaWatHp, pasHdr.port_a) + annotation (Line(points={{-100,-200},{-100,-150}}, color={0,127,255})); + connect(pasHdr.port_b, ports_bChiHeaWat) + annotation (Line(points={{-100,-130},{-100,200}}, color={0,127,255})); + connect(junDedSep.port_3, pumChiWat.ports_a) annotation (Line(points={{-70, + -140},{-60,-140},{-60,-60},{-48,-60}}, + color={0,127,255})); + connect(ports_aChiHeaWatHp, pasDedCom.port_a) annotation (Line(points={{-100, + -200},{-120,-200},{-120,-150}}, color={0,127,255})); + connect(pasDedCom.port_b, pumHeaWat.ports_a) annotation (Line(points={{-120, + -130},{-120,-60},{-130,-60}}, + color={0,127,255})); + connect(ports_aChiHeaWatHp, junDedSep.port_1) annotation (Line(points={{-100, + -200},{-80,-200},{-80,-150}}, color={0,127,255})); + connect(junDedSep.port_2, pumHeaWat.ports_a) annotation (Line(points={{-80, + -130},{-80,-60},{-130,-60}}, + color={0,127,255})); + annotation ( + defaultComponentName="pumPri", + Diagram( + coordinateSystem( + extent={{-200,-200},{200,200}})), + Icon( + coordinateSystem( + preserveAspectRatio=false, + extent={{-2400,-400},{2400,400}}), graphics={ + Line( + points={{2000,60},{2000,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and nHp >= 1), + Line( + points={{2000,400},{2000,60}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 1), + Line( + points={{2200,400},{2200,-400}}, + color={0,0,0}, + thickness=5, + pattern=LinePattern.Dash, + visible=nHp >= 1), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 1, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={2022,10}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 1, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={2000,260}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumHeaWatPriVar and nHp >= 1, + extent={{2080,-50},{2180,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{2020,-40},{2020,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 1), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 1, + extent={{-50,-50},{50,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={1822,10}, + rotation=90), + Line( + points={{1800,400},{1800,60}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 1), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 1, + extent={{-40,-40},{40,40}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={1800,260}, + rotation=90), + Line( + points={{1820,-40},{1820,-200},{2020,-200}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 1), + Bitmap( + visible=have_pumChiWatPriDed and have_pumChiWatPriVar and nHp >= 1, + extent={{1660,-50},{1760,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{2066,0},{2080,0}}, + color={0,0,0}, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 1), + Line( + points={{1760,0},{1778,0}}, + color={0,0,0}, + visible=have_pumChiWatPriDed and nHp >= 1), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumHeaWatPriVar and nHp >= 1, + extent={{2080,-50},{2180,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Bitmap( + visible=have_pumChiWatPriDed and not have_pumChiWatPriVar and nHp >= + 1, + extent={{1660,-104},{1760,-4}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Line( + points={{-2000,60},{-2000,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and nHp >= 6), + Line( + points={{-2000,400},{-2000,60}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 6), + Line( + points={{-1800,400},{-1800,-400}}, + color={0,0,0}, + thickness=5, + pattern=LinePattern.Dash, + visible=nHp >= 6), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 6, + extent={{-50,-50},{50,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={-1978,10}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 6, + extent={{-40,-40},{40,40}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={-2000,260}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumHeaWatPriVar and nHp >= 6, + extent={{-1920,-50},{-1820,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{-1980,-40},{-1980,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 6), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 6, + extent={{-50,-50},{50,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={-2178,10}, + rotation=90), + Line( + points={{-2200,400},{-2200,60}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 6), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 6, + extent={{-40,-40},{40,40}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={-2200,260}, + rotation=90), + Line( + points={{-2180,-40},{-2180,-200},{-1980,-200}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 6), + Bitmap( + visible=have_pumChiWatPriDed and have_pumChiWatPriVar and nHp >= 6, + extent={{-2340,-50},{-2240,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{-1934,0},{-1920,0}}, + color={0,0,0}, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 6), + Line( + points={{-2240,0},{-2222,0}}, + color={0,0,0}, + visible=have_pumChiWatPriDed and nHp >= 6), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumHeaWatPriVar and nHp >= 6, + extent={{-1920,-50},{-1820,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Bitmap( + visible=have_pumChiWatPriDed and not have_pumChiWatPriVar and nHp >= 6, + extent={{-2340,-50},{-2240,50}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Line( + points={{-1200,60},{-1200,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and nHp >= 5), + Line( + points={{-1200,400},{-1200,60}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 5), + Line( + points={{-1000,400},{-1000,-400}}, + color={0,0,0}, + thickness=5, + pattern=LinePattern.Dash, + visible=nHp >= 5), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 5, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={-1178,10}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 5, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={-1200,260}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumHeaWatPriVar and nHp >= 5, + extent={{-1120,-50},{-1020,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{-1180,-40},{-1180,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 5), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 5, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={-1378,10}, + rotation=90), + Line( + points={{-1400,400},{-1400,60}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 5), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 5, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={-1400,260}, + rotation=90), + Line( + points={{-1380,-40},{-1380,-200},{-1180,-200}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 5), + Bitmap( + visible=have_pumChiWatPriDed and have_pumChiWatPriVar and nHp >= 5, + extent={{-1540,-50},{-1440,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{-1134,0},{-1120,0}}, + color={0,0,0}, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 5), + Line( + points={{-1440,0},{-1422,0}}, + color={0,0,0}, + visible=have_pumChiWatPriDed and nHp >= 5), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumHeaWatPriVar and nHp >= 5, + extent={{-1120,-50},{-1020,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Bitmap( + visible=have_pumChiWatPriDed and not have_pumChiWatPriVar and nHp >= + 5, + extent={{-1540,-50},{-1440,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Line( + points={{-400,60},{-400,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and nHp >= 4), + Line( + points={{-400,400},{-400,60}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 4), + Line( + points={{-200,400},{-200,-400}}, + color={0,0,0}, + thickness=5, + pattern=LinePattern.Dash, + visible=nHp >= 4), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 4, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={-378,10}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 4, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={-400,260}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumHeaWatPriVar and nHp >= 4, + extent={{-320,-50},{-220,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{-380,-40},{-380,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 4), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 4, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={-578,10}, + rotation=90), + Line( + points={{-600,400},{-600,60}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 4), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 4, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={-600,260}, + rotation=90), + Line( + points={{-580,-40},{-580,-200},{-380,-200}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 4), + Bitmap( + visible=have_pumChiWatPriDed and have_pumChiWatPriVar and nHp >= 4, + extent={{-740,-50},{-640,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{-334,0},{-320,0}}, + color={0,0,0}, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 4), + Line( + points={{-640,0},{-622,0}}, + color={0,0,0}, + visible=have_pumChiWatPriDed and nHp >= 4), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumHeaWatPriVar and nHp >= 4, + extent={{-320,-50},{-220,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Bitmap( + visible=have_pumChiWatPriDed and not have_pumChiWatPriVar and nHp >= + 4, + extent={{-740,-50},{-640,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Line( + points={{400,60},{400,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and nHp >= 3), + Line( + points={{400,400},{400,60}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 3), + Line( + points={{600,400},{600,-400}}, + color={0,0,0}, + thickness=5, + pattern=LinePattern.Dash, + visible=nHp >= 3), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 3, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={422,10}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 3, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={400,260}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumHeaWatPriVar and nHp >= 3, + extent={{480,-50},{580,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{420,-40},{420,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 3), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 3, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={222,10}, + rotation=90), + Line( + points={{200,400},{200,60}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 3), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 3, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={200,260}, + rotation=90), + Line( + points={{220,-40},{220,-200},{420,-200}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 3), + Bitmap( + visible=have_pumChiWatPriDed and have_pumChiWatPriVar and nHp >= 3, + extent={{60,-50},{160,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{466,0},{480,0}}, + color={0,0,0}, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 3), + Line( + points={{160,0},{178,0}}, + color={0,0,0}, + visible=have_pumChiWatPriDed and nHp >= 3), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumHeaWatPriVar and nHp >= 3, + extent={{480,-50},{580,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Bitmap( + visible=have_pumChiWatPriDed and not have_pumChiWatPriVar and nHp >= + 3, + extent={{60,-50},{160,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Line( + points={{1200,60},{1200,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and nHp >= 2), + Line( + points={{1200,400},{1200,60}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 2), + Line( + points={{1400,400},{1400,-400}}, + color={0,0,0}, + thickness=5, + pattern=LinePattern.Dash, + visible=nHp >= 2), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 2, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={1222,10}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 2, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={1200,260}, + rotation=90), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and have_pumHeaWatPriVar and nHp >= 2, + extent={{1280,-50},{1380,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{1220,-40},{1220,-400}}, + color={0,0,0}, + thickness=5, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 2), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 2, + extent={{-50,-50},{50,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Pumps/Single.svg", + origin={1022,10}, + rotation=90), + Line( + points={{1000,400},{1000,60}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 2), + Bitmap( + visible=have_pumChiWatPriDed and nHp >= 2, + extent={{-40,-40},{40,40}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/Check.svg", + origin={1000,260}, + rotation=90), + Line( + points={{1020,-40},{1020,-200},{1220,-200}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 2), + Bitmap( + visible=have_pumChiWatPriDed and have_pumChiWatPriVar and nHp >= 2, + extent={{860,-50},{960,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/VFD.svg"), + Line( + points={{1266,0},{1280,0}}, + color={0,0,0}, + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and nHp >= 2), + Line( + points={{960,0},{978,0}}, + color={0,0,0}, + visible=have_pumChiWatPriDed and nHp >= 2), + Bitmap( + visible=typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and not have_pumHeaWatPriVar and nHp >= 2, + extent={{1280,-50},{1380,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg"), + Bitmap( + visible=have_pumChiWatPriDed and not have_pumChiWatPriVar and nHp >= + 2, + extent={{860,-50},{960,50}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/MotorStarter.svg")}), + Documentation(revisions=" +
+This model represents dedicated primary HW pumps and, optionally,
+separate dedicated primary CHW pumps if the parameter
+have_pumChiWatPriDed
is set to true.
+The pump components are connected to the heat pump outlet,
+in a \"pump away\" configuration.
+Variable speed or constant speed pumps can be modeled by
+setting the parameters have_pumHeaWatPriVar
+and have_pumChiWatPriVar
.
+If headered pumps are modeled
+(typArrPumPri=Buildings.Templates.Components.Types.PumpArrangement.Headered
),
+this component resolves to a direct fluid pass-through.
+
+This model validates the model + +Buildings.Templates.Plants.HeatPumps.Components.HeatPumpGroups.AirToWater +in a configuration in which the heat pump components are exposed +to a constant differential pressure and a varying +return temperature. +
+
+The model is configured to represent either a non-reversible heat pump
+(component hpAwNrv
) or a reversible heat pump
+(component hpAw
) that switches between cooling and heating
+mode.
+
+This model validates the model + +Buildings.Templates.Plants.HeatPumps.Components.PumpsPrimaryDedicated +for the following configurations. +
+pumPriCom
.
+pumPriHdr
.
+pumPriSep
.
+pumPriHea
.
+
+In each configuration, two identical heat pumps are represented by fixed flow resistances
+(components hp*
).
+
+The model uses open loop controls and the simulation allows verifying that design flow +is obtained in each loop and each heat pump when the pumps are enabled. +
+
+In the configurations with common constant speed dedicated primary pumps or
+headered constant speed primary pumps, this requires adjusting the
+design pressure drop of the balancing valves which are modeled by fixed flow
+resistances in the isolation valve components
+valHeaWatIso*
and valChiWatIso*
.
+This adjustment is done programmatically using the function
+
+Buildings.Templates.Utilities.computeBalancingPressureDrop.
+
+Similarly, in the configuration with variable speed pumps pumPriHea
,
+the design head of the pumps is voluntarily chosen higher than necessary
+and the required pump speed needed to provide the design HP flow is computed
+at initialization by solving for a balancing valve pressure drop of zero.
+Note that this requires solving a numerical Jacobian at initialization.
+Although this is handled well by various Modelica tools, the parameter
+use_spePumIni
allows switching to a default value in
+this validation model for better integration into the continuous integration
+test workflow.
+
+This model validates the model + +Buildings.Templates.Plants.HeatPumps.Components.ValvesIsolation +for the following configurations. +
+valIsoCom
.
+valIsoHeaInl
.
+valIsoSep
.
+
+In each configuration, two identical heat pumps are represented by fixed
+flow resistances (components hp*
).
+
+The model uses open loop controls and the simulation allows verifying that design +flow is obtained in each loop and each heat pump when the valves are open. +
+")); +end ValvesIsolation; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Validation/package.mo b/Buildings/Templates/Plants/HeatPumps/Components/Validation/package.mo new file mode 100644 index 00000000000..d0e544e07bc --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Validation/package.mo @@ -0,0 +1,13 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +package Validation "Package with validation models" + extends Modelica.Icons.ExamplesPackage; + annotation ( + Documentation( + info=" ++This package contains validation models for the classes within + +Buildings.Templates.Plants.HeatPumps.Components. +
+")); +end Validation; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/Validation/package.order b/Buildings/Templates/Plants/HeatPumps/Components/Validation/package.order new file mode 100644 index 00000000000..2fae7671638 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/Validation/package.order @@ -0,0 +1,3 @@ +HeatPumpGroupAirToWater +PumpsPrimaryDedicated +ValvesIsolation diff --git a/Buildings/Templates/Plants/HeatPumps/Components/ValvesIsolation.mo b/Buildings/Templates/Plants/HeatPumps/Components/ValvesIsolation.mo new file mode 100644 index 00000000000..997b4cd520c --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/ValvesIsolation.mo @@ -0,0 +1,1229 @@ +within Buildings.Templates.Plants.HeatPumps.Components; +model ValvesIsolation + "Heat pump isolation valves" + replaceable package Medium=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "Medium model" + annotation (__ctrlFlow(enable=false)); + final parameter Buildings.Templates.Components.Types.Valve typ= + Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + "Valve type" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Integer nHp( + final min=1) + "Number of heat pumps" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Boolean have_chiWat + "Set to true if the plant provides CHW" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Boolean have_valHpInlIso + "Set to true for isolation valves at HP inlet" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Boolean have_valHpOutIso + "Set to true for isolation valves at HP outlet" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Boolean have_pumChiWatPriDed( + start=false) + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=have_chiWat)); + parameter Modelica.Units.SI.MassFlowRate mHeaWatHp_flow_nominal[nHp]( + each final min=0, + each start=0) + "HW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.PressureDifference dpHeaWatHp_nominal[nHp]( + each final min=0, + each start=Buildings.Templates.Data.Defaults.dpChiWatChi) + "Pressure drop at design HW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.PressureDifference dpBalHeaWatHp_nominal[nHp]( + each final min=0)=fill(0, nHp) + "Balancing valve pressure drop at design HW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.MassFlowRate mChiWatHp_flow_nominal[nHp]( + each start=0, + each final min=0) + "CHW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=have_chiWat)); + final parameter Modelica.Units.SI.PressureDifference dpChiWatHp_nominal[nHp]= + dpHeaWatHp_nominal .*(mChiWatHp_flow_nominal ./ mHeaWatHp_flow_nominal) .^ 2 + "Pressure drop at design CHW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=have_chiWat)); + parameter Modelica.Units.SI.PressureDifference dpBalChiWatHp_nominal[nHp]( + each final min=0, + each start=0)=fill(0, nHp) + "Balancing valve pressure drop at design CHW mass flow rate - Each heat pump" + annotation (Dialog(group="Nominal condition", + enable=have_chiWat)); + parameter Modelica.Units.SI.PressureDifference dpValveHeaWat_nominal[nHp]=fill(Buildings.Templates.Data.Defaults.dpValIso, nHp) + "HW isolation valve pressure drop: identical for inlet and outlet valves" + annotation (Dialog(group="Nominal condition")); + final parameter Modelica.Units.SI.PressureDifference dpFixedHeaWat_nominal[nHp]= + dpHeaWatHp_nominal + dpBalHeaWatHp_nominal + "Fixed HW pressure drop: HP + balancing valve" + annotation (Dialog(group="Nominal condition")); + final parameter Modelica.Units.SI.PressureDifference dpHeaWat_nominal[nHp]= + dpFixedHeaWat_nominal +(if have_valHpOutIso then dpValveHeaWat_nominal else fill(0, nHp)) + + (if have_valHpInlIso then dpValveHeaWat_nominal else fill(0, nHp)) + "Total HW pressure drop: fixed + valves" + annotation (Dialog(group="Nominal condition")); + parameter Modelica.Units.SI.PressureDifference dpValveChiWat_nominal[nHp]( + each start=0)=fill(Buildings.Templates.Data.Defaults.dpValIso, nHp) + "Isolation valve CHW pressure drop: identical for inlet and outlet valves" + annotation (Dialog(group="Nominal condition", + enable=have_chiWat)); + final parameter Modelica.Units.SI.PressureDifference dpFixedChiWat_nominal[nHp]= + if have_chiWat then dpChiWatHp_nominal + dpBalChiWatHp_nominal else fill(0, nHp) + "Total fixed CHW pressure drop" + annotation (Dialog(group="Nominal condition", + enable=have_chiWat)); + final parameter Modelica.Units.SI.PressureDifference dpChiWat_nominal[nHp]= + dpFixedChiWat_nominal +(if have_chiWat and have_valHpOutIso then dpValveChiWat_nominal + else fill(0, nHp)) +(if have_chiWat and have_valHpInlIso then dpValveChiWat_nominal + else fill(0, nHp)) + "Total CHW pressure drop: fixed + valves" + annotation (Dialog(group="Nominal condition", + enable=have_chiWat)); + final parameter Buildings.Templates.Components.Data.Valve datValHeaWatHpOutIso[nHp]( + each typ=typ, + m_flow_nominal=mHeaWatHp_flow_nominal, + dpValve_nominal=dpValveHeaWat_nominal, + dpFixed_nominal=dpFixedHeaWat_nominal) + "Heat pump outlet HW isolation valve parameters" + annotation (Placement(transformation(extent={{-30,80},{-10,100}}))); + // dpFixed_nominal only applied to inlet valves if there is no outlet valve. + final parameter Buildings.Templates.Components.Data.Valve datValHeaWatHpInlIso[nHp]( + each typ=typ, + m_flow_nominal=mHeaWatHp_flow_nominal, + dpValve_nominal=dpValveHeaWat_nominal, + dpFixed_nominal=if not have_valHpOutIso then dpFixedHeaWat_nominal else fill(0, nHp)) + "Heat pump inlet HW isolation valve parameters" + annotation (Placement(transformation(extent={{-30,80},{-10,100}}))); + final parameter Buildings.Templates.Components.Data.Valve datValChiWatHpOutIso[nHp]( + each typ=typ, + m_flow_nominal=mChiWatHp_flow_nominal, + dpValve_nominal=dpValveChiWat_nominal, + dpFixed_nominal=dpFixedChiWat_nominal) + "Heat pump outlet CHW isolation valve parameters" + annotation (Placement(transformation(extent={{10,80},{30,100}}))); + // dpFixed_nominal only applied to inlet valves if there is no outlet valve. + final parameter Buildings.Templates.Components.Data.Valve datValChiWatHpInlIso[nHp]( + each typ=typ, + m_flow_nominal=mChiWatHp_flow_nominal, + dpValve_nominal=dpValveChiWat_nominal, + dpFixed_nominal=if not have_valHpOutIso then dpFixedChiWat_nominal else fill(0, nHp)) + "Heat pump inlet CHW isolation valve parameters" + annotation (Placement(transformation(extent={{10,80},{30,100}}))); + parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial + "Type of energy balance: dynamic (3 initialization options) or steady state" + annotation (Evaluate=true, + Dialog(tab="Dynamics",group="Conservation equations")); + parameter Modelica.Units.SI.Time tau=10 + "Time constant at nominal flow" + annotation (Dialog(tab="Dynamics",group="Nominal condition", + enable=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState), + __ctrlFlow(enable=false)); + parameter Boolean allowFlowReversal=true + "Set to false to simplify equations, assuming, but not enforcing, no flow reversal" + annotation (Dialog(tab="Assumptions"), + Evaluate=true); + parameter Boolean use_inputFilter=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState + "= true, if opening is filtered with a 2nd order CriticalDamping filter" + annotation (__ctrlFlow(enable=false), + Dialog(tab="Dynamics",group="Filtered opening", + enable=have_valHpInlIso or have_valHpOutIso)); + parameter Modelica.Units.SI.Time riseTime=120 + "Rise time of the filter (time to reach 99.6 % of an opening step)" + annotation (__ctrlFlow(enable=false), + Dialog(tab="Dynamics",group="Filtered opening", + enable=use_inputFilter and have_valHpInlIso or have_valHpOutIso)); + parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput + "Type of initialization (no init/steady state/initial state/initial output)" + annotation (__ctrlFlow(enable=false), + Dialog(tab="Dynamics",group="Filtered opening", + enable=use_inputFilter and have_valHpInlIso or have_valHpOutIso)); + parameter Real y_start=1 + "Initial position of actuator" + annotation (__ctrlFlow(enable=false), + Dialog(tab="Dynamics",group="Filtered opening", + enable=use_inputFilter and have_valHpInlIso or have_valHpOutIso)); + parameter Boolean from_dp=true + "= true, use m_flow = f(dp) else dp = f(m_flow)" + annotation (Evaluate=true, + Dialog(tab="Advanced", + enable=have_valHpInlIso or have_valHpOutIso)); + parameter Boolean linearized=true + "= true, use linear relation between m_flow and dp for any flow rate" + annotation (Evaluate=true, + Dialog(tab="Advanced", + enable=have_valHpInlIso or have_valHpOutIso)); + Modelica.Fluid.Interfaces.FluidPort_b port_bChiWat( + redeclare final package Medium=Medium, + m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if have_chiWat + "CHW supply (to primary loop)" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={-100,200}), iconTransformation( + extent={{-10,-10},{10,10}}, + rotation=0, + origin={2400,600}))); + Modelica.Fluid.Interfaces.FluidPort_a port_aChiWat( + redeclare final package Medium=Medium, + m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if have_chiWat + "CHW return (from primary loop)" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={180,200}), iconTransformation( + extent={{-10,-10},{10,10}}, + rotation=0, + origin={2400,200}))); + Modelica.Fluid.Interfaces.FluidPort_b port_bHeaWat( + redeclare final package Medium=Medium, + m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + "HW supply (to primary loop)" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={-180,200}), iconTransformation( + extent={{-10,-10},{10,10}}, + rotation=180, + origin={-2400,0}))); + Modelica.Fluid.Interfaces.FluidPort_a port_aHeaWat( + redeclare final package Medium=Medium, + m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + "HW return (from primary loop)" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={100,200}), iconTransformation( + extent={{-10,-10},{10,10}}, + rotation=180, + origin={-2400,400}))); + Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiHeaWatHp[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + "CHW/HW return (HP entering)" + annotation (Placement(transformation(extent={{-10,-40},{10,40}},rotation=90, + origin={100,-200}), + iconTransformation(extent={{-10,-40},{10,40}},rotation=90,origin={500,-700}))); + Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiHeaWatHp[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if not have_pumChiWatPriDed + "CHW/HW supply (HP leaving)" + annotation (Placement(transformation( + extent={{-10,-40},{10,40}}, + rotation=90, + origin={-100,-200}), iconTransformation( + extent={{-10,-40},{10,40}}, + rotation=90, + origin={-500,-700}))); + Modelica.Fluid.Interfaces.FluidPorts_a ports_aHeaWatHp[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if have_pumChiWatPriDed + "HW supply (HP leaving)" + annotation (Placement(transformation( + extent={{-10,-40},{10,40}}, + rotation=90, + origin={-180,-200}), iconTransformation( + extent={{-10,-40},{10,40}}, + rotation=90, + origin={-660,-700}))); + Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiWatHp[nHp]( + redeclare each final package Medium=Medium, + each m_flow( + min=if allowFlowReversal then - Modelica.Constants.inf else 0), + each h_outflow( + start=Medium.h_default, + nominal=Medium.h_default)) + if have_pumChiWatPriDed + "CHW supply (HP leaving)" + annotation (Placement(transformation( + extent={{-10,-40},{10,40}}, + rotation=90, + origin={-20,-200}), iconTransformation( + extent={{-10,-40},{10,40}}, + rotation=90, + origin={-340,-700}))); + Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus + "Plant control bus" + annotation (Placement(transformation(extent={{-20,180},{20,220}}), + iconTransformation(extent={{-20,380},{20,420}}))); + Buildings.Templates.Components.Actuators.Valve valHeaWatHpOutIso[nHp]( + redeclare each final package Medium=Medium, + final dat=datValHeaWatHpOutIso, + each final typ=typ, + each final use_inputFilter=use_inputFilter, + each final riseTime=riseTime, + each final init=init, + each final y_start=y_start, + each final from_dp=from_dp, + each final linearized=linearized) + if have_valHpOutIso + "HP outlet HW isolation valve" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=90, + origin={-180,0}))); + Buildings.Templates.Components.Actuators.Valve valChiWatHpOutIso[nHp]( + redeclare each final package Medium=Medium, + final dat=datValChiWatHpOutIso, + each final typ=typ, + each final use_inputFilter=use_inputFilter, + each final riseTime=riseTime, + each final init=init, + each final y_start=y_start, + each final from_dp=from_dp, + each final linearized=linearized) + if have_valHpOutIso and have_chiWat + "HP outlet CHW isolation valve" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=90, + origin={-100,0}))); + Buildings.Templates.Components.Actuators.Valve valHeaWatHpInlIso[nHp]( + redeclare each final package Medium=Medium, + final dat=datValHeaWatHpInlIso, + each final typ=typ, + each final use_inputFilter=use_inputFilter, + each final riseTime=riseTime, + each final init=init, + each final y_start=y_start, + each final from_dp=from_dp, + each final linearized=linearized) + if have_valHpInlIso + "HP inlet HW isolation valve" + annotation (Placement(transformation(extent={{10,10},{-10,-10}},rotation=90, + origin={100,0}))); + Buildings.Templates.Components.Actuators.Valve valChiWatHpInlIso[nHp]( + redeclare each final package Medium=Medium, + final dat=datValChiWatHpInlIso, + each final typ=typ, + each final use_inputFilter=use_inputFilter, + each final riseTime=riseTime, + each final init=init, + each final y_start=y_start, + each final from_dp=from_dp, + each final linearized=linearized) + if have_valHpInlIso and have_chiWat + "HP inlet CHW isolation valve" + annotation (Placement(transformation(extent={{10,10},{-10,-10}},rotation=90, + origin={180,0}))); + Buildings.Templates.Components.Routing.PassThroughFluid pasHeaWatHpOut[nHp]( + redeclare each final package Medium=Medium) + if not have_valHpOutIso + "Direct fluid pass-through" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=90, + origin={-160,0}))); + Buildings.Templates.Components.Routing.PassThroughFluid pasChiWatHpOut[nHp]( + redeclare each final package Medium=Medium) + if not have_valHpOutIso and have_chiWat + "Direct fluid pass-through" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=90, + origin={-80,0}))); + Fluid.Delays.DelayFirstOrder junHeaWatSup( + redeclare final package Medium=Medium, + final tau=tau, + final m_flow_nominal=sum(mHeaWatHp_flow_nominal), + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final prescribedHeatFlowRate=false, + final nPorts=nHp + 1) + "Fluid volume at junction" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={-160,50}))); + Fluid.Delays.DelayFirstOrder junChiWatSup( + redeclare final package Medium=Medium, + final tau=tau, + final m_flow_nominal=sum(mChiWatHp_flow_nominal), + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final prescribedHeatFlowRate=false, + final nPorts=nHp + 1) + if have_chiWat + "Fluid volume at junction" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={-82,50}))); + Fluid.Delays.DelayFirstOrder junHeaWatRet( + redeclare final package Medium=Medium, + final tau=tau, + final m_flow_nominal=sum(mHeaWatHp_flow_nominal), + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final prescribedHeatFlowRate=false, + final nPorts=nHp + 1) + "Fluid volume at junction" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={80,50}))); + /* + HW pressure drop computed in this component in the absence of isolation valves + at both inlet and outlet. + */ + Fluid.FixedResistances.PressureDrop pasHeaWatHpInl[nHp]( + redeclare each final package Medium=Medium, + final m_flow_nominal=mHeaWatHp_flow_nominal, + final dp_nominal=if not have_valHpInlIso and not have_valHpOutIso then dpFixedHeaWat_nominal + else fill(0, nHp)) + if not have_valHpInlIso + "Direct fluid pass-through with optional fluid resistance" + annotation (Placement(transformation(extent={{10,10},{-10,-10}},rotation=90, + origin={80,0}))); + /* + CHW pressure drop computed in this component in the absence of isolation valves + at both inlet and outlet. + */ + Fluid.FixedResistances.PressureDrop pasChiWatHpInl[nHp]( + redeclare each final package Medium=Medium, + final m_flow_nominal=mChiWatHp_flow_nominal, + final dp_nominal=if not have_valHpInlIso and not have_valHpOutIso then dpFixedChiWat_nominal + else fill(0, nHp)) + if not have_valHpInlIso and have_chiWat + "Direct fluid pass-through with optional fluid resistance" + annotation (Placement(transformation(extent={{10,10},{-10,-10}},rotation=90, + origin={160,0}))); + Fluid.Delays.DelayFirstOrder junChiWatRet( + redeclare final package Medium=Medium, + final tau=tau, + final m_flow_nominal=sum(mChiWatHp_flow_nominal), + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + final prescribedHeatFlowRate=false, + final nPorts=nHp + 1) + if have_chiWat + "Fluid volume at junction" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={160,50}))); +protected + Buildings.Templates.Components.Interfaces.Bus busValHeaWatHpInlIso[nHp] + if have_valHpInlIso + "Heat pump inlet HW isolation valve control bus" + annotation (Placement(transformation(extent={{40,140},{80,180}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValHeaWatHpOutIso[nHp] + if have_valHpOutIso + "Heat pump outlet HW isolation valve control bus" + annotation (Placement(transformation(extent={{-80,140},{-40,180}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValChiWatHpInlIso[nHp] + if have_chiWat and have_valHpInlIso + "Heat pump inlet CHW isolation valve control bus" + annotation (Placement(transformation(extent={{10,160},{50,200}}), + iconTransformation(extent={{-466,50},{-426,90}}))); + Buildings.Templates.Components.Interfaces.Bus busValChiWatHpOutIso[nHp] + if have_chiWat and have_valHpOutIso + "Heat pump outlet CHW isolation valve control bus" + annotation (Placement(transformation(extent={{-50,160},{-10,200}}), + iconTransformation(extent={{-466,50},{-426,90}}))); +equation + connect(bus.valHeaWatHpInlIso, busValHeaWatHpInlIso) + annotation (Line(points={{0,200},{0,160},{60,160}},color={255,204,51},thickness=0.5)); + connect(bus.valHeaWatHpOutIso, busValHeaWatHpOutIso) + annotation (Line(points={{0,200},{0,160},{-60,160}},color={255,204,51},thickness=0.5)); + connect(bus.valChiWatHpInlIso, busValChiWatHpInlIso) + annotation (Line(points={{0,200},{0,180},{30,180}},color={255,204,51},thickness=0.5)); + connect(bus.valChiWatHpOutIso, busValChiWatHpOutIso) + annotation (Line(points={{0,200},{0,180},{-30,180}},color={255,204,51},thickness=0.5)); + connect(ports_aHeaWatHp, valHeaWatHpOutIso.port_a) + annotation (Line(points={{-180,-200},{-180,-10}},color={0,127,255})); + connect(ports_aChiHeaWatHp, valHeaWatHpOutIso.port_a) + annotation (Line(points={{-100,-200},{-120,-200},{-120,-20},{-180,-20},{ + -180,-10}}, + color={0,127,255})); + connect(ports_aChiHeaWatHp, valChiWatHpOutIso.port_a) + annotation (Line(points={{-100,-200},{-100,-200},{-100,-10}},color={0,127,255})); + connect(ports_aChiWatHp, valChiWatHpOutIso.port_a) + annotation (Line(points={{-20,-200},{-20,-20},{-100,-20},{-100,-10}}, color={0,127,255})); + connect(ports_aHeaWatHp, pasHeaWatHpOut.port_a) + annotation (Line(points={{-180,-200},{-160,-200},{-160,-10}}, color={0,127,255})); + connect(ports_aChiHeaWatHp, pasHeaWatHpOut.port_a) + annotation (Line(points={{-100,-200},{-120,-200},{-120,-20},{-160,-20},{ + -160,-10}}, + color={0,127,255})); + connect(ports_aChiHeaWatHp, pasChiWatHpOut.port_a) + annotation (Line(points={{-100,-200},{-80,-200},{-80,-10}}, color={0,127,255})); + connect(ports_aChiWatHp, pasChiWatHpOut.port_a) + annotation (Line(points={{-20,-200},{-20,-20},{-80,-20},{-80,-10}}, + color={0,127,255})); + connect(valHeaWatHpOutIso.port_b, junHeaWatSup.ports[1:nHp]) + annotation (Line(points={{-180,10},{-180,20},{-160,20},{-160,40}},color={0,127,255})); + connect(pasHeaWatHpOut.port_b, junHeaWatSup.ports[1:nHp]) + annotation (Line(points={{-160,10},{-160,40}},color={0,127,255})); + connect(junHeaWatSup.ports[nHp + 1], port_bHeaWat) + annotation (Line(points={{-160,40},{-180,40},{-180,200}},color={0,127,255})); + connect(valChiWatHpOutIso.port_b, junChiWatSup.ports[1:nHp]) + annotation (Line(points={{-100,10},{-100,20},{-82,20},{-82,40}},color={0,127,255})); + connect(pasChiWatHpOut.port_b, junChiWatSup.ports[1:nHp]) + annotation (Line(points={{-80,10},{-80,40},{-82,40}},color={0,127,255})); + connect(port_bChiWat, junChiWatSup.ports[nHp + 1]) + annotation (Line(points={{-100,200},{-100,40},{-82,40}},color={0,127,255})); + connect(port_aHeaWat, junHeaWatRet.ports[nHp + 1]) + annotation (Line(points={{100,200},{100,40},{80,40}},color={0,127,255})); + connect(junHeaWatRet.ports[1:nHp], valHeaWatHpInlIso.port_a) + annotation (Line(points={{80,40},{80,20},{100,20},{100,10}},color={0,127,255})); + connect(pasHeaWatHpInl.port_a, junHeaWatRet.ports[1:nHp]) + annotation (Line(points={{80,10},{80,26},{80,40},{80,40}},color={0,127,255})); + connect(port_aChiWat, junChiWatRet.ports[nHp + 1]) + annotation (Line(points={{180,200},{180,40},{160,40}},color={0,127,255})); + connect(valChiWatHpInlIso.port_a, junChiWatRet.ports[1:nHp]) + annotation (Line(points={{180,10},{180,20},{160,20},{160,40}},color={0,127,255})); + connect(pasChiWatHpInl.port_a, junChiWatRet.ports[1:nHp]) + annotation (Line(points={{160,10},{160,26},{160,40},{160,40}},color={0,127,255})); + connect(pasHeaWatHpInl.port_b, ports_bChiHeaWatHp) + annotation (Line(points={{80,-10},{80,-200},{100,-200}}, color={0,127,255})); + connect(valHeaWatHpInlIso.port_b, ports_bChiHeaWatHp) + annotation (Line(points={{100,-10},{100,-200}},color={0,127,255})); + connect(pasChiWatHpInl.port_b, ports_bChiHeaWatHp) + annotation (Line(points={{160,-10},{160,-180},{100,-180},{100,-200}},color={0,127,255})); + connect(valChiWatHpInlIso.port_b, ports_bChiHeaWatHp) + annotation (Line(points={{180,-10},{180,-180},{100,-180},{100,-200}}, + color={0,127,255})); + connect(busValHeaWatHpInlIso, valHeaWatHpInlIso.bus) + annotation (Line(points={{60,160},{110,160},{110,0}},color={255,204,51},thickness=0.5)); + connect(busValChiWatHpInlIso, valChiWatHpInlIso.bus) + annotation (Line(points={{30,180},{190,180},{190,0}},color={255,204,51},thickness=0.5)); + connect(busValChiWatHpOutIso, valChiWatHpOutIso.bus) + annotation (Line(points={{-30,180},{-110,180},{-110,0}},color={255,204,51},thickness=0.5)); + connect(busValHeaWatHpOutIso, valHeaWatHpOutIso.bus) + annotation (Line(points={{-60,160},{-190,160},{-190,0}},color={255,204,51},thickness=0.5)); + + annotation ( + defaultComponentName="valIso", + Diagram( + coordinateSystem( + extent={{-200,-200},{200,200}})), + Icon( + coordinateSystem( + preserveAspectRatio=false, + extent={{-2400,-700},{2400,700}}), graphics={ + Line( + points={{1000,-160},{1000,-700}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 2), + Line( + points={{200,-160},{200,-700}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 3), + Line( + points={{-600,-160},{-600,-700}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 4), + Line( + points={{-1400,-160},{-1400,-700}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 5), + Line( + points={{-2200,-160},{-2200,-700}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 6), + Line( + points={{1800,-160},{1800,-700}}, + color={0,0,0}, + thickness=5, + visible=have_pumChiWatPriDed and nHp >= 1), + Line( + points={{2400,200},{2400,-400},{2200,-400}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=have_chiWat and nHp >= 1), + Line( + points={{1800,-160},{1800,600},{2400,600}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and nHp >= 1), + Bitmap( + visible=have_chiWat and have_valHpOutIso and nHp >= 1, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={1800,-200}), + Line( points={{-2400,400},{2200,400},{2200,-700}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=nHp >= 1), + Bitmap( + visible=have_valHpInlIso and nHp >= 1, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={2200,-200}), + Bitmap( + visible=have_chiWat and nHp >= 1 and have_valHpInlIso, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={2400,-200}), + Line( visible=have_chiWat and nHp >= 1 and have_valHpInlIso, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={2370,-200}, + rotation=-90), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and nHp >= 1 and have_valHpInlIso, + extent={{2260,-240},{2340,-160}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpInlIso and nHp >= 1, + extent={{2060,-240},{2140,-160}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_valHpInlIso and nHp >= 1, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={2170,-200}, + rotation=-90), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpOutIso and nHp >= 1, + extent={{1860,-240},{1940,-160}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and have_valHpOutIso and nHp >= 1, + extent={{1660,-240},{1740,-160}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_chiWat and have_valHpOutIso and nHp >= 1, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={1770,-200}, + rotation=-90), + Rectangle( + extent={{1780,20},{1820,-20}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 1), + Line( + points={{1000,-160},{1000,600},{1800,600}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and nHp >= 2), + Bitmap( + visible=have_chiWat and have_valHpOutIso and nHp >= 2, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={1000,-200}), + Line( points={{1400,400},{1400,-700}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=nHp >= 2), + Bitmap( + visible=have_valHpInlIso and nHp >= 2, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={1400,-200}), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and nHp >= 2 and have_valHpInlIso, + extent={{1460,-240},{1540,-160}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpInlIso and nHp >= 2, + extent={{1260,-240},{1340,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_valHpInlIso and nHp >= 2, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={1370,-200}, + rotation=-90), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpOutIso and nHp >= 2, + extent={{1060,-240},{1140,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and have_valHpOutIso and nHp >= 2, + extent={{860,-240},{940,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_chiWat and have_valHpOutIso and nHp >= 2, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={970,-200}, + rotation=-90), + Rectangle( + extent={{980,20},{1020,-20}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 2), + Line( points={{1200,4},{1200,-696}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 2), + Bitmap( + visible=have_valHpOutIso and nHp >= 2, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={1200,-200}), + Line( visible=have_valHpOutIso and nHp >= 2, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={1170,-200}, + rotation=-90), + Line( + points={{200,-160},{200,600},{1000,600}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and nHp >= 3), + Bitmap( + visible=have_chiWat and have_valHpOutIso and nHp >= 3, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={200,-200}), + Line( points={{600,400},{600,-700}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=nHp >= 3), + Bitmap( + visible=have_valHpInlIso and nHp >= 3, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={600,-200}), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpInlIso and nHp >= 3, + extent={{460,-240},{540,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_valHpInlIso and nHp >= 3, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={570,-200}, + rotation=-90), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpOutIso and nHp >= 3, + extent={{260,-240},{340,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and have_valHpOutIso and nHp >= 3, + extent={{60,-240},{140,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_chiWat and have_valHpOutIso and nHp >= 3, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={170,-200}, + rotation=-90), + Rectangle( + extent={{180,20},{220,-20}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 3), + Line( points={{400,0},{400,-700}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 3), + Bitmap( + visible=have_valHpOutIso and nHp >= 3, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={400,-200}), + Line( visible=have_valHpOutIso and nHp >= 3, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={370,-200}, + rotation=-90), + Line( + points={{-600,-160},{-600,600},{200,600}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and nHp >= 4), + Bitmap( + visible=have_chiWat and have_valHpOutIso and nHp >= 4, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-600,-200}), + Line( points={{-200,400},{-200,-700}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=nHp >= 4), + Bitmap( + visible=have_valHpInlIso and nHp >= 4, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-200,-200}), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpInlIso and nHp >= 4, + extent={{-340,-240},{-260,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_valHpInlIso and nHp >= 4, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-230,-200}, + rotation=-90), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpOutIso and nHp >= 4, + extent={{-540,-240},{-460,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and have_valHpOutIso and nHp >= 4, + extent={{-740,-240},{-660,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_chiWat and have_valHpOutIso and nHp >= 4, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-630,-200}, + rotation=-90), + Rectangle( + extent={{-620,20},{-580,-20}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 4), + Line( points={{-400,0},{-400,-700}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 4), + Bitmap( + visible=have_valHpOutIso and nHp >= 4, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-400,-200}), + Line( visible=have_valHpOutIso and nHp >= 4, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-430,-200}, + rotation=-90), + Line( + points={{-1400,-160},{-1400,600},{-600,600}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and nHp >= 5), + Bitmap( + visible=have_chiWat and have_valHpOutIso and nHp >= 5, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-1400,-200}), + Line( points={{-1000,400},{-1000,-700}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=nHp >= 5), + Bitmap( + visible=have_valHpInlIso and nHp >= 5, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-1000,-200}), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpInlIso and nHp >= 5, + extent={{-1140,-240},{-1060,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_valHpInlIso and nHp >= 5, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-1030,-200}, + rotation=-90), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpOutIso and nHp >= 5, + extent={{-1340,-240},{-1260,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and have_valHpOutIso and nHp >= 5, + extent={{-1540,-240},{-1460,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_chiWat and have_valHpOutIso and nHp >= 5, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-1430,-200}, + rotation=-90), + Rectangle( + extent={{-1420,20},{-1380,-20}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 5), + Line( points={{-1200,0},{-1200,-700}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 5), + Bitmap( + visible=have_valHpOutIso and nHp >= 5, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-1200,-200}), + Line( visible=have_valHpOutIso and nHp >= 5, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-1230,-200}, + rotation=-90), + Line( + points={{-2200,-160},{-2200,600},{-1400,600}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and nHp >= 6), + Bitmap( + visible=have_chiWat and have_valHpOutIso and nHp >= 6, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-2200,-200}), + Line( points={{-1800,400},{-1800,-700}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=nHp >= 6), + Bitmap( + visible=have_valHpInlIso and nHp >= 6, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-1800,-200}), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpInlIso and nHp >= 6, + extent={{-1940,-240},{-1860,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_valHpInlIso and nHp >= 6, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-1830,-200}, + rotation=-90), + Bitmap( + visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_valHpOutIso and nHp >= 6, + extent={{-2140,-240},{-2060,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and have_valHpOutIso and nHp >= 6, + extent={{-2340,-240},{-2260,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( visible=have_chiWat and have_valHpOutIso and nHp >= 6, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-2230,-200}, + rotation=-90), + Rectangle( + extent={{-2220,20},{-2180,-22}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 6), + Line( points={{-2000,0},{-2000,-700}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 6), + Bitmap( + visible=have_valHpOutIso and nHp >= 6, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-2000,-200}), + Line( visible=have_valHpOutIso and nHp >= 6, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-2030,-200}, + rotation=-90), + Line( points={{-2400,0},{2000,0},{2000,-700}}, + color={0,0,0}, + thickness=5, + visible=nHp >= 1), + Bitmap( + visible=have_valHpOutIso and nHp >= 1, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={2000,-200}), + Line( visible=have_valHpOutIso and nHp >= 1, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={1970,-200}, + rotation=-90), + Line(points={{1820,-508}}, color={0,0,0}), + Line( + points={{160,150},{0,150},{0,-50}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and not have_pumChiWatPriDed and nHp >= 1, + origin={1950,-400}, + rotation=90), + Line( + points={{160,150},{0,150},{0,-50}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and not have_pumChiWatPriDed and nHp >= 2, + origin={1150,-400}, + rotation=90), + Line( + points={{160,150},{0,150},{0,-50}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and not have_pumChiWatPriDed and nHp >= 3, + origin={350,-400}, + rotation=90), + Line( + points={{160,150},{0,150},{0,-50}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and not have_pumChiWatPriDed and nHp >= 4, + origin={-450,-400}, + rotation=90), + Line( + points={{160,150},{0,150},{0,-50}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and not have_pumChiWatPriDed and nHp >= 5, + origin={-1250,-400}, + rotation=90), + Line( + points={{160,150},{0,150},{0,-50}}, + color={0,0,0}, + thickness=5, + visible=have_chiWat and not have_pumChiWatPriDed and nHp >= 6, + origin={-2050,-400}, + rotation=90), + Rectangle( + extent={{2180,220},{2220,178}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 2), + Line( + points={{2400,200},{1600,200},{1600,-400},{1400,-400}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=have_chiWat and nHp >= 2), + Bitmap( + visible=have_chiWat and nHp >= 2 and have_valHpInlIso, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={1600,-200}), + Line( visible=have_chiWat and nHp >= 2 and have_valHpInlIso, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={1570,-200}, + rotation=-90), + Rectangle( + extent={{1380,220},{1420,178}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 3), + Line( + points={{1600,200},{800,200},{800,-400},{600,-400}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=have_chiWat and nHp >= 3), + Bitmap( + visible=have_chiWat and nHp >= 3 and have_valHpInlIso, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={800,-200}), + Line( visible=have_chiWat and nHp >= 3 and have_valHpInlIso, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={770,-200}, + rotation=-90), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and nHp >= 3 and have_valHpInlIso, + extent={{660,-240},{740,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Rectangle( + extent={{580,220},{620,180}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 4), + Rectangle( + extent={{-220,220},{-180,180}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 5), + Rectangle( + extent={{-1020,220},{-980,180}}, + lineColor={0,0,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + visible=have_chiWat and nHp >= 6), + Line( + points={{800,200},{0,200},{0,-400},{-200,-400}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=have_chiWat and nHp >= 4), + Bitmap( + visible=have_chiWat and nHp >= 4 and have_valHpInlIso, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={0,-200}), + Line( visible=have_chiWat and nHp >= 4 and have_valHpInlIso, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-30,-200}, + rotation=-90), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and nHp >= 4 and have_valHpInlIso, + extent={{-140,-240},{-60,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( + points={{0,200},{-800,200},{-800,-400},{-1000,-400}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=have_chiWat and nHp >= 5), + Bitmap( + visible=have_chiWat and nHp >= 5 and have_valHpInlIso, + extent={{-100,-100},{100,100}}, + fileName= + "modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-800,-200}), + Line( visible=have_chiWat and nHp >= 5 and have_valHpInlIso, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-830,-200}, + rotation=-90), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and nHp >= 5 and have_valHpInlIso, + extent={{-940,-240},{-860,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg"), + Line( + points={{-800,200},{-1600,200},{-1600,-400},{-1800,-400}}, + color={0,0,0}, + pattern=LinePattern.Dash, + thickness=5, + visible=have_chiWat and nHp >= 6), + Bitmap( + visible=have_chiWat and nHp >= 6 and have_valHpInlIso, + extent={{-100,-100},{100,100}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Valves/TwoWay.svg", + rotation=360, + origin={-1600,-200}), + Line( visible=have_chiWat and nHp >= 6 and have_valHpInlIso, + points={{0,30},{0,-30}}, + color={0,0,0}, + origin={-1630,-200}, + rotation=-90), + Bitmap(visible=typ == Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition + and have_chiWat and nHp >= 6 and have_valHpInlIso, + extent={{-1740,-240},{-1660,-160}}, + fileName="modelica://Buildings/Resources/Images/Templates/Components/Actuators/TwoPosition.svg")}), + Documentation( + info=" +
+This model represents the heat pump isolation valves.
+The isolation valves are modeled as two-way two-position
+valves, which can be located at the heat pump inlet and/or
+outlet depending on the settings of the parameters have_valHpInlIso
+and have_valHpOutIso
.
+It is assumed that the heat pumps always provide heating hot water.
+Optionally, chilled water return and supply and the associated isolation valves
+can be modeled by setting the parameter have_chiWat
to true.
+
+By default, the isolation valves are modeled considering a linear
+variation of the pressure drop with the flow rate (linearized=true
),
+as opposed to the quadratic relationship usually considered for
+a turbulent flow regime.
+By limiting the size of the system of nonlinear equations, this setting
+reduces the risk of solver failure and the time to solution.
+", revisions="
+
+This package contains component models that are used in the templates +within + +Buildings.Templates.Plants.HeatPumps. +
+")); +end Components; diff --git a/Buildings/Templates/Plants/HeatPumps/Components/package.order b/Buildings/Templates/Plants/HeatPumps/Components/package.order new file mode 100644 index 00000000000..426b14e3579 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Components/package.order @@ -0,0 +1,7 @@ +PumpsPrimaryDedicated +ValvesIsolation +Controls +HeatPumpGroups +Data +Validation +Interfaces diff --git a/Buildings/Templates/Plants/HeatPumps/Configuration/HeatPumpPlant.mo b/Buildings/Templates/Plants/HeatPumps/Configuration/HeatPumpPlant.mo new file mode 100644 index 00000000000..be40d255458 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Configuration/HeatPumpPlant.mo @@ -0,0 +1,138 @@ +within Buildings.Templates.Plants.HeatPumps.Configuration; +record HeatPumpPlant + "Configuration parameters for heat pump plant" + extends Modelica.Icons.Record; + // Generic + parameter Buildings.Templates.Components.Types.HeatPump typ + "Type of heat pump" + annotation (Evaluate=true); + parameter Buildings.Templates.Components.Types.HeatPumpModel typMod + "Type of heat pump model" + annotation (Evaluate=true); + parameter Boolean have_heaWat + "Set to true if the plant provides HW" + annotation (Evaluate=true); + parameter Boolean have_hotWat + "Set to true if the plant provides DHW" + annotation (Evaluate=true); + parameter Boolean have_chiWat + "Set to true if the plant provides CHW" + annotation (Evaluate=true); + parameter Boolean have_hrc + "Set to true for plants with a sidestream heat recovery chiller" + annotation (Evaluate=true); + parameter Integer nHp + "Number of heat pumps" + annotation (Evaluate=true); + parameter Boolean is_rev + "Set to true for reversible heat pumps, false for heating only" + annotation (Evaluate=true); + parameter Boolean have_valHpInlIso + "Set to true for isolation valves at HP inlet" + annotation (Evaluate=true); + parameter Boolean have_valHpOutIso + "Set to true for isolation valves at HP outlet" + annotation (Evaluate=true); + parameter Buildings.Templates.Plants.HeatPumps.Types.Controller typCtl + "Type of controller" + annotation (Evaluate=true); + parameter Integer nAirHan + "Number of air handling units served by the plant" + annotation (Evaluate=true); + parameter Integer nEquZon + "Number of terminal units (zone equipment) served by the plant" + annotation (Evaluate=true); + // Default fluid properties + parameter Modelica.Units.SI.Density rhoHeaWat_default + "HW default density" + annotation (Evaluate=true); + parameter Modelica.Units.SI.SpecificHeatCapacity cpHeaWat_default + "HW default specific heat capacity" + annotation (Evaluate=true); + parameter Modelica.Units.SI.Density rhoChiWat_default + "CHW default density" + annotation (Evaluate=true); + parameter Modelica.Units.SI.SpecificHeatCapacity cpChiWat_default + "CHW default specific heat capacity" + annotation (Evaluate=true); + parameter Modelica.Units.SI.Density rhoSou_default + "Source fluid default density" + annotation (Evaluate=true); + parameter Modelica.Units.SI.SpecificHeatCapacity cpSou_default + "Source fluid default specific heat capacity" + annotation (Evaluate=true); + // HW loop + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumHeaWatPri + "Type of primary HW pumps" + annotation (Evaluate=true); + parameter Integer nPumHeaWatPri + "Number of primary HW pumps" + annotation (Evaluate=true); + parameter Integer nPumHeaWatSec + "Number of secondary HW pumps" + annotation (Evaluate=true); + parameter Boolean have_valHeaWatMinByp + "Set to true if the HW loop has a minimum flow bypass valve" + annotation (Evaluate=true); + parameter Buildings.Templates.Components.Types.PumpArrangement typArrPumPri + "Type of primary pump arrangement" + annotation (Evaluate=true); + parameter Boolean have_pumHeaWatPriVar + "Set to true for variable speed primary HW pumps" + annotation (Evaluate=true); + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary typPumHeaWatSec + "Type of secondary HW pumps" + annotation (Evaluate=true); + parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis + "Type of CHW/HW distribution system" + annotation (Evaluate=true); + parameter Boolean have_senDpHeaWatRemWir + "Set to true for remote HW differential pressure sensor(s) hardwired to plant or pump controller" + annotation (Evaluate=true); + parameter Integer nSenDpHeaWatRem + "Number of remote HW differential pressure sensors used for HW pump speed control" + annotation (Evaluate=true); + // CHW loop + parameter Boolean have_pumChiWatPriDed + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true); + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumChiWatPri + "Type of primary CHW pumps" + annotation (Evaluate=true); + parameter Integer nPumChiWatPri + "Number of primary CHW pumps" + annotation (Evaluate=true); + parameter Integer nPumChiWatSec + "Number of secondary CHW pumps" + annotation (Evaluate=true); + parameter Boolean have_valChiWatMinByp + "Set to true if the CHW loop has a minimum flow bypass valve" + annotation (Evaluate=true); + parameter Boolean have_pumChiWatPriVar + "Set to true for variable speed primary CHW pumps" + annotation (Evaluate=true); + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary typPumChiWatSec + "Type of secondary CHW pumps" + annotation (Evaluate=true); + parameter Boolean have_senDpChiWatRemWir + "Set to true for remote CHW differential pressure sensor(s) hardwired to plant or pump controller" + annotation (Evaluate=true); + parameter Integer nSenDpChiWatRem + "Number of remote CHW differential pressure sensors used for CHW pump speed control" + annotation (Evaluate=true); + parameter Boolean have_inpSch + "Set to true to provide schedule via software input point" + annotation (Evaluate=true); + annotation ( + defaultComponentPrefixes="parameter", + defaultComponentName="cfg", + Documentation( + info=" ++This record provides the set of configuration parameters for +the heat pump plant models within + +Buildings.Templates.Plants.HeatPumps. +
+")); +end HeatPumpPlant; diff --git a/Buildings/Templates/Plants/HeatPumps/Configuration/package.mo b/Buildings/Templates/Plants/HeatPumps/Configuration/package.mo new file mode 100644 index 00000000000..8febf249dd3 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Configuration/package.mo @@ -0,0 +1,9 @@ +within Buildings.Templates.Plants.HeatPumps; +package Configuration "Records for configuration parameters" + extends Modelica.Icons.MaterialPropertiesPackage; + annotation (Documentation(info=" ++This package provides records for configuration parameters. +
+")); +end Configuration; diff --git a/Buildings/Templates/Plants/HeatPumps/Configuration/package.order b/Buildings/Templates/Plants/HeatPumps/Configuration/package.order new file mode 100644 index 00000000000..e15cae8bbc9 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Configuration/package.order @@ -0,0 +1 @@ +HeatPumpPlant diff --git a/Buildings/Templates/Plants/HeatPumps/Data/HeatPumpPlant.mo b/Buildings/Templates/Plants/HeatPumps/Data/HeatPumpPlant.mo new file mode 100644 index 00000000000..309f5f718d6 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Data/HeatPumpPlant.mo @@ -0,0 +1,127 @@ +within Buildings.Templates.Plants.HeatPumps.Data; +record HeatPumpPlant + "Record for heat pump plant" + extends Modelica.Icons.Record; + // Generic + parameter Buildings.Templates.Plants.HeatPumps.Configuration.HeatPumpPlant cfg + "Configuration parameters" + annotation (Dialog(enable=false)); + parameter String id="" + "System tag" + annotation (Dialog(tab="Advanced")); + parameter Buildings.Templates.Plants.HeatPumps.Components.Data.Controller ctl( + final cfg=cfg) + "Controller" + annotation (Dialog(group="Controls")); + parameter Buildings.Templates.Plants.HeatPumps.Components.Data.HeatPumpGroup + hp( + final typ=cfg.typ, + final nHp=cfg.nHp, + final is_rev=cfg.is_rev, + final typMod=cfg.typMod, + final cpHeaWat_default=cfg.cpHeaWat_default, + final cpSou_default=cfg.cpSou_default, + TChiWatSupHp_nominal=ctl.TChiWatSup_nominal, + capCooHp_nominal=ctl.capCooHp_nominal, + mHeaWatHp_flow_nominal=ctl.VHeaWatHp_flow_nominal*cfg.rhoHeaWat_default, + capHeaHp_nominal=ctl.capHeaHp_nominal, + mChiWatHp_flow_nominal=ctl.VChiWatHp_flow_nominal*cfg.rhoChiWat_default, + THeaWatSupHp_nominal=ctl.THeaWatSup_nominal) + "Heat pumps" + annotation (Dialog(group="Heat pumps")); + // HW loop + parameter Buildings.Templates.Components.Data.PumpMultiple pumHeaWatPri( + final nPum=cfg.nPumHeaWatPri, + final rho_default=cfg.rhoHeaWat_default, + final typ=if cfg.typPumHeaWatPri <> Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None + then Buildings.Templates.Components.Types.Pump.Multiple else Buildings.Templates.Components.Types.Pump.None, + m_flow_nominal=fill(hp.nHp * ( + if cfg.have_chiWat and cfg.typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None then + max(hp.mHeaWatHp_flow_nominal, hp.mChiWatHp_flow_nominal) else hp.mHeaWatHp_flow_nominal) / + max(cfg.nPumHeaWatPri, 1), + cfg.nPumHeaWatPri)) + "Primary HW pumps" + annotation (Dialog(group="Primary HW loop")); + final parameter Buildings.Templates.Components.Data.PumpSingle pumHeaWatPriSin[max(cfg.nPumHeaWatPri, 1)]( + each typ=pumHeaWatPri.typ, + m_flow_nominal=if pumHeaWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then {0} else pumHeaWatPri.m_flow_nominal, + dp_nominal=if pumHeaWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then {0} else pumHeaWatPri.dp_nominal, + per( + pressure( + V_flow=if pumHeaWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then + [0] else pumHeaWatPri.per.pressure.V_flow, + dp=if pumHeaWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then + [0] else pumHeaWatPri.per.pressure.dp)), + each rho_default=pumHeaWatPri.rho_default) + "Cast multiple pump record into single pump record array"; + parameter Buildings.Templates.Components.Data.PumpMultiple pumHeaWatSec( + final nPum=cfg.nPumHeaWatSec, + final rho_default=cfg.rhoHeaWat_default, + final typ=if cfg.typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + then Buildings.Templates.Components.Types.Pump.Multiple else Buildings.Templates.Components.Types.Pump.None) + "Secondary HW pumps" + annotation (Dialog(group="Secondary HW loop", + enable=cfg.have_heaWat and cfg.typPumHeaWatSec==Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized)); + // CHW loop + parameter Buildings.Templates.Components.Data.PumpMultiple pumChiWatPri( + final nPum=cfg.nPumChiWatPri, + final rho_default=cfg.rhoChiWat_default, + final typ=if cfg.typPumChiWatPri <> Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None + then Buildings.Templates.Components.Types.Pump.Multiple else Buildings.Templates.Components.Types.Pump.None, + m_flow_nominal=fill(hp.mChiWatHp_flow_nominal * hp.nHp / max(cfg.nPumChiWatPri, 1), cfg.nPumChiWatPri)) + "Primary CHW pumps" + annotation (Dialog(group="Primary CHW loop", + enable=cfg.typPumChiWatPri<>Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None)); + final parameter Buildings.Templates.Components.Data.PumpSingle pumChiWatPriSin[max(cfg.nPumChiWatPri, 1)]( + each typ=pumChiWatPri.typ, + m_flow_nominal=if pumChiWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then {0} else pumChiWatPri.m_flow_nominal, + dp_nominal=if pumChiWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then {0} else pumChiWatPri.dp_nominal, + per( + pressure( + V_flow=if pumChiWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then + [ + 0] else pumChiWatPri.per.pressure.V_flow, + dp=if pumChiWatPri.typ == Buildings.Templates.Components.Types.Pump.None + then + [ + 0] else pumChiWatPri.per.pressure.dp)), + each rho_default=pumChiWatPri.rho_default) + "Cast multiple pump record into single pump record array"; + parameter Buildings.Templates.Components.Data.PumpMultiple pumChiWatSec( + final nPum=cfg.nPumChiWatSec, + final rho_default=cfg.rhoChiWat_default, + final typ=if cfg.typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + then Buildings.Templates.Components.Types.Pump.Multiple else Buildings.Templates.Components.Types.Pump.None) + "Secondary CHW pumps" + annotation (Dialog(group="Secondary CHW loop", + enable=cfg.typPumChiWatSec==Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized)); + annotation ( + defaultComponentName="dat", + Documentation( + info=" ++This record provides the set of sizing and operating parameters for +the heat pump plant models within + +Buildings.Templates.Plants.HeatPumps. +
++Most of the parameters should be assigned through the sub-record +dedicated to the controller. +All parameters that are also needed to parameterize other plant +components are propagated from the controller sub-record +to the corresponding equipment sub-records. +Note that those parameter bindings are not final so they may be +overwritten in case a component is parameterized at nominal +conditions that differ from the design conditions specified +in the controller sub-record. +
+")); +end HeatPumpPlant; diff --git a/Buildings/Templates/Plants/HeatPumps/Data/package.mo b/Buildings/Templates/Plants/HeatPumps/Data/package.mo new file mode 100644 index 00000000000..14334eb8a65 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Data/package.mo @@ -0,0 +1,11 @@ +within Buildings.Templates.Plants.HeatPumps; +package Data "Records for design and operating parameters" + extends Modelica.Icons.MaterialPropertiesPackage; + annotation ( + Documentation( + info=" ++This package provides records for design and operating parameters. +
+")); +end Data; diff --git a/Buildings/Templates/Plants/HeatPumps/Data/package.order b/Buildings/Templates/Plants/HeatPumps/Data/package.order new file mode 100644 index 00000000000..e15cae8bbc9 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Data/package.order @@ -0,0 +1 @@ +HeatPumpPlant diff --git a/Buildings/Templates/Plants/HeatPumps/Interfaces/Bus.mo b/Buildings/Templates/Plants/HeatPumps/Interfaces/Bus.mo new file mode 100644 index 00000000000..98cba382fc0 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Interfaces/Bus.mo @@ -0,0 +1,16 @@ +within Buildings.Templates.Plants.HeatPumps.Interfaces; +expandable connector Bus + "Control bus for heat pump plant" + extends Modelica.Icons.SignalBus; + annotation ( + defaultComponentName="bus", + Documentation( + info=" ++ This expandable connector provides a standard interface for + all control signals of the heat pump plant models within + + Buildings.Templates.Plants.HeatPumps. +
+ ")); +end Bus; diff --git a/Buildings/Templates/Plants/HeatPumps/Interfaces/PartialHeatPumpPlant.mo b/Buildings/Templates/Plants/HeatPumps/Interfaces/PartialHeatPumpPlant.mo new file mode 100644 index 00000000000..8f57e405b53 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Interfaces/PartialHeatPumpPlant.mo @@ -0,0 +1,772 @@ +within Buildings.Templates.Plants.HeatPumps.Interfaces; +partial model PartialHeatPumpPlant + "Interface class for heat pump plant" + replaceable package MediumHeaWat=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "HW medium" + annotation (Dialog(enable=have_heaWat), + __ctrlFlow(enable=false)); + replaceable package MediumHotWat=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "DHW medium" + annotation (Dialog(enable=have_hotWat), + __ctrlFlow(enable=false)); + replaceable package MediumChiWat=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "CHW medium" + annotation (Dialog(enable=have_chiWat), + __ctrlFlow(enable=false)); + /* + Derived classes representing AWHP shall use: + redeclare final package MediumSou = MediumAir + */ + replaceable package MediumSou=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "Source-side medium" + annotation (Dialog(enable=typ==Buildings.Templates.Components.Types.HeatPump.WaterToWater), + __ctrlFlow(enable=false)); + replaceable package MediumAir=Buildings.Media.Air + constrainedby Modelica.Media.Interfaces.PartialMedium + "Air medium" + annotation (Dialog(enable=typ==Buildings.Templates.Components.Types.HeatPump.AirToWater), + __ctrlFlow(enable=false)); + // The current implementation only supports plants that provide HHW. + final parameter Boolean have_heaWat=true + "Set to true if the plant provides HW" + annotation (Evaluate=true, + Dialog(group="Configuration")); + parameter Boolean have_chiWat=true + "Set to true if the plant provides CHW" + annotation (Evaluate=true, + Dialog(group="Configuration")); + // RFE: To be exposed for templates that include optional DHW service. + final parameter Boolean have_hotWat=false + "Set to true if the plant provides DHW" + annotation (Evaluate=true, + Dialog(group="Configuration")); + // RFE(AntoineGautier): Add option for sidestream HRC. Always excluded for now. + final parameter Boolean have_hrc( + start=false)=false + "Set to true for plants with a sidestream heat recovery chiller" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=have_heaWat and have_chiWat)); + parameter Buildings.Templates.Components.Types.HeatPump typ + "Type of heat pump" + annotation (Evaluate=true, + Dialog(group="Heat pumps")); + parameter Buildings.Templates.Plants.HeatPumps.Configuration.HeatPumpPlant cfg( + final cpChiWat_default=cpChiWat_default, + final cpHeaWat_default=cpHeaWat_default, + final cpSou_default=cpSou_default, + final have_chiWat=have_chiWat, + final have_heaWat=have_heaWat, + final have_hrc=have_hrc, + final have_hotWat=have_hotWat, + final have_pumHeaWatPriVar=have_pumHeaWatPriVar, + final have_pumChiWatPriVar=have_pumChiWatPriVar, + final have_pumChiWatPriDed=have_pumChiWatPriDed, + final have_valChiWatMinByp=have_valChiWatMinByp, + final have_valHeaWatMinByp=have_valHeaWatMinByp, + final have_valHpInlIso=have_valHpInlIso, + final have_valHpOutIso=have_valHpOutIso, + final is_rev=is_rev, + final nHp=nHp, + final nPumChiWatPri=nPumChiWatPri, + final nPumChiWatSec=nPumChiWatSec, + final nPumHeaWatPri=nPumHeaWatPri, + final nPumHeaWatSec=nPumHeaWatSec, + final rhoChiWat_default=rhoChiWat_default, + final rhoHeaWat_default=rhoHeaWat_default, + final rhoSou_default=rhoSou_default, + final typ=typ, + final typArrPumPri=typArrPumPri, + final typDis=typDis, + final typPumChiWatPri=typPumChiWatPri, + final typPumHeaWatPri=typPumHeaWatPri, + final typPumChiWatSec=typPumChiWatSec, + final typPumHeaWatSec=typPumHeaWatSec, + final typCtl=ctl.typ, + final nAirHan=ctl.nAirHan, + final nEquZon=ctl.nEquZon, + final have_senDpHeaWatRemWir=ctl.have_senDpHeaWatRemWir, + final nSenDpHeaWatRem=ctl.nSenDpHeaWatRem, + final have_senDpChiWatRemWir=ctl.have_senDpChiWatRemWir, + final nSenDpChiWatRem=ctl.nSenDpChiWatRem, + final have_inpSch=ctl.have_inpSch) + "Configuration parameters" + annotation (__ctrlFlow(enable=false)); + parameter Buildings.Templates.Plants.HeatPumps.Data.HeatPumpPlant dat( + cfg=cfg) + "Design and operating parameters" + annotation (Placement(transformation(extent={{-120,360},{-100,380}}))); + // RFE(AntoineGautier): Allow specifying subset of units dedicated to HW, CHW or DHW production. + parameter Integer nHp( + final min=1, + start=1) + "Total number of heat pumps" + annotation (Evaluate=true, + Dialog(group="Heat pumps")); + parameter Boolean is_rev + "Set to true for reversible heat pumps, false for heating only" + annotation (Evaluate=true, + Dialog(group="Heat pumps")); + // Plants with AWHP. + // RFE(AntoineGautier): Add constant primary-only option. + final parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis_select1( + start=Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2)= + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2 + "Type of distribution system" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ==Buildings.Templates.Components.Types.HeatPump.AirToWater), + choices( + choice=Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2 + "Constant primary - Variable secondary centralized")); + // Plants with WWHP. + parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis_select2( + start=Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2) + "Type of distribution system" + annotation (Evaluate=true, + Dialog(group="Configuration", + enable=typ==Buildings.Templates.Components.Types.HeatPump.WaterToWater)); + final parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis= + if typ == Buildings.Templates.Components.Types.HeatPump.AirToWater then typDis_select1 + else typDis_select2 + "Type of distribution system" + annotation (Evaluate=true); + final parameter Boolean have_valHpInlIso=if not have_chiWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Dedicated then false + else true + "Set to true for isolation valves at HP inlet" + annotation (Evaluate=true); + final parameter Boolean have_valHpOutIso=if not have_chiWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Dedicated then false + elseif nHp == 1 then false elseif have_pumChiWatPriDed then false else true + "Set to true for isolation valves at HP outlet" + annotation (Evaluate=true); + parameter Buildings.Templates.Components.Types.PumpArrangement typArrPumPri= + Buildings.Templates.Components.Types.PumpArrangement.Dedicated + "Type of primary pump arrangement" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + final parameter Boolean have_bypHeaWatFix= + have_heaWat and typDis <> Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + and typDis <> Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + "Set to true if the HW loop has a fixed bypass" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + final parameter Boolean have_valHeaWatMinByp=have_heaWat and typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + "Set to true if the HW loop has a minimum flow bypass valve" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + // Constant primary plants with dedicated primary pumps. + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumHeaWatPri_select1( + start=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)= + Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Type of primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_heaWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and (typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + or typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2)), + choices( + choice=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant + "Constant speed pump specified separately", + choice=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Variable speed pump specified separately")); + // Constant primary plants with headered primary pumps. + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumHeaWatPri_select2( + start=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)= + Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Type of primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_heaWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered + and (typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + or typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2)), + choices(choice=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant + "Constant speed pump specified separately", + choice=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Variable speed pump specified separately")); + // Variable primary plants with headered primary pumps require variable speed pumps. + final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumHeaWatPri= + if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated + and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2) + then typPumHeaWatPri_select1 elseif have_heaWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Headered and (typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only or typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2) + then typPumHeaWatPri_select2 elseif have_heaWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Dedicated and (typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only or typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2) then + Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + elseif have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2) + then Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable else + Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None + "Type of primary HW pumps" + annotation (Evaluate=true); + final parameter Boolean have_pumHeaWatPriVar= + typPumHeaWatPri == Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Set to true for variable speed primary HW pumps" + annotation (Evaluate=true); + parameter Integer nPumHeaWatPri_select( + final min=0, + start=0)=nHp + "Number of primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_heaWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered)); + final parameter Integer nPumHeaWatPri=if have_heaWat then (if typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Headered then nPumHeaWatPri_select + else nHp) else 0 + "Number of primary HW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + // RFE: Only centralized secondary HW pumps are currently supported for primary-secondary plants. + final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary typPumHeaWatSec= + if have_heaWat and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2 + or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2) + then Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + else Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + "Type of secondary HW pumps" + annotation (Evaluate=true, + Dialog(group="Secondary HW loop")); + // Primary-secondary plants. + parameter Integer nPumHeaWatSec_select( + final min=0)=nHp + "Number of secondary HW pumps" + annotation (Evaluate=true, + Dialog(group="Secondary HW loop", + enable=have_heaWat and (typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2 + or typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2))); + final parameter Integer nPumHeaWatSec( + final min=0)=if not have_heaWat or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + then 0 else nPumHeaWatSec_select + "Number of secondary HW pumps" + annotation (Evaluate=true, + Dialog(group="Secondary HW loop")); + // Plants with dedicated primary pumps. + parameter Boolean have_pumChiWatPriDed_select( + start=false)=false + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_chiWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated)); + final parameter Boolean have_pumChiWatPriDed=if have_chiWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Dedicated then have_pumChiWatPriDed_select + else false + "Set to true for plants with separate dedicated primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + final parameter Boolean have_bypChiWatFix= + have_chiWat and typDis <> Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + and typDis <> Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + "Set to true if the CHW loop has a fixed bypass" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + final parameter Boolean have_valChiWatMinByp=have_chiWat and typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + "Set to true if the CHW loop has a minimum flow bypass valve" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + // Constant primary plants with separate dedicated primary CHW pumps. + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumChiWatPri_select1( + start=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)= + typPumHeaWatPri + "Type of primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_pumChiWatPriDed and (typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + or typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2))); + // Constant primary plants with headered primary pumps. + parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumChiWatPri_select2( + start=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)= + typPumHeaWatPri + "Type of primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_chiWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered + and (typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + or typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2)), + choices(choice=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant + "Constant speed pump specified separately", + choice=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Variable speed pump specified separately")); + // Variable primary plants with headered primary CHW pumps require variable speed pumps. + final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumChiWatPri= + if have_pumChiWatPriDed and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only + or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2) + then typPumChiWatPri_select1 elseif have_chiWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Headered and (typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Only or typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2) + then typPumChiWatPri_select2 elseif have_pumChiWatPriDed and (typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only or typDis == + Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2) then + Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + elseif have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered + and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2) + then Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable else + Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None + "Type of primary CHW pumps" + annotation (Evaluate=true); + final parameter Boolean have_pumChiWatPriVar= + typPumChiWatPri == Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable + "Set to true for variable speed primary CHW pumps" + annotation (Evaluate=true); + // Plants with headered primary CHW pumps. + parameter Integer nPumChiWatPri_select( + final min=0, + start=0)=nHp + "Number of primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop", + enable=have_chiWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered)); + final parameter Integer nPumChiWatPri=if have_chiWat and typArrPumPri == + Buildings.Templates.Components.Types.PumpArrangement.Headered then nPumChiWatPri_select + elseif have_pumChiWatPriDed then nHp else 0 + "Number of primary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Primary loop")); + // RFE: Currently, only centralized secondary CHW pumps are supported for primary-secondary plants. + final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary typPumChiWatSec= + if have_chiWat and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2 + or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2) + then Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized + else Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + "Type of secondary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Secondary CHW loop")); + parameter Integer nPumChiWatSec_select( + final min=0)=nHp + "Number of secondary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Secondary CHW loop", + enable=have_chiWat and (typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2 + or typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2))); + final parameter Integer nPumChiWatSec( + final min=0)=if not have_chiWat or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only + then 0 else nPumChiWatSec_select + "Number of secondary CHW pumps" + annotation (Evaluate=true, + Dialog(group="Secondary CHW loop")); + // Design and operating parameters. + final parameter Modelica.Units.SI.MassFlowRate mHeaWatPri_flow_nominal=if have_heaWat + then dat.hp.mHeaWatHp_flow_nominal * nHp else 0 + "Primary HW mass flow rate" + annotation (Evaluate=true); + final parameter Modelica.Units.SI.MassFlowRate mHeaWat_flow_nominal=if have_heaWat + then (if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + then mHeaWatPri_flow_nominal else sum(dat.pumHeaWatSec.m_flow_nominal)) else 0 + "HW mass flow rate (total, distributed to consumers)" + annotation (Evaluate=true); + final parameter Modelica.Units.SI.HeatFlowRate capHea_nominal=if have_heaWat + then abs(dat.hp.capHeaHp_nominal) * nHp else 0 + "Heating capacity - All units"; + final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal= + capHea_nominal + "Heating heat flow rate - All units"; + final parameter Modelica.Units.SI.Temperature THeaWatSup_nominal=dat.ctl.THeaWatSup_nominal + "Maximum HW supply temperature"; + final parameter Modelica.Units.SI.Temperature THeaWatRet_nominal= + THeaWatSup_nominal - QHea_flow_nominal / cpHeaWat_default / + mHeaWat_flow_nominal + "HW return temperature"; + final parameter Modelica.Units.SI.MassFlowRate mChiWatPri_flow_nominal=if have_chiWat + then dat.hp.mChiWatHp_flow_nominal * nHp else 0 + "Primary CHW mass flow rate" + annotation (Evaluate=true); + final parameter Modelica.Units.SI.MassFlowRate mChiWat_flow_nominal=if have_chiWat + then (if typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None + then mChiWatPri_flow_nominal else sum(dat.pumChiWatSec.m_flow_nominal)) else 0 + "CHW mass flow rate - Total, distributed to consumers" + annotation (Evaluate=true); + final parameter Modelica.Units.SI.HeatFlowRate capCoo_nominal=if have_chiWat + then abs(dat.hp.capCooHp_nominal) * nHp else 0 + "Cooling capacity - All units"; + final parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal=- + capCoo_nominal + "Cooling heat flow rate - All units"; + final parameter Modelica.Units.SI.Temperature TChiWatSup_nominal=dat.ctl.TChiWatSup_nominal + "Minimum CHW supply temperature"; + final parameter Modelica.Units.SI.Temperature TChiWatRet_nominal=if is_rev + then TChiWatSup_nominal - QCoo_flow_nominal / cpChiWat_default / + mChiWat_flow_nominal else Buildings.Templates.Data.Defaults.TChiWatRet + "CHW return temperature - Each heat pump" + annotation (Dialog(group="Nominal condition")); + final parameter Modelica.Units.SI.Temperature TSouHea_nominal=dat.hp.TSouHeaHp_nominal + "OAT or source fluid supply temperature (evaporator entering) in heating mode - Each heat pump"; + final parameter Modelica.Units.SI.Temperature TSouCoo_nominal=dat.hp.TSouCooHp_nominal + "OAT or source fluid supply temperature (evaporator entering) in cooling mode - Each heat pump"; + // Dynamics and miscellaneous parameterss. + parameter Modelica.Units.SI.Time tau=30 + "Time constant at nominal flow" + annotation (Dialog(tab="Dynamics",group="Nominal condition")); + parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial + "Type of energy balance: dynamic (3 initialization options) or steady state" + annotation (Evaluate=true, + Dialog(tab="Dynamics",group="Conservation equations")); + parameter Boolean allowFlowReversal=true + "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)" + annotation (Dialog(tab="Assumptions"), + Evaluate=true); + parameter Boolean show_T=false + "= true, if actual temperature at port is computed" + annotation (Dialog(tab="Advanced",group="Diagnostics")); + final parameter MediumHeaWat.Density rhoHeaWat_default=MediumHeaWat.density(staHeaWat_default) + "HW default density" + annotation (Evaluate=true); + final parameter MediumHeaWat.SpecificHeatCapacity cpHeaWat_default= + MediumHeaWat.specificHeatCapacityCp(staHeaWat_default) + "HW default specific heat capacity" + annotation (Evaluate=true); + final parameter MediumHeaWat.ThermodynamicState staHeaWat_default=MediumHeaWat.setState_pTX( + T=THeaWatSup_nominal, + p=MediumHeaWat.p_default, + X=MediumHeaWat.X_default) + "HW default state" + annotation (Evaluate=true); + final parameter MediumChiWat.Density rhoChiWat_default=MediumChiWat.density(staChiWat_default) + "CHW default density" + annotation (Evaluate=true); + final parameter MediumChiWat.SpecificHeatCapacity cpChiWat_default= + MediumChiWat.specificHeatCapacityCp(staChiWat_default) + "CHW default specific heat capacity" + annotation (Evaluate=true); + final parameter MediumChiWat.ThermodynamicState staChiWat_default=MediumChiWat.setState_pTX( + T=TChiWatSup_nominal, + p=MediumChiWat.p_default, + X=MediumChiWat.X_default) + "CHW default state" + annotation (Evaluate=true); + /* + Source fluid default state = heating mode: + - Impact of difference between TSouHea_nominal and TSouCoo_nominal on cp is about 0.5 %. + - Impact of difference between TSouHea_nominal and TSouCoo_nominal on rho is about 2 %, + with rhoSouHea_nominal > rhoSouCoo_nominal, so conservative for pump sizing. + */ + final parameter MediumSou.Density rhoSou_default=MediumSou.density(staSou_default) + "Source fluid default density" + annotation (Evaluate=true); + final parameter MediumSou.SpecificHeatCapacity cpSou_default=MediumSou.specificHeatCapacityCp(staSou_default) + "Source fluid default specific heat capacity" + annotation (Evaluate=true); + final parameter MediumSou.ThermodynamicState staSou_default=MediumSou.setState_pTX( + T=TSouHea_nominal, + p=MediumSou.p_default, + X=MediumSou.X_default) + "Source fluid default state" + annotation (Evaluate=true); + Modelica.Fluid.Interfaces.FluidPort_a port_aHeaWat( + redeclare final package Medium=MediumHeaWat, + m_flow( + final min=if allowFlowReversal then - Modelica.Constants.inf else 0), + h_outflow( + start=MediumHeaWat.h_default, + nominal=MediumHeaWat.h_default)) + if have_heaWat + "HW return" + annotation (Placement(transformation(extent={{590,-370},{610,-350}}), + iconTransformation(extent={{190,-190},{210,-170}}))); + Modelica.Fluid.Interfaces.FluidPort_b port_bHeaWat( + redeclare final package Medium=MediumHeaWat, + m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + h_outflow( + start=MediumHeaWat.h_default, + nominal=MediumHeaWat.h_default)) + if have_heaWat + "HW supply" + annotation (Placement(transformation(extent={{590,-290},{610,-270}}), + iconTransformation(extent={{190,-110},{210,-90}}))); + Modelica.Fluid.Interfaces.FluidPort_a port_aChiWat( + redeclare final package Medium=MediumChiWat, + m_flow( + final min=if allowFlowReversal then - Modelica.Constants.inf else 0), + h_outflow( + start=MediumChiWat.h_default, + nominal=MediumChiWat.h_default)) + if have_chiWat + "CHW return" + annotation (Placement(transformation(extent={{590,-10},{610,10}}), + iconTransformation(extent={{190,-50},{210,-30}}))); + Modelica.Fluid.Interfaces.FluidPort_b port_bChiWat( + redeclare final package Medium=MediumChiWat, + m_flow( + max=if allowFlowReversal then + Modelica.Constants.inf else 0), + h_outflow( + start=MediumChiWat.h_default, + nominal=MediumChiWat.h_default)) + if have_chiWat + "CHW supply" + annotation (Placement(transformation(extent={{590,70},{610,90}}), + iconTransformation(extent={{190,30},{210,50}}))); + Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus + "Plant control bus" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=90, + origin={-600,320}), + iconTransformation(extent={{-20,-20},{20,20}},rotation=90,origin={-200,180}))); + Buildings.Templates.AirHandlersFans.Interfaces.Bus busAirHan[cfg.nAirHan] + if cfg.nAirHan > 0 + "Air handling unit control bus" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=-90, + origin={600,340}), + iconTransformation(extent={{-20,-20},{20,20}},rotation=-90,origin={200,180}))); + Buildings.Templates.ZoneEquipment.Interfaces.Bus busEquZon[cfg.nEquZon] + if cfg.nEquZon > 0 + "Terminal unit control bus" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=-90, + origin={600,300}), + iconTransformation(extent={{-20,-20},{20,20}},rotation=-90,origin={200,120}))); + BoundaryConditions.WeatherData.Bus busWea + "Weather bus" + annotation (Placement(transformation(extent={{-20,380},{20,420}}), + iconTransformation(extent={{-20,180},{20,220}}))); + replaceable Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialController ctl + constrainedby + Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialController( + final cfg=cfg, + final dat=dat.ctl) + "Plant controller" + annotation ( + Dialog(group="Controls"), + Placement(transformation(extent={{460,310},{480,330}}))); + // Miscellaneous + Buildings.Fluid.Sources.Outside out( + redeclare replaceable package Medium=Buildings.Media.Air, + nPorts=1) + "Outdoor air conditions" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=-90, + origin={0,380}))); + Buildings.Fluid.Sensors.Temperature TOut( + redeclare replaceable package Medium=Buildings.Media.Air, + warnAboutOnePortConnection=false) + "OA temperature" + annotation (Placement(transformation(extent={{-30,370},{-10,390}}))); +initial equation + if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated then + assert(nPumHeaWatPri == nHp, "In " + getInstanceName() + ": " + + "In case of dedicated primary HW pumps, the number pumps (=" + String(nPumHeaWatPri) + + ") must be equal to the number of heat pumps (=" + String(nHp) + ")."); + end if; + if have_pumChiWatPriDed then + assert(nPumChiWatPri == nHp, "In " + getInstanceName() + ": " + + "In case of separate dedicated primary CHW pumps, the number pumps (=" + + String(nPumChiWatPri) + ") must be equal to the number of heat pumps (=" + + String(nHp) + ")."); + end if; +equation + /* Control point connection - start */ + connect(TOut.T, bus.TOut); + /* Control point connection - stop */ + connect(bus, ctl.bus) + annotation (Line(points={{-600,320},{460,320}}, color={255,204,51},thickness=0.5)); + connect(ctl.busAirHan, busAirHan) + annotation (Line(points={{480,326},{580,326},{580,340},{600,340}}, color={255,204,51},thickness=0.5)); + connect(ctl.busEquZon, busEquZon) + annotation (Line(points={{480,314},{580,314},{580,300},{600,300}}, color={255,204,51},thickness=0.5)); + connect(busWea, out.weaBus) + annotation (Line(points={{0,400},{0,390},{0.2,390}},color={255,204,51},thickness=0.5)); + connect(out.ports[1], TOut.port) + annotation (Line(points={{0,370},{-20,370}}, + color={0,127,255})); + annotation ( + defaultComponentName="plaHp", + Icon( + coordinateSystem( + preserveAspectRatio=false, + extent={{-200,-200},{200,200}}), + graphics={ + Line( + points={{20,-100},{20,-180},{200,-180}}, + color={28,108,200}, + thickness=5, + pattern=LinePattern.Dash, + visible=have_chiWat), + Line( + points={{0,40},{0,-100},{-40,-100}}, + color={28,108,200}, + thickness=5, + origin={160,-100}, + rotation=-90, + visible=have_chiWat), + Rectangle( + extent={{-200,200},{200,-200}}, + lineColor={0,0,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-151,-212},{149,-252}}, + textColor={0,0,255}, + textString="%name"), + Line( + points={{20,-40},{20,-100},{-60,-100}}, + color={238,46,47}, + pattern=LinePattern.Dash, + thickness=5), + Line( + points={{-60,60},{20,60},{20,-40}}, + color={238,46,47}, + thickness=5, + pattern=LinePattern.Dash), + Line( + points={{100,-100},{100,-180}}, + color={238,46,47}, + thickness=5, + visible=have_heaWat), + Rectangle( + extent={{-160,130},{-60,30}}, + lineColor={0,0,255}, + pattern=LinePattern.None, + fillColor={95,95,95}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-130,100},{-90,60}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Line( + points={{-122,96},{-126,68}}, + color={0,0,0}), + Line( + points={{-98,96},{-94,68}}, + color={0,0,0}), + Rectangle( + extent={{-160,-32},{-60,-132}}, + lineColor={0,0,255}, + pattern=LinePattern.None, + fillColor={95,95,95}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-130,-62},{-90,-102}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Line( + points={{-122,-66},{-126,-94}}, + color={0,0,0}), + Line( + points={{-98,-66},{-94,-94}}, + color={0,0,0}), + Line( + points={{100,38},{100,-42}}, + color={28,108,200}, + thickness=5, + visible=have_chiWat), + Line( + points={{0,40},{0,-100}}, + color={28,108,200}, + thickness=5, + visible=have_chiWat, + origin={160,40}, + rotation=-90), + Line( + points={{0,40},{0,-140}}, + color={28,108,200}, + thickness=5, + visible=have_chiWat, + origin={160,-40}, + rotation=-90, + pattern=LinePattern.Dash), + Line( + points={{-60,-60},{60,-60},{60,40}}, + color={238,46,47}, + thickness=5), + Line( + points={{-60,100},{60,100},{60,40}}, + color={238,46,47}, + thickness=5), + Ellipse( + extent={{-40,-40},{0,-80}}, + lineColor={0,0,0}, + fillPattern=FillPattern.Sphere, + fillColor={0,100,199}), + Polygon( + points={{-20,-41},{-20,-79},{-1,-60},{-20,-41}}, + lineColor={0,0,0}, + pattern=LinePattern.None, + fillPattern=FillPattern.HorizontalCylinder, + fillColor={255,255,255}), + Ellipse( + extent={{-40,120},{0,80}}, + lineColor={0,0,0}, + fillPattern=FillPattern.Sphere, + fillColor={0,100,199}), + Polygon( + points={{-20,119},{-20,81},{-1,100},{-20,119}}, + lineColor={0,0,0}, + pattern=LinePattern.None, + fillPattern=FillPattern.HorizontalCylinder, + fillColor={255,255,255}), + Line( + points={{0,40},{0,-100},{-40,-100}}, + color={238,46,47}, + thickness=5, + visible=have_heaWat, + origin={160,-100}, + rotation=-90), + Line( + points={{0,40},{0,-140},{-80,-140}}, + color={238,46,47}, + thickness=5, + visible=have_heaWat, + pattern=LinePattern.Dash, + origin={160,-180}, + rotation=-90), + Ellipse( + extent={{130,-80},{170,-120}}, + lineColor={0,0,0}, + fillPattern=FillPattern.Sphere, + fillColor={0,100,199}, + startAngle=0, + endAngle=360, + visible=have_heaWat and typPumHeaWatSec<>Buildings.Templates.HeatingPlants.HotWater.Types.PumpsSecondary.None), + Polygon( + points={{150,-81},{150,-119},{169,-100},{150,-81}}, + lineColor={0,0,0}, + pattern=LinePattern.None, + fillPattern=FillPattern.HorizontalCylinder, + fillColor={255,255,255}, + visible=have_heaWat and typPumHeaWatSec<>Buildings.Templates.HeatingPlants.HotWater.Types.PumpsSecondary.None), + Ellipse( + extent={{130,60},{170,20}}, + lineColor={0,0,0}, + fillPattern=FillPattern.Sphere, + fillColor={0,100,199}, + startAngle=0, + endAngle=360, + visible=have_chiWat and typPumChiWatSec<>Buildings.Templates.HeatingPlants.HotWater.Types.PumpsSecondary.None), + Polygon( + points={{150,59},{150,21},{169,40},{150,59}}, + lineColor={0,0,0}, + pattern=LinePattern.None, + fillPattern=FillPattern.HorizontalCylinder, + fillColor={255,255,255}, + visible=have_chiWat and typPumChiWatSec<>Buildings.Templates.HeatingPlants.HotWater.Types.PumpsSecondary.None)}), + Diagram( + coordinateSystem( + preserveAspectRatio=false, + extent={{-600,-400},{600,400}})), + Documentation( + revisions=" ++This partial class provides a standard interface for heat pump +plant models. +
+")); +end PartialHeatPumpPlant; diff --git a/Buildings/Templates/Plants/HeatPumps/Interfaces/package.mo b/Buildings/Templates/Plants/HeatPumps/Interfaces/package.mo new file mode 100644 index 00000000000..08e63c1de08 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Interfaces/package.mo @@ -0,0 +1,9 @@ +within Buildings.Templates.Plants.HeatPumps; +package Interfaces "Interface classes" + extends Modelica.Icons.InterfacesPackage; + annotation (Documentation(info=" ++This package contains interface classes. +
+")); +end Interfaces; diff --git a/Buildings/Templates/Plants/HeatPumps/Interfaces/package.order b/Buildings/Templates/Plants/HeatPumps/Interfaces/package.order new file mode 100644 index 00000000000..395e1f57ca1 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Interfaces/package.order @@ -0,0 +1,2 @@ +Bus +PartialHeatPumpPlant diff --git a/Buildings/Templates/Plants/HeatPumps/Types.mo b/Buildings/Templates/Plants/HeatPumps/Types.mo new file mode 100644 index 00000000000..eced4ebe8bf --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Types.mo @@ -0,0 +1,48 @@ +within Buildings.Templates.Plants.HeatPumps; +package Types + "Package with type definitions" + extends Modelica.Icons.TypesPackage; + type Controller = enumeration( + AirToWater + "Controller for AWHP plant", + OpenLoop + "Open loop controller") + "Enumeration to specify the plant controller"; + type Distribution = enumeration( + Constant1Only + "Constant primary-only", + Variable1Only + "Variable primary-only", + Constant1Variable2 + "Constant primary - Variable secondary centralized", + Variable1And2 + "Variable primary - Variable secondary centralized") + "Enumeration to specify the type of CHW/HW distribution system"; + type PumpsPrimary = enumeration( + Constant + "Constant speed pump specified separately", + Variable + "Variable speed pump specified separately", + None + "No pump") + "Enumeration to specify the type of primary pumps"; + type PumpsSecondary = enumeration( + None + "No secondary pumps (primary-only)", + Centralized + "Variable secondary centralized") + "Enumeration to specify the type of secondary HW pumps"; + type SensorLocation = enumeration( + Return + "Sensor in the return line", + Supply + "Sensor in the supply line") + "Enumeration to specify the sensor location"; + annotation ( + Documentation( + info=" ++This package contains type definitions. +
+")); +end Types; diff --git a/Buildings/Templates/Plants/HeatPumps/Validation/AirToWater.mo b/Buildings/Templates/Plants/HeatPumps/Validation/AirToWater.mo new file mode 100644 index 00000000000..dc1438e2bd2 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Validation/AirToWater.mo @@ -0,0 +1,386 @@ +within Buildings.Templates.Plants.HeatPumps.Validation; +model AirToWater + "Validation of AWHP plant template" + extends Modelica.Icons.Example; + replaceable package Medium=Buildings.Media.Water + constrainedby Modelica.Media.Interfaces.PartialMedium + "Main medium (common for CHW and HW)"; + parameter Boolean have_chiWat=true + "Set to true if the plant provides CHW" + annotation (Evaluate=true, + Dialog(group="Configuration")); + inner parameter UserProject.Data.AllSystems datAll( + pla(final cfg=pla.cfg)) + "Plant parameters" + annotation (Placement(transformation(extent={{-120,160},{-100,180}}))); + parameter Boolean allowFlowReversal=true + "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)" + annotation (Dialog(tab="Assumptions"), + Evaluate=true); + parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial + "Type of energy balance: dynamic (3 initialization options) or steady state" + annotation (Evaluate=true, + Dialog(tab="Dynamics",group="Conservation equations")); + BoundaryConditions.WeatherData.ReaderTMY3 weaDat( + filNam=Modelica.Utilities.Files.loadResource( + "modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos")) + "Outdoor conditions" + annotation (Placement(transformation(extent={{-10,-10},{10,10}},rotation=0, + origin={-170,-40}))); + Fluid.HeatExchangers.SensibleCooler_T loaHeaWat( + redeclare final package Medium=Medium, + final m_flow_nominal=pla.mHeaWat_flow_nominal, + show_T=true, + final dp_nominal=0, + final energyDynamics=energyDynamics, + tau=300, + QMin_flow=-pla.capHea_nominal) + "HW system approximated by prescribed return temperature" + annotation (Placement(transformation(extent={{70,-110},{90,-90}}))); + Fluid.HeatExchangers.Heater_T loaChiWat( + redeclare final package Medium=Medium, + final m_flow_nominal=pla.mChiWat_flow_nominal, + show_T=true, + final dp_nominal=0, + final energyDynamics=energyDynamics, + tau=300, + QMax_flow=pla.capCoo_nominal) + if have_chiWat + "CHW system system approximated by prescribed return temperature" + annotation (Placement(transformation(extent={{70,-50},{90,-30}}))); + Fluid.Actuators.Valves.TwoWayEqualPercentage valDisHeaWat( + redeclare final package Medium=Medium, + m_flow_nominal=pla.mHeaWat_flow_nominal, + dpValve_nominal=3E4, + dpFixed_nominal=datAll.pla.ctl.dpHeaWatRemSet_max[1] - 3E4) + "Distribution system approximated by variable flow resistance" + annotation (Placement(transformation(extent={{110,-110},{130,-90}}))); + Fluid.Actuators.Valves.TwoWayEqualPercentage valDisChiWat( + redeclare final package Medium=Medium, + m_flow_nominal=pla.mChiWat_flow_nominal, + dpValve_nominal=3E4, + dpFixed_nominal=datAll.pla.ctl.dpChiWatRemSet_max[1] - 3E4) + if have_chiWat + "Distribution system approximated by variable flow resistance" + annotation (Placement(transformation(extent={{110,-50},{130,-30}}))); + Buildings.Templates.Plants.HeatPumps.AirToWater pla( + redeclare final package MediumHeaWat=Medium, + final dat=datAll.pla, + final have_chiWat=have_chiWat, + nHp=3, + typArrPumPri=Buildings.Templates.Components.Types.PumpArrangement.Dedicated, + typPumHeaWatPri_select2=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable, + typPumChiWatPri_select1=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant, + final energyDynamics=energyDynamics, + final allowFlowReversal=allowFlowReversal, + show_T=true, + ctl( + nAirHan=1, + nEquZon=0, + have_senVHeaWatPri_select=true, + have_senVChiWatPri_select=true, + have_senTHeaWatPriRet_select=true, + have_senTChiWatPriRet_select=true, + have_senTHeaWatSecRet=true, + have_senTChiWatSecRet=true, + have_senDpHeaWatRemWir=true)) + "Heat pump plant" + annotation (Placement(transformation(extent={{-80,-100},{-40,-60}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant TDum( + k=293.15, + y(final unit="K", + displayUnit="degC")) + "Placeholder signal for request generator" + annotation (Placement(transformation(extent={{-180,130},{-160,150}}))); + Fluid.Sensors.RelativePressure dpHeaWatRem_1( + redeclare final package Medium = Medium) + "HW differential pressure at one remote location" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={40,-120}))); + Fluid.Sensors.RelativePressure dpChiWatRem_1( + redeclare final package Medium = Medium) if have_chiWat + "CHW differential pressure at one remote location" + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={40,-60}))); + Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.PlantRequests reqPlaRes( + final heaCoi=Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased, final + cooCoi=if have_chiWat then Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased + else Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.None) + "Plant and reset request" + annotation (Placement(transformation(extent={{90,102},{70,122}}))); + AirHandlersFans.Interfaces.Bus busAirHan "AHU control bus" annotation ( + Placement(transformation(extent={{-60,100},{-20,140}}),iconTransformation( + extent={{-340,-140},{-300,-100}}))); + Interfaces.Bus busPla "Plant control bus" annotation (Placement( + transformation(extent={{-100,-40},{-60,0}}), iconTransformation(extent + ={{-370,-70},{-330,-30}}))); + Buildings.Controls.OBC.CDL.Routing.RealVectorFilter dpChiWatRem( + final nin=pla.cfg.nSenDpChiWatRem, + final nout=pla.cfg.nSenDpChiWatRem) if have_chiWat + "Gather all remote CHW differential pressure signals" + annotation (Placement(transformation(extent={{10,10},{-10,30}}))); + Buildings.Controls.OBC.CDL.Routing.RealVectorFilter dpHeaWatRem( + final nin=pla.cfg.nSenDpHeaWatRem, + final nout=pla.cfg.nSenDpHeaWatRem) + "Gather all remote HW differential pressure signals" + annotation (Placement(transformation(extent={{10,-30},{-10,-10}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ratFlo( + table=[0,0,0; 5,0,0; 7,1,0; 12,0.2,0.2; 16,0,1; 22,0.1,0.1; 24,0,0], + timeScale=3600) + "Source signal for flow rate ratio – Index 1 for HW, 2 for CHW" + annotation (Placement(transformation(extent={{-180,70},{-160,90}}))); + Buildings.Controls.OBC.CDL.Reals.PID ctlEquZon[if have_chiWat then 2 else 1]( + each k=0.1, + each Ti=60, + each final reverseActing=true) "Zone equipment controller" + annotation (Placement(transformation(extent={{70,70},{90,90}}))); + Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter norFlo[if have_chiWat + then 2 else 1]( + k=if have_chiWat then {1/pla.mHeaWat_flow_nominal,1/pla.mChiWat_flow_nominal} + else {1/pla.mHeaWat_flow_nominal}) + "Normalize flow rate" annotation ( + Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={180,0}))); + Fluid.Sensors.MassFlowRate mChiWat_flow( + redeclare final package Medium = Medium) if have_chiWat + "CHW mass flow rate" annotation ( + Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={160,-60}))); + Fluid.Sensors.MassFlowRate mHeaWat_flow(redeclare final package Medium = + Medium) "HW mass flow rate" annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={160,-120}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter TChiWatRet(p=pla.TChiWatRet_nominal + - pla.TChiWatSup_nominal) if have_chiWat + "Prescribed CHW return temperature" + annotation (Placement(transformation(extent={{-130,30},{-110,50}}))); + Buildings.Controls.OBC.CDL.Reals.AddParameter THeaWatRet(p=pla.THeaWatRet_nominal + - pla.THeaWatSup_nominal) "Prescribed HW return temperature" + annotation (Placement(transformation(extent={{-130,-10},{-110,10}}))); + Buildings.Controls.OBC.CDL.Reals.Max max2 "Limit prescribed HWRT" + annotation (Placement(transformation(extent={{-90,-10},{-70,10}}))); + Buildings.Controls.OBC.CDL.Reals.Min min1 if have_chiWat + "Limit prescribed CHWRT" + annotation (Placement(transformation(extent={{-90,30},{-70,50}}))); + Buildings.Controls.OBC.CDL.Integers.Multiply mulInt[4] + "Importance multiplier" + annotation (Placement(transformation(extent={{0,110},{-20,130}}))); + Buildings.Controls.OBC.CDL.Integers.Sources.Constant cst[4](each k=10) + "Constant" + annotation (Placement(transformation(extent={{40,150},{20,170}}))); + Buildings.Fluid.FixedResistances.PressureDrop pipHeaWat( + redeclare final package Medium =Medium, + final m_flow_nominal=pla.mHeaWat_flow_nominal, + final dp_nominal=max( + max(datAll.pla.pumHeaWatPri.dp_nominal), + max(datAll.pla.pumHeaWatSec.dp_nominal)) - datAll.pla.ctl.dpHeaWatRemSet_max[1]) + "Piping" + annotation (Placement(transformation(extent={{10,-150},{-10,-130}}))); + Buildings.Fluid.FixedResistances.PressureDrop pipChiWat( + redeclare final package Medium =Medium, + final m_flow_nominal=pla.mChiWat_flow_nominal, + final dp_nominal=max( + max(datAll.pla.pumChiWatPri.dp_nominal), + max(datAll.pla.pumChiWatSec.dp_nominal)) - datAll.pla.ctl.dpChiWatRemSet_max[1]) + if have_chiWat + "Piping" + annotation (Placement(transformation(extent={{10,-90},{-10,-70}}))); + Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(k=293.15) + "Constant limiting prescribed return temperature" + annotation (Placement(transformation(extent={{-180,10},{-160,30}}))); + Controls.Utilities.PlaceholderInteger ph[2](each final have_inp=have_chiWat, + each final u_internal=0) "Placeholder value" + annotation (Placement(transformation(extent={{40,114},{20,134}}))); +equation + if have_chiWat then + connect(mulInt[3].y, busAirHan.reqResChiWat) + annotation (Line(points={{-22,120},{-40,120}}, color={255,127,0})); + connect(mulInt[4].y, busAirHan.reqPlaChiWat) + annotation (Line(points={{-22,120},{-40,120}}, color={255,127,0})); + end if; + connect(weaDat.weaBus, pla.busWea) + annotation (Line(points={{-160,-40},{-60,-40},{-60,-60}}, + color={255,204,51},thickness=0.5)); + connect(pla.port_bChiWat, loaChiWat.port_a) + annotation (Line(points={{-40,-76},{-20,-76},{-20,-40},{70,-40}}, + color={0,127,255})); + connect(loaChiWat.port_b, valDisChiWat.port_a) + annotation (Line(points={{90,-40},{110,-40}}, + color={0,127,255})); + connect(loaHeaWat.port_b, valDisHeaWat.port_a) + annotation (Line(points={{90,-100},{110,-100}}, + color={0,127,255})); + connect(pla.port_bHeaWat, loaHeaWat.port_a) + annotation (Line(points={{-40,-90},{-20,-90},{-20,-100},{70,-100}}, + color={0,127,255})); + connect(loaChiWat.port_a, dpChiWatRem_1.port_a) + annotation (Line(points={{70,-40},{40,-40},{40,-50}}, color={0,127,255})); + connect(dpHeaWatRem_1.port_a, loaHeaWat.port_a) annotation (Line(points={{40,-110}, + {40,-100},{70,-100}}, color={0,127,255})); + connect(TDum.y, reqPlaRes.TAirSup) annotation (Line(points={{-158,140},{100, + 140},{100,120},{92,120}},color={0,0,127})); + connect(TDum.y, reqPlaRes.TAirSupSet) annotation (Line(points={{-158,140},{ + 100,140},{100,115},{92,115}}, + color={0,0,127})); + connect(busAirHan, pla.busAirHan[1]) annotation (Line( + points={{-40,120},{-40,-62}}, + color={255,204,51}, + thickness=0.5)); + connect(pla.bus, busPla) annotation (Line( + points={{-80,-62},{-80,-20}}, + color={255,204,51}, + thickness=0.5)); + connect(dpHeaWatRem.y, busPla.dpHeaWatRem) + annotation (Line(points={{-12,-20},{-80,-20}}, color={0,0,127})); + connect(dpChiWatRem.y, busPla.dpChiWatRem) + annotation (Line(points={{-12,20},{-20,20},{-20,-18},{-80,-18},{-80,-20}}, + color={0,0,127})); + connect(valDisChiWat.y_actual, reqPlaRes.uCooCoiSet) annotation (Line(points={{125,-33}, + {140,-33},{140,109},{92,109}}, color={0,0,127})); + connect(valDisHeaWat.y_actual, reqPlaRes.uHeaCoiSet) annotation (Line(points={{125,-93}, + {136,-93},{136,104},{92,104}}, color={0,0,127})); + connect(dpHeaWatRem_1.p_rel, dpHeaWatRem.u[1]) annotation (Line(points={{31,-120}, + {20,-120},{20,-20},{12,-20}}, + color={0,0,127})); + connect(dpChiWatRem_1.p_rel, dpChiWatRem.u[1]) annotation (Line(points={{31,-60}, + {22,-60},{22,20},{12,20}}, + color={0,0,127})); + connect(valDisChiWat.port_b, mChiWat_flow.port_a) annotation (Line(points={{130,-40}, + {160,-40},{160,-50}}, color={0,127,255})); + connect(mChiWat_flow.port_b, dpChiWatRem_1.port_b) annotation (Line(points={{160, + -70},{160,-80},{40,-80},{40,-70}}, color={0,127,255})); + connect(valDisHeaWat.port_b, mHeaWat_flow.port_a) annotation (Line(points={{130, + -100},{160,-100},{160,-110}}, color={0,127,255})); + connect(mHeaWat_flow.port_b, dpHeaWatRem_1.port_b) annotation (Line(points={{160, + -130},{160,-140},{40,-140},{40,-130}}, color={0,127,255})); + connect(mHeaWat_flow.m_flow, norFlo[1].u) annotation (Line(points={{171,-120}, + {180,-120},{180,-12}}, color={0,0,127})); + connect(mChiWat_flow.m_flow, norFlo[2].u) + annotation (Line(points={{171,-60},{180,-60},{180,-12}}, color={0,0,127})); + connect(norFlo.y, ctlEquZon.u_m) annotation (Line(points={{180,12},{180,60},{80, + 60},{80,68}}, color={0,0,127})); + connect(ratFlo.y[1:(if have_chiWat then 2 else 1)], ctlEquZon.u_s) + annotation (Line(points={{-158,80},{68,80}}, color={0,0,127})); + connect(ctlEquZon[2].y, valDisChiWat.y) annotation (Line(points={{92,80},{100, + 80},{100,-20},{120,-20},{120,-28}}, color={0,0,127})); + connect(ctlEquZon[1].y, valDisHeaWat.y) annotation (Line(points={{92,80},{100, + 80},{100,-84},{120,-84},{120,-88}}, color={0,0,127})); + connect(busPla.THeaWatPriSup, THeaWatRet.u) annotation (Line( + points={{-80,-20},{-140,-20},{-140,0},{-132,0}}, + color={255,204,51}, + thickness=0.5)); + connect(busPla.TChiWatPriSup, TChiWatRet.u) annotation (Line( + points={{-80,-20},{-140,-20},{-140,40},{-132,40}}, + color={255,204,51}, + thickness=0.5)); + connect(TChiWatRet.y,min1. u1) annotation (Line(points={{-108,40},{-100,40},{-100, + 46},{-92,46}}, color={0,0,127})); + connect(min1.y, loaChiWat.TSet) annotation (Line(points={{-68,40},{62,40},{62, + -32},{68,-32}}, color={0,0,127})); + connect(max2.y, loaHeaWat.TSet) annotation (Line(points={{-68,0},{60,0},{60,-92}, + {68,-92}}, color={0,0,127})); + connect(cst.y, mulInt.u1) annotation (Line(points={{18,160},{6,160},{6,126},{2, + 126}}, color={255,127,0})); + connect(mulInt[1].y, busAirHan.reqResHeaWat) annotation (Line(points={{-22,120}, + {-30,120},{-30,120},{-40,120}}, color={255,127,0})); + connect(mulInt[2].y, busAirHan.reqPlaHeaWat) + annotation (Line(points={{-22,120},{-40,120}}, color={255,127,0})); + connect(pipHeaWat.port_b, pla.port_aHeaWat) annotation (Line(points={{-10,-140}, + {-30,-140},{-30,-98},{-40,-98}}, color={0,127,255})); + connect(pipChiWat.port_b, pla.port_aChiWat) annotation (Line(points={{-10,-80}, + {-20,-80},{-20,-84},{-40,-84}}, color={0,127,255})); + connect(mChiWat_flow.port_b, pipChiWat.port_a) annotation (Line(points={{160,-70}, + {160,-80},{10,-80}}, color={0,127,255})); + connect(mHeaWat_flow.port_b, pipHeaWat.port_a) annotation (Line(points={{160,-130}, + {160,-140},{10,-140}}, color={0,127,255})); + connect(con.y, min1.u2) annotation (Line(points={{-158,20},{-100,20},{-100,34}, + {-92,34}}, color={0,0,127})); + connect(con.y, max2.u1) annotation (Line(points={{-158,20},{-100,20},{-100,6}, + {-92,6}}, color={0,0,127})); + connect(THeaWatRet.y, max2.u2) annotation (Line(points={{-108,0},{-100,0},{ + -100,-6},{-92,-6}}, color={0,0,127})); + connect(reqPlaRes.yChiWatResReq, ph[1].u) annotation (Line(points={{68,120},{ + 50,120},{50,124},{42,124}}, color={255,127,0})); + connect(reqPlaRes.yChiPlaReq, ph[2].u) annotation (Line(points={{68,115},{50, + 115},{50,124},{42,124}}, color={255,127,0})); + connect(reqPlaRes.yHotWatResReq, mulInt[1].u2) annotation (Line(points={{68, + 109},{12,109},{12,114},{2,114}}, color={255,127,0})); + connect(reqPlaRes.yHotWatPlaReq, mulInt[2].u2) annotation (Line(points={{68, + 104},{12,104},{12,114},{2,114}}, color={255,127,0})); + connect(ph[1].y, mulInt[3].u2) annotation (Line(points={{18,124},{12,124},{12, + 114},{2,114}}, color={255,127,0})); + connect(ph[2].y, mulInt[4].u2) annotation (Line(points={{18,124},{12,124},{12, + 114},{2,114}}, color={255,127,0})); + annotation ( + __Dymola_Commands( + file= + "modelica://Buildings/Resources/Scripts/Dymola/Templates/Plants/HeatPumps/Validation/AirToWater.mos" + "Simulate and plot"), + experiment( + Tolerance=1e-6, + StopTime=86400.0), + Documentation( + info=" ++This model validates + +Buildings.Templates.Plants.HeatPumps.AirToWater +by simulating a 24-hour period with overlapping heating and +cooling loads. +The heating loads reach their peak value first, the cooling loads reach it last. +
++Three equally sized heat pumps are modeled. All can be lead/lag alternated. +A unique aggregated load is modeled on each loop by means of a cooling or heating +component controlled to maintain a constant ΔT +and a modulating valve controlled to track a prescribed flow rate. +An importance multiplier of 10 is applied to the plant requests +and reset requests generated from the valve position. +
+
+The user can toggle the top-level parameter have_chiWat
+to switch between a cooling and heating system (the default setting)
+to a heating-only system.
+Advanced equipment and control options can be modified via the parameter
+dialog of the plant component.
+
+Simulating this model shows how the plant responds to a varying load by +
++This class provides the set of sizing and operating parameters for +the whole HVAC system. +It is aimed for validation purposes only. +
+")); +end AllSystems; diff --git a/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/Data/package.mo b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/Data/package.mo new file mode 100644 index 00000000000..e083ed1c4bd --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/Data/package.mo @@ -0,0 +1,12 @@ +within Buildings.Templates.Plants.HeatPumps.Validation.UserProject; +package Data "Package with classes for storing system parameters" + extends Modelica.Icons.MaterialPropertiesPackage; + annotation ( + Documentation( + info=" ++This package provides records for design and operating parameters +that are used for validation purposes. +
+")); +end Data; diff --git a/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/Data/package.order b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/Data/package.order new file mode 100644 index 00000000000..3831742ec60 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/Data/package.order @@ -0,0 +1 @@ +AllSystems diff --git a/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/package.mo b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/package.mo new file mode 100644 index 00000000000..0080c5049a9 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/package.mo @@ -0,0 +1,11 @@ +within Buildings.Templates.Plants.HeatPumps.Validation; +package UserProject "Package with configured models" + extends Modelica.Icons.VariantsPackage; + annotation ( + Documentation( + info=" ++This package contains models used for validation purposes. +
+")); +end UserProject; diff --git a/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/package.order b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/package.order new file mode 100644 index 00000000000..0b7088ec633 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Validation/UserProject/package.order @@ -0,0 +1 @@ +Data diff --git a/Buildings/Templates/Plants/HeatPumps/Validation/package.mo b/Buildings/Templates/Plants/HeatPumps/Validation/package.mo new file mode 100644 index 00000000000..8d54b9e0ff9 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/Validation/package.mo @@ -0,0 +1,18 @@ +within Buildings.Templates.Plants.HeatPumps; +package Validation "Package with validation models" + extends Modelica.Icons.ExamplesPackage; + annotation ( + Documentation( + info=" ++This package contains models validating the templates within + +Buildings.Templates.Plants.HeatPumps +for various system configurations. +
+
+The models also illustrate parameter propagation from the top-level
+HVAC system record datAll
.
+
This package contains templates for heat pump plants.
+")); +end HeatPumps; diff --git a/Buildings/Templates/Plants/HeatPumps/package.order b/Buildings/Templates/Plants/HeatPumps/package.order new file mode 100644 index 00000000000..215baa2eb40 --- /dev/null +++ b/Buildings/Templates/Plants/HeatPumps/package.order @@ -0,0 +1,7 @@ +AirToWater +Components +Configuration +Data +Types +Validation +Interfaces diff --git a/Buildings/Templates/Plants/package.mo b/Buildings/Templates/Plants/package.mo new file mode 100644 index 00000000000..ce672ee403f --- /dev/null +++ b/Buildings/Templates/Plants/package.mo @@ -0,0 +1,10 @@ +within Buildings.Templates; +package Plants + "Central plants" + extends Modelica.Icons.Package; + annotation ( + Documentation( + info=" +This package contains templates for central plants.
+")); +end Plants; diff --git a/Buildings/Templates/Plants/package.order b/Buildings/Templates/Plants/package.order new file mode 100644 index 00000000000..fd79608553d --- /dev/null +++ b/Buildings/Templates/Plants/package.order @@ -0,0 +1,2 @@ +Controls +HeatPumps diff --git a/Buildings/Templates/Utilities/computeBalancingPressureDrop.mo b/Buildings/Templates/Utilities/computeBalancingPressureDrop.mo new file mode 100644 index 00000000000..4f03c83310f --- /dev/null +++ b/Buildings/Templates/Utilities/computeBalancingPressureDrop.mo @@ -0,0 +1,49 @@ +within Buildings.Templates.Utilities; +function computeBalancingPressureDrop + "Compute the design pressure drop of a balancing valve" + extends Modelica.Icons.Function; + input Modelica.Units.SI.MassFlowRate m_flow_nominal + "Design mass flow rate (target)"; + input Modelica.Units.SI.PressureDifference dp_nominal + "Pressure drop of equipment in series at design flow rate"; + input Buildings.Templates.Components.Data.PumpSingle datPum + "Pump parameters"; + input Real r_N(unit="1")=1 + "Relative revolution, r_N=N/N_nominal"; + output Modelica.Units.SI.PressureDifference dpBal_nominal + "Pressure drop of balancing valve at design flow rate"; +protected + Modelica.Units.SI.PressureDifference dpPum_nominal = + Buildings.Fluid.Movers.BaseClasses.Characteristics.pressure( + V_flow=m_flow_nominal / datPum.rho_default, + r_N=r_N, + d=Buildings.Utilities.Math.Functions.splineDerivatives( + x=datPum.per.pressure.V_flow, + y=datPum.per.pressure.dp), + dpMax=max(datPum.per.pressure.dp), + V_flow_max=max(datPum.per.pressure.V_flow), + per=Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParametersInternal( + n=size(datPum.per.pressure.V_flow, 1), + V_flow=datPum.per.pressure.V_flow, + dp=datPum.per.pressure.dp)) + "Pump head at target design flow"; +algorithm + dpBal_nominal := dpPum_nominal - dp_nominal; + annotation (Documentation(info=" ++Given the design mass flow rate, the design pressure drop +of all equipment in series, the pump parameters and the +pump speed, the function returns the pressure drop +of a balancing valve at design flow, so that the total +pressure drop is equal to the pump head. +
++The model + +Buildings.Templates.Plants.HeatPumps.Components.Validation.PumpsPrimaryDedicated +serves as a validation model for this function and illustrates how the function +can be used to calculate either the design pressure drop of balancing +valves or the primary pump speed required to provide the design flow. +
+")); +end computeBalancingPressureDrop; diff --git a/Buildings/Templates/Utilities/package.mo b/Buildings/Templates/Utilities/package.mo new file mode 100644 index 00000000000..098f8d76ed8 --- /dev/null +++ b/Buildings/Templates/Utilities/package.mo @@ -0,0 +1,27 @@ +within Buildings.Templates; +package Utilities "Package with utility functions" + extends Modelica.Icons.Package; + + annotation ( + Icon(coordinateSystem(extent={{-100.0,-100.0},{100.0,100.0}}), graphics={ + Polygon( + origin={1.3835,-4.1418}, + rotation=45.0, + fillColor={64,64,64}, + pattern=LinePattern.None, + fillPattern=FillPattern.Solid, + points={{-15.0,93.333},{-15.0,68.333},{0.0,58.333},{15.0,68.333},{15.0,93.333},{20.0,93.333},{25.0,83.333},{25.0,58.333},{10.0,43.333},{10.0,-41.667},{25.0,-56.667},{25.0,-76.667},{10.0,-91.667},{0.0,-91.667},{0.0,-81.667},{5.0,-81.667},{15.0,-71.667},{15.0,-61.667},{5.0,-51.667},{-5.0,-51.667},{-15.0,-61.667},{-15.0,-71.667},{-5.0,-81.667},{0.0,-81.667},{0.0,-91.667},{-10.0,-91.667},{-25.0,-76.667},{-25.0,-56.667},{-10.0,-41.667},{-10.0,43.333},{-25.0,58.333},{-25.0,83.333},{-20.0,93.333}}), + Polygon( + origin={10.1018,5.218}, + rotation=-45.0, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid, + points={{-15.0,87.273},{15.0,87.273},{20.0,82.273},{20.0,27.273},{10.0,17.273},{10.0,7.273},{20.0,2.273},{20.0,-2.727},{5.0,-2.727},{5.0,-77.727},{10.0,-87.727},{5.0,-112.727},{-5.0,-112.727},{-10.0,-87.727},{-5.0,-77.727},{-5.0,-2.727},{-20.0,-2.727},{-20.0,2.273},{-10.0,7.273},{-10.0,17.273},{-20.0,27.273},{-20.0,82.273}})}), + Documentation(revisions=" +", info=" ++This package contains utility functions that are used +in HVAC system templates. +
+")); +end Utilities; diff --git a/Buildings/Templates/Utilities/package.order b/Buildings/Templates/Utilities/package.order new file mode 100644 index 00000000000..b5898f9cd5b --- /dev/null +++ b/Buildings/Templates/Utilities/package.order @@ -0,0 +1 @@ +computeBalancingPressureDrop diff --git a/Buildings/Templates/package.order b/Buildings/Templates/package.order index 9c28253a22a..1cd7704ac04 100644 --- a/Buildings/Templates/package.order +++ b/Buildings/Templates/package.order @@ -1,6 +1,8 @@ UsersGuide AirHandlersFans Components +Plants +Utilities ZoneEquipment Data Types