Model of a building with loads provided as time series, connected to an ETS with domestic hot water storage tank. This model is the same as

Buildings.DHC.Loads.Combined.BuildingTimeSeriesWithETS
except that it implements an ETS that uses a heat pump with hot water
storage tank for production of domestic hot water.  That ETS model is

Buildings.DHC.ETS.Combined.HeatPumpHeatExchangerDHWTank.

within Buildings.DHC.Loads.Combined;
model BuildingTimeSeriesWithETSWithDHWTank
  "Model of a building with loads provided as time series, connected to an ETS with domestic hot water storage tank"
  extends
    Buildings.DHC.Loads.Combined.BaseClasses.PartialBuildingWithETS(
    redeclare Buildings.DHC.Loads.BaseClasses.BuildingTimeSeries bui(
      filNam=filNam,
      have_hotWat=true,
      T_aHeaWat_nominal=ets.THeaWatSup_nominal,
      T_bHeaWat_nominal=ets.THeaWatRet_nominal,
      T_aChiWat_nominal=ets.TChiWatSup_nominal,
      T_bChiWat_nominal=ets.TChiWatRet_nominal),
    redeclare
      Buildings.DHC.ETS.Combined.HeatPumpHeatExchangerDHWTank
      ets(
      final dT_nominal=dT_nominal,
      final TDisWatMin=TDisWatMin,
      final TDisWatMax=TDisWatMax,
      final TChiWatSup_nominal=TChiWatSup_nominal,
      final THeaWatSup_nominal=THeaWatSup_nominal,
      final THotWatSup_nominal=THotWatSup_nominal,
      final TColWat_nominal=TColWat_nominal,
      final dp_nominal=dp_nominal,
      final COPHeaWat_nominal=COPHeaWat_nominal,
      final COPHotWat_nominal=COPHotWat_nominal,
      have_hotWat=true,
      QChiWat_flow_nominal=QCoo_flow_nominal,
      QHeaWat_flow_nominal=QHea_flow_nominal,
      QHotWat_flow_nominal=QHot_flow_nominal,
      datWatHea=datWatHea));
  parameter String filNam
    "Library path of the file with thermal loads as time series";
  final parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal(
    max=-Modelica.Constants.eps)=
    bui.facMul * bui.QCoo_flow_nominal
    "Space cooling design load (<=0)"
  final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal(
    min=Modelica.Constants.eps)=
    bui.facMul * bui.QHea_flow_nominal
    "Space heating design load (>=0)"
  final parameter Modelica.Units.SI.HeatFlowRate QHot_flow_nominal(
    min=Modelica.Constants.eps)=
    bui.facMul * Buildings.DHC.Loads.BaseClasses.getPeakLoad(
      string="#Peak water heating load",
      filNam=Modelica.Utilities.Files.loadResource(filNam))
    "Hot water design load (>=0)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THotWatSupSet(
    final unit="K",
    displayUnit="degC")
    "Service hot water supply temperature set point"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TColWat(
    final unit="K",
    displayUnit="degC")
    "Cold water temperature"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter loaHeaNor(
    k=1/QHea_flow_nominal) "Normalized heating load"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold enaHeaCoo[2](each t=1e-4)
    "Threshold comparison to enable heating and cooling"
  Modelica.Blocks.Sources.BooleanConstant enaSHW(
    final k=true) if have_hotWat
    "SHW production enable signal"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter loaCooNor(k=1/
        QCoo_flow_nominal) "Normalized cooling load"
  parameter HotWater.Data.GenericDomesticHotWaterWithHeatExchanger datWatHea
    "Performance data"
equation
  connect(bui.QReqHotWat_flow, ets.QReqHotWat_flow)
  connect(THotWatSupSet, ets.THotWatSupSet)
  connect(TColWat, ets.TColWat)
  connect(enaHeaCoo[1].y, ets.uHea)
  connect(enaHeaCoo[2].y, ets.uCoo)
  connect(enaSHW.y, ets.uSHW)
  connect(loaHeaNor.y, enaHeaCoo[1].u)
  connect(loaCooNor.y, enaHeaCoo[2].u)
  connect(bui.QReqHea_flow, loaHeaNor.u)
  connect(bui.QReqCoo_flow, loaCooNor.u)
  connect(loaHeaNor.y, resTHeaWatSup.u)
end BuildingTimeSeriesWithETSWithDHWTank;


Package with models for loads

within Buildings.DHC.Loads;
package Combined "Package with models for loads"
  extends Modelica.Icons.VariantsPackage;
end Combined;


within Buildings.DHC.Loads.Combined;
package BaseClasses "Package with base classes that are used by multiple models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model with ETS model and partial building model. This model is composed of a heat pump based energy transfer station model

Buildings.DHC.ETS.Combined.HeatPumpHeatExchanger
connected to a repleacable building load model.

within Buildings.DHC.Loads.Combined.BaseClasses;
model PartialBuildingWithETS
  "Partial model with ETS model and partial building model"
  extends
    Buildings.DHC.Loads.BaseClasses.PartialBuildingWithPartialETS(
    nPorts_heaWat=1,
    nPorts_chiWat=1);
  parameter Modelica.Units.SI.Temperature TDisWatMin=6 + 273.15
    "District water minimum temperature"
  parameter Modelica.Units.SI.Temperature TDisWatMax=17 + 273.15
    "District water maximum temperature"
  parameter Modelica.Units.SI.TemperatureDifference dT_nominal(min=0) = 4
    "Water temperature drop/increase accross load and source-side HX (always positive)"
  parameter Modelica.Units.SI.Temperature TChiWatSup_nominal=18 + 273.15
    "Chilled water supply temperature"
  parameter Modelica.Units.SI.Temperature THeaWatSup_nominal=38 + 273.15
    "Heating water supply temperature"
  parameter Modelica.Units.SI.Temperature THotWatSup_nominal=63 + 273.15
    "Domestic hot water supply temperature to fixtures"
  parameter Modelica.Units.SI.Temperature TColWat_nominal=288.15
    "Cold water temperature (for hot water production)"
  parameter Modelica.Units.SI.Pressure dp_nominal(displayUnit="Pa")=50000
    "Pressure difference at nominal flow rate (for each flow leg)"
  parameter Real COPHeaWat_nominal(final unit="1") = 4.0
    "COP of heat pump for heating water production"
  parameter Real COPHotWat_nominal(final unit="1") = 2.3
    "COP of heat pump for hot water production"
  // IO CONNECTORS
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet(
    final unit="K",
    displayUnit="degC")
    "Chilled water supply temperature set point"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSupMaxSet(
    final unit="K",
    displayUnit="degC")
    "Heating water supply temperature set point - Maximum value"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSupMinSet(
    final unit="K",
    displayUnit="degC")
    "Heating water supply temperature set point - Minimum value"
  // COMPONENTS
  Buildings.Controls.OBC.CDL.Reals.Line resTHeaWatSup
    "HW supply temperature reset"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(k=0)
    "Zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(k=1)
    "One"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter mulPPumETS(u(final
        unit="W"), final k=facMul) if have_pum "Scaling"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PPumETS(
    final unit="W") if have_pum
    "ETS pump power"
equation
  connect(TChiWatSupSet, ets.TChiWatSupSet)
  connect(resTHeaWatSup.y, ets.THeaWatSupSet)
  connect(THeaWatSupMaxSet, resTHeaWatSup.f2)
  connect(THeaWatSupMinSet, resTHeaWatSup.f1)
  connect(one.y, resTHeaWatSup.x2)
  connect(zer.y, resTHeaWatSup.x1)
  connect(mulPPumETS.y, PPumETS)
  connect(ets.PPum, mulPPumETS.u)
end PartialBuildingWithETS;


within Buildings.DHC.Loads.Combined.Examples;
model BuildingTimeSeriesWithETS
  "Example model of a building in an ambient district network with loads provided as time series and heat pump heating, free cooling, and heat pump domestic hot water"
  extends Modelica.Icons.Example;
  package Medium=Buildings.Media.Water
    "Medium model";
  Buildings.Fluid.Sources.Boundary_pT supAmbWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar"),
    use_T_in=true,
    T=280.15,
    nPorts=1) "Ambient water supply"
  Buildings.Fluid.Sources.Boundary_pT sinAmbWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar"),
    nPorts=1) "Sink for ambient water"
  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium = Medium)
    "Mass flow rate sensor"
  Modelica.Blocks.Sources.Constant TDisSup(k(
      unit="K",
      displayUnit="degC") = 288.15)
    "District supply temperature"
  Buildings.DHC.Loads.Combined.BuildingTimeSeriesWithETS bui(
    redeclare package MediumSer = Medium,
    redeclare package MediumBui = Medium,
    bui(facMul=10),
    allowFlowReversalSer=true,
    THotWatSup_nominal=322.15,
    filNam="modelica://Buildings/Resources/Data/DHC/Loads/Examples/SwissOffice_20190916.mos")
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TColWat(k=bui.ets.TColWat_nominal)
    "Cold water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THotWatSupSet(k=bui.ets.THotWatSup_nominal)
    "Hot water supply temperature set point"
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(k=bui.TChiWatSup_nominal)
    "Chilled water supply temperature set point"
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupMaxSet(k=bui.THeaWatSup_nominal)
    "Heating water supply temperature set point - Maximum value"
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupMinSet(
   k(final unit="K",
     displayUnit="degC") = 301.15)
   "Heating water supply temperature set point - Minimum value"
equation
  connect(supAmbWat.ports[1], senMasFlo.port_a)
  connect(TDisSup.y,supAmbWat. T_in)
  connect(senMasFlo.port_b, bui.port_aSerAmb)
  connect(sinAmbWat.ports[1], bui.port_bSerAmb)
  connect(THeaWatSupMinSet.y, bui.THeaWatSupMinSet)
  connect(THeaWatSupMaxSet.y, bui.THeaWatSupMaxSet)
  connect(TChiWatSupSet.y, bui.TChiWatSupSet)
  connect(THotWatSupSet.y, bui.THotWatSupSet)
  connect(TColWat.y, bui.TColWat)
end BuildingTimeSeriesWithETS;


within Buildings.DHC.Loads.Combined.Examples;
model BuildingTimeSeriesWithETSDHWTank
    "Example model of a building in an ambient district network with loads provided as time series and heat pump heating, free cooling, and heat pump with storage tank domestic hot water"
  extends Modelica.Icons.Example;
  package Medium=Buildings.Media.Water
    "Medium model";
  Buildings.Fluid.Sources.Boundary_pT supAmbWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar"),
    use_T_in=true,
    T=280.15,
    nPorts=1) "Ambient water supply"
  Buildings.Fluid.Sources.Boundary_pT sinAmbWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar"),
    nPorts=1) "Sink for ambient water"
  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium = Medium)
    "Mass flow rate sensor"
  Modelica.Blocks.Sources.Constant TDisSup(k(
      unit="K",
      displayUnit="degC") = 288.15)
    "District supply temperature"
  Buildings.DHC.Loads.Combined.BuildingTimeSeriesWithETSWithDHWTank bui(
    redeclare package MediumSer = Medium,
    redeclare package MediumBui = Medium,
    bui(facMul=10),
    allowFlowReversalSer=true,
    THotWatSup_nominal=313.15,
    filNam=
        "modelica://Buildings/Resources/Data/DHC/Loads/Examples/SwissOffice_20190916.mos",
    datWatHea=datWatHea) "Building load with time series data"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TColWat(k=bui.ets.TColWat_nominal)
    "Cold water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THotWatSupSet(k=bui.THotWatSup_nominal)
    "Hot water supply temperature set point"
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(k=bui.TChiWatSup_nominal)
    "Chilled water supply temperature set point"
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupMaxSet(k=bui.THeaWatSup_nominal)
    "Heating water supply temperature set point - Maximum value"
 Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupMinSet(k=28 + 273.15)
    "Heating water supply temperature set point - Minimum value"
  parameter Buildings.DHC.Loads.HotWater.Data.GenericDomesticHotWaterWithHeatExchanger datWatHea(VTan=0.3,
      mDom_flow_nominal=0.03,
    TDom_nominal=318.15)
    "Performance data"

