Validation of the single zone model

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.Validation;
model ThermalZone "Validation of the single zone model"
  extends Modelica.Icons.Example;
  package MediumA = Buildings.Media.Air "Medium model";

  Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.ThermalZone thermalZone(
    redeclare package MediumA = MediumA,
    gainFactor=1) "Thermal zone model"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"

equation
  connect(weaDat.weaBus, thermalZone.weaBus)
end ThermalZone;


within Buildings.Examples;
package Tutorial "Tutorial with step by step instructions for how to build system models"
  extends Modelica.Icons.Information;
end Tutorial;


within Buildings.Examples.Tutorial;
package Boiler "Package with example for how to build a model for boiler with a heating load"
  extends Modelica.Icons.ExamplesPackage;
end Boiler;


within Buildings.Examples.Tutorial.Boiler;
model System1
  "1st part of the system model, consisting of the room with heat transfer"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TOut(T=263.15)
    "Outside temperature"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
equation
  connect(TOut.port, theCon.port_a)
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
end System1;


within Buildings.Examples.Tutorial.Boiler;
model System2
  "2nd part of the system model, consisting of the room with heat transfer and a radiator"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;

//-------------------------Step 2: Water as medium-------------------------//
  replaceable package MediumW =
      Buildings.Media.Water "Medium model";
//-------------------------------------------------------------------------//

//------------------------Step 4: Design conditions------------------------//
  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";
//------------------------------------------------------------------------//

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TOut(T=263.15)
    "Outside temperature"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"

//-------------------------Step 5: Radiator Model-------------------------//
 Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
//------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT sin(nPorts=1, redeclare package Medium = MediumW)
    "Sink for mass flow rate"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"

//------------------------Step 5: Pump for radiator-----------------------//
Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mRad_flow_nominal) "Pump for radiator"

//------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT sou(
    nPorts=1,
    redeclare package Medium = MediumW,
    T=TRadSup_nominal) "Sink for mass flow rate"

//--------------------------Step 6: Pump control--------------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysPum(
    uLow=273.15 + 19,
    uHigh=273.15 + 21)
    "Pump hysteresis"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad(realTrue=mRad_flow_nominal)
    "Radiator pump signal"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Negate output of hysteresis"
//------------------------------------------------------------------------//

equation
  connect(TOut.port, theCon.port_a)
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(rad.port_b, sin.ports[1])
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(sou.ports[1], pumRad.port_a)
  connect(pumRad.port_b, temSup.port_a)
  connect(temRoo.T, hysPum.u)
  connect(hysPum.y, not1.u)
  connect(not1.y, booToReaRad.u)
  connect(booToReaRad.y, pumRad.m_flow_in)
end System2;


within Buildings.Examples.Tutorial.Boiler;
model System3
  "3rd part of the system model, which adds the boiler loop with open loop control"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;
  replaceable package MediumW =
      Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

//-------------------------Step 4: Boiler design values-------------------------//
  parameter Modelica.Units.SI.Temperature TBoiSup_nominal=273.15 + 70
    "Boiler nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TBoiRet_min=273.15 + 60
    "Boiler minimum return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TBoiRet_min) "Boiler nominal mass flow rate";
//------------------------------------------------------------------------------//

//----------------Radiator loop: Three-way valve: mass flow rate----------------//
  parameter Modelica.Units.SI.MassFlowRate mRadVal_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";
//------------------------------------------------------------------------------//

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TOut(T=263.15)
    "Outside temperature"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mRad_flow_nominal) "Pump for radiator"

//-------------------------Step 3: Splitter and mixers------------------------//
  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mRadVal_flow_nominal,-mRad_flow_nominal,mRad_flow_nominal
         - mRadVal_flow_nominal},
    dp_nominal={100,-8000,6750}) "Mixer between valve and radiators"
  Buildings.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mRadVal_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={200,-200,-50}) "Splitter of boiler loop bypass"

  Buildings.Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,0,0},
    m_flow_nominal={mRad_flow_nominal,-mRadVal_flow_nominal,-mRad_flow_nominal
         + mRadVal_flow_nominal})
  Buildings.Fluid.FixedResistances.Junction mix2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,-200,0},
    m_flow_nominal={mRadVal_flow_nominal,-mBoi_flow_nominal,mBoi_flow_nominal})
    "Mixer"
  Buildings.Fluid.FixedResistances.Junction spl4(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal*{1,-1,-1},
    dp_nominal=200*{1,-1,-1}) "Splitter for radiator loop valve bypass"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Movers.FlowControlled_m_flow pumBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mBoi_flow_nominal) "Pump for boiler"

//-------------------------------Step 3: Boiler-------------------------------//
  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    dp_nominal=2000,
    Q_flow_nominal=Q_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue()) "Boiler"
//----------------------------------------------------------------------------//

//--------------------------Step 3: Three-way Valve---------------------------//
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for radiator loop"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT preSou(redeclare package Medium = MediumW,
      nPorts=1)
    "Source for pressure and to account for thermal expansion of water"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for boiler"
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(redeclare package Medium =
        MediumW, m_flow_nominal=mBoi_flow_nominal) "Return water temperature"
  Buildings.Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mBoi_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={0,0,-200}) "Splitter"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant const(k=1)
    "Constant control signal for valves"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant conBoi(k=mBoi_flow_nominal)
    "Constant mass flow rate for boiler pump"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant const1(k=0.5)
    "Constant control signal for valves"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysPum(
    uLow=273.15 + 19,
    uHigh=273.15 + 21)
    "Pump hysteresis"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad(realTrue=mRad_flow_nominal)
    "Radiator pump signal"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Negate output of hysteresis"
equation
  connect(TOut.port, theCon.port_a)
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(pumRad.port_b, temSup.port_a)
  connect(boi.port_b, pumBoi.port_a)
  connect(pumBoi.port_b, spl1.port_1)
  connect(spl1.port_2, spl.port_1)
  connect(spl.port_2, valRad.port_1)
  connect(valRad.port_2, mix.port_1)
  connect(spl1.port_3, valBoi.port_3)
  connect(valBoi.port_2, temRet.port_a)
  connect(temRet.port_b, boi.port_a)
  connect(boi.port_a, preSou.ports[1])
  connect(mix2.port_2, valBoi.port_1)
  connect(spl4.port_2, mix2.port_1)
  connect(spl2.port_2, spl4.port_1)
  connect(valRad.port_3, spl4.port_3)
  connect(spl.port_3, mix2.port_3)
  connect(mix.port_3, spl2.port_3)
  connect(mix.port_2, pumRad.port_a)
  connect(rad.port_b, spl2.port_1)
  connect(const.y, valRad.y)
  connect(conBoi.y, pumBoi.m_flow_in)
  connect(const.y, valBoi.y)

  connect(const1.y, boi.y)
  connect(temRoo.T,hysPum. u)
  connect(hysPum.y,not1. u)
  connect(not1.y,booToReaRad. u)
  connect(booToReaRad.y, pumRad.m_flow_in)
end System3;


within Buildings.Examples.Tutorial.Boiler;
model System4
  "4th part of the system model, which adds closed-loop control for the pumps and the boiler"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;
  replaceable package MediumW =
      Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

//-------------------------Step 4: Boiler design values-------------------------//
  parameter Modelica.Units.SI.Temperature TBoiSup_nominal=273.15 + 70
    "Boiler nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TBoiRet_min=273.15 + 60
    "Boiler minimum return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TBoiRet_min) "Boiler nominal mass flow rate";
//------------------------------------------------------------------------------//

//----------------Radiator loop: Three-way valve: mass flow rate----------------//
  parameter Modelica.Units.SI.MassFlowRate mRadVal_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";
//------------------------------------------------------------------------------//

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TOut(T=263.15)
    "Outside temperature"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mRad_flow_nominal) "Pump for radiator"

//-------------------------Step 3: Splitter and mixers------------------------//
  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mRadVal_flow_nominal,-mRad_flow_nominal,mRad_flow_nominal
         - mRadVal_flow_nominal},
    dp_nominal={100,-8000,6750}) "Mixer between valve and radiators"
  Buildings.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mRadVal_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={200,-200,-50}) "Splitter of boiler loop bypass"

  Buildings.Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,0,0},
    m_flow_nominal={mRad_flow_nominal,-mRadVal_flow_nominal,-mRad_flow_nominal
         + mRadVal_flow_nominal})
  Buildings.Fluid.FixedResistances.Junction mix2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,-200,0},
    m_flow_nominal={mRadVal_flow_nominal,-mBoi_flow_nominal,mBoi_flow_nominal})
    "Mixer"
  Buildings.Fluid.FixedResistances.Junction spl4(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal*{1,-1,-1},
    dp_nominal=200*{1,-1,-1}) "Splitter for radiator loop valve bypass"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Movers.FlowControlled_m_flow pumBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mBoi_flow_nominal) "Pump for boiler"

//-------------------------------Step 3: Boiler-------------------------------//
  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    dp_nominal=2000,
    Q_flow_nominal=Q_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue()) "Boiler"
//----------------------------------------------------------------------------//

//--------------------------Step 3: Three-way Valve---------------------------//
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for radiator loop"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT preSou(redeclare package Medium = MediumW,
      nPorts=1)
    "Source for pressure and to account for thermal expansion of water"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for boiler"
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(redeclare package Medium =
        MediumW, m_flow_nominal=mBoi_flow_nominal) "Return water temperature"
  Buildings.Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mBoi_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={0,0,-200}) "Splitter"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant const(k=1)
    "Constant control signal for valves"

//---------------------Step 2: Outdoor temperature sensor and control------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTOut(uLow=273.15 + 16, uHigh=273.15 + 17)
    "Hysteresis for on/off based on outside temperature"
  Buildings.Controls.OBC.CDL.Logical.Not not2

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTOut
    "Outdoor temperature sensor"
//------------------------------------------------------------------------------------//

//-------------------------------Step 4: Boiler hysteresis----------------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTBoi(uHigh=273.15 + 90,
                                             uLow=273.15 + 70)
    "Hysteresis for on/off of boiler"
  Buildings.Controls.OBC.CDL.Logical.Not not3
  Buildings.Controls.OBC.CDL.Logical.And and1
//------------------------------------------------------------------------------------//

//-------------------------Step 3: Boolean to real: Boiler Pump-----------------------//
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad1(realTrue=mBoi_flow_nominal)
    "Boiler pump signal"
//------------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Logical.And and2

//---------------------------------Step 4: Boiler signal------------------------------//
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad2(realTrue=1) "Boiler signal"
//------------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysPum(
    uLow=273.15 + 19,
    uHigh=273.15 + 21)
    "Pump hysteresis"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad(realTrue=mRad_flow_nominal)
    "Radiator pump signal"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Negate output of hysteresis"
equation
  connect(TOut.port, theCon.port_a)
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(pumRad.port_b, temSup.port_a)
  connect(boi.port_b, pumBoi.port_a)
  connect(pumBoi.port_b, spl1.port_1)
  connect(spl1.port_2, spl.port_1)
  connect(spl.port_2, valRad.port_1)
  connect(valRad.port_2, mix.port_1)
  connect(spl1.port_3, valBoi.port_3)
  connect(valBoi.port_2, temRet.port_a)
  connect(temRet.port_b, boi.port_a)
  connect(boi.port_a, preSou.ports[1])
  connect(mix2.port_2, valBoi.port_1)
  connect(spl4.port_2, mix2.port_1)
  connect(spl2.port_2, spl4.port_1)
  connect(valRad.port_3, spl4.port_3)
  connect(spl.port_3, mix2.port_3)
  connect(mix.port_3, spl2.port_3)
  connect(mix.port_2, pumRad.port_a)
  connect(rad.port_b, spl2.port_1)
  connect(const.y, valRad.y)
  connect(const.y, valBoi.y)

  connect(hysTOut.y, not2.u)
  connect(senTOut.port, TOut.port)
  connect(hysTBoi.y, not3.u)
  connect(not2.y, and1.u2)
  connect(boi.T, hysTBoi.u)
  connect(senTOut.T, hysTOut.u)
  connect(and1.y, booToReaRad1.u)
  connect(and1.y, and2.u1)
  connect(not3.y, and2.u2)
  connect(and2.y, booToReaRad2.u)
  connect(booToReaRad2.y, boi.y)
  connect(temRoo.T,hysPum. u)
  connect(hysPum.y,not1. u)
  connect(not1.y, and1.u1)
  connect(and1.y, booToReaRad.u)
  connect(booToReaRad.y, pumRad.m_flow_in)
  connect(booToReaRad1.y, pumBoi.m_flow_in)
end System4;


within Buildings.Examples.Tutorial.Boiler;
model System5
  "5th part of the system model, which adds closed-loop control for the valves"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;
  replaceable package MediumW =
      Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

//-------------------------Step 4: Boiler design values-------------------------//
  parameter Modelica.Units.SI.Temperature TBoiSup_nominal=273.15 + 70
    "Boiler nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TBoiRet_min=273.15 + 60
    "Boiler minimum return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TBoiRet_min) "Boiler nominal mass flow rate";
//------------------------------------------------------------------------------//

//----------------Radiator loop: Three-way valve: mass flow rate----------------//
  parameter Modelica.Units.SI.MassFlowRate mRadVal_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";
//------------------------------------------------------------------------------//

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TOut(T=263.15)
    "Outside temperature"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mRad_flow_nominal) "Pump for radiator"

//-------------------------Step 3: Splitter and mixers------------------------//
  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mRadVal_flow_nominal,-mRad_flow_nominal,mRad_flow_nominal
         - mRadVal_flow_nominal},
    dp_nominal={100,-8000,6750}) "Mixer between valve and radiators"
  Buildings.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mRadVal_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={200,-200,-50}) "Splitter of boiler loop bypass"

  Buildings.Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,0,0},
    m_flow_nominal={mRad_flow_nominal,-mRadVal_flow_nominal,-mRad_flow_nominal
         + mRadVal_flow_nominal})
  Buildings.Fluid.FixedResistances.Junction mix2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,-200,0},
    m_flow_nominal={mRadVal_flow_nominal,-mBoi_flow_nominal,mBoi_flow_nominal})
    "Mixer"
  Buildings.Fluid.FixedResistances.Junction spl4(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal*{1,-1,-1},
    dp_nominal=200*{1,-1,-1}) "Splitter for radiator loop valve bypass"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Movers.FlowControlled_m_flow pumBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mBoi_flow_nominal) "Pump for boiler"

//-------------------------------Step 3: Boiler-------------------------------//
  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    dp_nominal=2000,
    Q_flow_nominal=Q_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue()) "Boiler"
//----------------------------------------------------------------------------//

//--------------------------Step 3: Three-way Valve---------------------------//
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for radiator loop"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT preSou(redeclare package Medium = MediumW,
      nPorts=1)
    "Source for pressure and to account for thermal expansion of water"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for boiler"
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(redeclare package Medium =
        MediumW, m_flow_nominal=mBoi_flow_nominal) "Return water temperature"
  Buildings.Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mBoi_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={0,0,-200}) "Splitter"

//---------------------Step 2: Outdoor temperature sensor and control------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTOut(uLow=273.15 + 16, uHigh=273.15 + 17)
    "Hysteresis for on/off based on outside temperature"
  Buildings.Controls.OBC.CDL.Logical.Not not2

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTOut
    "Outdoor temperature sensor"