equation
  connect(supAmbWat.ports[1], senMasFlo.port_a)
  connect(TDisSup.y,supAmbWat. T_in)
  connect(senMasFlo.port_b, bui.port_aSerAmb)
  connect(sinAmbWat.ports[1], bui.port_bSerAmb)
  connect(THeaWatSupMinSet.y, bui.THeaWatSupMinSet)
  connect(THeaWatSupMaxSet.y, bui.THeaWatSupMaxSet)
  connect(TChiWatSupSet.y, bui.TChiWatSupSet)
  connect(THotWatSupSet.y, bui.THotWatSupSet)
  connect(TColWat.y, bui.TColWat)
end BuildingTimeSeriesWithETSDHWTank;


This package contains example models

within Buildings.DHC.Loads.Combined;
package Examples "This package contains example models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Model of a building with loads provided as time series, connected to an ETS for cooling. This model is composed of a direct controlled energy transfer station model for cooling

Buildings.DHC.ETS.Cooling.Direct
connected to a simplified building model
Buildings.DHC.Loads.BaseClasses.BuildingTimeSeries
where the space cooling loads are provided as time series.

within Buildings.DHC.Loads.Cooling;
model BuildingTimeSeriesWithETS
  "Model of a building with loads provided as time series, connected to an ETS for cooling"
  extends BaseClasses.PartialBuildingWithETS(
    redeclare Buildings.DHC.Loads.BaseClasses.BuildingTimeSeries bui(
      final have_heaWat=false,
      final have_chiWat=true,
      final have_hotWat=false,
      final filNam=filNam,
      T_aChiWat_nominal=TChiWatSup_nominal,
      T_bChiWat_nominal=TChiWatRet_nominal),
      mBui_flow_nominal=-QCoo_flow_nominal/(cp*dT_nominal),
          ets(
      QChiWat_flow_nominal=QCoo_flow_nominal));

  final parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal=
    bui.facMul * bui.QCoo_flow_nominal
    "Space cooling design load (<=0)";
  parameter Modelica.Units.SI.TemperatureDifference dT_nominal(min=0)=9
    "Water temperature drop/increase accross load and source-side HX (always positive)"
  parameter Modelica.Units.SI.Temperature TChiWatSup_nominal=7 + 273.15
    "Chilled water supply temperature"
  final parameter Modelica.Units.SI.Temperature TChiWatRet_nominal=
    TChiWatSup_nominal + dT_nominal
    "Chilled water return temperature"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState
    "Type of energy balance"
  parameter Boolean use_riseTime=false
    "Set to true to continuously change motor speed"
  parameter String filNam
    "Library path of the file with thermal loads as time series";
protected
  parameter Modelica.Units.SI.SpecificHeatCapacity cp=MediumSer.specificHeatCapacityCp(
    MediumSer.setState_pTX(
      MediumSer.p_default,
      MediumSer.T_default,
      MediumSer.X_default))
    "Default specific heat capacity of medium";
end BuildingTimeSeriesWithETS;


within Buildings.DHC.Loads;
package Cooling "This package contains models for energy transfer stations used in district cooling system."
  extends Modelica.Icons.VariantsPackage;
end Cooling;


within Buildings.DHC.Loads.Cooling;
package BaseClasses "Package with base classes that are used by multiple models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model with ETS model for cooling and partial building model. This model is composed of a direct controlled energy transfer station model for cooling

Buildings.DHC.ETS.Cooling.Direct
connected to a repleacable building load model.

within Buildings.DHC.Loads.Cooling.BaseClasses;
model PartialBuildingWithETS
  "Partial model with ETS model for cooling and partial building model"
  extends
    Buildings.DHC.Loads.BaseClasses.PartialBuildingWithPartialETS(
      nPorts_chiWat=1,
      redeclare Buildings.DHC.ETS.Cooling.Direct ets(
      final mBui_flow_nominal=mBui_flow_nominal,
      final controllerType=controllerType,
      final k=k,
      final Ti=Ti,
      final Td=Td,
      final yMax=yMax,
      final yMin=yMin));

  parameter Modelica.Units.SI.MassFlowRate mBui_flow_nominal(
    final min=0,
    final start=0.5)
    "Nominal mass flow rate"
  parameter Modelica.Units.SI.PressureDifference dpSup(
    final min=0,
    displayUnit="Pa")=5000
    "Pressure drop in the ETS supply side";
  parameter Modelica.Units.SI.PressureDifference dpRet(
    final min=0,
    displayUnit="Pa")=5000
    "Pressure drop in the ETS return side";
  // Controller parameters
  parameter Modelica.Blocks.Types.SimpleController controllerType=Modelica.Blocks.Types.SimpleController.PI
    "Type of controller"
  parameter Real k(
    final min=0,
    final unit="1")=0.1
    "Gain of controller"
  parameter Modelica.Units.SI.Time Ti(
    final min=Modelica.Constants.small)=60
    "Time constant of integrator block"
  parameter Modelica.Units.SI.Time Td(
    final min=0)=0.1
    "Time constant of derivative block"
  parameter Real yMax(
    final start=1)=1
    "Upper limit of output"
  parameter Real yMin=0
    "Lower limit of output"
  Modelica.Blocks.Interfaces.RealInput TDisRetSet(
     final unit="K",
     displayUnit="degC")
    "Setpoint for the minimum district return temperature"
equation
  connect(TDisRetSet,ets.TDisRetSet)
end PartialBuildingWithETS;


within Buildings.DHC.Loads.Cooling.Examples;
model BuildingTimeSeriesWithETS
  "Example model of a building with loads provided as time series and
  connected to an ETS for cooling"
  extends Modelica.Icons.Example;
  package Medium=Buildings.Media.Water
    "Medium model";
  Buildings.DHC.Loads.Cooling.BuildingTimeSeriesWithETS buiWitETS(
    filNam=
      "modelica://Buildings/Resources/Data/DHC/Loads/Examples/MediumOffice-90.1-2010-5A.mos")
  "Building Time Series load coupled with ETS"
  Buildings.Fluid.Sources.Boundary_pT supChiWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar") = 350000,
    use_T_in=true,
    T=280.15,
    nPorts=1)
    "Chilled water supply"
  Buildings.Fluid.Sources.Boundary_pT sinChiWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar") = 340000,
    nPorts=1)
    "Sink for chilled water"
  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium = Medium)
    "Mass flow rate sensor"
  Modelica.Blocks.Sources.Constant TDisRetSet(k=273.15 + 16)
    "Setpoint for district return temperature"
  Modelica.Blocks.Sources.Constant TDisSup(k(
      unit="K",
      displayUnit="degC") = 280.15)
    "District supply temperature"
equation
  connect(supChiWat.ports[1], senMasFlo.port_a)
  connect(senMasFlo.port_b, buiWitETS.port_aSerCoo)
  connect(buiWitETS.port_bSerCoo, sinChiWat.ports[1])
  connect(TDisSup.y, supChiWat.T_in)
  connect(TDisRetSet.y,buiWitETS.TDisRetSet)
end BuildingTimeSeriesWithETS;


This package contains an example illustrating the use of the model in
<a href=\

within Buildings.DHC.Loads.Cooling;
package Examples
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Model of a building with loads provided as time series, connected to an ETS for heating. This model is composed of a direct controlled energy transfer station model for heating

Buildings.DHC.ETS.Heating.Direct
connected to a simplified building model
Buildings.DHC.Loads.BaseClasses.BuildingTimeSeries
where the space heating loads are provided as time series.

within Buildings.DHC.Loads.Heating;
model BuildingTimeSeriesWithETS
  "Model of a building with loads provided as time series, connected to an ETS for heating"
  extends BaseClasses.PartialBuildingWithETS(
    redeclare Buildings.DHC.Loads.BaseClasses.BuildingTimeSeries bui(
      final have_heaWat=true,
      final have_chiWat=false,
      final have_hotWat=false,
      final filNam=filNam,
      T_aHeaWat_nominal=THeaWatSup_nominal,
      T_bHeaWat_nominal=THeaWatRet_nominal),
      mBui_flow_nominal=QHea_flow_nominal/(cp*dT_nominal),
          ets(
      QHeaWat_flow_nominal=QHea_flow_nominal));

  final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=
    bui.facMul * bui.QHea_flow_nominal
    "Space heating design load (>=0)";
  parameter Modelica.Units.SI.TemperatureDifference dT_nominal(min=0)=10
    "Water temperature drop/increase accross load and source-side HX (always positive)"
  parameter Modelica.Units.SI.Temperature THeaWatSup_nominal=50 + 273.15
    "Heating water supply temperature"
  final parameter Modelica.Units.SI.Temperature THeaWatRet_nominal=
    THeaWatSup_nominal - dT_nominal
    "Heating water return temperature"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState
    "Type of energy balance"
  parameter Boolean use_riseTime=false
    "Set to true to continuously change motor speed"
  parameter String filNam
    "Library path of the file with thermal loads as time series";
protected
  parameter Modelica.Units.SI.SpecificHeatCapacity cp=MediumSer.specificHeatCapacityCp(
    MediumSer.setState_pTX(
      MediumSer.p_default,
      MediumSer.T_default,
      MediumSer.X_default))
    "Default specific heat capacity of medium";
end BuildingTimeSeriesWithETS;


within Buildings.DHC.Loads;
package Heating "This package contains models for loads used in district heating systems."
  extends Modelica.Icons.VariantsPackage;
end Heating;


within Buildings.DHC.Loads.Heating;
package BaseClasses "Package with base classes that are used by multiple models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model with ETS model for heating and partial building model. This model is composed of a direct controlled energy transfer station model for cooling

Buildings.DHC.ETS.Cooling.Direct
connected to a repleacable building load model.

within Buildings.DHC.Loads.Heating.BaseClasses;
model PartialBuildingWithETS
  "Partial model with ETS model for heating and partial building model"
  extends
    Buildings.DHC.Loads.BaseClasses.PartialBuildingWithPartialETS(
      nPorts_heaWat=1,
      redeclare Buildings.DHC.ETS.Heating.Direct ets(
      final mBui_flow_nominal=mBui_flow_nominal,
      final controllerType=controllerType,
      final k=k,
      final Ti=Ti,
      final Td=Td,
      final yMax=yMax,
      final yMin=yMin));

  parameter Modelica.Units.SI.MassFlowRate mBui_flow_nominal(
    final min=0,
    final start=0.5)
    "Nominal mass flow rate"
  parameter Modelica.Units.SI.PressureDifference dpSup(
    final min=0,
    displayUnit="Pa")=5000
    "Pressure drop in the ETS supply side";
  parameter Modelica.Units.SI.PressureDifference dpRet(
    final min=0,
    displayUnit="Pa")=5000
    "Pressure drop in the ETS return side";
  // Controller parameters
  parameter Modelica.Blocks.Types.SimpleController controllerType=Modelica.Blocks.Types.SimpleController.PI
    "Type of controller"
  parameter Real k(
    final min=0,
    final unit="1")=0.1
    "Gain of controller"
  parameter Modelica.Units.SI.Time Ti(
    final min=Modelica.Constants.small)=60
    "Time constant of integrator block"
  parameter Modelica.Units.SI.Time Td(
    final min=0)=0.1
    "Time constant of derivative block"
  parameter Real yMax(
    final start=1)=1
    "Upper limit of output"
  parameter Real yMin=0
    "Lower limit of output"
  Modelica.Blocks.Interfaces.RealInput TDisRetSet(
     final unit="K",
     displayUnit="degC")
    "Setpoint for the maximum district return temperature"
equation
  connect(TDisRetSet,ets.TDisRetSet)
end PartialBuildingWithETS;


within Buildings.DHC.Loads.Heating.Examples;
model BuildingTimeSeriesWithETS
  "Example model of a building with loads provided as time series and
  connected to an ETS for cooling"
  extends Modelica.Icons.Example;
  package Medium=Buildings.Media.Water
    "Medium model";
  Buildings.DHC.Loads.Heating.BuildingTimeSeriesWithETS buiWitETS(filNam="modelica://Buildings/Resources/Data/DHC/Loads/Examples/MediumOffice-90.1-2010-5A.mos")
    "Building Time Series load coupled with ETS"
  Buildings.Fluid.Sources.Boundary_pT supHeaWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar") = 350000,
    use_T_in=true,
    nPorts=1) "Heating water supply"
  Buildings.Fluid.Sources.Boundary_pT sinHeaWat(
    redeclare package Medium = Medium,
    p(displayUnit="bar") = 340000,
    nPorts=1) "Sink for heating water"
  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium = Medium)
    "Mass flow rate sensor"
  Modelica.Blocks.Sources.Constant TDisRetSet(k=273.15 + 45)
    "Setpoint for district return temperature"
  Modelica.Blocks.Sources.Constant TDisSup(k(
      unit="K",
      displayUnit="degC") = 323.15)
    "District supply temperature"