//------------------------------------------------------------------------------------//

//-------------------------------Step 4: Boiler hysteresis----------------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTBoi(uHigh=273.15 + 90,
                                             uLow=273.15 + 70)
    "Hysteresis for on/off of boiler"
  Buildings.Controls.OBC.CDL.Logical.Not not3
  Buildings.Controls.OBC.CDL.Logical.And and1
//------------------------------------------------------------------------------------//

//-------------------------Step 3: Boolean to real: Boiler Pump-----------------------//
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad1(realTrue=mBoi_flow_nominal)
    "Boiler pump signal"
//------------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Logical.And and2

//---------------------------------Step 4: Boiler signal------------------------------//
 Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad2(realTrue=1) "Boiler signal"
//------------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysPum(
    uLow=273.15 + 19,
    uHigh=273.15 + 21)
    "Pump hysteresis"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad(realTrue=mRad_flow_nominal)
    "Radiator pump signal"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Negate output of hysteresis"

//------------------------Step 2: Boiler loop valve control-----------------------//
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetBoiRet(k=TBoiRet_min)
    "Temperature setpoint for boiler return"
  Buildings.Controls.OBC.CDL.Reals.PID conPIDBoi(
    Td=1,
    Ti=120,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=0.1,
    reverseActing=false) "Controller for valve in boiler loop"
//--------------------------------------------------------------------------------//

//----------------------Step 3: Radiator loop valve control-----------------------//
  Buildings.Controls.OBC.CDL.Reals.PID conPIDRad(
    Td=1,
    Ti=120,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=0.1) "Controller for valve in radiator loop"
//--------------------------------------------------------------------------------//
  Buildings.Controls.OBC.CDL.Reals.Line TSetSup
    "Setpoint for supply water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupMin(k=273.15 + 21)
    "Minimum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupMax(k=273.15 + 50)
    "Maximum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TRooMin(k=273.15 + 19)
    "Minimum room air temperature"
equation
  connect(TOut.port, theCon.port_a)
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(pumRad.port_b, temSup.port_a)
  connect(boi.port_b, pumBoi.port_a)
  connect(pumBoi.port_b, spl1.port_1)
  connect(spl1.port_2, spl.port_1)
  connect(spl.port_2, valRad.port_1)
  connect(valRad.port_2, mix.port_1)
  connect(spl1.port_3, valBoi.port_3)
  connect(valBoi.port_2, temRet.port_a)
  connect(temRet.port_b, boi.port_a)
  connect(boi.port_a, preSou.ports[1])
  connect(mix2.port_2, valBoi.port_1)
  connect(spl4.port_2, mix2.port_1)
  connect(spl2.port_2, spl4.port_1)
  connect(valRad.port_3, spl4.port_3)
  connect(spl.port_3, mix2.port_3)
  connect(mix.port_3, spl2.port_3)
  connect(mix.port_2, pumRad.port_a)
  connect(rad.port_b, spl2.port_1)

  connect(hysTOut.y, not2.u)
  connect(senTOut.port, TOut.port)
  connect(hysTBoi.y, not3.u)
  connect(not2.y, and1.u2)
  connect(boi.T, hysTBoi.u)
  connect(senTOut.T, hysTOut.u)
  connect(and1.y, booToReaRad1.u)
  connect(and1.y, and2.u1)
  connect(not3.y, and2.u2)
  connect(and2.y, booToReaRad2.u)
  connect(booToReaRad2.y, boi.y)
  connect(temRoo.T,hysPum. u)
  connect(hysPum.y,not1. u)
  connect(not1.y, and1.u1)
  connect(and1.y, booToReaRad.u)
  connect(temSup.T, conPIDRad.u_m)
  connect(conPIDRad.y, valRad.y)
  connect(booToReaRad.y, pumRad.m_flow_in)
  connect(booToReaRad1.y, pumBoi.m_flow_in)
  connect(conPIDBoi.y, valBoi.y)
  connect(TSetBoiRet.y, conPIDBoi.u_s)
  connect(temRet.T, conPIDBoi.u_m)
  connect(conPIDRad.u_s, TSetSup.y)
  connect(TSetSup.x1, TRooMin.y)
  connect(TSupMax.y, TSetSup.f1)
  connect(TSupMin.y, TSetSup.f2)
  connect(TSupMin.y, TSetSup.x2)
  connect(TSetSup.u, temRoo.T)
end System5;


within Buildings.Examples.Tutorial.Boiler;
model System6
  "6th part of the system model, which adds weather data and changes to PI control"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;
  replaceable package MediumW =
      Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

  parameter Modelica.Units.SI.Temperature TBoiSup_nominal=273.15 + 70
    "Boiler nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TBoiRet_min=273.15 + 60
    "Boiler minimum return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TBoiRet_min) "Boiler nominal mass flow rate";
//------------------------------------------------------------------------------//

//----------------Radiator loop: Three-way valve: mass flow rate----------------//
  parameter Modelica.Units.SI.MassFlowRate mRadVal_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mRad_flow_nominal) "Pump for radiator"

//----------------------------------------------------------------------------//
  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mRadVal_flow_nominal,-mRad_flow_nominal,mRad_flow_nominal
         - mRadVal_flow_nominal},
    dp_nominal={100,-8000,6750}) "Mixer between valve and radiators"
  Buildings.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mRadVal_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={200,-200,-50}) "Splitter of boiler loop bypass"

  Buildings.Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,0,0},
    m_flow_nominal={mRad_flow_nominal,-mRadVal_flow_nominal,-mRad_flow_nominal
         + mRadVal_flow_nominal})
  Buildings.Fluid.FixedResistances.Junction mix2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,-200,0},
    m_flow_nominal={mRadVal_flow_nominal,-mBoi_flow_nominal,mBoi_flow_nominal})
    "Mixer"
  Buildings.Fluid.FixedResistances.Junction spl4(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal*{1,-1,-1},
    dp_nominal=200*{1,-1,-1}) "Splitter for radiator loop valve bypass"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Movers.FlowControlled_m_flow pumBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mBoi_flow_nominal) "Pump for boiler"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    dp_nominal=2000,
    Q_flow_nominal=Q_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue()) "Boiler"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for radiator loop"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT preSou(redeclare package Medium = MediumW,
      nPorts=1)
    "Source for pressure and to account for thermal expansion of water"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for boiler"
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(redeclare package Medium =
        MediumW, m_flow_nominal=mBoi_flow_nominal) "Return water temperature"
  Buildings.Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mBoi_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={0,0,-200}) "Splitter"

//--------------------------------------------------------------------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTOut(uLow=273.15 + 16, uHigh=273.15 + 17)
    "Hysteresis for on/off based on outside temperature"
  Buildings.Controls.OBC.CDL.Logical.Not not2

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTOut
    "Outdoor temperature sensor"
//--------------------------------------------------------------------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysTBoi(uHigh=273.15 + 90,
                                             uLow=273.15 + 70)
    "Hysteresis for on/off of boiler"
  Buildings.Controls.OBC.CDL.Logical.Not not3
  Buildings.Controls.OBC.CDL.Logical.And and1
//--------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad1(realTrue=mBoi_flow_nominal)
    "Boiler pump signal"
//--------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Logical.And and2

 Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad2(realTrue=1)
    "Boiler signal"

//--------------------------------------------------------------------------------//
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysPum(
    uLow=273.15 + 19,
    uHigh=273.15 + 21)
    "Pump hysteresis"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad(realTrue=mRad_flow_nominal)
    "Radiator pump signal"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Negate output of hysteresis"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetBoiRet(k=TBoiRet_min)
    "Temperature setpoint for boiler return"

  Buildings.Controls.OBC.CDL.Reals.PID conPIDBoi(
    Td=1,
    Ti=120,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=0.1,
    reverseActing=false) "Controller for valve in boiler loop"