equation
  connect(supHeaWat.ports[1], senMasFlo.port_a)
  connect(TDisSup.y,supHeaWat. T_in)
  connect(TDisRetSet.y,buiWitETS.TDisRetSet)
  connect(senMasFlo.port_b, buiWitETS.port_aSerHea)
  connect(buiWitETS.port_bSerHea, sinHeaWat.ports[1])
end BuildingTimeSeriesWithETS;


within Buildings.DHC.Loads.Heating;
package Examples
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.DHC.Loads.HotWater;
model DirectHeatExchangerWithElectricHeat
  "A model for generating hot water using a district heat exchanger and supplemental electric resistance"
  extends
    Buildings.DHC.Loads.HotWater.BaseClasses.PartialFourPortDHW;
  parameter Modelica.Units.SI.Efficiency eps(min=0,max=1) = 0.8 "Heat exchanger effectiveness";
  parameter Boolean have_eleHea = true "True if has auxiliary electric heater";
  parameter Modelica.Units.SI.HeatFlowRate QMax_flow(min=0) = Modelica.Constants.inf "Maximum heat flow rate for electric heater (positive)"
  parameter Modelica.Units.SI.MassFlowRate mDom_flow_nominal "Nominal flow rate of domestic hot water";
  parameter Modelica.Units.SI.MassFlowRate mHea_flow_nominal "Nominal flow rate of heating source water";
  Buildings.Fluid.HeatExchangers.Heater_T heaEle(
    redeclare package Medium = MediumDom,
    m_flow_nominal=mDom_flow_nominal,
    dp_nominal=dpEle_nominal,
    QMax_flow=QMax_flow) if have_eleHea == true
    "Supplemental electric resistance domestic hot water heater"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemHot(redeclare package Medium =
        MediumDom,
                m_flow_nominal=mDom_flow_nominal)
    "Temperature sensor for hot water supply"
  Buildings.Fluid.HeatExchangers.ConstantEffectiveness hex(
    redeclare package Medium1 = MediumDom,
    redeclare package Medium2 = MediumHea,
    m1_flow_nominal=mDom_flow_nominal,
    m2_flow_nominal=mHea_flow_nominal,
    dp1_nominal=dpDom_nominal,
    dp2_nominal=dpHea_nominal,
    eps=eps) "Domestic hot water heater heat exchanger"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemHexOut(redeclare package Medium =
        MediumDom,
                m_flow_nominal=mDom_flow_nominal)
    "Temperature sensor for hot water leaving heat exchanger"
  parameter Modelica.Units.SI.PressureDifference dpDom_nominal=0
    "Pressure difference in heat exchanger on domestic water side";
  parameter Modelica.Units.SI.PressureDifference dpHea_nominal=0
    "Pressure difference in heat exchanger on heating water side";
  parameter Modelica.Units.SI.PressureDifference dpEle_nominal=0
    "Pressure difference in electric reheater for domestic water";
  Modelica.Blocks.Interfaces.RealOutput THexOut
    "Temperature of hot water leaving heat exchanger"
  Modelica.Blocks.Interfaces.RealOutput PEle(unit="W")
    "Electric power required for electric heater"
  Modelica.Blocks.Sources.Constant zero(k=0) if have_eleHea == false "Zero power if no heater"
protected
  Buildings.Fluid.FixedResistances.LosslessPipe pip(
    redeclare package Medium = MediumDom,
    final m_flow_nominal=mDom_flow_nominal,
    final show_T=false) if have_eleHea == false
    "Pipe without electric resistance"

equation
  connect(senTemHexOut.port_a, hex.port_b1)
  connect(senTemHexOut.port_b, heaEle.port_a)
  connect(senTemHexOut.port_b, pip.port_a)
  connect(heaEle.port_b, senTemHot.port_a)
  connect(pip.port_b, senTemHot.port_a)
  connect(TDomSet, heaEle.TSet)
  connect(senTemHexOut.T, THexOut)
  connect(heaEle.Q_flow, PEle)
  connect(zero.y, PEle)
  connect(port_aDom, hex.port_a1)
  connect(hex.port_a2, port_aHea)
  connect(senTemHot.port_b, port_bDom)
  connect(hex.port_b2, port_bHea)
end DirectHeatExchangerWithElectricHeat;


within Buildings.DHC.Loads;
package HotWater "Package of models for domestic hot water generation and loads served by district networks"
   extends Modelica.Icons.VariantsPackage;
end HotWater;


within Buildings.DHC.Loads.HotWater;
model StorageTankWithExternalHeatExchanger
  "A model of a storage tank with external heat exchanger to produce hot water"
  extends
    Buildings.DHC.Loads.HotWater.BaseClasses.PartialFourPortDHW(
    final allowFlowReversalHea=false);

  parameter Buildings.DHC.Loads.HotWater.Data.GenericDomesticHotWaterWithHeatExchanger
    dat "Performance data"

  parameter Real k=0.1 "Proportional gain of circulation pump controller";
  parameter Real Ti=60 "Integrator time constant of circulation pump controller";

  parameter Modelica.Media.Interfaces.Types.Temperature TTan_start=323.15
    "Start value of tank temperature"
  final parameter Real eps =
    dat.QHex_flow_nominal / CMin_flow_nominal / ( dat.TDom_nominal + dat.dTHexApp_nominal - dat.TCol_nominal)
    "Heat exchanger effectiveness"
  Buildings.Fluid.Movers.Preconfigured.FlowControlled_dp pumHex(
    redeclare package Medium = MediumHea,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    use_riseTime=false,
    riseTime=10,
    m_flow_nominal=dat.mHex_flow_nominal,
    dp_nominal=dat.dpHexHea_nominal) "Pump with head as input"

  Buildings.Fluid.Storage.Stratified tan(
    redeclare package Medium = MediumHea,
    kIns=dat.kIns,
    final T_start=TTan_start,
    hTan=dat.hTan,
    dIns=dat.dIns,
    VTan=dat.VTan,
    nSeg=dat.nSeg,
    m_flow_nominal=dat.mHex_flow_nominal)
    "Heating water tank"
  Modelica.Blocks.Interfaces.RealOutput PEle(unit="W")
    "Electric power required for pumping equipment"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemHot(
    redeclare package Medium =  MediumDom,
    final allowFlowReversal=allowFlowReversalDom,
    m_flow_nominal=dat.mDom_flow_nominal)
    "Temperature sensor for hot water supply"

  Buildings.Fluid.HeatExchangers.ConstantEffectiveness hex(
    redeclare package Medium1 = MediumDom,
    redeclare package Medium2 = MediumHea,
    final allowFlowReversal1=allowFlowReversalDom,
    m1_flow_nominal=dat.mDom_flow_nominal,
    m2_flow_nominal=dat.mHex_flow_nominal,
    dp1_nominal=dat.dpHexHea_nominal,
    from_dp2=true,
    dp2_nominal=dat.dpHexDom_nominal,
    eps=eps)
  Buildings.Fluid.FixedResistances.Junction junTop(
    redeclare package Medium = MediumHea,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=dat.mHex_flow_nominal*{1,1,1},
    dp_nominal=zeros(3)) "Flow junction at top of tank"
  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium = MediumDom)
    "Mass flow rate of domestic hot water"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TTanTop(
    T(displayUnit="degC"))
    "Fluid temperature at the top of the tank"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TTanBot(
    T(displayUnit="degC"))
    "Fluid temperature at the bottom of the tank"

  Buildings.DHC.Loads.HotWater.BaseClasses.HeatExchangerPumpController conPum(final mDom_flow_nominal=dat.mDom_flow_nominal,
      final dpPum_nominal=dat.dpHexHea_nominal)
    "Controller for pump of heat exchanger"
  Buildings.DHC.Loads.HotWater.BaseClasses.TankChargingController conCha "Controller for tank charge signal"

  Buildings.Fluid.Actuators.Valves.ThreeWayLinear divVal(
    redeclare package Medium = MediumHea,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    use_strokeTime=false,
    m_flow_nominal=dat.mHex_flow_nominal,
    dpValve_nominal=1000) "Diversion valve to reduce mixing in tank"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemRet(
    redeclare package Medium = MediumHea,
    final allowFlowReversal=allowFlowReversalDom,
    m_flow_nominal=dat.mHex_flow_nominal)
    "Temperature sensor for return heating water from heat exchanger"
  Buildings.DHC.Loads.HotWater.BaseClasses.TankValveController conVal "Diversion valve controller"

  Buildings.Controls.OBC.CDL.Reals.AddParameter dTHexApp(p=dat.dTHexApp_nominal)
    "Offset for heat exchanger approach temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput charge
    "Output true if tank needs to be charged, false if it is sufficiently charged"
protected
  parameter Modelica.Units.SI.SpecificHeatCapacity cpHea_default =
    MediumHea.specificHeatCapacityCp(MediumHea.setState_pTX(
      MediumHea.p_default,
      MediumHea.T_default,
      MediumHea.X_default))
    "Specific heat capacity of heating medium at default medium state";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpDom_default =
    MediumDom.specificHeatCapacityCp(MediumDom.setState_pTX(
      MediumDom.p_default,
      MediumDom.T_default,
      MediumDom.X_default))
    "Specific heat capacity of domestic hot water medium at default medium state";
  parameter Modelica.Units.SI.ThermalConductance CMin_flow_nominal =
    min(dat.mHex_flow_nominal*cpHea_default, dat.mDom_flow_nominal*cpDom_default)
    "Minimum heat capacity flow rate";
initial equation
  assert(eps < 1, "In " + getInstanceName() + ": Heat exchanger effectivness must be below 1, received eps = " + String(eps) + ". Check sizing.");

equation
  connect(tan.port_a, junTop.port_3)
  connect(pumHex.P, PEle)
  connect(junTop.port_2, port_aHea)
  connect(hex.port_b1, senMasFlo.port_a)
  connect(senMasFlo.port_b, senTemHot.port_a)
  connect(TTanTop.port, tan.heaPorVol[1])
  connect(senMasFlo.m_flow, conPum.mDom_flow)
  connect(senTemHot.T, conPum.TDom)
  connect(conPum.TDomSet, TDomSet)
  connect(conCha.TTanTop, TTanTop.T)
  connect(conCha.charge, charge)
  connect(senTemHot.port_b, port_bDom)
  connect(conPum.dpPumHex, pumHex.dp_in)

  connect(port_aDom, hex.port_a1)
  connect(junTop.port_1, hex.port_a2)
  connect(hex.port_b2, pumHex.port_a)
  connect(senTemRet.port_b, divVal.port_2)
  connect(divVal.port_1, tan.fluPorVol[integer(dat.nSeg/2)])
  connect(senTemRet.T, conVal.TRet)
  connect(conVal.y, divVal.y)
  connect(TTanBot.port, tan.heaPorVol[dat.nSeg])
  connect(conCha.TTanTopSet, dTHexApp.y)
  connect(dTHexApp.u, TDomSet)
  connect(divVal.port_3, tan.fluPorVol[dat.nSeg])
  connect(tan.port_b, port_bHea)
  connect(pumHex.port_b, senTemRet.port_a)
  connect(TTanBot.T, conCha.TTanBot)
end StorageTankWithExternalHeatExchanger;


A model for a thermostatic mixing valve