//--------------------------------------------------------------------------------//

  Buildings.Controls.OBC.CDL.Reals.PID conPIDRad(
    Td=1,
    Ti=120,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=0.1) "Controller for valve in radiator loop"
//------------------------------------------------------------------------------//
  Buildings.Controls.OBC.CDL.Reals.Line TSetSup
    "Setpoint for supply water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupMin(k=273.15 + 21)
    "Minimum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupMax(k=273.15 + 50)
    "Maximum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TRooMin(k=273.15 + 19)
    "Minimum room air temperature"
//--- Weather data -------------------------------------------------------------//
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  BoundaryConditions.WeatherData.Bus weaBus
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TOut
    "Outside temperature"
//------------------------------------------------------------------------------//

equation
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(pumRad.port_b, temSup.port_a)
  connect(boi.port_b, pumBoi.port_a)
  connect(pumBoi.port_b, spl1.port_1)
  connect(spl1.port_2, spl.port_1)
  connect(spl.port_2, valRad.port_1)
  connect(valRad.port_2, mix.port_1)
  connect(spl1.port_3, valBoi.port_3)
  connect(valBoi.port_2, temRet.port_a)
  connect(temRet.port_b, boi.port_a)
  connect(boi.port_a, preSou.ports[1])
  connect(mix2.port_2, valBoi.port_1)
  connect(spl4.port_2, mix2.port_1)
  connect(spl2.port_2, spl4.port_1)
  connect(valRad.port_3, spl4.port_3)
  connect(spl.port_3, mix2.port_3)
  connect(mix.port_3, spl2.port_3)
  connect(mix.port_2, pumRad.port_a)
  connect(rad.port_b, spl2.port_1)

  connect(hysTOut.y, not2.u)
  connect(hysTBoi.y, not3.u)
  connect(not2.y, and1.u2)
  connect(boi.T, hysTBoi.u)
  connect(senTOut.T, hysTOut.u)
  connect(and1.y, booToReaRad1.u)
  connect(and1.y, and2.u1)
  connect(not3.y, and2.u2)
  connect(and2.y, booToReaRad2.u)
  connect(booToReaRad2.y, boi.y)
  connect(temRoo.T,hysPum. u)
  connect(hysPum.y,not1. u)
  connect(not1.y, and1.u1)
  connect(and1.y, booToReaRad.u)
  connect(temSup.T, conPIDRad.u_m)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.TDryBul, TOut.T)
  connect(TOut.port, theCon.port_a)
  connect(TOut.port, senTOut.port)
  connect(booToReaRad.y, pumRad.m_flow_in)
  connect(conPIDRad.y, valRad.y)
  connect(booToReaRad1.y, pumBoi.m_flow_in)
  connect(conPIDBoi.y, valBoi.y)
  connect(TSetBoiRet.y, conPIDBoi.u_s)
  connect(temRet.T, conPIDBoi.u_m)
  connect(TSetSup.x1,TRooMin. y)
  connect(TSupMax.y,TSetSup. f1)
  connect(TSupMin.y,TSetSup. f2)
  connect(TSupMin.y,TSetSup. x2)
  connect(TSetSup.u, temRoo.T)
  connect(conPIDRad.u_s,TSetSup. y)
end System6;


within Buildings.Examples.Tutorial.Boiler;
model System7
  "7th part of the system model, which implements the on/off control using a state machine"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air;
  replaceable package MediumW =
      Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

  parameter Modelica.Units.SI.Temperature TBoiSup_nominal=273.15 + 70
    "Boiler nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TBoiRet_min=273.15 + 60
    "Boiler minimum return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TBoiRet_min) "Boiler nominal mass flow rate";
//------------------------------------------------------------------------------//

//----------------Radiator loop: Three-way valve: mass flow rate----------------//
  parameter Modelica.Units.SI.MassFlowRate mRadVal_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mRad_flow_nominal) "Pump for radiator"

//----------------------------------------------------------------------------//
  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mRadVal_flow_nominal,-mRad_flow_nominal,mRad_flow_nominal
         - mRadVal_flow_nominal},
    dp_nominal={100,-8000,6750}) "Mixer between valve and radiators"
  Buildings.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mRadVal_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={200,-200,-50}) "Splitter of boiler loop bypass"

  Buildings.Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,0,0},
    m_flow_nominal={mRad_flow_nominal,-mRadVal_flow_nominal,-mRad_flow_nominal
         + mRadVal_flow_nominal})
  Buildings.Fluid.FixedResistances.Junction mix2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,-200,0},
    m_flow_nominal={mRadVal_flow_nominal,-mBoi_flow_nominal,mBoi_flow_nominal})
    "Mixer"
  Buildings.Fluid.FixedResistances.Junction spl4(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal*{1,-1,-1},
    dp_nominal=200*{1,-1,-1}) "Splitter for radiator loop valve bypass"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Movers.FlowControlled_m_flow pumBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mBoi_flow_nominal) "Pump for boiler"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    dp_nominal=2000,
    Q_flow_nominal=Q_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue()) "Boiler"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for radiator loop"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Sources.Boundary_pT preSou(redeclare package Medium = MediumW,
      nPorts=1)
    "Source for pressure and to account for thermal expansion of water"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for boiler"
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(redeclare package Medium =
        MediumW, m_flow_nominal=mBoi_flow_nominal) "Return water temperature"
  Buildings.Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mBoi_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={0,0,-200}) "Splitter"

//------------------------------------------------------------------------------------//

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTOut
    "Outdoor temperature sensor"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad1(realTrue=mBoi_flow_nominal)
    "Boiler pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad2(realTrue=1)
    "Boiler on/off signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaRad(realTrue=mRad_flow_nominal)
    "Radiator pump signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetBoiRet(k=TBoiRet_min)
    "Temperature setpoint for boiler return"
  Buildings.Controls.OBC.CDL.Reals.PID conPIDBoi(
    Td=1,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=0.1,
    Ti=120,
    reverseActing=false) "Controller for valve in boiler loop"
  Buildings.Controls.OBC.CDL.Reals.PID conPIDRad(
    Td=1,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=0.1,
    Ti=120) "Controller for valve in radiator loop"
  Buildings.Controls.OBC.CDL.Reals.Line TSetSup
    "Setpoint for supply water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupMin(k=273.15 + 21)
    "Minimum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupMax(k=273.15 + 50)
    "Maximum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TRooMin(k=273.15 + 19)
    "Minimum room air temperature"

  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  BoundaryConditions.WeatherData.Bus weaBus
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TOut
    "Outside temperature"

//-------------------------Step 2: State machine implementation-------------------------//
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
    "Root of the state graph"
  Modelica.StateGraph.Alternative alternative
    "Split for alternative execution paths"
  Modelica.StateGraph.InitialStepWithSignal allOff(
    nOut=1,
    nIn=1) "System off"
  Modelica.StateGraph.TransitionWithSignal T1 "Transition to switch pumps on"
  Modelica.StateGraph.StepWithSignal boilerOn(
    nIn=1,
    nOut=1) "Boiler is on"
  Modelica.StateGraph.TransitionWithSignal T2 "Transition to boiler on"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThrBoi(t=273.15 +
        90) "Threshold for boiler control"
  Modelica.StateGraph.TransitionWithSignal T3(
    waitTime=10, enableTimer=true) "Transition to switch boiler off"
  Modelica.StateGraph.TransitionWithSignal T4(
    waitTime=10, enableTimer=true) "Transition to all off"
  Modelica.StateGraph.Step pumpsOn(nIn=1, nOut=1) "Pumps are on"
//--------------------------------------------------------------------------------------//
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lessThreshold(t=273.15 +
        19)
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lessThreshold1(t=273.15
         + 16)
  Buildings.Controls.OBC.CDL.Logical.And and3
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lessThreshold2(t=273.15
         + 70) "Threshold for boiler control"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThrTRoo(t=273.15 +
        21) "Threshold for room temperature"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThrTROut(t=273.15
         + 17) "Threshold for room temperature"
  Controls.OBC.CDL.Logical.Or or1
    "Switch off system if outside is sufficiently warm, or room is sufficiently warm"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Negate output of hysteresis"

equation
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(pumRad.port_b, temSup.port_a)
  connect(boi.port_b, pumBoi.port_a)
  connect(pumBoi.port_b, spl1.port_1)
  connect(spl1.port_2, spl.port_1)
  connect(spl.port_2, valRad.port_1)
  connect(valRad.port_2, mix.port_1)
  connect(spl1.port_3, valBoi.port_3)
  connect(valBoi.port_2, temRet.port_a)
  connect(temRet.port_b, boi.port_a)
  connect(boi.port_a, preSou.ports[1])
  connect(mix2.port_2, valBoi.port_1)
  connect(spl4.port_2, mix2.port_1)
  connect(spl2.port_2, spl4.port_1)
  connect(valRad.port_3, spl4.port_3)
  connect(spl.port_3, mix2.port_3)
  connect(mix.port_3, spl2.port_3)
  connect(mix.port_2, pumRad.port_a)
  connect(rad.port_b, spl2.port_1)

  connect(booToReaRad2.y, boi.y)
  connect(temSup.T, conPIDRad.u_m)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.TDryBul, TOut.T)
  connect(TOut.port, theCon.port_a)
  connect(TOut.port, senTOut.port)
  connect(allOff.outPort[1], T1.inPort)
  connect(temRoo.T, lessThreshold.u)
  connect(lessThreshold1.u, senTOut.T)

  connect(lessThreshold.y, and3.u1)
  connect(lessThreshold1.y, and3.u2)
  connect(boi.T, lessThreshold2.u)
  connect(T2.outPort, boilerOn.inPort[1])
  connect(boi.T, greThrBoi.u)
  connect(boilerOn.outPort[1], T3.inPort)
  connect(temRoo.T, greThrTRoo.u)

  connect(senTOut.T, greThrTROut.u)

  connect(greThrTRoo.y, or1.u1)
  connect(greThrTROut.y, or1.u2)

  connect(not1.y, booToReaRad.u)
  connect(not1.y, booToReaRad1.u)
  connect(T4.outPort, allOff.inPort[1])
  connect(conPIDRad.y, valRad.y)
  connect(booToReaRad.y, pumRad.m_flow_in)
  connect(conPIDBoi.y, valBoi.y)
  connect(booToReaRad1.y, pumBoi.m_flow_in)
  connect(TSetBoiRet.y, conPIDBoi.u_s)
  connect(temRet.T, conPIDBoi.u_m)
  connect(T1.condition, and3.y)
  connect(booToReaRad2.u, boilerOn.active)
  connect(lessThreshold2.y, T2.condition)
  connect(T4.condition, or1.y)
  connect(T3.condition, greThrBoi.y)
  connect(allOff.active, not1.u)
  connect(pumpsOn.outPort[1], alternative.inPort)
  connect(alternative.outPort, pumpsOn.inPort[1])
  connect(T4.inPort, alternative.split[1])
  connect(T2.inPort, alternative.split[2])
  connect(T1.outPort, alternative.join[1])
  connect(T3.outPort, alternative.join[2])
  connect(TSetSup.x1,TRooMin. y)
  connect(TSupMax.y,TSetSup. f1)
  connect(TSupMin.y,TSetSup. f2)
  connect(TSupMin.y,TSetSup. x2)
  connect(TSetSup.u, temRoo.T)
  connect(conPIDRad.u_s,TSetSup. y)
end System7;


within Buildings.Examples.Tutorial;
package CDL "Package with examples for how to implement a control sequence using CDL"
  extends Modelica.Icons.ExamplesPackage;
end CDL;


Open loop model. This model extends from the open loop partial model

Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop,
which implements the HVAC system model and a simple room.
In this partial model, the room is modeled
as a first order response.

within Buildings.Examples.Tutorial.CDL;
model System1 "Open loop model"
  extends Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop;

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant y1(k=mRad_flow_nominal)
    "Control signal of 1"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant y2(k=1)
    "Control signal of 1"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant y3(k=1)
    "Constant control signal of 1"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant y4(k=1)
    "Control signal of 1"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant y5(k=mBoi_flow_nominal)
    "Control signal of 1"
equation
  connect(y1.y, pumRad.m_flow_in)
  connect(y3.y, boi.y)
  connect(y2.y, valBoi.y)
  connect(y4.y, valRad.y)
  connect(y5.y, pumBoi.m_flow_in)
end System1;


within Buildings.Examples.Tutorial.CDL;
model System2 "Open loop model with control architecture implemented"
  extends Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop;

  Controls.OpenLoopBoilerReturn conBoiRet
    "Controller for boiler return water temperature"
  Controls.OpenLoopSystemOnOff conSysSta
    "Controller that switches the system on and off"
  Controls.OpenLoopRadiatorSupply conRadSup
    "Controller for the mixing valve for the radiator supply water"
  Controls.OpenLoopEquipmentOnOff conEquSta
    "Controller that switches the equipment on and off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal radPumCon(
    realTrue=mRad_flow_nominal)
    "Type conversion for radiator pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiPumCon(
    realTrue=mBoi_flow_nominal)
    "Type conversion for boiler pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiSigCon(
    realTrue=1)
    "Type conversion for boiler signal"
equation
  connect(conSysSta.onSys, conEquSta.onSys)
  connect(conEquSta.onPum, boiPumCon.u)
  connect(radPumCon.u, conEquSta.onPum)
  connect(boiSigCon.u, conEquSta.onBoi)
  connect(radPumCon.y, pumRad.m_flow_in)
  connect(boiPumCon.y, pumBoi.m_flow_in)
  connect(boiSigCon.y, boi.y)
  connect(conRadSup.yVal, valRad.y)
  connect(conEquSta.TBoi, boi.T)
  connect(conSysSta.TOut, senTOut.T)
  connect(conRadSup.TRoo, temRoo.T)
  connect(conSysSta.TRoo, temRoo.T)
  connect(temRet.T, conBoiRet.TRet)
  connect(conBoiRet.yVal, valBoi.y)
  connect(temSup.T, conRadSup.TSup)
end System2;


Open loop model with boiler return temperature control. In this step, we added the controller for the boiler return water temperature.

within Buildings.Examples.Tutorial.CDL;
model System3 "Open loop model with boiler return temperature control"
  extends Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop;

  Controls.BoilerReturn conBoiRet
   "Controller for boiler return water temperature"
  Controls.OpenLoopSystemOnOff conSysSta
    "Controller that switches the system on and off"
  Controls.OpenLoopRadiatorSupply conRadSup
    "Controller for the mixing valve for the radiator supply water"
  Controls.OpenLoopEquipmentOnOff conEquSta
    "Controller that switches the equipment on and off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal radPumCon(
    realTrue=mRad_flow_nominal)
    "Type conversion for radiator pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiPumCon(
    realTrue=mBoi_flow_nominal)
    "Type conversion for boiler pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiSigCon(
    realTrue=1)
    "Type conversion for boiler signal"