within Buildings.DHC.Loads.HotWater;
model ThermostaticMixingValve
  "A model for a thermostatic mixing valve"
  replaceable package Medium = Buildings.Media.Water "Water media model";
  parameter Modelica.Units.SI.MassFlowRate mMix_flow_nominal
    "Nominal mixed water flow rate to fixture";

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller";
  parameter Real k(
    min=100*Buildings.Controls.OBC.CDL.Constants.eps)=1
    "Gain of controller"
  parameter Real Ti(
    final quantity="Time",
    final unit="s",
    min=100*Buildings.Controls.OBC.CDL.Constants.eps)=0.5
    "Time constant of integrator block"
  parameter Real Td(
    final quantity="Time",
    final unit="s",
    min=100*Buildings.Controls.OBC.CDL.Constants.eps)=0.1
    "Time constant of derivative block"
  parameter Real relTol = 0.005 "Relative tolerance on energy balance, if not met, a warning will be issued at end of simulation"

  Modelica.Fluid.Interfaces.FluidPort_a port_hot(redeclare package Medium =
        Medium) "Port for hot water supply"
  Modelica.Fluid.Interfaces.FluidPort_a port_col(redeclare package Medium =
        Medium) "Port for domestic cold water supply"
  Modelica.Blocks.Interfaces.RealInput TMixSet(
    final unit="K",
    displayUnit="degC") "Temperature setpoint of mixed water outlet"

  Modelica.Blocks.Interfaces.RealInput yMixSet(final min=0, final unit="1")
    "Mixed water fractional flow rate at TMixSet, as fraction of mMix_flow_nominal"

  Buildings.Fluid.Sensors.TemperatureTwoPort senTHot(
    redeclare final package Medium = Medium,
    allowFlowReversal=false,
    final m_flow_nominal=mMix_flow_nominal,
    tau=0) "Hot water temperature"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTCol(
    redeclare final package Medium = Medium,
    allowFlowReversal=false,
    final m_flow_nominal=mMix_flow_nominal,
    tau=0) "Cold water temperature"

  Buildings.Fluid.Sensors.TemperatureTwoPort senTMix(
    redeclare final package Medium = Medium,
    allowFlowReversal=false,
    final m_flow_nominal=mMix_flow_nominal,
    tau=0) "Mixed water temperature"

  Buildings.Controls.OBC.CDL.Reals.PID conPID(
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    yMax=1,
    yMin=0)

  Buildings.Controls.OBC.CDL.Reals.Divide ratEne
    "Ratio of actual over required energy (must be near 1 if load is satisfied)"
  Buildings.Fluid.FixedResistances.Junction jun(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    tau=1,
    m_flow_nominal={-mMix_flow_nominal,mMix_flow_nominal,mMix_flow_nominal},
    dp_nominal={0,0,0}) "Mixing of hot water and cold water"
protected
  Buildings.Controls.OBC.CDL.Reals.Multiply mulMHot_flow
    "Multiplication to output required hot water mass flow rate"

  EnergyMeter eneMetReq "Required energy"
  EnergyMeter eneMetAct "Actual energy"

  block EnergyMeter "Block that outputs integrated energy, bounded away from zero"
    extends Modelica.Blocks.Icons.Block;

    Modelica.Blocks.Interfaces.RealInput TMix(final unit="K", displayUnit="degC")
      "Temperature of mixed water outlet"
    Modelica.Blocks.Interfaces.RealInput TCol(final unit="K", displayUnit="degC")
      "Temperature of cold water"
    Modelica.Blocks.Interfaces.RealInput m_flow(final unit="kg/s")
      "Mass flow rate"
    Modelica.Blocks.Interfaces.RealOutput E(final unit="J") "Consumed energy"
    Modelica.Units.SI.Energy EInt(
      start=0,
      fixed=true,
      unbounded=true,
      nominal=1E9) "Integral of H_flow";
    Modelica.Units.SI.HeatFlowRate H_flow "Enthalpy flow rate";
  equation
    der(EInt) = H_flow;
    H_flow = m_flow * Buildings.Utilities.Psychrometrics.Constants.cpWatLiq * (TMix-TCol);
    E = max(Buildings.Utilities.Psychrometrics.Constants.cpWatLiq*1, EInt);
  end EnergyMeter;

protected
  parameter Modelica.Units.SI.Temperature dTSmall = 0.1 "Small temperature used to avoid division by zero";

  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gaiMMix_flow(final k=mMix_flow_nominal)
    "Gain for multiplying domestic hot water schedule"

  Buildings.Fluid.Movers.BaseClasses.IdealSource floSouHot(
    redeclare final package Medium = Medium,
    allowFlowReversal=false,
    m_flow_small=1E-4*mMix_flow_nominal,
    final control_m_flow=true,
    final control_dp=false)
    "Forced mass flow rate for hot water"
  Buildings.Fluid.Sources.MassFlowSource_T sinMMix(
    redeclare final package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Sink for mixed mass flow rate"

  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gaiMMix_sign(final k=-1)
    "Gain to invert sign"
equation
  connect(senTHot.port_a, port_hot)
  connect(port_col, senTCol.port_a)
  connect(yMixSet, gaiMMix_flow.u)
  connect(floSouHot.port_a, senTHot.port_b)
  connect(conPID.u_s, TMixSet)
  connect(senTMix.T, conPID.u_m)
  connect(sinMMix.m_flow_in, gaiMMix_sign.y)
  connect(mulMHot_flow.y, floSouHot.m_flow_in)
  connect(gaiMMix_flow.y, mulMHot_flow.u1)
  connect(conPID.y, mulMHot_flow.u2)
  connect(gaiMMix_flow.y, gaiMMix_sign.u)
  connect(senTMix.port_b, sinMMix.ports[1])
  connect(eneMetReq.TMix, TMixSet)
  connect(eneMetReq.TCol, senTCol.T)
  connect(gaiMMix_flow.y, eneMetReq.m_flow)
  connect(eneMetAct.TMix, senTMix.T)
  connect(eneMetAct.TCol, senTCol.T)
  connect(eneMetAct.m_flow, gaiMMix_flow.y)
  connect(eneMetReq.E, ratEne.u2)
  connect(eneMetAct.E, ratEne.u1)
  when terminal() then
    assert(
      abs(1-ratEne.y) < relTol,
      "In " + getInstanceName() + ": Required domestic hot water flow rate is not met. Ratio of actual over required energy = " + String(ratEne.y),
      level=AssertionLevel.warning);
  end when;
  connect(floSouHot.port_b, jun.port_3)
  connect(senTCol.port_b, jun.port_2)
  connect(jun.port_1, senTMix.port_a)
end ThermostaticMixingValve;


Controller for pump of storage tank with external heat exchanger. Controller for heat exchanger mass flow rate.

within Buildings.DHC.Loads.HotWater.BaseClasses;
block HeatExchangerPumpController
  "Controller for pump of storage tank with external heat exchanger"
  parameter Modelica.Units.SI.MassFlowRate mDom_flow_nominal
    "Domestic hot water design flow rate (used for scaling)";
  parameter Modelica.Units.SI.PressureDifference dpPum_nominal(
    displayUnit="Pa",
    min=0)
    "Heating water pump head at full speed through heat exchanger";

  parameter Real k=0.1 "Proportioanl gain of circulation pump controller";
  parameter Real Ti=60 "Integrator time constant of circulation pump controller";
  parameter Real yMin(min=0) = 0.3 "Minimum controller output when pump is on";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput mDom_flow(
    final unit="kg/s")
    "Domestic hot water mass flow rate"
  Modelica.Blocks.Interfaces.RealInput TDomSet(
    final unit="K",
    displayUnit="degC")
    "Temperature setpoint for domestic hot water source from heater"
  Modelica.Blocks.Interfaces.RealInput TDom(
    final unit="K",
    displayUnit="degC")
    "Measured hot water temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpPumHex(
    final unit="Pa",
    displayUnit="Pa")
    "Set point for pump head on heating water side"

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysMasFlo(
    uLow=mDom_flow_nominal/1E4,
    uHigh=2*mDom_flow_nominal/1E4,
    y(start=false))
    "Hysteresis used to switch secondary pump on and off"

  Buildings.Controls.OBC.CDL.Reals.PIDWithReset conPI(
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    k=k,
    Ti=Ti,
    yMin=0.03,
    y_reset=0)
    "PI controller for pump"

  Buildings.Controls.OBC.CDL.Reals.Switch swi "Switch for pump control"

protected
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter pumHea(final k=dpPum_nominal)
    "Gain for hex pump head"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(final k=0) "Outputs zero"
equation
  connect(conPI.y, pumHea.u)
  connect(hysMasFlo.y,conPI. trigger)
  connect(hysMasFlo.u, mDom_flow)
  connect(pumHea.y, swi.u1)
  connect(con.y, swi.u3)
  connect(hysMasFlo.y, swi.u2)
  connect(swi.y, dpPumHex)
  connect(TDomSet, conPI.u_s)
  connect(TDom, conPI.u_m)
end HeatExchangerPumpController;


within Buildings.DHC.Loads.HotWater;
package BaseClasses "Package with base classes that are used by multiple models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.DHC.Loads.HotWater.BaseClasses;
partial model PartialFourPortDHW
  "A partial model for domestic water heating"
  extends Modelica.Blocks.Icons.Block;
  replaceable package MediumDom =
    Modelica.Media.Interfaces.PartialMedium "Medium for domestic water in the component"
  replaceable package MediumHea =
    Modelica.Media.Interfaces.PartialMedium "Medium for heating source in the component"

  parameter Boolean allowFlowReversalDom=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for domestic water"
  parameter Boolean allowFlowReversalHea=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for heating water"

  Modelica.Fluid.Interfaces.FluidPort_a port_aDom(
    redeclare final package Medium = MediumDom,
    m_flow(min=if allowFlowReversalDom then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumDom.h_default, nominal=MediumDom.h_default))
    "Fluid connector for cold water (or recirculation water)"

  Modelica.Fluid.Interfaces.FluidPort_b port_bDom(
    redeclare final package Medium = MediumDom,
    m_flow(max=if allowFlowReversalDom then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumDom.h_default, nominal=MediumDom.h_default))
    "Fluid connector for heated domestic hot water"

  Modelica.Fluid.Interfaces.FluidPort_a port_aHea(
    redeclare final package Medium = MediumHea,
    m_flow(min=if allowFlowReversalHea then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumHea.h_default, nominal=MediumHea.h_default))
    "Fluid connector for heating water (positive design flow direction is from port_a to port_b)"

  Modelica.Fluid.Interfaces.FluidPort_b port_bHea(
    redeclare final package Medium = MediumHea,
    m_flow(max=if allowFlowReversalHea then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumHea.h_default, nominal=MediumHea.h_default))
    "Fluid connector b for heating water (positive design flow direction is from port_a to port_b)"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TDomSet(
    final unit="K",
    displayUnit="degC")
    "Temperature setpoint for heated domestic water"
end PartialFourPortDHW;


Controller to enable or disable storage tank charging. Controller that outputs charge=true if the domestic hot
water tank needs to be charged, and false otherwise.

within Buildings.DHC.Loads.HotWater.BaseClasses;
block TankChargingController
  "Controller to enable or disable storage tank charging"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TTanTop(
    final unit="K",
    displayUnit="degC") "Measured temperature at top of tank"
  Modelica.Blocks.Interfaces.RealInput TTanTopSet(
    final unit="K",
    displayUnit="degC")
    "Temperature setpoint for top section of hot water tank"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput charge
    "Outputs true if tank should be charged"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TTanBot(final unit="K", displayUnit=
        "degC") "Measured temperature at bottom of tank"
  Buildings.Controls.OBC.CDL.Logical.Latch lat
  Buildings.Controls.OBC.CDL.Logical.Not not1
protected
  Buildings.Controls.OBC.CDL.Reals.Hysteresis cha(uLow=-5, uHigh=0)
    "Outputs true if tank should be charged"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub

protected
  Buildings.Controls.OBC.CDL.Reals.Hysteresis cha1(uLow=-5, uHigh=0)
    "Outputs true if tank should be charged"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub1
equation
  connect(sub.u2, TTanTop)
  connect(sub.u1, TTanTopSet)
  connect(sub.y, cha.u)
  connect(sub1.y, cha1.u)
  connect(TTanTopSet, sub1.u1)
  connect(TTanBot, sub1.u2)
  connect(cha.y, lat.u)
  connect(lat.y, charge)
  connect(cha1.y, not1.u)
  connect(not1.y, lat.clr)
end TankChargingController;


Controller to divert the water to the middle or bottom of the tank. Controller that outputs the commanded position for the valve that diverts the return
water to the middle or bottom of the tank.

within Buildings.DHC.Loads.HotWater.BaseClasses;
block TankValveController
  "Controller to divert the water to the middle or bottom of the tank"

  parameter Modelica.Units.SI.Temperature TSwi = 318.15 "Switching temperature for return water";

  Modelica.Blocks.Interfaces.RealInput TRet(final unit="K", displayUnit="degC")
    "Return water temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y "Valve position"
  Modelica.Blocks.Continuous.LimIntegrator ram(
    k=1/120,
    outMax=1,
    outMin=0,
    strict=false)
                 "Ramp signal for valve position"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea
protected
  Buildings.Controls.OBC.CDL.Reals.Hysteresis cha(uLow=TSwi - 1, uHigh=TSwi + 1)
    "Outputs true if tank should be charged"

equation
  connect(cha.y, booToRea.u)
  connect(booToRea.y, ram.u)
  connect(ram.y, y)
  connect(cha.u, TRet)
end TankValveController;


within Buildings.DHC.Loads.HotWater;
package Data "Package for data related to hot water generation"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


within Buildings.DHC.Loads.HotWater.Examples;
model HeaterAndFixtureDirectHeatExchangerWithElectricHeat
  "Example model for direct heat exchanger with auxiliary electric heater"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Water "Medium model";
  Buildings.Fluid.Sources.Boundary_pT           souCol(
    nPorts=3,
    redeclare package Medium = Medium,
    T(displayUnit="degC") = 283.15)
              "Source of domestic cold water"
  Buildings.DHC.Loads.HotWater.ThermostaticMixingValve theMixVal(redeclare
      package                                                                                Medium = Medium,
      mMix_flow_nominal=1) "Ideal thermostatic mixing valve"
  Buildings.Fluid.Sources.MassFlowSource_T souDisAmb(
    redeclare package Medium = Medium,
    m_flow=1,
    T(displayUnit="degC") = 298.15,
    nPorts=1) "Source of district water from ambient network"
  Modelica.Blocks.Sources.Constant conTHotSet(k(
      final unit="K",
      displayUnit="degC") = 313.15)
    "Temperature setpoint for hot water supply to fixture"
  Buildings.Fluid.Sources.Boundary_pT sinDis(
    redeclare package Medium = Medium,
    T(displayUnit="degC"),
    nPorts=3)              "Sink of district network water"
  Modelica.Blocks.Sources.Constant conTSetMix(k(
      final unit="K",
      displayUnit="degC") = 308.15)
    "Temperature setpoint for mixed water supply to fixture"
  Buildings.DHC.Loads.HotWater.DirectHeatExchangerWithElectricHeat gen(
    redeclare package MediumDom = Medium,
    redeclare package MediumHea = Medium,
    mDom_flow_nominal=1,
    mHea_flow_nominal=1)
    "Hot water generated by heat exchanger and auxiliary heat"
  Modelica.Blocks.Sources.CombiTimeTable sch(
    tableOnFile=true,
    tableName="tab1",
    fileName=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/Data/DHC/Loads/HotWater/DHW_ApartmentMidRise.mos"),
    smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
    "Domestic hot water fixture draw fraction schedule"

  Buildings.DHC.Loads.HotWater.DirectHeatExchangerWithElectricHeat genNoEle(
    redeclare package MediumDom = Medium,
    redeclare package MediumHea = Medium,
    have_eleHea=false,
    mDom_flow_nominal=1,
    mHea_flow_nominal=1)
    "Hot water generated by heat exchanger without auxiliary heat"
  Buildings.DHC.Loads.HotWater.ThermostaticMixingValve theMixValNoEle(redeclare
      package                                                                                Medium = Medium,
      mMix_flow_nominal=1) "Ideal thermostatic mixing valve"
  Buildings.Fluid.Sources.MassFlowSource_T souDisHot(
    redeclare package Medium = Medium,
    m_flow=1,
    T(displayUnit="degC") = 323.15,
    nPorts=1) "Source of district water from hot network"
equation

  connect(conTSetMix.y,theMixVal. TMixSet)
  connect(conTHotSet.y, gen.TDomSet)
  connect(sch.y[1], theMixVal.yMixSet)
  connect(gen.port_bDom, theMixVal.port_hot)
  connect(theMixVal.port_col, souCol.ports[1])
  connect(gen.port_aDom, souCol.ports[2])
  connect(gen.port_bHea, sinDis.ports[1])
  connect(gen.port_aHea, souDisAmb.ports[1])
  connect(sch.y[1], theMixValNoEle.yMixSet)
  connect(conTSetMix.y, theMixValNoEle.TMixSet)
  connect(conTHotSet.y, genNoEle.TDomSet)
  connect(genNoEle.port_bDom, theMixValNoEle.port_hot)
  connect(souDisHot.ports[1], genNoEle.port_aHea)
  connect(genNoEle.port_bHea, sinDis.ports[2])
  connect(theMixValNoEle.port_col, souCol.ports[3])
  connect(genNoEle.port_aDom, sinDis.ports[3])
end HeaterAndFixtureDirectHeatExchangerWithElectricHeat;


within Buildings.DHC.Loads.HotWater;
package Examples "Example implementations of district-integrated DHW models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.DHC.Loads.HotWater.Examples;
model StorageTankWithExternalHeatExchanger
  "Example model for storage tank with external heat exchanger"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Water "Medium model";
  parameter Modelica.Units.SI.Temperature TCol = 273.15+10 "Temperature of domestic cold water supply";
  parameter Modelica.Units.SI.MassFlowRate mHea_flow_nominal = datWatHea.QHex_flow_nominal/4200/(55 - 50) "Tank heater water loop nominal mass flow";
  parameter Buildings.DHC.Loads.HotWater.Data.GenericDomesticHotWaterWithHeatExchanger
    datWatHea(VTan=0.1892706, mDom_flow_nominal=6.52944E-06*1000)
    "Data for heat pump water heater with tank"

  Modelica.Blocks.Sources.CombiTimeTable sch(
    tableOnFile=true,
    tableName="tab1",
    fileName=Modelica.Utilities.Files.loadResource(
        "modelica://Buildings/Resources/Data/DHC/Loads/HotWater/DHW_ApartmentMidRise.mos"),
    smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
    "Domestic hot water fixture draw fraction schedule"

  Buildings.Fluid.Sources.Boundary_pT souCol(
    nPorts=2,
    redeclare package Medium = Medium,
    T(displayUnit="degC") = 283.15) "Source of domestic cold water"
  Modelica.Blocks.Sources.Constant conTSetMix(k(
      final unit="K",
      displayUnit="degC") = 308.15)
    "Temperature setpoint for mixed water supply to fixture"
  Buildings.DHC.Loads.HotWater.StorageTankWithExternalHeatExchanger
    domHotWatTan(redeclare package MediumDom = Medium, redeclare package
      MediumHea = Medium,
    dat=datWatHea)        "Storage tank with external heat exchanger"
  Buildings.DHC.Loads.HotWater.ThermostaticMixingValve theMixVal(redeclare
      package                                                                                Medium = Medium,
      mMix_flow_nominal=1.2*datWatHea.mDom_flow_nominal)
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea(realTrue=
        mHea_flow_nominal)
  Modelica.Blocks.Sources.Constant conTSetHot(k(
      final unit="K",
      displayUnit="degC") = 313.15)
    "Temperature setpoint for hot water supply to fixture"
  Buildings.Fluid.HeatExchangers.Heater_T hea(
    redeclare package Medium = Medium,
    m_flow_nominal=mHea_flow_nominal,
    dp_nominal=0)
  Buildings.Fluid.Movers.FlowControlled_m_flow mov(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=mHea_flow_nominal)
  Buildings.Fluid.Sensors.TemperatureTwoPort senTem(
    redeclare package Medium = Medium,
    m_flow_nominal=mHea_flow_nominal,
    tau=0)
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar(p=5) "dT for heater"
  Buildings.Fluid.Sources.Boundary_pT preRef(
    nPorts=1,
    redeclare package Medium = Medium,
    T(displayUnit="degC")) "Reference pressure"
equation
  connect(theMixVal.yMixSet, sch.y[1])
  connect(conTSetMix.y, theMixVal.TMixSet)
  connect(domHotWatTan.port_bDom, theMixVal.port_hot)
  connect(souCol.ports[1], domHotWatTan.port_aDom)
  connect(souCol.ports[2], theMixVal.port_col)
  connect(booToRea.u, domHotWatTan.charge)
  connect(domHotWatTan.TDomSet, conTSetHot.y)
  connect(mov.port_b, domHotWatTan.port_aHea)
  connect(hea.port_b, mov.port_a)
  connect(booToRea.y, mov.m_flow_in)
  connect(domHotWatTan.port_bHea, senTem.port_a)
  connect(senTem.port_b, hea.port_a)
  connect(addPar.y, hea.TSet)
  connect(senTem.T, addPar.u)
  connect(hea.port_b, preRef.ports[1])
end StorageTankWithExternalHeatExchanger;


within Buildings.DHC.Loads.Steam;
model BuildingTimeSeriesAtETS
  "Steam heating building interconnection with the district piping only
  and the load at the ETS provided as a time series."
  replaceable package MediumSte = Buildings.Media.Steam constrainedby
    Modelica.Media.Interfaces.PartialMedium
     "Steam medium";
  replaceable package MediumWat =
   Buildings.Media.Specialized.Water.TemperatureDependentDensity
   constrainedby Modelica.Media.Interfaces.PartialMedium
    "Water medium";

  constant Boolean allowFlowReversal = false
    "= false to simplify equations, assuming, but not enforcing, no flow reversal. Set to false because the flow rate is prescribed."

  parameter Boolean have_prv = false
    "Set to true if the building has a pressure reducing valve (PRV) station";
  // Nominal conditions
  parameter Modelica.Units.SI.Power Q_flow_nominal
    "Nominal heat flow rate"
  parameter Modelica.Units.SI.PressureDifference dp_nominal(displayUnit="Pa")
    "Pressure drop at nominal mass flow rate"
  parameter Modelica.Units.SI.AbsolutePressure pSte_nominal=MediumSte.p_default
    "Nominal pressure of steam entering the building"
  parameter Modelica.Units.SI.AbsolutePressure pLow_nominal=0.8*MediumSte.p_default
    "Nominal low pressure setpoint, downstream of PRV (if present)"
  parameter Modelica.Units.SI.Temperature TSte_nominal=
     MediumSte.saturationTemperature(pSte_nominal)
     "Nominal temperature of steam entering the building"
  parameter Modelica.Units.SI.Temperature TLow_nominal=
     MediumSte.temperature(
       MediumSte.setState_phX(
         p=pLow_nominal,
         h=MediumSte.specificEnthalpy(MediumSte.setState_pTX(
            p=pSte_nominal,
            T=TSte_nominal,
            X=MediumSte.X_default)),
         X=MediumSte.X_default))
     "Nominal temperature of steam entering heat exchanger, if PRV present"
  parameter Modelica.Units.SI.SpecificEnthalpy dh_nominal=
    MediumSte.specificEnthalpy(MediumSte.setState_pTX(
        p=if have_prv then pLow_nominal else pSte_nominal,
        T=if have_prv then TLow_nominal else TSte_nominal,
        X=MediumSte.X_default)) -
      MediumWat.specificEnthalpy(MediumWat.setState_pTX(
        p=if have_prv then pLow_nominal else pSte_nominal,
        T=if have_prv then TLow_nominal else TSte_nominal,
        X=MediumWat.X_default))
    "Nominal change in enthalpy across the heat exchanger"
  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=
    Q_flow_nominal/dh_nominal
    "Nominal mass flow rate"

  parameter Modelica.Units.SI.Volume V=1
    "Total volume of the steam side of the heat exchanger";

  // Assumptions
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  // Initialization
  parameter MediumSte.AbsolutePressure p_start=MediumSte.p_default
    "Start value of pressure"
  parameter MediumSte.Temperature T_start=MediumSte.T_default
    "Start value of temperature"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Initial value of mass flow rate"

  // Buildings.DHC.Loads.Heating load time series
  parameter Boolean tableOnFile=false
    "= true, if table is defined on file or in function usertab"
  parameter Real QHeaLoa[:, :] = fill(0.0, 0, 2)
    "Table matrix (time = first column; e.g., table=[0, 0; 1, 1; 2, 4])"
  parameter String tableName="NoName"
    "Table name on file or in function usertab (see docu)"
  parameter String fileName="NoName" "File where matrix is stored";MATLAB MAT-files (*.mat)",
          caption="Open file in which table is present")));
  parameter Integer columns[:]=2:size(QHeaLoa, 2)
    "Columns of table to be interpolated"
  parameter Modelica.Blocks.Types.Smoothness smoothness=
    Modelica.Blocks.Types.Smoothness.LinearSegments
    "Smoothness of table interpolation"
  parameter Modelica.Units.SI.Time timeScale(
    min=Modelica.Constants.eps)=1 "Time scale of first table column"

  // Diagnostics
   parameter Boolean show_T = false
    "= true, if actual temperature at port is computed"

  MediumSte.ThermodynamicState sta_a=
      MediumSte.setState_phX(port_a.p,
                          noEvent(actualStream(port_a.h_outflow)),
                          noEvent(actualStream(port_a.Xi_outflow))) if show_T
    "Medium properties in port_a";

  MediumWat.ThermodynamicState sta_b=
      MediumWat.setState_phX(port_b.p,
                          noEvent(actualStream(port_b.h_outflow)),
                          noEvent(actualStream(port_b.Xi_outflow))) if show_T
    "Medium properties in port_b";

  // Advanced
  parameter Modelica.Units.SI.Density rho_a_default=
    MediumSte.density(MediumSte.setState_pTX(
      p=pSte_nominal,T=TSte_nominal,X=MediumSte.X_default))
    "Default steam density"
  parameter Modelica.Units.SI.Density rho_b_default=
    MediumWat.density(MediumWat.setState_pTX(
      p=101325,T=273.15+90,X=MediumWat.X_default))
    "Default water density"

  Modelica.Blocks.Interfaces.RealOutput Q_flow(
    final quantity="HeatFlowRate",
    final unit="W",
    displayUnit="kW")
    "Total heat transfer rate"
  Modelica.Blocks.Interfaces.RealOutput EHea(
    final quantity="HeatFlow",
    final unit="J",
    displayUnit="kWh")
    "Total heating energy"
  Modelica.Fluid.Interfaces.FluidPort_a port_a(
    redeclare final package Medium = MediumSte)
    "Inlet port"
  Modelica.Fluid.Interfaces.FluidPort_b port_b(
    redeclare final package Medium = MediumWat)
    "Outlet port"
  Modelica.Blocks.Sources.CombiTimeTable QHea(
    final tableOnFile=tableOnFile,
    final table=QHeaLoa,
    final tableName=tableName,
    final fileName=fileName,
    final columns=columns,
    final smoothness=smoothness,
    final extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    final timeScale=timeScale)
    "Heating demand"
  Modelica.Blocks.Continuous.Integrator IntEHea(y(unit="J"))
    "Integrator for heating energy of building"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumCNR(
    redeclare final package Medium = MediumWat,
    final energyDynamics=energyDynamics,
    p_start=steTra.pAtm,
    T_start=steTra.TSat,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m_flow_nominal,
    final show_T=show_T,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    init=Modelica.Blocks.Types.Init.InitialOutput,
    final m_flow_start=m_flow_start)
    "Condensate return pump"
  Buildings.DHC.Loads.Steam.BaseClasses.ControlVolumeCondensation vol(
    redeclare final package MediumSte = MediumSte,
    redeclare final package MediumWat = MediumWat,
    final allowFlowReversal=allowFlowReversal,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    final p_start=if have_prv then pLow_nominal else pSte_nominal,
    final m_flow_nominal=m_flow_nominal,
    final show_T=show_T,
    final V=V)
    "Steam side of the heat exchanger, modeled as a steady state control volume"
  Buildings.DHC.Loads.Steam.BaseClasses.SteamTrap steTra(
    redeclare final package Medium = MediumWat,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m_flow_nominal,
    final show_T=show_T)
    "Steam trap"
  Buildings.Fluid.Sensors.SpecificEnthalpyTwoPort hIn(
    redeclare final package Medium = MediumSte,
    final m_flow_nominal=m_flow_nominal)
    "Enthalpy in"
  Buildings.Fluid.Sensors.SpecificEnthalpyTwoPort hOut(
    redeclare final package Medium = MediumWat,
    final m_flow_nominal=m_flow_nominal)
    "Enthalpy out"
  Modelica.Blocks.Math.Add dh(final k2=-1)
    "Change in enthalpy with building-side fluid"
  Modelica.Blocks.Math.Division m_flow "Mass flow"
  Buildings.DHC.Loads.Steam.BaseClasses.ValveSelfActing prv(
    redeclare final package Medium = MediumSte,
    final m_flow_nominal=m_flow_nominal,
    final show_T=show_T,
    final pb_nominal=pLow_nominal) if have_prv
    "Optional pressure reducing valve"