equation
  connect(conSysSta.onSys, conEquSta.onSys)
  connect(conEquSta.onPum, boiPumCon.u)
  connect(radPumCon.u, conEquSta.onPum)
  connect(boiSigCon.u, conEquSta.onBoi)
  connect(radPumCon.y, pumRad.m_flow_in)
  connect(boiPumCon.y, pumBoi.m_flow_in)
  connect(boiSigCon.y, boi.y)
  connect(conRadSup.yVal, valRad.y)
  connect(conEquSta.TBoi, boi.T)
  connect(conSysSta.TOut, senTOut.T)
  connect(conRadSup.TRoo, temRoo.T)
  connect(conSysSta.TRoo, temRoo.T)
  connect(temRet.T, conBoiRet.TRet)
  connect(conBoiRet.yVal, valBoi.y)

  connect(temSup.T, conRadSup.TSup)
end System3;


Open loop model with equipment on/off control. In this step, we added the controller for the boiler on/off control.

within Buildings.Examples.Tutorial.CDL;
model System4 "Open loop model with equipment on/off control"
  extends Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop;

  Controls.BoilerReturn conBoiRet
   "Controller for boiler return water temperature"
  Controls.OpenLoopSystemOnOff conSysSta
    "Controller that switches the system on and off"
  Controls.OpenLoopRadiatorSupply conRadSup
    "Controller for the mixing valve for the radiator supply water"
  Controls.EquipmentOnOff conEquSta
    "Controller that switches the equipment on and off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal radPumCon(
    realTrue=mRad_flow_nominal)
    "Type conversion for radiator pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiPumCon(
    realTrue=mBoi_flow_nominal)
    "Type conversion for boiler pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiSigCon(
    realTrue=1)
    "Type conversion for boiler signal"
equation
  connect(conSysSta.onSys, conEquSta.onSys)
  connect(conEquSta.onPum, boiPumCon.u)
  connect(radPumCon.u, conEquSta.onPum)
  connect(boiSigCon.u, conEquSta.onBoi)
  connect(radPumCon.y, pumRad.m_flow_in)
  connect(boiPumCon.y, pumBoi.m_flow_in)
  connect(boiSigCon.y, boi.y)
  connect(conRadSup.yVal, valRad.y)
  connect(conEquSta.TBoi, boi.T)
  connect(conSysSta.TOut, senTOut.T)
  connect(conRadSup.TRoo, temRoo.T)
  connect(conSysSta.TRoo, temRoo.T)
  connect(temRet.T, conBoiRet.TRet)
  connect(conBoiRet.yVal, valBoi.y)

  connect(temSup.T, conRadSup.TSup)
end System4;


Open loop model with system on/off control. In this step, we added the controller for the system on/off control.

within Buildings.Examples.Tutorial.CDL;
model System5 "Open loop model with system on/off control"
  extends Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop;

  Controls.BoilerReturn conBoiRet
   "Controller for boiler return water temperature"
  Controls.SystemOnOff conSysSta
    "Controller that switches the system on and off"
  Controls.OpenLoopRadiatorSupply conRadSup
    "Controller for the mixing valve for the radiator supply water"
  Controls.EquipmentOnOff conEquSta
    "Controller that switches the equipment on and off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal radPumCon(
    realTrue=mRad_flow_nominal)
    "Type conversion for radiator pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiPumCon(
    realTrue=mBoi_flow_nominal)
    "Type conversion for boiler pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiSigCon(
    realTrue=1)
    "Type conversion for boiler signal"
equation
  connect(conSysSta.onSys, conEquSta.onSys)
  connect(conEquSta.onPum, boiPumCon.u)
  connect(radPumCon.u, conEquSta.onPum)
  connect(boiSigCon.u, conEquSta.onBoi)
  connect(radPumCon.y, pumRad.m_flow_in)
  connect(boiPumCon.y, pumBoi.m_flow_in)
  connect(boiSigCon.y, boi.y)
  connect(conRadSup.yVal, valRad.y)
  connect(conEquSta.TBoi, boi.T)
  connect(conSysSta.TOut, senTOut.T)
  connect(conRadSup.TRoo, temRoo.T)
  connect(conSysSta.TRoo, temRoo.T)
  connect(temRet.T, conBoiRet.TRet)
  connect(conBoiRet.yVal, valBoi.y)

  connect(temSup.T, conRadSup.TSup)
end System5;


Closed loop model with all controls implemented. In this step, we added the last controller, which is controlling the mixing valve for the
radiator supply water temperature.

within Buildings.Examples.Tutorial.CDL;
model System6 "Closed loop model with all controls implemented"
  extends
    Buildings.Examples.Tutorial.CDL.BaseClasses.PartialOpenLoop;

  Controls.BoilerReturn conBoiRet
   "Controller for boiler return water temperature"
  Controls.SystemOnOff conSysSta
    "Controller that switches the system on and off"
  Controls.RadiatorSupply conRadSup
    "Controller for the mixing valve for the radiator supply water"
  Controls.EquipmentOnOff conEquSta
    "Controller that switches the equipment on and off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal radPumCon(
    realTrue=mRad_flow_nominal)
    "Type conversion for radiator pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiPumCon(
    realTrue=mBoi_flow_nominal)
    "Type conversion for boiler pump signal"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal boiSigCon(
    realTrue=1)
    "Type conversion for boiler signal"
equation
  connect(conSysSta.onSys, conEquSta.onSys)
  connect(conEquSta.onPum, boiPumCon.u)
  connect(radPumCon.u, conEquSta.onPum)
  connect(boiSigCon.u, conEquSta.onBoi)
  connect(radPumCon.y, pumRad.m_flow_in)
  connect(boiPumCon.y, pumBoi.m_flow_in)
  connect(boiSigCon.y, boi.y)
  connect(conRadSup.yVal, valRad.y)
  connect(conEquSta.TBoi, boi.T)
  connect(conSysSta.TOut, senTOut.T)
  connect(conRadSup.TRoo, temRoo.T)
  connect(conSysSta.TRoo, temRoo.T)
  connect(temRet.T, conBoiRet.TRet)
  connect(conBoiRet.yVal, valBoi.y)

  connect(temSup.T, conRadSup.TSup)
end System6;


within Buildings.Examples.Tutorial.CDL;
package BaseClasses "Package that contains the model of the HVAC system and the building load"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model with open loop system