equation
  connect(IntEHea.y, EHea)
  connect(QHea.y[1], Q_flow)
  connect(IntEHea.u, Q_flow)
  connect(pumCNR.port_b, port_b)
  connect(steTra.port_b, pumCNR.port_a)
  connect(hIn.port_b, vol.port_a)
  connect(vol.port_b, hOut.port_a)
  connect(hOut.port_b, steTra.port_a)
  connect(dh.y, m_flow.u2)
  connect(QHea.y[1], m_flow.u1)
  connect(m_flow.y, pumCNR.m_flow_in)
  connect(hIn.h_out, dh.u1)
  connect(hOut.h_out, dh.u2)
  connect(port_a, prv.port_a)
  if have_prv then
    connect(prv.port_b, hIn.port_a)
  else
  connect(port_a, hIn.port_a)
  end if;
end BuildingTimeSeriesAtETS;


within Buildings.DHC.Loads;
package Steam "Package with models for loads involving steam systems"
  extends Modelica.Icons.VariantsPackage;
end Steam;


within Buildings.DHC.Loads.Steam.BaseClasses;
model ControlVolumeCondensation
  "Control volume model exhibiting the condensation process of water"
  extends
    Buildings.DHC.BaseClasses.Steam.PartialSaturatedControlVolume(
      redeclare final package Medium_a=MediumSte,
      redeclare final package Medium_b=MediumWat);
equation
  // boundary conditions at the ports
  port_a.m_flow = mSte_flow;
  port_a.h_outflow = hSte;
  port_b.m_flow = mWat_flow;
  port_b.h_outflow = hWat;
end ControlVolumeCondensation;


within Buildings.DHC.Loads.Steam;
package BaseClasses "Package with base classes for Buildings.DHC.Loads.Steam"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.DHC.Loads.Steam.BaseClasses;
model SteamTrap "Steam trap with isenthalpic expansion from high to atmospheric
  pressure, followed by a isobaric condensation process as flashed steam
  is brought back to a liquid state"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
      redeclare replaceable package Medium=Buildings.Media.Water);

  constant Modelica.Units.SI.AbsolutePressure pAtm=101325
     "Atmospheric pressure discharge state";
  constant Modelica.Units.SI.Temperature TSat=
    Buildings.Media.Steam.saturationTemperature(pAtm)
    "Saturation temperature at atmospheric pressure";

  Modelica.Blocks.Interfaces.RealOutput QLos_flow(unit="W")
    "Heat transfer loss rate"

  Medium.SpecificEnthalpy dh
    "Change in enthalpy";
equation
  // Pressure setpoints
  port_b.p = pAtm;

  // Flashed steam condenses
  port_b.h_outflow = Medium.specificEnthalpy(
    state=Medium.setState_pTX(
      p=pAtm,
      T=TSat,
      X=inStream(port_a.Xi_outflow)));
  dh = port_b.h_outflow - inStream(port_a.h_outflow);

  // Return reverse flow as the inStream value
  port_a.h_outflow = inStream(port_a.h_outflow);

  // Steady state conservation of mass
  port_a.m_flow + port_b.m_flow = 0;

  // Steady state conservation of energy
  port_a.m_flow*dh = QLos_flow;
end SteamTrap;


within Buildings.DHC.Loads.Steam.BaseClasses;
model ValveSelfActing "Ideal pressure reducing valve for steam heating systems"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    final allowFlowReversal=false);
  parameter Modelica.Units.SI.Pressure pb_nominal(
    displayUnit="Pa",
    min=101325)
    "Nominal outlet pressure"

  parameter Modelica.Units.SI.PressureDifference dp_start(displayUnit="Pa")=pb_nominal
    "Guess value of dp = port_a.p - port_b.p"

  Buildings.Fluid.Sensors.Pressure pUp(redeclare final package Medium = Medium)
    "Pressure sensor"
  Buildings.Utilities.Math.SmoothMax dpSet(final deltaX=0.5) "Pressure drop setpoint"

protected
  Buildings.Fluid.Movers.BaseClasses.IdealSource ideSou(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final dp_start=dp_start,
    m_flow_start=m_flow_nominal,
    final m_flow_small=m_flow_small,
    final show_T=show_T,
    final control_m_flow=false,
    final control_dp=true) "Ideal source controlling dp"
  Modelica.Blocks.Sources.RealExpression pbSet(final y=pb_nominal)
    "Downstream pressure setpoint"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0) "Zero"
  Buildings.Controls.OBC.CDL.Reals.Subtract dpReq "Calculating dp required"

equation
  assert(dpReq.y > 0, "pb_nominal is set higher than the upstream pressure in "
  + getInstanceName() + ", which results in a negative pressure drop.
  This is not typical of real systems and should be verified.", AssertionLevel.warning);

  connect(ideSou.port_b, port_b)
  connect(pUp.port, ideSou.port_a)
  connect(zer.y, dpSet.u1)
  connect(dpSet.y, ideSou.dp_in)
  connect(port_a, ideSou.port_a)
  connect(pUp.p, dpReq.u1)
  connect(pbSet.y, dpReq.u2)
  connect(dpReq.y, dpSet.u2)
end ValveSelfActing;


within Buildings.DHC.Loads.Steam.BaseClasses.Examples;
model ControlVolumeCondensation
  "Example model for heat transfer with the condensation control volume"
  extends Modelica.Icons.Example;

package MediumSte = Buildings.Media.Steam (
  T_default=273.15+180,
  p_default=1e6)
    "Steam medium - Medium model for port_a (inlet)";
package MediumWat =
      Buildings.Media.Specialized.Water.TemperatureDependentDensity
    "Water medium - Medium model for port_b (outlet)";

  Buildings.DHC.Loads.Steam.BaseClasses.ControlVolumeCondensation volDyn(
    V=1,
    redeclare package MediumWat = MediumWat,
    redeclare package MediumSte = MediumSte,
    m_flow_nominal=0.01,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    allowFlowReversal=true) "Dynamic volume"
  Buildings.DHC.Loads.Steam.BaseClasses.ControlVolumeCondensation volSte(
    V=1,
    redeclare package MediumWat = MediumWat,
    redeclare package MediumSte = MediumSte,
    m_flow_nominal=0.01,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=true) "Steady volume"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = MediumSte,
    use_m_flow_in=true,
    T=453.15,
    nPorts=1) "Flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = MediumSte,
    use_m_flow_in=true,
    T=453.15,
    nPorts=1) "Flow source"
  Modelica.Fluid.Sources.FixedBoundary bou(
    redeclare package Medium = MediumWat,
    p=volDyn.p_start,
    T=293.15,
    nPorts=2) "Boundary condition"
  Modelica.Blocks.Sources.Ramp ramp(
    duration=1,
    offset=2,
    height=-1) "Ramp signal"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFlo
    "Heat flow sensor"
  Modelica.Blocks.Sources.Constant const(k=-10000) "Heat loss"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHeaFlo
    "Prescribed heat flow rate"
equation
  connect(sou.ports[1], volDyn.port_a)
  connect(volDyn.port_b, bou.ports[1])
  connect(preHeaFlo.port,heaFlo. port_a)
  connect(preHeaFlo.Q_flow,const. y)
  connect(heaFlo.port_b, volDyn.heatPort)
  connect(sou1.ports[1], volSte.port_a)
  connect(ramp.y, sou.m_flow_in)
  connect(ramp.y, sou1.m_flow_in)
  connect(volSte.port_b, bou.ports[2])
end ControlVolumeCondensation;