within Buildings.Examples.Tutorial.CDL.BaseClasses;
partial model PartialOpenLoop "Partial model with open loop system"
  extends Modelica.Icons.Example;
  replaceable package MediumA = Buildings.Media.Air "Medium model for air";
  replaceable package MediumW = Buildings.Media.Water "Medium model for water";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 40
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=Q_flow_nominal/
      4200/(TRadSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

  parameter Modelica.Units.SI.Temperature TBoiSup_nominal=273.15 + 70
    "Boiler nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TBoiRet_min=273.15 + 60
    "Boiler minimum return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TBoiRet_min) "Boiler nominal mass flow rate";

  parameter Modelica.Units.SI.MassFlowRate mRadVal_flow_nominal=Q_flow_nominal/
      4200/(TBoiSup_nominal - TRadRet_nominal)
    "Radiator nominal mass flow rate";

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
    "Room air volume"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/30)
    "Thermal conductance with the ambient"
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable timTab(
      extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.Periodic,
      smoothness=Buildings.Controls.OBC.CDL.Types.Smoothness.ConstantSegments,
      table=[-6, 0;
              8, QRooInt_flow;
             18, 0],
      timeScale=3600) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal) "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(redeclare package Medium = MediumW,
      m_flow_nominal=mRad_flow_nominal) "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo(
    T(displayUnit="degC"))
    "Room temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRad_flow_nominal,
    nominalValuesDefineDefaultPressureCurve=true)
    "Pump for radiator"

  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mRadVal_flow_nominal,-mRad_flow_nominal,mRad_flow_nominal
         - mRadVal_flow_nominal},
    dp_nominal={100,-8000,6750}) "Mixer between valve and radiators"
  Buildings.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mRadVal_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={200,-200,-50}) "Splitter of boiler loop bypass"

  Buildings.Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,0,0},
    m_flow_nominal={mRad_flow_nominal,-mRadVal_flow_nominal,-mRad_flow_nominal
         + mRadVal_flow_nominal}) "Flow splitter in return from radiator"
  Buildings.Fluid.FixedResistances.Junction mix2(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal={0,-200,0},
    m_flow_nominal={mRadVal_flow_nominal,-mBoi_flow_nominal,mBoi_flow_nominal})
    "Mixer"
  Buildings.Fluid.FixedResistances.Junction spl4(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal*{1,-1,-1},
    dp_nominal=200*{1,-1,-1}) "Splitter for radiator loop valve bypass"

  Buildings.Fluid.Movers.FlowControlled_m_flow pumBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    nominalValuesDefineDefaultPressureCurve=true)
                                      "Pump for boiler"

  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    dp_nominal=2000,
    Q_flow_nominal=Q_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue()) "Boiler"

  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valRad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mRadVal_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for radiator loop"

  Buildings.Fluid.Sources.Boundary_pT preSou(redeclare package Medium = MediumW,
      nPorts=1)
    "Source for pressure and to account for thermal expansion of water"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear valBoi(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mBoi_flow_nominal,
    l={0.01,0.01},
    dpValve_nominal=6000) "Three-way valve for boiler"
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(
    redeclare package Medium = MediumW,
    m_flow_nominal=mBoi_flow_nominal) "Return water temperature"
  Buildings.Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={mBoi_flow_nominal,-mBoi_flow_nominal,-mBoi_flow_nominal},
    dp_nominal={0,0,-200}) "Splitter"

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTOut
    "Outdoor temperature sensor"

  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TOut
    "Outside temperature"

equation
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(pumRad.port_b, temSup.port_a)
  connect(boi.port_b, pumBoi.port_a)
  connect(pumBoi.port_b, spl1.port_1)
  connect(spl1.port_2, spl.port_1)
  connect(spl.port_2, valRad.port_1)
  connect(valRad.port_2, mix.port_1)
  connect(spl1.port_3, valBoi.port_3)
  connect(valBoi.port_2, temRet.port_a)
  connect(temRet.port_b, boi.port_a)
  connect(boi.port_a, preSou.ports[1])
  connect(mix2.port_2, valBoi.port_1)
  connect(spl4.port_2, mix2.port_1)
  connect(spl2.port_2, spl4.port_1)
  connect(valRad.port_3, spl4.port_3)
  connect(spl.port_3, mix2.port_3)
  connect(mix.port_3, spl2.port_3)
  connect(mix.port_2, pumRad.port_a)
  connect(rad.port_b, spl2.port_1)

  connect(weaDat.weaBus, weaBus)
  connect(weaBus.TDryBul, TOut.T)
  connect(TOut.port, theCon.port_a)
  connect(TOut.port, senTOut.port)
end PartialOpenLoop;


Control for boiler return. Controller that takes as an input the boiler return water temperature TRet
and outputs the valve control signal yVal.
The valve control signal is computed using a PI-controller that tracks a constant
set point of TSet.

within Buildings.Examples.Tutorial.CDL.Controls;
block BoilerReturn "Control for boiler return"
  parameter Real TSet(
    final unit="K",
    displayUnit="degC") = 333.15
    "Set point for boiler temperature";
  parameter Real k=0.1 "Gain of controller";
  parameter Modelica.Units.SI.Time Ti=120 "Time constant of integrator block";
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRet(
    final unit="K",
    displayUnit="degC")
    "Return water temperature to boiler"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yVal(
    final unit="1")
    "Valve control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant T(
    final k=TSet)
    "Set point temperature"
  Buildings.Controls.OBC.CDL.Reals.PID conPID(
    final k=k,
    final Ti=Ti,
    reverseActing=false) "Controller for valve in boiler loop"
equation
  connect(conPID.y, yVal)
  connect(conPID.u_s, T.y)
  connect(TRet, conPID.u_m)
end BoilerReturn;


Controller for equipment on/off control. Controller that takes as an input the boiler water temperature TBoi
and the system on command onSys, and outputs
the on command for the pumps onPum and the boiler onBoi.

within Buildings.Examples.Tutorial.CDL.Controls;
block EquipmentOnOff "Controller for equipment on/off control"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TBoi(
    final unit="K",
    displayUnit="degC")
    "Boiler temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput onSys
    "System on command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput onPum
    "Pump on command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput onBoi
    "Boiler on command"
  Buildings.Controls.OBC.CDL.Logical.And and1
    "And operator to switch boiler on based on temperature and system on command"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Negation of output signal, because boiler should be off if temperature exceed uHigh"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(
  uHigh=273.15 + 90,
  uLow=273.15  + 70) "Hysteresis for on/off of boiler"
equation

  connect(TBoi, hys.u)
  connect(hys.y, not1.u)
  connect(onSys, onPum)
  connect(and1.u1, not1.y)
  connect(and1.u2, onSys)
  connect(and1.y, onBoi)
end EquipmentOnOff;


Open loop controller for boiler return. Open loop controller that outputs a constant control signal for the valve
of the boiler return.

within Buildings.Examples.Tutorial.CDL.Controls;
block OpenLoopBoilerReturn "Open loop controller for boiler return"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRet(
    final unit="K",
    displayUnit="degC")
    "Return water temperature to boiler"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yVal(
    final unit="1")
    "Valve control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(k=1)
    "Constant valve control signal"
equation
  connect(con.y, yVal)
end OpenLoopBoilerReturn;


Open loop controller for equipment on/off control. Open loop controller that outputs a constant control signal for the system on command.

within Buildings.Examples.Tutorial.CDL.Controls;
block OpenLoopEquipmentOnOff
  "Open loop controller for equipment on/off control"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TBoi(
    final unit="K",
    displayUnit="degC")
    "Boiler temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput onSys
    "System on command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput onPum
    "Pump on command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput onBoi
    "Boiler on command"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(k=true)
    "Constant control signal"
equation

  connect(con.y, onBoi)
  connect(con.y, onPum)
end OpenLoopEquipmentOnOff;


Open loop controller for mixing valve in radiator loop. Open loop controller that outputs a constant control signal for the mixing valve of the radiator loop.

within Buildings.Examples.Tutorial.CDL.Controls;
block OpenLoopRadiatorSupply
  "Open loop controller for mixing valve in radiator loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRoo(
    final unit="K",
    displayUnit="degC")
    "Room air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSup(
    final unit="K",
    displayUnit="degC")
    "Measured supply water temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yVal(
    final unit="1")
    "Valve control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(k=1)
    "Constant valve control signal"
equation
  connect(con.y, yVal)
end OpenLoopRadiatorSupply;


Open loop controller for system on/off. Open loop controller that outputs a constant control signal for the system on command.

within Buildings.Examples.Tutorial.CDL.Controls;
block OpenLoopSystemOnOff
  "Open loop controller for system on/off"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC")
    "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRoo(
    final unit="K",
    displayUnit="degC")
    "Room air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput onSys
    "System on command"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(k=true)
    "Constant control signal"
equation
  connect(con.y, onSys)
end OpenLoopSystemOnOff;


within Buildings.Examples.Tutorial.CDL;
package Controls "Package with the controllers used in the tutorial"
extends Modelica.Icons.VariantsPackage;
end Controls;


Controller for mixing valve in radiator loop. Controller that takes as an input the room air temperature TRoo and
the supply water temperature TSup,
and outputs the commanded mixing valve position yVal.

within Buildings.Examples.Tutorial.CDL.Controls;
block RadiatorSupply "Controller for mixing valve in radiator loop"

  parameter Real TSupMin(
    final unit="K",
    displayUnit="degC") = 294.15
    "Minimum supply water temperature";
  parameter Real TSupMax(
    final unit="K",
    displayUnit="degC") = 323.15
    "Maximum supply water temperature";
  parameter Real TRooMin(
    final unit="K",
    displayUnit="degC") = 292.15
    "Room air temperature at which supply water temperature is at TSupMax";

  parameter Real k=0.1 "Gain of controller";
  parameter Modelica.Units.SI.Time Ti=120 "Time constant of integrator block";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRoo(
    final unit="K",
    displayUnit="degC")
    "Room air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSup(
    final unit="K",
    displayUnit="degC")
    "Measured supply water temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yVal(
    final unit="1")
    "Valve control signal"
  Buildings.Controls.OBC.CDL.Reals.PID conPIDRad(
    final k=k,
    final Ti=Ti,
    final yMax=1,
    final yMin=0,
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI)
    "Controller for valve in radiator loop"
  Buildings.Controls.OBC.CDL.Reals.Line TSetSup
    "Setpoint for supply water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TMinSup(
    final k=TSupMin)
    "Minimum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TMaxSup(
    final k=TSupMax)
    "Maximum heating supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TMinRoo(
    final k=TRooMin)
    "Minimum room air temperature"
equation
  connect(TMinSup.y,TSetSup. x2)
  connect(TMinSup.y,TSetSup. f2)
  connect(TMaxSup.y,TSetSup. f1)
  connect(TSetSup.x1,TMinRoo. y)
  connect(conPIDRad.u_s,TSetSup. y)
  connect(TSetSup.u, TRoo)
  connect(TSup, conPIDRad.u_m)
  connect(conPIDRad.y, yVal)
end RadiatorSupply;


Controller for system on/off. Controller that takes as an input the outside air temperature TOut and
the room air temperature TRoo,
and outputs the system on command onSys.

within Buildings.Examples.Tutorial.CDL.Controls;
block SystemOnOff "Controller for system on/off"
  parameter Real TRooSet(
    final unit="K",
    displayUnit="degC") = 293.65
    "Room air temperature set point";
  parameter Real dTRoo(
    min=0.5,
    final unit="K") = 1
    "Room air temperature dead band";
  parameter Real TOutLow(
    final unit="K",
    displayUnit="degC") = 289.15
    "Outdoor temperature below which system is allowed to switch on";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC")
    "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRoo(
    final unit="K",
    displayUnit="degC")
    "Room air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput onSys
    "System on command"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetOut(k=TOutLow + 0.5)
    "Set point for outdoor air temperature plus half the dead band"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetRoo(k=TRooSet)
    "Set point for room air temperature"
  Buildings.Controls.OBC.CDL.Logical.And and1
    "And operator to switch boiler on based on temperature and system on command"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub "Inputs different"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis onTOut(
    final uLow=-0.5,
    final uHigh=0.5) "On/off control based on outside air temperature"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub1 "Inputs different"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis onTRoo(
    final uLow=-0.5,
    final uHigh=0.5) "On/off control based on room air temperature"
equation
  connect(and1.y, onSys)
  connect(TSetOut.y, sub.u1)
  connect(TOut, sub.u2)
  connect(sub.y, onTOut.u)
  connect(onTOut.y, and1.u1)
  connect(TSetRoo.y, sub1.u1)
  connect(TRoo, sub1.u2)
  connect(sub1.y, onTRoo.u)
  connect(onTRoo.y, and1.u2)
end SystemOnOff;


Validation model for the return temperature controller of the boiler. Validation model for the boiler return water temperature controller.
The input to the controller is a ramp signal of increasing measured return water temperature.
The validation shows that as the temperature crosses the set point, the valve opens.

within Buildings.Examples.Tutorial.CDL.Controls.Validation;
model BoilerReturn
  "Validation model for the return temperature controller of the boiler"
    extends Modelica.Icons.Example;

  Buildings.Examples.Tutorial.CDL.Controls.BoilerReturn conBoiRet
    "Controller for boiler return water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TRet(
    height=50,
    duration=3600,
    offset=293.15) "Return water temperature"
equation
  connect(TRet.y, conBoiRet.TRet)
end BoilerReturn;


Validation model for the equipment on/off controller. Validation model for the equipment on/off controller.
The input to the controller is a ramp signal of increasing measured boiler water temperature,
and a on/off signal for the overall system.
The validation shows that the pumps are on/off based on the overall system, and the boiler is
also on/off based on this system unless the return water temperature exceeds <i>90</i>°C.

within Buildings.Examples.Tutorial.CDL.Controls.Validation;
model EquipmentOnOff
  "Validation model for the equipment on/off controller"
    extends Modelica.Icons.Example;

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TBoi(
    height=40,
    duration=3600,
    offset=333.15) "Boiler temperature"
  Buildings.Examples.Tutorial.CDL.Controls.EquipmentOnOff
    conEquSta "Controller for equipment on/off"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse onSys(
    period=600)
    "System on signal"
equation
  connect(TBoi.y, conEquSta.TBoi)
  connect(onSys.y, conEquSta.onSys)
end EquipmentOnOff;


<html>
<p>
This package contains models that validate the controls models.
The examples plot various outputs, which have been verified against
analytical solutions or by inspecting their change due to parametric changes.
These model outputs are stored as reference data to
allow continuous validation whenever models in the library change.
</p>
</html>

within Buildings.Examples.Tutorial.CDL.Controls;
package Validation
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation model for the valve of the radiator supply. Validation model for the boiler return water temperature controller.
The input to the controller is a ramp signal of increasing measured return water temperature.
The validation shows that as the temperature crosses the set point, the valve opens.

within Buildings.Examples.Tutorial.CDL.Controls.Validation;
model RadiatorSupply
  "Validation model for the valve of the radiator supply"
    extends Modelica.Icons.Example;

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TRoo(
    height=-4,
    duration=3600,
    offset=297.15) "Room air temperature"
  Buildings.Examples.Tutorial.CDL.Controls.RadiatorSupply
    conRadSup "Controller for radiator supply water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TSup(
    amplitude=20,
    freqHz=1/720,
    offset=303.15) "Measured supply water temperature"
equation
  connect(TRoo.y, conRadSup.TRoo)
  connect(conRadSup.TSup, TSup.y)
end RadiatorSupply;


Validation model for the system on/off controller. Validation model for the system on/off controller.
The input to the controller are time varying signals for the outdoor air temperature
and the room air temperature.
The validation shows that the system is commanded on (onSys=true) if
the outdoor air temperature and the room air temperature are both low.

within Buildings.Examples.Tutorial.CDL.Controls.Validation;
model SystemOnOff
  "Validation model for the system on/off controller"
    extends Modelica.Icons.Example;

  Buildings.Examples.Tutorial.CDL.Controls.SystemOnOff
    conSysSta "Controller for system on/off"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TOut(
    amplitude=5,
    freqHz=1/720,
    offset=290.15) "Outside air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TRoo(
    amplitude=4,
    freqHz=1/720,
    phase=1.5707963267949,
    offset=293.15) "Room air temperature"
equation
  connect(TOut.y, conSysSta.TOut)
  connect(TRoo.y, conSysSta.TRoo)
end SystemOnOff;


within Buildings.Examples.Tutorial;
package SimpleHouse "Package with example for how to build a simple building envelope with a radiator heating system and ventilation system"
extends Modelica.Icons.ExamplesPackage;
end SimpleHouse;