within Buildings.DHC.Loads.Steam.BaseClasses;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.DHC.Loads.Steam.BaseClasses.Examples;
model SteamTrap "Example model to demonstrate the steam trap"
  extends Modelica.Icons.Example;

  package MediumWat = Buildings.Media.Water "Water medium";

  parameter Modelica.Units.SI.Temperature TSatHig=273.15+110
     "High pressure saturation temperature";
  parameter Modelica.Units.SI.Temperature TSatLow=273.15+100
     "Low pressure saturation temperature";
  parameter Modelica.Units.SI.AbsolutePressure pSat=143380
     "Saturation pressure";
  parameter Modelica.Units.SI.PressureDifference dp=pSat-101325
    "Prescribed pressure change";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=10
    "Nominal mass flow rate";

  Modelica.Blocks.Sources.Ramp ram(
    height=m_flow_nominal,
    duration(displayUnit="min") = 60,
    startTime(displayUnit="min") = 60)
    "Ramp"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = MediumWat,
    p=pSat,
    T=TSatHig,
    nPorts=1)
    "Source"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = MediumWat,
    p=pSat - dp,
    T=TSatLow,
    nPorts=1)
    "Sink"
  Buildings.DHC.Loads.Steam.BaseClasses.SteamTrap steTra(
    redeclare package Medium = MediumWat,
    m_flow_nominal=m_flow_nominal,
    show_T=true)
    "Steam trap"
  Buildings.Fluid.Movers.FlowControlled_m_flow pum(
    redeclare package Medium = MediumWat,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=m_flow_nominal,
    nominalValuesDefineDefaultPressureCurve=true)
    "Pump"
  Fluid.Sensors.SpecificEnthalpyTwoPort hIn(
    redeclare package Medium = MediumWat,
    m_flow_nominal=m_flow_nominal)
    "Inflowing specific enthalpy"
  Fluid.Sensors.SpecificEnthalpyTwoPort hOut(
    redeclare package Medium = MediumWat,
    m_flow_nominal=m_flow_nominal)
    "Outflowing specific enthalpy"
equation
  connect(pum.port_b, sin.ports[1])
  connect(ram.y, pum.m_flow_in)
  connect(sou.ports[1], hIn.port_a)
  connect(hIn.port_b, steTra.port_a)
  connect(steTra.port_b, hOut.port_a)
  connect(hOut.port_b, pum.port_a)
end SteamTrap;


within Buildings.DHC.Loads.Steam.BaseClasses.Examples;
model ValveSelfActing
  "Example model for self-acting steam valve with a noisy inlet pressure input"
  extends Modelica.Icons.Example;
  package MediumSte = Buildings.Media.Steam(p_default=400000,
    T_default=273.15+143.61,
    h_default=2738100) "Medium model";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Nominal mass flow rate";

  Buildings.DHC.Loads.Steam.BaseClasses.ValveSelfActing prv(
    redeclare final package Medium = MediumSte,
    m_flow_nominal=m_flow_nominal,
    show_T=true,
    pb_nominal=300000,
    dp_start(displayUnit="Pa"))
     "Self acting pressure reducing valve"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare final package Medium = MediumSte,
    use_p_in=true,
    p(displayUnit="Pa"),
    T(displayUnit="K") = MediumSte.saturationTemperature(sou.p),
    nPorts=1) "Source"
  Buildings.Fluid.Sensors.SpecificEnthalpyTwoPort speEntIn(
    redeclare final package Medium = MediumSte,
    m_flow_nominal=m_flow_nominal,
    tau=0)
    "Upstream specific enthalpy"
  Buildings.Fluid.Sensors.SpecificEnthalpyTwoPort speEntOut(
    redeclare final package Medium = MediumSte,
    m_flow_nominal=m_flow_nominal,
    tau=0)
    "Downstream specific enthalpy"
  Fluid.Sources.Boundary_pT sin(
    redeclare final package Medium = MediumSte,
    p=200000,
    T=MediumSte.saturationTemperature(sin.p),
    nPorts=1) "Sink"
  Fluid.FixedResistances.PressureDrop res(
    redeclare final package Medium = MediumSte,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=1000) "Pressure drop"
  Controls.OBC.CDL.Reals.Sources.Ramp pInSig(
    height=400000,
    duration=15,
    offset=500000 - 200000) "Signal for inlet pressure"
equation
  connect(sou.ports[1], speEntIn.port_a)
  connect(speEntIn.port_b, prv.port_a)
  connect(prv.port_b, speEntOut.port_a)
  connect(sin.ports[1], res.port_b)
  connect(res.port_a, speEntOut.port_b)
  connect(pInSig.y, sou.p_in)
end ValveSelfActing;


within Buildings.DHC.Loads.Steam.Examples;
model BuildingTimeSeriesAtETS
  "Example model for time series load with external read-in file."
  extends Modelica.Icons.Example;

  package MediumSte = Buildings.Media.Steam (p_default=400000,
    T_default=273.15+143.61,
    h_default=2738100) "Steam medium";
  package MediumWat =
    Buildings.Media.Specialized.Water.TemperatureDependentDensity
    "Water medium";

  parameter Modelica.Units.SI.AbsolutePressure pSat=400000
    "Saturation pressure";
  parameter Modelica.Units.SI.Temperature TSat=
     MediumSte.saturationTemperature(pSat)
     "Saturation temperature";
  parameter Modelica.Units.SI.Power Q_flow_nominal= 2e4
    "Nominal heat flow rate";

  Buildings.DHC.Loads.Steam.BuildingTimeSeriesAtETS bui(
    redeclare package MediumSte = MediumSte,
    redeclare package MediumWat = MediumWat,
    have_prv=true,
    pLow_nominal=200000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal=3000,
    tableOnFile=false,
    final Q_flow_nominal=Q_flow_nominal,
    final pSte_nominal=pSat,
    QHeaLoa=[0,Q_flow_nominal*0.2; 6,Q_flow_nominal; 16,Q_flow_nominal*0.1; 24,Q_flow_nominal*0.2],
    columns={2},
    smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative,
    timeScale(displayUnit="h") = 3600,
    show_T=true)
    "Building model with time series load at the ETS"
  Buildings.Fluid.Sources.Boundary_pT souSte(
    redeclare final package Medium = MediumSte,
    p(displayUnit="Pa") = pSat,
    T=TSat,
    nPorts=1)
    "Steam source"
  Buildings.Fluid.Sources.Boundary_pT watSin(
    redeclare final package Medium = MediumWat,
    p=101325,
    nPorts=1)
    "Water sink"
equation
  connect(souSte.ports[1], bui.port_a)
  connect(bui.port_b, watSin.ports[1])
end BuildingTimeSeriesAtETS;


within Buildings.DHC.Loads.Steam;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Model of a one-pipe distribution network with plug flow pipes in the main line with hydraulic diameter calculated from nominal velocity. This model represents a one-pipe distribution network using a connection model with a plug flow pipe
model (pressure drop, heat transfer, transport delays) in the main line whose hydraulic diameters
are calculated based on nominal velocity at nominal flow rate
Buildings.DHC.Networks.Connections.Connection1PipePlugFlow. The same pipe model at the end of
the distribution line (after the last connection).

within Buildings.DHC.Networks;
model Distribution1PipePlugFlow_v
  "Model of a one-pipe distribution network with plug flow pipes in the main line with hydraulic diameter calculated from nominal velocity"
  extends Buildings.DHC.Networks.BaseClasses.PartialDistribution1Pipe(
    tau=5*60,
    redeclare Buildings.DHC.Networks.Connections.Connection1PipePlugFlow_v
      con[nCon](
      each final dIns=dIns,
      each final kIns=kIns,
      each final v_nominal=v_nominal,
      each final roughness=roughness,
      each final cPip=cPip,
      each final rhoPip=rhoPip,
      each final thickness=thickness,
      final lDis=lDis),
    redeclare model Model_pipDis = Buildings.Fluid.FixedResistances.PlugFlowPipe (
        final length=lEnd,
        final dIns=dIns,
        final kIns=kIns,
        final v_nominal=v_nominal,
        final roughness=roughness,
        final cPip=cPip,
        final rhoPip=rhoPip,
        final thickness=thickness));

  parameter Modelica.Units.SI.Length lDis[nCon]
    "Length of the distribution pipe before each connection";
  parameter Modelica.Units.SI.Length lEnd
    "Length of the end of the distribution line (after last connection)";
  parameter Modelica.Units.SI.Length dIns=0.05
    "Thickness of pipe insulation, used to compute R";
  parameter Modelica.Units.SI.ThermalConductivity kIns=0.028
    "Heat conductivity of pipe insulation, used to compute R";
  parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)";
  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)";
  parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel";
  parameter Modelica.Units.SI.Density rhoPip=930
    "Density of pipe wall material. 930 for PE, 8000 for steel";
  parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness";
  Modelica.Fluid.Interfaces.HeatPorts_a heatPorts[nCon + 1]
    "Multiple heat ports that connect to outside of pipe wall"
equation
  connect(con.heatPortDis, heatPorts[1:nCon])
  connect(pipEnd.heatPort, heatPorts[nCon + 1])
end Distribution1PipePlugFlow_v;


Model of a one-pipe distribution network with hydraulic diameter of main line pipes calculated from pressure drop per length. This is a model of a one-pipe distribution network using a connection model with pipes in the main line whose hydraulic diameters
are calculated at initialization based on the pressure drop per pipe length at nominal flow rate
Buildings.DHC.Networks.Connections.Connection1Pipe_R. The same pipe model is also used
at the end of the distribution line (after the last connection) only on the supply side.

within Buildings.DHC.Networks;
model Distribution1Pipe_R
  "Model of a one-pipe distribution network with hydraulic diameter of main line pipes calculated from pressure drop per length"
  extends Buildings.DHC.Networks.BaseClasses.PartialDistribution1Pipe(
    tau=5*60,
    redeclare Buildings.DHC.Networks.Connections.Connection1Pipe_R
      con[nCon](
      each final dp_length_nominal=dp_length_nominal,
      final lDis=lDis,
      final dhDis=dhDis),
    redeclare model Model_pipDis = Buildings.DHC.Networks.Pipes.PipeAutosize(
        final dp_length_nominal=dp_length_nominal,
        final dh(fixed=true) = dhEnd,
        final length=lEnd),
    pipEnd(fac=1));
  parameter Real dp_length_nominal(final unit="Pa/m") = 250
    "Pressure drop per pipe length at nominal flow rate";
  parameter Modelica.Units.SI.Length lDis[nCon]
    "Length of the distribution pipe before each connection";

  parameter Modelica.Units.SI.Length lEnd
    "Length of the end of the distribution line (after last connection)";
  final parameter Modelica.Units.SI.Length dhDis[nCon](
    each fixed=false,
    each start=0.05,
    each min=0.01)
    "Hydraulic diameter of the distribution pipe before each connection";

  final parameter Modelica.Units.SI.Length dhEnd(
    fixed=false,
    start=0.05,
    min=0.01)
    "Hydraulic diameter of of the end of the distribution line (after last connection)";
end Distribution1Pipe_R;


Model of a two-pipe distribution network using plug flow pipe models in the main lines with hydraulic diameter calculated from nominal velocity. This is a model of a two-pipe distribution network using a connection model with a plug flow pipe
model (pressure drop, heat transfer, transport delays) in the main lines whose hydraulic diameters
are calculated based on nominal velocity at nominal flow rate
Buildings.DHC.Networks.Connections.Connection2PipePlugFlow. The same pipe model is also used
at the end of the distribution line (after the last connection) only on the supply side.

within Buildings.DHC.Networks;
model Distribution2PipePlugFlow_v
  "Model of a two-pipe distribution network using plug flow pipe models in the main lines with hydraulic diameter calculated from nominal velocity"
  extends Buildings.DHC.Networks.BaseClasses.PartialDistribution2Pipe(
      redeclare Connections.Connection2PipePlugFlow_v con[nCon](
      final lDis=lDis,
      each final dIns=dIns,
      each final kIns=kIns,
      each final v_nominal=v_nominal,
      each final roughness=roughness,
      each final cPip=cPip,
      each final rhoPip=rhoPip,
      each final thickness=thickness),
      redeclare model Model_pipDis = Buildings.Fluid.FixedResistances.PlugFlowPipe(
        final length=lEnd,
        final dIns=dIns,
        final kIns=kIns,
        final v_nominal=v_nominal,
        final roughness=roughness,
        final cPip=cPip,
        final rhoPip=rhoPip,
        final thickness=thickness));
   parameter Modelica.Units.SI.Length lDis[nCon]
    "Length of the distribution pipe before each connection (supply only, not counting return line)";
   parameter Modelica.Units.SI.Length lEnd
    "Length of the end of the distribution line (supply only, not counting return line)";
   parameter Modelica.Units.SI.Length dIns=0.05
    "Thickness of pipe insulation, used to compute R";
   parameter Modelica.Units.SI.ThermalConductivity kIns=0.028
    "Heat conductivity of pipe insulation, used to compute R";
   parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)";
   parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)";
   parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel";
   parameter Modelica.Units.SI.Density rhoPip=930
    "Density of pipe wall material. 930 for PE, 8000 for steel";
   parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness";
  Modelica.Fluid.Interfaces.HeatPorts_a heatPortsDis[nCon + 1]
    "Multiple heat ports that connect to outside of pipe wall for distribution pipe"
  Modelica.Fluid.Interfaces.HeatPorts_a heatPortsRet[nCon]
    "Multiple heat ports that connect to outside of pipe wall for return pipe"
equation
  connect(con.heatPortRet, heatPortsRet)
  connect(con.heatPortDis, heatPortsDis[1:nCon])
  connect(pipEnd.heatPort, heatPortsDis[nCon + 1])
end Distribution2PipePlugFlow_v;


Model of a two-pipe distribution network with hydraulic diameter of main line pipes calculated from pressure drop per length. This is a model of a two-pipe distribution network using a connection model with pipes in the main lines whose hydraulic diameters
are calculated at initialization based on the pressure drop per pipe length at nominal flow rate
Buildings.DHC.Networks.Connections.Connection2Pipe_R. The same pipe model is also used
at the end of the distribution line (after the last connection) only on the supply side.

within Buildings.DHC.Networks;
model Distribution2Pipe_R
  "Model of a two-pipe distribution network with hydraulic diameter of main line pipes calculated from pressure drop per length"
  extends Buildings.DHC.Networks.BaseClasses.PartialDistribution2Pipe(
    tau=5*60,
    redeclare Buildings.DHC.Networks.Connections.Connection2Pipe_R
      con[nCon](
      each final dp_length_nominal=dp_length_nominal,
      final lDis=lDis,
      final dhDis=dhDis,
      final dhDisRet=dhDisRet),
    redeclare model Model_pipDis = Buildings.DHC.Networks.Pipes.PipeAutosize(
        roughness=7e-6,
        fac=1.5,
        final dp_length_nominal=dp_length_nominal,
        final dh(fixed=true) = dhEnd,
        final length=lEnd),
    pipEnd(fac=1));
  parameter Real dp_length_nominal(final unit="Pa/m") = 250
    "Pressure drop per pipe length at nominal flow rate";
  parameter Modelica.Units.SI.Length lDis[nCon]
    "Length of the distribution pipe before each connection (supply only, not counting return line)";

  parameter Modelica.Units.SI.Length lEnd
    "Length of the end of the distribution line (supply only, not counting return line)";
  final parameter Modelica.Units.SI.Length dhDis[nCon](
    each fixed=false,
    each start=0.05,
    each min=0.01)
    "Hydraulic diameter of the distribution pipe before each connection";
  final parameter Modelica.Units.SI.Length dhDisRet[nCon](
    each fixed=false,
    each start=0.05,
    each min=0.01)
    "Hydraulic diameter of the distribution pipe before each connection";

  final parameter Modelica.Units.SI.Length dhEnd(
    fixed=false,
    start=0.05,
    min=0.01) "Hydraulic diameter of the end of the distribution line";
end Distribution2Pipe_R;


within Buildings.DHC;
package Networks "Package of models for district energy distribution networks"
  extends Modelica.Icons.VariantsPackage;
end Networks;


within Buildings.DHC.Networks.BaseClasses;
model DifferenceEnthalpyFlowRate
  "Sensor outputting the difference between two enthalpy flow rates"
  extends Fluid.Interfaces.PartialFourPortInterface(
    redeclare replaceable package Medium2=Medium1,
    final m1_flow_nominal=m_flow_nominal,
    final m2_flow_nominal=m_flow_nominal,
    final allowFlowReversal1=allowFlowReversal,
    final allowFlowReversal2=allowFlowReversal,
    final m1_flow_small=m_flow_small,
    final m2_flow_small=m_flow_small,
    final show_T=false);
  parameter Boolean have_integrator=false
    "Set to true to output the time integral"
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal(min=0)
    "Nominal mass flow rate"
  parameter Modelica.Units.SI.Time tau(min=0) = 0
    "Time constant at nominal flow rate";
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (InitialState and InitialOutput are identical)"
  parameter Boolean allowFlowReversal=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal"
  parameter Modelica.Units.SI.SpecificEnthalpy h1_out_start=
      Medium1.specificEnthalpy_pTX(
      p=Medium1.p_default,
      T=Medium1.T_default,
      X=Medium1.X_default)
    "Initial or guess value of measured specific enthalpy"
  parameter Modelica.Units.SI.SpecificEnthalpy h2_out_start=
      Medium2.specificEnthalpy_pTX(
      p=Medium2.p_default,
      T=Medium2.T_default,
      X=Medium2.X_default)
    "Initial or guess value of measured specific enthalpy"
  parameter Medium1.MassFlowRate m_flow_small(min=0)=1E-4*abs(m_flow_nominal)
    "Small mass flow rate for regularization of zero flow"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dH_flow(
    final unit="W")
    "Difference in enthalpy flow rate between stream 1 and 2"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput E(
    final unit="J") if have_integrator
    "Time integral of enthalpy flow rate difference between stream 1 and 2"
  Fluid.Sensors.EnthalpyFlowRate senEntFlo1(
    redeclare final package Medium=Medium1,
    final m_flow_nominal=m_flow_nominal,
    final tau=tau,
    final initType=initType,
    final allowFlowReversal=allowFlowReversal,
    final h_out_start=h1_out_start)
    "Enthalpy flow rate of fluid stream 1"
  Fluid.Sensors.EnthalpyFlowRate senEntFlo2(
    redeclare final package Medium=Medium2,
    final m_flow_nominal=m_flow_nominal,
    final tau=tau,
    final initType=initType,
    final allowFlowReversal=allowFlowReversal,
    final h_out_start=h2_out_start)
    "Enthalpy flow rate of fluid stream 2"
  Buildings.Controls.OBC.CDL.Reals.Subtract dif
    "Compute the difference"
  Modelica.Blocks.Continuous.Integrator int(
    y(unit="J")) if have_integrator
    "Time integral computation"
equation
  connect(port_a1,senEntFlo1.port_a)
  connect(senEntFlo1.port_b,port_b1)
  connect(port_b2,senEntFlo2.port_b)
  connect(senEntFlo2.port_a,port_a2)
  connect(dif.y,dH_flow)
  connect(senEntFlo1.H_flow,dif.u1)
  connect(senEntFlo2.H_flow,dif.u2)
  connect(int.y,E)
  connect(dif.y,int.u)
end DifferenceEnthalpyFlowRate;


within Buildings.DHC.Networks;
package BaseClasses "Package with base classes that are used by multiple models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.DHC.Networks.BaseClasses;
partial model PartialConnection1Pipe
  "Partial model for connecting an agent to a one-pipe distribution network"
  replaceable package Medium=Modelica.Media.Interfaces.PartialMedium
    "Medium model";
  replaceable model Model_pipDis=Fluid.Interfaces.PartialTwoPortInterface (
    redeclare final package Medium=Medium,
    final m_flow_nominal=mDis_flow_nominal,
    final allowFlowReversal=allowFlowReversal);
  replaceable model Model_pipCon=Fluid.Interfaces.PartialTwoPortInterface (
    redeclare final package Medium=Medium,
    final m_flow_nominal=mCon_flow_nominal,
    final allowFlowReversal=allowFlowReversal);
  parameter Boolean show_entFlo=false
    "Set to true to output enthalpy flow rate difference"
  parameter Boolean show_TOut=false
    "Set to true to output temperature at connection outlet"
  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal
    "Nominal mass flow rate in the distribution line";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal
    "Nominal mass flow rate in the connection line";
  parameter Boolean allowFlowReversal=false
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  final parameter Modelica.Fluid.Types.Dynamics massDynamics=energyDynamics
    "Type of mass balance: dynamic (3 initialization options) or steady state, must be steady state if energyDynamics is steady state"
  parameter Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow for dynamic energy and momentum balance"
  // IO CONNECTORS
  Modelica.Fluid.Interfaces.FluidPort_a port_aDis(
    redeclare final package Medium=Medium,
    m_flow(
      min=
        if allowFlowReversal then
          -Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "Distribution inlet port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bDis(
    redeclare final package Medium=Medium,
    m_flow(
      max=
        if allowFlowReversal then
          +Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "Distribution outlet port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aCon(
    redeclare final package Medium=Medium,
    m_flow(
      min=
        if allowFlowReversal then
          -Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "Connection return port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bCon(
    redeclare final package Medium=Medium,
    m_flow(
      max=
        if allowFlowReversal then
          +Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "Connection supply port"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mCon_flow(
    final unit="kg/s")
    "Connection supply mass flow rate (measured)"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dH_flow(
      final unit="W") if show_entFlo
    "Difference in enthalpy flow rate between connection supply and return"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mByp_flow(
    final unit="kg/s") "Bypass mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TOut(
    final unit="K",
    displayUnit="degC") if show_TOut
    "Temperature in distribution line at connection outlet"
  // COMPONENTS
  Fluid.FixedResistances.Junction junConSup(
    redeclare final package Medium=Medium,
    final portFlowDirection_1=
      if allowFlowReversal then
        Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else
        Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=
      if allowFlowReversal then
        Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else
        Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=
      if allowFlowReversal then
        Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else
        Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final dp_nominal={0,0,0},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final m_flow_nominal={mDis_flow_nominal,-mDis_flow_nominal,-mCon_flow_nominal})
    "Junction with connection supply"
  Fluid.FixedResistances.Junction junConRet(
    redeclare final package Medium=Medium,
    final portFlowDirection_1=
      if allowFlowReversal then
        Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else
        Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=
      if allowFlowReversal then
        Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else
        Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=
      if allowFlowReversal then
        Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else
        Modelica.Fluid.Types.PortFlowDirection.Entering,
    final dp_nominal={0,0,0},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final m_flow_nominal={mDis_flow_nominal,-mDis_flow_nominal,mCon_flow_nominal})
    "Junction with connection return"
  Model_pipDis pipDis
    "Distribution pipe"
  Model_pipCon pipCon
    "Connection pipe"
  Buildings.Fluid.Sensors.MassFlowRate senMasFloCon(
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal)
    "Connection supply mass flow rate (measured)"
  Buildings.Fluid.Sensors.MassFlowRate senMasFloByp(
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal)
    "Bypass mass flow rate (measured)"
  DifferenceEnthalpyFlowRate senDifEntFlo(
    redeclare final package Medium1=Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=mCon_flow_nominal) if show_entFlo
    "Difference in enthalpy flow rate"
  Fluid.Sensors.TemperatureTwoPort senTOut(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=mDis_flow_nominal) if show_TOut
    "Temperature in distribution line at connection outlet"
protected
  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(Medium.setState_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default))
    "Specific heat capacity of medium at default medium state";

equation
  // Connect statements involving conditionally removed components are
  // removed at translation time by Modelica specification.
  // Only obsolete statements corresponding to the default model structure need
  // to be programmatically removed.
  if not show_entFlo then
    connect(port_bCon,senMasFloCon.port_b)
    connect(port_aCon,junConRet.port_3)
  end if;
  if not show_TOut then
    connect(junConRet.port_2,port_bDis)
  end if;
  connect(junConSup.port_3,pipCon.port_a)
  connect(senMasFloCon.m_flow,mCon_flow)
  connect(port_aDis,pipDis.port_a)
  connect(junConSup.port_2,senMasFloByp.port_a)
  connect(senMasFloByp.port_b,junConRet.port_1)
  connect(senMasFloByp.m_flow,mByp_flow)
  connect(senMasFloCon.port_b, senDifEntFlo.port_a1)
  connect(senDifEntFlo.port_b1, port_bCon)
  connect(senDifEntFlo.port_b2, junConRet.port_3)
  connect(senDifEntFlo.port_a2, port_aCon)
  connect(senDifEntFlo.dH_flow, dH_flow)
  connect(port_bDis, senTOut.port_b)
  connect(junConRet.port_2, senTOut.port_a)
  connect(senTOut.T, TOut)
  connect(pipCon.port_b, senMasFloCon.port_a)
  connect(pipDis.port_b, junConSup.port_1)
end PartialConnection1Pipe;