Performance data for electric chillers

within Buildings.Fluid.Chillers;
package Data "Performance data for electric chillers"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


within Buildings.Fluid.Chillers.Examples;
model AbsorptionIndirectSteam
  "Test model for absorption indirect steam chiller"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Water
   "Medium model";

  parameter Buildings.Fluid.Chillers.Data.AbsorptionIndirectSteam.Generic per(
   QEva_flow_nominal=-10000,
   P_nominal=150,
   PLRMax=1,
   PLRMin=0.15,
   mEva_flow_nominal=0.247,
   mCon_flow_nominal=1.1,
   dpEva_nominal=0,
   dpCon_nominal=0,
   capFunEva={0.690571,0.065571,-0.00289,0},
   capFunCon={0.245507,0.023614,0.0000278,0.000013},
   genHIR={0.18892,0.968044,1.119202,-0.5034},
   EIRP={1,0,0},
   genConT={0.712019,-0.00478,0.000864,-0.000013},
   genEvaT={0.995571,0.046821,-0.01099,0.000608})
    "Chiller performance data"

  Buildings.Fluid.Chillers.AbsorptionIndirectSteam absIndSte(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    show_T=true,
    per=per,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  "Absorption chiller"
  Buildings.Fluid.Sources.MassFlowSource_T conPum(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    m_flow=per.mCon_flow_nominal,
    use_T_in=true,
    nPorts=1)
   "Condenser water pump"
  Buildings.Fluid.Sources.MassFlowSource_T evaPum(
    redeclare package Medium = Medium,
    m_flow=per.mEva_flow_nominal,
    use_T_in=true,
    nPorts=1)
   "Evaporator water pump"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TConEnt(
    height=5,
    duration(displayUnit="h") = 14400,
    offset=20 + 273.15,
    startTime=0)
   "Condenser entering water temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TEvaEnt(
    height=4,
    duration(displayUnit="h") = 14400,
    offset=12 + 273.15,
    startTime=0)
    "Evaporator entering water temperature"
  Buildings.Fluid.Sources.Boundary_pT heaVol(
    redeclare package Medium = Medium,
    nPorts=1)
   "Volume for heating load"
  Buildings.Fluid.Sources.Boundary_pT cooVol(
    redeclare package Medium = Medium,
    nPorts=1)
   "Volume for cooling load"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TEvaSet(
    height=4,
    duration(displayUnit="h") = 14400,
    offset=6 + 273.15,
    startTime=0)
    "Evaporator setpoint water temperature"
  Modelica.Blocks.Sources.BooleanPulse onOff(period=3600/2) "Control input"
equation
  connect(TConEnt.y,conPum. T_in)
  connect(TEvaEnt.y,evaPum. T_in)
  connect(absIndSte.port_a2, evaPum.ports[1])
  connect(absIndSte.TSet, TEvaSet.y)
  connect(conPum.ports[1], absIndSte.port_a1)
  connect(absIndSte.port_b1, heaVol.ports[1])
  connect(cooVol.ports[1], absIndSte.port_b2)
  connect(onOff.y, absIndSte.on)
end AbsorptionIndirectSteam;


within Buildings.Fluid.Chillers.Examples;
model AbsorptionIndirectSteamVaryingLoad
  "Absorption chiller with varying cooling load"
  package Medium = Buildings.Media.Water "Medium model";

  parameter Data.AbsorptionIndirectSteam.Generic per(
    QEva_flow_nominal=-10000,
    P_nominal=150,
    PLRMax=1,
    PLRMin=0.15,
    mEva_flow_nominal=0.247,
    mCon_flow_nominal=1.1,
    dpEva_nominal=0,
    dpCon_nominal=0,
    capFunEva={0.690571,0.065571,-0.00289,0},
    capFunCon={0.245507,0.023614,0.0000278,0.000013},
    genHIR={0.18892,0.968044,1.119202,-0.5034},
    EIRP={1,0,0},
    genConT={0.712019,-0.00478,0.000864,-0.000013},
    genEvaT={0.995571,0.046821,-0.01099,0.000608})
     "Chiller performance data"

  Buildings.Fluid.Chillers.AbsorptionIndirectSteam chi(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    per=per,
    show_T=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    T1_start=25 + 273.15,
    T2_start=10 + 273.15) "Absorption indirect chiller"

  Buildings.Fluid.Sources.MassFlowSource_T conPum(
    redeclare package Medium = Medium,
    m_flow=per.mCon_flow_nominal,
    T=273.15 + 30,
    nPorts=1)
    "Condenser water pump"

  Buildings.Fluid.Sources.Boundary_pT bouCoo(
    redeclare package Medium = Medium, nPorts=1)
    "Boundary condition for cooling loop"

  Buildings.Fluid.Sources.Boundary_pT heaBou(
    redeclare package Medium = Medium,
    nPorts=1) "Boundary condition for heating"

  Controls.OBC.CDL.Logical.Sources.Constant on(k=true) "On signal"

  Movers.FlowControlled_m_flow pum(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=per.mEva_flow_nominal,
    inputType=Buildings.Fluid.Types.InputType.Continuous,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false) "Chilled water pump"
  Sources.PropertySource_T proSou(
    redeclare package Medium = Medium,
    use_T_in=true) "Cooling load"
  Controls.OBC.CDL.Reals.Sources.Constant TSet(k=273.15 + 10) "Set point"
  Controls.OBC.CDL.Reals.Sources.Ramp mPum_flow(
    height=per.mEva_flow_nominal,
    duration=86400,
    offset=0) "Pump flow rate"
  Controls.OBC.CDL.Reals.Divide QEva_QGen
    "Ratio of cooling provided over required steam"
  Controls.OBC.CDL.Reals.Divide QEva_P
    "Ratio of cooling provided over pump energy"
  Controls.OBC.CDL.Reals.MultiplyByParameter gai(k=-1)
    "Gain to switch sign"
  Controls.OBC.CDL.Reals.Sources.Constant TEnt(k=273.15 + 15)
    "Entering evaporator temperature"
equation
  connect(chi.on, on.y)
  connect(conPum.ports[1], chi.port_a1)
  connect(chi.port_b1, heaBou.ports[1])
  connect(bouCoo.ports[1], pum.port_a)
  connect(proSou.port_a, pum.port_b)
  connect(proSou.port_b, chi.port_a2)
  connect(pum.port_a, chi.port_b2)
  connect(TSet.y, chi.TSet)
  connect(chi.QEva_flow, gai.u)
  connect(QEva_P.u2, chi.P)
  connect(QEva_QGen.u2, chi.QGen_flow)
  connect(gai.y, QEva_P.u1)
  connect(gai.y, QEva_QGen.u1)
  connect(mPum_flow.y, pum.m_flow_in)
  connect(TEnt.y, proSou.T_in)
end AbsorptionIndirectSteamVaryingLoad;


within Buildings.Fluid.Chillers.Examples;
model Carnot_TEva
  "Test model for chiller based on Carnot efficiency and evaporator outlet temperature control signal"
  extends Modelica.Icons.Example;
 package Medium1 = Buildings.Media.Water "Medium model";
 package Medium2 = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator outlet-inlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";
  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal=-100E3
    "Evaporator heat flow rate";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=QEva_flow_nominal/
      dTEva_nominal/4200 "Nominal mass flow rate at chilled water side";

  Buildings.Fluid.Chillers.Carnot_TEva chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m2_flow_nominal=m2_flow_nominal,
    show_T=true,
    QEva_flow_nominal=QEva_flow_nominal,
    allowFlowReversal1=false,
    allowFlowReversal2=false,
    use_eta_Carnot_nominal=true,
    dp1_nominal=6000,
    dp2_nominal=6000) "Chiller model"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    use_T_in=false,
    use_m_flow_in=true,
    T=298.15)
  Buildings.Fluid.Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    m_flow=m2_flow_nominal,
    use_T_in=false,
    T=295.15)
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT sin2(nPorts=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.Sources.Ramp TEvaLvg(
    duration=60,
    startTime=1800,
    offset=273.15 + 6,
    height=10) "Control signal for evaporator leaving temperature"
  Modelica.Blocks.Math.Gain mCon_flow(k=-1/cp1_default/dTEva_nominal)
    "Condenser mass flow rate"
  Modelica.Blocks.Math.Add QCon_flow(k2=-1) "Condenser heat flow rate"

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp1_default=
      Medium1.specificHeatCapacityCp(Medium1.setState_pTX(
      Medium1.p_default,
      Medium1.T_default,
      Medium1.X_default))
    "Specific heat capacity of medium 1 at default medium state";
equation
  connect(sou1.ports[1], chi.port_a1)
  connect(sou2.ports[1], chi.port_a2)
  connect(sin2.ports[1], chi.port_b2)
  connect(TEvaLvg.y, chi.TSet)
  connect(chi.P, QCon_flow.u1)
  connect(chi.QEva_flow, QCon_flow.u2)
  connect(QCon_flow.y, mCon_flow.u)
  connect(mCon_flow.y, sou1.m_flow_in)
  connect(chi.port_b1, sin1.ports[1])
end Carnot_TEva;


within Buildings.Fluid.Chillers.Examples;
model Carnot_y "Test model for chiller based on Carnot_y efficiency"
  extends Modelica.Icons.Example;
 package Medium1 = Buildings.Media.Water "Medium model";
 package Medium2 = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.Power P_nominal=10E3
    "Nominal compressor power (at y=1)";
  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator outlet-inlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";

  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=-P_nominal*
      COPc_nominal/dTEva_nominal/4200
    "Nominal mass flow rate at chilled water side";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=m2_flow_nominal*(
      COPc_nominal + 1)/COPc_nominal
    "Nominal mass flow rate at condenser water wide";

  Buildings.Fluid.Chillers.Carnot_y chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    P_nominal=P_nominal,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    use_eta_Carnot_nominal=true,
    dp1_nominal=6000,
    dp2_nominal=6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    T1_start=303.15,
    T2_start=278.15) "Chiller model"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    use_T_in=true,
    m_flow=m1_flow_nominal,
    T=298.15)
  Buildings.Fluid.Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    use_T_in=true,
    m_flow=m2_flow_nominal,
    T=291.15)
  Buildings.Fluid.Sources.Boundary_pT sin1(
    nPorts=1,
    redeclare package Medium = Medium1)
  Buildings.Fluid.Sources.Boundary_pT sin2(
    nPorts=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.Sources.Ramp uCom(
    height=-1,
    duration=60,
    offset=1,
    startTime=1800) "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TCon_in(
    height=10,
    duration=60,
    offset=273.15 + 20,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEva_in(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
equation
  connect(sou1.ports[1], chi.port_a1)
  connect(sou2.ports[1], chi.port_a2)
  connect(chi.port_b1, sin1.ports[1])
  connect(sin2.ports[1], chi.port_b2)
  connect(TCon_in.y, sou1.T_in)
  connect(TEva_in.y, sou2.T_in)
  connect(uCom.y, chi.y)
end Carnot_y;


Test model for chiller electric EIR

within Buildings.Fluid.Chillers.Examples;
model ElectricEIR "Test model for chiller electric EIR"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Chillers.Examples.BaseClasses.PartialElectric(
      P_nominal=-per.QEva_flow_nominal/per.COP_nominal,
      mEva_flow_nominal=per.mEva_flow_nominal,
      mCon_flow_nominal=per.mCon_flow_nominal,
    sou1(nPorts=1),
    sou2(nPorts=1));

  parameter Data.ElectricEIR.ElectricEIRChiller_McQuay_WSC_471kW_5_89COP_Vanes
    per "Chiller performance data"

  Buildings.Fluid.Chillers.ElectricEIR chi(
       redeclare package Medium1 = Medium1,
       redeclare package Medium2 = Medium2,
       per=per,
       energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
       dp1_nominal=6000,
       dp2_nominal=6000) "Chiller model"

equation
  connect(sou1.ports[1], chi.port_a1)
  connect(chi.port_b1, res1.port_a)
  connect(sou2.ports[1], chi.port_a2)
  connect(chi.port_b2, res2.port_a)
  connect(chi.on, greaterThreshold.y)
  connect(chi.TSet, TSet.y)
end ElectricEIR;


within Buildings.Fluid.Chillers.Examples;
model ElectricEIR_AirCooled
  "Test model for chiller electric EIR with air-cooled condenser"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Chillers.Examples.BaseClasses.PartialElectric_AirCooled(
      P_nominal=-per.QEva_flow_nominal/per.COP_nominal,
      mEva_flow_nominal=per.mEva_flow_nominal,
      mCon_flow_nominal=per.mCon_flow_nominal,
    sou1(nPorts=1),
    sou2(nPorts=1));

  parameter Data.ElectricEIR.ElectricEIRChiller_York_YCAL0033EE_101kW_3_1COP_AirCooled
    per "Chiller performance data"

  Buildings.Fluid.Chillers.ElectricEIR chi(
       redeclare package Medium1 = Medium1,
       redeclare package Medium2 = Medium2,
       per=per,
       energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
       dp1_nominal=6000,
       dp2_nominal=6000) "Chiller model"

equation
  connect(sou1.ports[1], chi.port_a1)
  connect(chi.port_b1, res1.port_a)
  connect(sou2.ports[1], chi.port_a2)
  connect(chi.port_b2, res2.port_a)
  connect(chi.on, greaterThreshold.y)
  connect(chi.TSet, TSet.y)
end ElectricEIR_AirCooled;


within Buildings.Fluid.Chillers.Examples;
model ElectricEIR_HeatRecovery
  "Test model for chiller electric EIR with heat recovery"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Chillers.Examples.BaseClasses.PartialElectric(
      P_nominal=-per.QEva_flow_nominal/per.COP_nominal,
      mEva_flow_nominal=per.mEva_flow_nominal,
      mCon_flow_nominal=per.mCon_flow_nominal,
    sou1(nPorts=1),
    sou2(nPorts=1),
    TSet(
     height=8,
     offset=273.15 + 25));

  parameter Data.ElectricEIR.ElectricEIRChiller_McQuay_WSC_471kW_5_89COP_Vanes
    per "Chiller performance data"

  Buildings.Fluid.Chillers.ElectricEIR chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    have_switchover=true,
    per=per,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp1_nominal=6000,
    dp2_nominal=6000) "Chiller model"

  Controls.OBC.CDL.Logical.Sources.Constant fal(final k=false)
    "Constant false signal"
equation
  connect(sou1.ports[1], chi.port_a1)
  connect(chi.port_b1, res1.port_a)
  connect(sou2.ports[1], chi.port_a2)
  connect(chi.port_b2, res2.port_a)
  connect(chi.on, greaterThreshold.y)
  connect(chi.TSet, TSet.y)
  connect(fal.y, chi.coo)
end ElectricEIR_HeatRecovery;


within Buildings.Fluid.Chillers.Examples;
model ElectricReformulatedEIR
  "Test model for chiller electric reformulated EIR"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Chillers.Examples.BaseClasses.PartialElectric(
      P_nominal=-per.QEva_flow_nominal/per.COP_nominal,
      mEva_flow_nominal=per.mEva_flow_nominal,
      mCon_flow_nominal=per.mCon_flow_nominal,
    sou1(nPorts=1),
    sou2(nPorts=1));

  parameter
    Data.ElectricReformulatedEIR.ReformEIRChiller_McQuay_WSC_471kW_5_89COP_Vanes
    per "Chiller performance data"

  Buildings.Fluid.Chillers.ElectricReformulatedEIR chi(
       redeclare package Medium1 = Medium1,
       redeclare package Medium2 = Medium2,
       per=per,
       energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
       dp1_nominal=6000,
       dp2_nominal=6000) "Chiller model"

equation
  connect(sou1.ports[1], chi.port_a1)
  connect(chi.port_b1, res1.port_a)
  connect(sou2.ports[1], chi.port_a2)
  connect(chi.port_b2, res2.port_a)
  connect(chi.on, greaterThreshold.y)
  connect(TSet.y, chi.TSet)
end ElectricReformulatedEIR;


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


within Buildings.Fluid.Chillers.Examples;
package BaseClasses "Package with base classes for Buildings.Fluid.Chillers.Examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Fluid.Chillers.Examples.BaseClasses;
partial model PartialElectric
  "Base class for test model of chiller electric EIR"
 package Medium1 = Buildings.Media.Water "Medium model";
 package Medium2 = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.Power P_nominal
    "Nominal compressor power (at y=1)";
  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=10
    "Temperature difference evaporator inlet-outlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";
  parameter Modelica.Units.SI.MassFlowRate mEva_flow_nominal
    "Nominal mass flow rate at evaporator";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal
    "Nominal mass flow rate at condenser";

  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium1,
    use_T_in=true,
    m_flow=mCon_flow_nominal,
    T=298.15) "Mass flow source"
  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = Medium2,
    use_T_in=true,
    m_flow=mEva_flow_nominal,
    T=291.15) "Mass flow source"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1) "Pressure source"
  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2,
    nPorts=1) "Pressure source"
  Modelica.Blocks.Sources.Ramp TSet(
    duration=3600,
    startTime=3*3600,
    offset=273.15 + 10,
    height=8) "Set point for leaving chilled water temperature"
  Modelica.Blocks.Sources.Ramp TCon_in(
    height=10,
    offset=273.15 + 20,
    duration=3600,
    startTime=2*3600) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEva_in(
    offset=273.15 + 15,
    height=5,
    startTime=3600,
    duration=3600) "Evaporator inlet temperature"
  Modelica.Blocks.Sources.Pulse pulse(period=3600/2)
    "Pulse signal generator"
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold(threshold=0.5)
    "Greater threshold"
  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium1,
    m_flow_nominal=mCon_flow_nominal,
    dp_nominal=6000) "Flow resistance"
  Buildings.Fluid.FixedResistances.PressureDrop res2(
    dp_nominal=6000,
    redeclare package Medium = Medium2,
    m_flow_nominal=mEva_flow_nominal) "Flow resistance"
equation
  connect(TCon_in.y, sou1.T_in)
  connect(TEva_in.y, sou2.T_in)

  connect(greaterThreshold.u, pulse.y)
  connect(res1.port_b, sin1.ports[1])
  connect(res2.port_b, sin2.ports[1])
end PartialElectric;


within Buildings.Fluid.Chillers.Examples.BaseClasses;
partial model PartialElectric_AirCooled
  "Base class for test model of chiller electric EIR with air-cooled condenser"
 package Medium1 = Buildings.Media.Air "Medium model";
 package Medium2 = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.Power P_nominal
    "Nominal compressor power (at y=1)";
  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=10
    "Temperature difference evaporator inlet-outlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";
  parameter Modelica.Units.SI.MassFlowRate mEva_flow_nominal
    "Nominal mass flow rate at evaporator";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal
    "Nominal mass flow rate at condenser";

  Sources.MassFlowSource_WeatherData sou1(
    redeclare package Medium = Medium1,
    m_flow=mCon_flow_nominal)
    "Weather data"
  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = Medium2,
    use_T_in=true,
    m_flow=mEva_flow_nominal,
    T=291.15) "Mass flow source"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1) "Pressure source"
  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2,
    nPorts=1) "Pressure source"
  Modelica.Blocks.Sources.Ramp TSet(
    duration=3600*6,
    startTime=197.25*24*3600,
    offset=273.15 + 5,
    height=5) "Set point for leaving chilled water temperature"
  Modelica.Blocks.Sources.Ramp TEva_in(
    offset=273.15 + 10,
    height=6,
    startTime=197*24*3600,
    duration=12*3600)
    "Evaporator inlet temperature"
  Modelica.Blocks.Sources.Pulse pulse(period=3600/2)
    "Pulse signal"
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold(threshold=0.5)
    "Greater threshold"
  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium1,
    m_flow_nominal=mCon_flow_nominal,
    dp_nominal=6000) "Flow resistance"
  Buildings.Fluid.FixedResistances.PressureDrop res2(
    dp_nominal=6000,
    redeclare package Medium = Medium2,
    m_flow_nominal=mEva_flow_nominal) "Flow resistance"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource(
        "modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
equation
  connect(TEva_in.y, sou2.T_in)

  connect(greaterThreshold.u, pulse.y)
  connect(res1.port_b, sin1.ports[1])
  connect(res2.port_b, sin2.ports[1])
  connect(weaDat.weaBus, sou1.weaBus)
end PartialElectric_AirCooled;


Reversible chiller using Carnot approach with losses (frost, heat, inertia). Model of a reversible chiller.

within Buildings.Fluid.Chillers.ModularReversible;
model CarnotWithLosses
  "Reversible chiller using Carnot approach with losses (frost, heat, inertia)"
  extends Buildings.Fluid.Chillers.ModularReversible.Modular(
    QHea_flow_nominal=PEle_nominal*refCyc.refCycChiHea.COP_nominal,
    redeclare model RefrigerantCycleChillerHeating =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (
        PEle_nominal=PEle_nominal,
        redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal,
        etaCarnot_nominal=etaCarnot_nominal,
        use_constAppTem=true,
        TAppCon_nominal=TAppCon_nominal,
        TAppEva_nominal=TAppEva_nominal),
    redeclare model RefrigerantCycleChillerCooling =
        Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (
        redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.FunctionalIcingFactor
          iceFacCal(redeclare function icingFactor =
              Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.Functions.wetterAfjei1997),
        TAppCon_nominal=TAppCon_nominal,
        TAppEva_nominal=TAppEva_nominal,
        etaCarnot_nominal=etaCarnot_nominal),
    final allowDifferentDeviceIdentifiers=false,
    redeclare model RefrigerantCycleInertia =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
        (
        final refIneFreConst=1/refIneTimCon,
        final nthOrd=1,
        initType=Modelica.Blocks.Types.Init.InitialOutput));

  parameter Real etaCarnot_nominal=0.3 "Constant Carnot effectiveness";
  parameter Modelica.Units.SI.TemperatureDifference TAppCon_nominal=if
      cpCon < 1500 then 5 else 2
    "Temperature difference between refrigerant and working fluid outlet in condenser"
  parameter Modelica.Units.SI.TemperatureDifference TAppEva_nominal=if
      cpEva < 1500 then 5 else 2
    "Temperature difference between refrigerant and working fluid outlet in evaporator"
  parameter Modelica.Units.SI.Time refIneTimCon = 300
    "Refrigerant cycle inertia time constant for first order delay"
  parameter Integer nthOrd=1 "Order of refrigerant cycle interia"
end CarnotWithLosses;


Large scale water to water chiller

within Buildings.Fluid.Chillers.ModularReversible;
model LargeScaleWaterToWater "Large scale water to water chiller"
  extends Modular(
    dpEva_nominal=datTab.dpEva_nominal*scaFac^2,
    dpCon_nominal=datTab.dpCon_nominal*scaFac^2,
    final dTEva_nominal=-QCoo_flow_nominal/cpEva/mEva_flow_nominal,
    final dTCon_nominal=(PEle_nominal - QCoo_flow_nominal)/cpCon/mCon_flow_nominal,
    redeclare replaceable package MediumCon = Buildings.Media.Water,
    redeclare replaceable package MediumEva = Buildings.Media.Water,
    final GEvaIns=0,
    final GEvaOut=0,
    final CEva=0,
    final use_evaCap=false,
    final GConIns=0,
    final GConOut=0,
    final CCon=0,
    final TConHea_nominal=0,
    final TEvaHea_nominal=0,
    final use_conCap=false,
        redeclare replaceable
    Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021 safCtrPar
      constrainedby
      Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Generic(
      final tabUppHea=datTab.tabLowBou,
      final tabLowCoo=datTab.tabLowBou,
      final use_TEvaOutCoo=datTab.use_TEvaOutForOpeEnv,
      final use_TConOutCoo=datTab.use_TConOutForOpeEnv),
    redeclare model RefrigerantCycleInertia =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.NoInertia,
    redeclare model RefrigerantCycleChillerHeating =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.NoHeating,
    redeclare model RefrigerantCycleChillerCooling =
        Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D (
        redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal, datTab=datTab),
    final use_rev=false,
    final QHea_flow_nominal=0,
    final mCon_flow_nominal=autCalMasCon_flow,
    final mEva_flow_nominal=autCalMasEva_flow,
    final tauCon=autCalVCon*rhoCon/autCalMasCon_flow,
    final tauEva=autCalVEva*rhoEva/autCalMasEva_flow);
  final parameter Real scaFac=refCyc.refCycChiCoo.scaFac "Scaling factor of chiller";

  extends Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.LargeScaleWaterToWaterDeclarations(
    final autCalMasCon_flow=max(5E-5*abs(QCoo_flow_nominal) + 0.3161, autCalMMin_flow),
    final autCalMasEva_flow=max(5E-5*abs(QCoo_flow_nominal) - 0.5662, autCalMMin_flow),
    final autCalVCon=max(2E-7*abs(QCoo_flow_nominal) - 84E-4, autCalVMin),
    final autCalVEva=max(1E-7*abs(QCoo_flow_nominal) - 66E-4, autCalVMin));
  replaceable parameter
    Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic
    datTab constrainedby Data.TableData2D.Generic "Data Table of Chiller"
end LargeScaleWaterToWater;


Grey-box model for reversible and non-reversible chillers. Model of a reversible, modular chiller.
  This models allows combining any of the available modules
  for refrigerant heating or cooling cycles, inertias,
  heat losses, and safety controls.
  All features are optional.

within Buildings.Fluid.Chillers.ModularReversible;
model Modular
  "Grey-box model for reversible and non-reversible chillers"
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.PartialReversibleRefrigerantMachine(
    final use_COP=use_rev,
    final use_EER=true,
    con(preDro(m_flow(nominal=-QCoo_flow_nominal/1000/10))),
    eva(preDro(m_flow(nominal=-QCoo_flow_nominal/1000/10))),
    safCtr(redeclare
        Buildings.Fluid.Chillers.ModularReversible.Controls.Safety.OperationalEnvelope
        opeEnv),
    final PEle_nominal=refCyc.refCycChiCoo.PEle_nominal,
    mEva_flow_nominal=-QCoo_flow_nominal/(dTEva_nominal*cpEva),
    mCon_flow_nominal=(PEle_nominal - QCoo_flow_nominal)/(dTCon_nominal*cpCon),
    use_rev=false,
    redeclare final Buildings.Fluid.Chillers.ModularReversible.BaseClasses.RefrigerantCycle refCyc(
      redeclare model RefrigerantCycleChillerCooling = RefrigerantCycleChillerCooling,
      redeclare model RefrigerantCycleChillerHeating = RefrigerantCycleChillerHeating,
      final allowDifferentDeviceIdentifiers=allowDifferentDeviceIdentifiers));
  parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal(max=0)
    "Nominal cooling capcaity"
  parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=0
    "Nominal heating capacity"

  replaceable model RefrigerantCycleChillerCooling =
      Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle
      (PEle_nominal=0)
    constrainedby
    Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
       final useInChi=true,
       final TCon_nominal=TConCoo_nominal,
       final TEva_nominal=TEvaCoo_nominal,
       final QCoo_flow_nominal=QCoo_flow_nominal,
       final cpCon=cpCon,
       final cpEva=cpEva)
  "Refrigerant cycle module for the cooling mode"

  replaceable model RefrigerantCycleChillerHeating =
      Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.NoHeating
      (PEle_nominal=PEle_nominal)
       constrainedby
    Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle(
       final useInHeaPum=false,
       final TCon_nominal=TEvaHea_nominal,
       final TEva_nominal=TConHea_nominal,
       final QHea_flow_nominal=QHea_flow_nominal,
       final cpCon=cpCon,
       final cpEva=cpEva)
  "Refrigerant cycle module for the heating mode"
  parameter Modelica.Units.SI.Temperature TEvaCoo_nominal
    "Nominal temperature of the cooled fluid"
  parameter Modelica.Units.SI.Temperature TConCoo_nominal
    "Nominal temperature of the heated fluid"
  parameter Modelica.Units.SI.Temperature TEvaHea_nominal
    "Nominal temperature of the heated fluid"
  parameter Modelica.Units.SI.Temperature TConHea_nominal
    "Nominal temperature of the cooled fluid"

  Modelica.Blocks.Interfaces.BooleanInput coo if not use_busConOnl and use_rev
    "=true for cooling, =false for heating"
  Modelica.Blocks.Sources.BooleanConstant conCoo(final k=true)
    if not use_busConOnl and not use_rev
    "Locks the device in cooling mode if designated to be not reversible"
  Modelica.Blocks.Logical.Not notCoo "Not cooling is heating"
equation
  connect(conCoo.y, sigBus.coo)
  connect(coo, sigBus.coo)
  connect(eff.QUse_flow, refCycIneEva.y)
  connect(eff.hea, notCoo.y)
  connect(notCoo.u, sigBus.coo)
end Modular;


within Buildings.Fluid.Chillers;
package ModularReversible "Package for reversible and non-reversible chillers using a modular model approach"
extends Modelica.Icons.VariantsPackage;
end ModularReversible;


within Buildings.Fluid.Chillers.ModularReversible;
package UsersGuide
  "User's Guide for modular reversible heat pump and chiller models"
  extends Modelica.Icons.Information;
end UsersGuide;


within Buildings.Fluid.Chillers.ModularReversible;
package BaseClasses "Package with base classes for Buildings.Fluid.Chillers.ModularReversible"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Refrigerant cycle model of a chiller. Modular refrigerant cycle model for chiller applications used in
  the model
  Buildings.Fluid.Chillers.ModularReversible.Modular and extending models
  of the modular approach.

within Buildings.Fluid.Chillers.ModularReversible.BaseClasses;
model RefrigerantCycle "Refrigerant cycle model of a chiller"
  extends Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.PartialModularRefrigerantCycle;

  parameter Boolean allowDifferentDeviceIdentifiers=false
    "if use_rev=true, device data for cooling and heating need to entered. Set allowDifferentDeviceIdentifiers=true to allow different device identifiers devIde"

  replaceable model RefrigerantCycleChillerCooling =
      Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.NoCooling(
        useInChi=true)
    constrainedby
      Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle
    "Replaceable model for refrigerant cycle of a chiller in main operation mode"

  replaceable model RefrigerantCycleChillerHeating =
      Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.NoHeating(
        useInHeaPum=true)
    constrainedby
      Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle
    "Replaceable model for refrigerant cycle of a chiller in reversed operation mode"

  RefrigerantCycleChillerCooling refCycChiCoo
    "Refrigerant cycle instance for cooling"
  RefrigerantCycleChillerHeating refCycChiHea
    "Refrigerant cycle instance for heating"

protected
  parameter String devIde =
    if use_rev then refCycChiHea.devIde else refCycChiCoo.devIde
    "Data source for refrigerant cycle";

initial algorithm
  if not allowDifferentDeviceIdentifiers then
    assert(
      devIde == refCycChiCoo.devIde,
      "In " + getInstanceName() + ": Device identifiers devIde for reversible operation are not equal.
      Cooling device identifier is '" + refCycChiCoo.devIde + "' but heating is '"
      + devIde + "'. To allow this, set 'allowDifferentDeviceIdentifiers=true'.",
      AssertionLevel.error);
  end if;
equation
  connect(pasTrhModSet.u, sigBus.coo);

  connect(sigBus,refCycChiHea.sigBus)
  connect(sigBus,refCycChiCoo.sigBus)

  connect(swiPEle.u2, sigBus.coo)
  connect(swiQEva.u2, sigBus.coo)
  connect(swiQCon.u2, sigBus.coo)
  connect(refCycChiCoo.QEva_flow, swiQEva.u1)
  connect(refCycChiCoo.QCon_flow, swiQCon.u1)
  connect(refCycChiCoo.PEle, swiPEle.u1)
  connect(refCycChiHea.PEle, swiPEle.u3)
  connect(refCycChiHea.QCon_flow, swiQEva.u3)
  connect(refCycChiHea.QEva_flow, swiQCon.u3)
end RefrigerantCycle;


Package of control sequences

within Buildings.Fluid.Chillers.ModularReversible;
package Controls "Package of control sequences"
  extends Modelica.Icons.Package;
end Controls;


Indicates if the chiller operation is within a defined envelope. Model to check if the operating conditions of a chiller are inside
  the given boundaries. If not, the heat pump or chiller will switch off.

within Buildings.Fluid.Chillers.ModularReversible.Controls.Safety;
model OperationalEnvelope
  "Indicates if the chiller operation is within a defined envelope"
  extends
    HeatPumps.ModularReversible.Controls.Safety.BaseClasses.PartialOperationalEnvelope;
  Modelica.Blocks.Logical.Not notCoo "=true for heating"
equation
    if use_TEvaOutHea then
    connect(bouMapHea.TUseSid, sigBus.TEvaOutMea)
  else
    connect(bouMapHea.TUseSid, sigBus.TEvaInMea)
  end if;
  if use_TConOutCoo then
    connect(bouMapCoo.TAmbSid, sigBus.TConOutMea)
  else
    connect(bouMapCoo.TAmbSid, sigBus.TConInMea)
  end if;
  if use_TConOutHea then
    connect(bouMapHea.TAmbSid, sigBus.TConOutMea)
  else
    connect(bouMapHea.TAmbSid, sigBus.TConInMea)
  end if;
  if use_TEvaOutCoo then
    connect(bouMapCoo.TUseSid, sigBus.TEvaOutMea)
  else
    connect(bouMapCoo.TUseSid, sigBus.TEvaInMea)
  end if;
  connect(notCoo.y, swiHeaCoo.u2)
  connect(notCoo.u, sigBus.coo)
end OperationalEnvelope;


within Buildings.Fluid.Chillers.ModularReversible.Controls;
package Safety "Contains typical safety controllers for chillers"
  extends Modelica.Icons.Package;
end Safety;


Package for data records

within Buildings.Fluid.Chillers.ModularReversible;
package Data "Package for data records"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Package with two-dimensional data

within Buildings.Fluid.Chillers.ModularReversible.Data;
package TableData2D "Package with two-dimensional data"
  extends Modelica.Icons.MaterialPropertiesPackage;
end TableData2D;


Package for EN15411 data records

within Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D;
package EN14511 "Package for EN15411 data records"
end EN14511;


A2W Vitocal 251 by Viessmann. Data from the planning book (Planungshandbuch) from Viessmann.


within Buildings.Fluid.Chillers.ModularReversible.Examples;
model CarnotWithLosses
  "Example for reversible Carnot chiller model"
  extends Modelica.Icons.Example;
  package MediumCon = Buildings.Media.Water "Medium model for condenser";
  package MediumEva = Buildings.Media.Water "Medium model for evaporator";

  Buildings.Fluid.Chillers.ModularReversible.CarnotWithLosses chi(
    redeclare package MediumCon = MediumCon,
    redeclare package MediumEva = MediumEva,
    QCoo_flow_nominal=-30000,
    redeclare
      Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar(
      minOffTime=100,
      use_maxCycRat=false,
      tabUppHea=[263.15,313.15; 333.15,313.15],
      tabLowCoo=[263.15,283.15; 333.15,283.15],
      use_TEvaOutCoo=true),
    TConCoo_nominal=313.15,
    dpCon_nominal(displayUnit="Pa") = 6000,
    use_conCap=false,
    CCon=0,
    GConOut=0,
    GConIns=0,
    TEvaCoo_nominal=278.15,
    dTEva_nominal(displayUnit="K") = 10,
    dTCon_nominal(displayUnit="K") = 5,
    dpEva_nominal(displayUnit="Pa") = 6000,
    use_evaCap=false,
    CEva=0,
    GEvaOut=0,
    GEvaIns=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    QHea_flow_nominal=40000,
    TConHea_nominal=293.15,
    TEvaHea_nominal=303.15)
                 "Chiller instance with reversbile Carnot approach"
  Buildings.Fluid.Sources.MassFlowSource_T souCon(
    nPorts=1,
    redeclare package Medium = MediumCon,
    use_T_in=true,
    m_flow=chi.mCon_flow_nominal,
    T=298.15) "Condenser source"
  Buildings.Fluid.Sources.MassFlowSource_T souEva(
    nPorts=1,
    redeclare package Medium = MediumEva,
    use_T_in=true,
    m_flow=chi.mEva_flow_nominal,
    T=291.15) "Evaporator source"
  Buildings.Fluid.Sources.Boundary_pT sinCon(nPorts=1, redeclare package Medium =
        MediumCon) "Condenser sink"
  Buildings.Fluid.Sources.Boundary_pT sinEva(nPorts=1, redeclare package Medium =
        MediumEva) "Evaporator sink"
  Modelica.Blocks.Sources.SawTooth ySet(
    amplitude=-1,
    period=500,
    offset=1,
    startTime=500)  "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
equation
  connect(souCon.ports[1], chi.port_a1)
  connect(souEva.ports[1], chi.port_a2)
  connect(chi.port_b1, sinCon.ports[1])
  connect(sinEva.ports[1], chi.port_b2)
  connect(TConIn.y, souCon.T_in)
  connect(TEvaIn.y, souEva.T_in)
  connect(ySet.y, chi.ySet)
end CarnotWithLosses;


within Buildings.Fluid.Chillers.ModularReversible.Examples;
model LargeScaleWaterToWater
  "Example for large scale water to water chiller"
  extends Modelica.Icons.Example;
  package MediumCon = Buildings.Media.Water "Medium model for condenser";
  package MediumEva = Buildings.Media.Water "Medium model for evaporator";

  Buildings.Fluid.Chillers.ModularReversible.LargeScaleWaterToWater chi(
    redeclare
      Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.EN14511.Carrier30XWP1012_1MW
      datTab,
    redeclare Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar,
    redeclare package MediumCon = MediumCon,
    redeclare package MediumEva = MediumEva,
    QCoo_flow_nominal=-1000000,
    TConCoo_nominal=313.15,
    dpCon_nominal(displayUnit="Pa") = 6000,
    TEvaCoo_nominal=278.15,
    dpEva_nominal(displayUnit="Pa") = 6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Large scale water to water chiller"
  Buildings.Fluid.Sources.MassFlowSource_T souCon(
    nPorts=1,
    redeclare package Medium = MediumCon,
    use_T_in=true,
    m_flow=chi.mCon_flow_nominal,
    T=298.15) "Condenser source"
  Buildings.Fluid.Sources.MassFlowSource_T souEva(
    nPorts=1,
    redeclare package Medium = MediumEva,
    use_T_in=true,
    m_flow=chi.mEva_flow_nominal,
    T=291.15) "Evaporator source"
  Buildings.Fluid.Sources.Boundary_pT sinCon(nPorts=1, redeclare package Medium =
        MediumCon) "Condenser sink"
  Buildings.Fluid.Sources.Boundary_pT sinEva(nPorts=1, redeclare package Medium =
        MediumEva) "Evaporator sink"
  Modelica.Blocks.Sources.Ramp ySet(
    height=-1,
    duration=900,
    offset=1,
    startTime=1800) "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
equation
  connect(souCon.ports[1], chi.port_a1)
  connect(souEva.ports[1], chi.port_a2)
  connect(chi.port_b1, sinCon.ports[1])
  connect(sinEva.ports[1], chi.port_b2)
  connect(TConIn.y, souCon.T_in)
  connect(TEvaIn.y, souEva.T_in)
  connect(ySet.y, chi.ySet)
end LargeScaleWaterToWater;


Example for modular reversible chiller

within Buildings.Fluid.Chillers.ModularReversible.Examples;
model Modular
  "Example for modular reversible chiller"
  extends Modelica.Icons.Example;
  package MediumCon = Buildings.Media.Air "Medium model for condenser";
  package MediumEva = Buildings.Media.Water "Medium model for evaporator";

  Buildings.Fluid.Chillers.ModularReversible.Modular chi(
    redeclare package MediumCon = MediumCon,
    redeclare package MediumEva = MediumEva,
    use_rev=true,
    allowDifferentDeviceIdentifiers=true,
    QCoo_flow_nominal=-30000,
    redeclare model RefrigerantCycleInertia =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
        (
        refIneFreConst=1/300,
        nthOrd=1,
        initType=Modelica.Blocks.Types.Init.InitialState),
    redeclare
      Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar(minOffTime=100, use_opeEnv=false),
    TConCoo_nominal=313.15,
    dpCon_nominal(displayUnit="Pa") = 6000,
    use_conCap=false,
    CCon=0,
    GConOut=0,
    GConIns=0,
    TEvaCoo_nominal=278.15,
    dTEva_nominal=5,
    dTCon_nominal=5,
    dpEva_nominal(displayUnit="Pa") = 6000,
    use_evaCap=false,
    CEva=0,
    GEvaOut=0,
    GEvaIns=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    QHea_flow_nominal=30000,
    redeclare model RefrigerantCycleChillerCooling =
        Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (etaCarnot_nominal=0.35),
    redeclare model RefrigerantCycleChillerHeating =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
          redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal, datTab=
            Buildings.Fluid.HeatPumps.ModularReversible.Data.TableData2D.EN14511.Vitocal251A08()),
    TEvaHea_nominal=303.15,
    TConHea_nominal=298.15)
                 "Modular reversible chiller instance"
  Buildings.Fluid.Sources.MassFlowSource_T souCon(
    nPorts=1,
    redeclare package Medium = MediumCon,
    use_T_in=true,
    m_flow=chi.mCon_flow_nominal,
    T=298.15) "Condenser source"
  Buildings.Fluid.Sources.MassFlowSource_T souEva(
    nPorts=1,
    redeclare package Medium = MediumEva,
    use_T_in=true,
    m_flow=chi.mEva_flow_nominal,
    T=291.15) "Evaporator source"
  Buildings.Fluid.Sources.Boundary_pT sinCon(nPorts=1, redeclare package Medium =
        MediumCon) "Condenser sink"
  Buildings.Fluid.Sources.Boundary_pT sinEva(nPorts=1, redeclare package Medium =
        MediumEva) "Evaporator sink"
  Modelica.Blocks.Sources.SawTooth ySet(
    amplitude=-1,
    period=500,
    offset=1,
    startTime=500)  "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
  Modelica.Blocks.Sources.BooleanStep chiCoo(startTime=2100, startValue=true)
    "Chilling mode on"
equation
  connect(souCon.ports[1], chi.port_a1)
  connect(souEva.ports[1], chi.port_a2)
  connect(chi.port_b1, sinCon.ports[1])
  connect(sinEva.ports[1], chi.port_b2)
  connect(TConIn.y, souCon.T_in)
  connect(TEvaIn.y, souEva.T_in)
  connect(ySet.y, chi.ySet)
  connect(chiCoo.y, chi.coo)
end Modular;


within Buildings.Fluid.Chillers.ModularReversible;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Carnot EER with a constant Carnot effectiveness. This model uses a constant Carnot effectiveness approach
  to compute the efficiency of the chiller.

within Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle;
model ConstantCarnotEffectiveness "Carnot EER with a constant Carnot effectiveness"
  extends
    Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
      useInChi=true,
      PEle_nominal=-QCoo_flow_nominal/EER_nominal,
      devIde="ConstantCarnotEffectiveness");
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialCarnot(
     TAppCon_nominal=if cpCon < 1500 then 5 else 2,
     TAppEva_nominal=if cpEva < 1500 then 5 else 2,
     final useForChi=true,
     final QEva_flow_nominal=QCoo_flow_nominal,
     final QCon_flow_nominal=PEle_nominal-QCoo_flow_nominal,
     constPEle(final k=PEle_nominal),
    proQUse_flow(nu=4));
  parameter Real EER_nominal(
    min=0,
    final unit="1") = etaCarnot_nominal*(TEva_nominal - TAppEva_nominal)/(
    TCon_nominal + TAppCon_nominal - (TEva_nominal - TAppEva_nominal))
    "Nominal EER";

  Modelica.Blocks.Sources.Constant constNegOne(final k=-1)
    "Negative one to negative evaporator heat flow rate"
equation
  connect(swiQUse.u2, sigBus.onOffMea)
  connect(swiPEle.y, redQCon.u2)
  connect(swiPEle.y, PEle)
  connect(swiPEle.u2, sigBus.onOffMea)
  connect(pasThrYMea.u, sigBus.yMea)
  if useInChi then
    connect(pasThrTCon.u, sigBus.TConOutMea)
    connect(pasThrTEva.u, sigBus.TEvaOutMea)
  else
    connect(pasThrTCon.u, sigBus.TEvaOutMea)
    connect(pasThrTEva.u, sigBus.TConOutMea)
  end if;
  connect(swiQUse.y, proRedQEva.u2)
  connect(constNegOne.y, proQUse_flow.u[4])
end ConstantCarnotEffectiveness;


within Buildings.Fluid.Chillers.ModularReversible;
package RefrigerantCycle "Package for chiller refrigerant cycle modules"
   extends Modelica.Icons.MaterialPropertiesPackage;
end RefrigerantCycle;


Performance data based on condenser outlet and evaporator inlet temperature. This model uses two-dimensional table data typically given
  by manufacturers as required by e.g. European Norm 14511
  or ASHRAE 205 to calculate
  QEva_flow and PEle.

within Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle;
model TableData2D
  "Performance data based on condenser outlet and evaporator inlet temperature"
  extends
    Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
    final devIde=datTab.devIde,
    PEle_nominal=Modelica.Blocks.Tables.Internal.getTable2DValueNoDer2(
        tabIdePEle,
        TEva_nominal,
        TCon_nominal) * scaFac);
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialTableData2D(
    final useInRevDev=not useInChi,
    final use_TConOutForTab=datTab.use_TConOutForTab,
    final use_TEvaOutForTab=datTab.use_TEvaOutForTab,
    tabQUse_flow(final table=datTab.tabQEva_flow),
    tabPEle(final table=datTab.tabPEle),
    scaFac=QCoo_flow_nominal/QCooNoSca_flow_nominal,
    mEva_flow_nominal=datTab.mEva_flow_nominal*scaFac,
    mCon_flow_nominal=datTab.mCon_flow_nominal*scaFac,
    final valTabQEva_flow = {{-tabQUse_flow.table[j, i] for i in 2:numCol} for j in 2:numRow},
    final valTabQCon_flow = valTabQEva_flow .+ valTabPEle,
    final mCon_flow_max=max(valTabQCon_flow) * scaFac / cpCon / dTMin,
    final mCon_flow_min=min(valTabQCon_flow) * scaFac / cpCon / dTMax,
    final mEva_flow_min=min(valTabQEva_flow) * scaFac / cpEva / dTMax,
    final mEva_flow_max=max(valTabQEva_flow) * scaFac / cpEva / dTMin);
  parameter Modelica.Units.SI.HeatFlowRate QCooNoSca_flow_nominal=
        Modelica.Blocks.Tables.Internal.getTable2DValueNoDer2(
        tabIdeQUse_flow,
        TEva_nominal,
        TCon_nominal)
    "Unscaled nominal cooling capacity "
  replaceable parameter Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic datTab
    "Data Table of Chiller"

equation

  connect(scaFacTimPel.y, PEle)
  connect(scaFacTimPel.y, redQCon.u2)
  connect(scaFacTimQUse_flow.y, proRedQEva.u2)
  connect(yMeaTimScaFac.u1, sigBus.yMea)
  connect(reaPasThrTEvaOut.u, sigBus.TEvaOutMea)
  connect(reaPasThrTEvaIn.u, sigBus.TEvaInMea)
  connect(reaPasThrTConIn.u, sigBus.TConInMea)
  connect(reaPasThrTConOut.u, sigBus.TConOutMea)

  if useInChi then
    connect(reaPasThrTConOut.y, tabPEle.u2)
    connect(reaPasThrTConIn.y, tabPEle.u2)
    connect(reaPasThrTConIn.y, tabQUse_flow.u2)
    connect(reaPasThrTConOut.y, tabQUse_flow.u2)
    connect(reaPasThrTEvaOut.y, tabQUse_flow.u1)
    connect(reaPasThrTEvaIn.y, tabQUse_flow.u1)
    connect(reaPasThrTEvaOut.y, tabPEle.u1)
    connect(reaPasThrTEvaIn.y, tabPEle.u1)
  else
    connect(reaPasThrTConOut.y, tabPEle.u1)
    connect(reaPasThrTConOut.y, tabQUse_flow.u1)
    connect(reaPasThrTConIn.y, tabQUse_flow.u1)
    connect(reaPasThrTConIn.y, tabPEle.u1)
    connect(reaPasThrTEvaOut.y, tabPEle.u2)
    connect(reaPasThrTEvaOut.y, tabQUse_flow.u2)
    connect(reaPasThrTEvaIn.y, tabQUse_flow.u2)
    connect(reaPasThrTEvaIn.y, tabPEle.u2)
  end if;
end TableData2D;


Placeholder to disable cooling. Using this model, the chiller will always be off.
  This option is mainly used to avoid warnings about
  partial model which must be replaced.

within Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses;
model NoCooling
  "Placeholder to disable cooling"
  extends PartialChillerCycle(
    TEva_nominal=273.15,
    TCon_nominal=273.15,
    cpEva=4184,
    cpCon=4184,
    PEle_nominal=0,
    redeclare final
      Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
      iceFacCal,
    devIde="NoCooling",
    QCoo_flow_nominal=0);

  Modelica.Blocks.Sources.Constant const(final k=0) "Zero energy flows"
equation
  connect(const.y, redQCon.u2)
  connect(const.y, PEle)
  connect(const.y, proRedQEva.u2)
end NoCooling;


within Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle;
package BaseClasses "Package with partial classes of performance Data"
end BaseClasses;


Partial model of refrigerant cycle used for chiller applications. Partial refrigerant cycle model for chillers.
  It adds the specification for frosting calculation
  and restricts to the intended choices under
  choicesAllMatching.

within Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses;
partial model PartialChillerCycle
  "Partial model of refrigerant cycle used for chiller applications"
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialRefrigerantCycle;
  parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal
    "Nominal cooling capacity"
  parameter Boolean useInChi
    "=false to indicate that this model is used as a heat pump";
equation
  connect(iceFacCal.iceFac, sigBus.iceFacChiMea)
end PartialChillerCycle;


Example using the Carnot model approach

within Buildings.Fluid.Chillers.ModularReversible.Validation;
model Carnot_y "Example using the Carnot model approach"
  extends Buildings.Fluid.HeatPumps.ModularReversible.Validation.Comparative.BaseClasses.PartialComparison(
    m1_flow_nominal=chi.m1_flow_nominal,
    m2_flow_nominal=chi.m2_flow_nominal,
    sin2(nPorts=1),
    sou2(nPorts=1),
    sin1(nPorts=1),
    sou1(nPorts=1));
  extends Modelica.Icons.Example;
  Buildings.Fluid.Chillers.Carnot_y chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    etaCarnot_nominal=etaCarnot_nominal,
    TCon_nominal=TCon_nominal,
    TEva_nominal=TEva_nominal,
    tau1=tau1,
    tau2=tau2,
    P_nominal=QUse_flow_nominal/chi.COP_nominal,
    dTEva_nominal=-dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    use_eta_Carnot_nominal=false,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    T1_start=T1_start,
    T2_start=T2_start)
                     "Chiller model"

equation
  connect(sin2.ports[1], chi.port_b2)
  connect(chi.port_a2, sou2.ports[1])
  connect(chi.port_b1, sin1.ports[1])
  connect(chi.port_a1, sou1.ports[1])
  connect(chi.y, uCom.y)
end Carnot_y;


Validation case for modular Carnot approach. Validation case for
Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness.

within Buildings.Fluid.Chillers.ModularReversible.Validation;
model ConstantCarnotEffectiveness
  "Validation case for modular Carnot approach"
  extends BaseClasses.PartialModularComparison(chi(redeclare model
        RefrigerantCycleChillerCooling =
          Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
          (etaCarnot_nominal=etaCarnot_nominal)));
  extends Modelica.Icons.Example;
end ConstantCarnotEffectiveness;


Package for model validation

within Buildings.Fluid.Chillers.ModularReversible;
package Validation "Package for model validation"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation case for table data approach. Validation case for
Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D.

within Buildings.Fluid.Chillers.ModularReversible.Validation;
model TableData2D "Validation case for table data approach"
  extends BaseClasses.PartialModularComparison(
    TEva_nominal=TEvaIn_nominal,
    TCon_nominal=TConIn_nominal,
    chi(redeclare model RefrigerantCycleChillerCooling =
          Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D (
            datTab(
            tabPEle=[0,293.15,303.15; 288.15,14122.8,14122.8; 298.15,14122.8,14122.8],
            mCon_flow_nominal=m1_flow_nominal,
            mEva_flow_nominal=m2_flow_nominal,
            dpCon_nominal=0,
            dpEva_nominal=0,
            devIde="CarnotTableData",
            use_TEvaOutForTab=false,
            use_TConOutForTab=false,
            tabQEva_flow=[0,293.15,303.15; 288.15,-35499.7,-30000; 298.15,0,-36220.8],
            tabLowBou=[273.15,273.15; 273.15,273.15],
            use_TEvaOutForOpeEnv=false,
            use_TConOutForOpeEnv=false))));

  extends Modelica.Icons.Example;
end TableData2D;


Package with partial validation models

within Buildings.Fluid.Chillers.ModularReversible.Validation;
package BaseClasses "Package with partial validation models"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Fluid.Chillers.ModularReversible.Validation.BaseClasses;
partial model PartialModularComparison
  "Partial model for comparison to the Carnot model"
  extends Buildings.Fluid.HeatPumps.ModularReversible.Validation.Comparative.BaseClasses.PartialComparison(
    m1_flow_nominal=chi.mCon_flow_nominal,
    m2_flow_nominal=chi.mEva_flow_nominal,
    sou1(nPorts=1),
    sin2(nPorts=1),
    sou2(nPorts=1),
    sin1(nPorts=1));

  Modular chi(
    redeclare final package MediumCon = Medium1,
    redeclare final package MediumEva = Medium2,
    QCoo_flow_nominal=-QUse_flow_nominal,
    redeclare final model RefrigerantCycleInertia =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.NoInertia,
    final use_rev=false,
    final use_intSafCtr=false,
    final tauCon=tau1,
    final TConCoo_nominal=TCon_nominal,
    final dTCon_nominal=dTCon_nominal,
    final dpCon_nominal=dp1_nominal,
    final use_conCap=false,
    final CCon=0,
    final GConOut=0,
    final TEvaHea_nominal=0,
    final TConHea_nominal=0,
    final GConIns=0,
    final tauEva=tau2,
    final TEvaCoo_nominal=TEva_nominal,
    final dTEva_nominal=dTEva_nominal,
    final dpEva_nominal=dp2_nominal,
    final use_evaCap=false,
    final CEva=0,
    final GEvaOut=0,
    final GEvaIns=0,
    final TCon_start=T1_start,
    final TEva_start=T2_start,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Modular chiller model"

equation
  connect(chi.port_a1, sou1.ports[1])
  connect(chi.port_b2, sin2.ports[1])
  connect(chi.port_a2, sou2.ports[1])
  connect(chi.port_b1, sin1.ports[1])
  connect(chi.ySet, uCom.y)
end PartialModularComparison;


Validation with EnergyPlus model

within Buildings.Fluid.Chillers.Validation;
model AbsorptionIndirectSteam_EnergyPlus
  "Validation with EnergyPlus model"
  package Medium = Buildings.Media.Water "Medium model";

  parameter Data.AbsorptionIndirectSteam.Generic per(
    QEva_flow_nominal=-10000,
    P_nominal=150,
    PLRMax=1,
    PLRMin=0.15,
    mEva_flow_nominal=0.247,
    mCon_flow_nominal=1.1,
    dpEva_nominal=0,
    dpCon_nominal=0,
    capFunEva={0.690571,0.065571,-0.00289,0},
    capFunCon={0.245507,0.023614,0.0000278,0.000013},
    genHIR={0.18892,0.968044,1.119202,-0.5034},
    EIRP={1,0,0},
    genConT={0.712019,-0.00478,0.000864,-0.000013},
    genEvaT={0.995571,0.046821,-0.01099,0.000608})
     "Chiller performance data"

  Buildings.Fluid.Chillers.AbsorptionIndirectSteam absChi(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    per=per,
    show_T=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    T1_start=25 + 273.15,
    T2_start=10 + 273.15) "Absorption indirect chiller"

  Buildings.Fluid.Sources.MassFlowSource_T conPum(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    m_flow=per.mCon_flow_nominal,
    use_T_in=true,
    nPorts=1)
    "Condenser water pump"

  Buildings.Fluid.Sources.MassFlowSource_T evaPum(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    m_flow=per.mEva_flow_nominal,
    nPorts=1,
    use_T_in=true)
    "Evaporator water pump"

  Buildings.Fluid.Sources.Boundary_pT cooVol(
    redeclare package Medium = Medium,
    nPorts=1)
     "Volume for cooling load"

  Buildings.Fluid.Sources.Boundary_pT heaVol(
    redeclare package Medium = Medium,
    nPorts=1)
     "Volume for heating load"

  Modelica.Blocks.Math.RealToBoolean realToBoolean(threshold=1)

  Modelica.Blocks.Sources.CombiTimeTable datRea(
    tableOnFile=true,
    fileName=ModelicaServices.ExternalReferences.loadResource(
        "modelica://Buildings/Resources/Data/Fluid/Chillers/Validation/IndirectAbsorptionChiller/IndirectAbsorptionChiller.dat"),
    columns=2:11,
    tableName="EnergyPlus",
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments)
    "Reader for \"IndirectAbsorptionChiller.idf\" EnergyPlus example results"

  Modelica.Blocks.Sources.RealExpression QGen_EP(y=datRea.y[10])
    "EnergyPlus results: generator heat flow rate"
  Modelica.Blocks.Sources.RealExpression QCon_EP(y=datRea.y[6])
    "EnergyPlus results: condenser heat flow rate"
  Modelica.Blocks.Sources.RealExpression QEva_EP(y=-1*datRea.y[2])
    "EnergyPlus results: evaporator heat flow rate"

  Controls.OBC.UnitConversions.From_degC TConIn "Condenser inlet temperature"
  Controls.OBC.UnitConversions.From_degC TEvaSet
    "Evaporator setpoint temperature"
  Controls.OBC.UnitConversions.From_degC TEvaIn "Evaporator inlet temperature"
equation
  connect(evaPum.ports[1], absChi.port_a2)
  connect(absChi.on, realToBoolean.y)
  connect(conPum.ports[1], absChi.port_a1)
  connect(absChi.port_b1, heaVol.ports[1])
  connect(absChi.port_b2, cooVol.ports[1])
  connect(datRea.y[1], realToBoolean.u)
  connect(datRea.y[5], evaPum.m_flow_in)
  connect(datRea.y[9], conPum.m_flow_in)
  connect(datRea.y[7], TConIn.u)
  connect(TConIn.y, conPum.T_in)
  connect(datRea.y[4], TEvaSet.u)
  connect(TEvaSet.y, absChi.TSet)
  connect(datRea.y[3], TEvaIn.u)
  connect(TEvaIn.y, evaPum.T_in)
end AbsorptionIndirectSteam_EnergyPlus;


within Buildings.Fluid.Chillers.Validation;
model CarnotVerifyCOP
  "Test model to verify the COP computation for non-zero approach temperatures"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Water "Medium model";

  parameter Real COP_nominal = 3 "Coefficient of performance";

  parameter Modelica.Units.SI.Temperature TCon_nominal=273.15 + 30
    "Nominal condenser temperature";
  parameter Modelica.Units.SI.Temperature TEva_nominal=273.15 + 5
    "Nominal evaporator temperature";

  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal=-10E3
    "Nominal evaporator heat flow rate (QEva_flow_nominal < 0)";

  parameter Modelica.Units.SI.HeatFlowRate QCon_flow_nominal=-QEva_flow_nominal
      *(1 + 1/COP_nominal)
    "Nominal condenser heat flow rate (QCon_flow_nominal > 0)";

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator outlet-inlet";

  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";

  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal=QCon_flow_nominal/
      cp_default/dTCon_nominal "Nominal mass flow rate at condenser";

  parameter Modelica.Units.SI.MassFlowRate mEva_flow_nominal=QEva_flow_nominal/
      cp_default/dTEva_nominal "Nominal mass flow rate of evaporator";

  final 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 1 at default medium state";

  Carnot_TEva chi_TEva(
    dp1_nominal=0,
    dp2_nominal=0,
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    QEva_flow_nominal=QEva_flow_nominal,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m1_flow_nominal=mCon_flow_nominal,
    m2_flow_nominal=mEva_flow_nominal,
    use_eta_Carnot_nominal=false,
    COP_nominal=COP_nominal,
    show_T=true,
    TCon_nominal=TCon_nominal,
    TEva_nominal=TEva_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Chiller with evaporator leaving water temperature as set point"

  Sources.MassFlowSource_T bouCon(
    nPorts=1,
    redeclare package Medium = Medium,
    m_flow=mCon_flow_nominal,
    T=TCon_nominal - QCon_flow_nominal/cp_default/mCon_flow_nominal)
    "Boundary condition for condenser"
  Sources.MassFlowSource_T bouEva(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=mEva_flow_nominal,
    T=TEva_nominal - QEva_flow_nominal/cp_default/mEva_flow_nominal)
    "Boundary condition for evaporator"

  Modelica.Blocks.Sources.Constant TEvaLvg(k=273.15 + 5)
    "Leaving water temperature"
  Sources.Boundary_pT bou(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"
  Sources.Boundary_pT bou1(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"

  Carnot_y chi_y(
    dp1_nominal=0,
    dp2_nominal=0,
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m1_flow_nominal=mCon_flow_nominal,
    m2_flow_nominal=mEva_flow_nominal,
    use_eta_Carnot_nominal=false,
    COP_nominal=COP_nominal,
    show_T=true,
    TCon_nominal=TCon_nominal,
    TEva_nominal=TEva_nominal,
    P_nominal=QEva_flow_nominal + QCon_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Chiller with control signal as set point"
  Sources.MassFlowSource_T bouCon1(
    nPorts=1,
    redeclare package Medium = Medium,
    m_flow=mCon_flow_nominal,
    T=TCon_nominal - QCon_flow_nominal/cp_default/mCon_flow_nominal)
    "Boundary condition for condenser"
  Sources.MassFlowSource_T bouEva1(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=mEva_flow_nominal,
    T=TEva_nominal - QEva_flow_nominal/cp_default/mEva_flow_nominal)
    "Boundary condition for evaporator"
  Modelica.Blocks.Sources.Constant y(k=1) "Control signal"
  Sources.Boundary_pT bou2(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"
  Sources.Boundary_pT bou3(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"
equation
  connect(bouCon.ports[1], chi_TEva.port_a1)
  connect(TEvaLvg.y, chi_TEva.TSet)
  connect(bou.ports[1], chi_TEva.port_b2)
  connect(chi_TEva.port_a2, bouEva.ports[1])
  connect(bou1.ports[1], chi_TEva.port_b1)
  connect(bouCon1.ports[1], chi_y.port_a1)
  connect(bou2.ports[1], chi_y.port_b2)
  connect(chi_y.port_a2, bouEva1.ports[1])
  connect(bou3.ports[1], chi_y.port_b1)
  connect(y.y, chi_y.y)
end CarnotVerifyCOP;


within Buildings.Fluid.Chillers.Validation;
model CarnotVerifyEtaCarnot
  "Test model to verify the Carnot effectiveness computation for non-zero approach temperatures"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Water "Medium model";

  parameter Real etaCarnot_nominal=0.315046
    "Carnot effectiveness (=COP/COP_Carnot) used if use_eta_Carnot_nominal = true";

  parameter Modelica.Units.SI.TemperatureDifference TAppCon_nominal=2
    "Temperature difference between refrigerant and working fluid outlet in condenser";

  parameter Modelica.Units.SI.TemperatureDifference TAppEva_nominal=2
    "Temperature difference between refrigerant and working fluid outlet in evaporator";

  parameter Real COP_nominal = etaCarnot_nominal * (TEva_nominal-TAppEva_nominal)/
    (TCon_nominal + TAppCon_nominal - (TEva_nominal-TAppEva_nominal))  "Coefficient of performance";

  parameter Modelica.Units.SI.Temperature TCon_nominal=273.15 + 30
    "Nominal condenser temperature";

  parameter Modelica.Units.SI.Temperature TEva_nominal=273.15 + 5
    "Nominal evaporator temperature";

  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal=-10E3
    "Nominal evaporator heat flow rate (QEva_flow_nominal < 0)";

  parameter Modelica.Units.SI.HeatFlowRate QCon_flow_nominal=-QEva_flow_nominal
      *(1 + 1/COP_nominal)
    "Nominal condenser heat flow rate (QCon_flow_nominal > 0)";

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator outlet-inlet";

  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";

  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal=QCon_flow_nominal/
      cp_default/dTCon_nominal "Nominal mass flow rate at condenser";

  parameter Modelica.Units.SI.MassFlowRate mEva_flow_nominal=QEva_flow_nominal/
      cp_default/dTEva_nominal "Nominal mass flow rate of evaporator";

  final 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 1 at default medium state";

  Carnot_TEva chi_TEva(
    dp1_nominal=0,
    dp2_nominal=0,
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    QEva_flow_nominal=QEva_flow_nominal,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m1_flow_nominal=mCon_flow_nominal,
    m2_flow_nominal=mEva_flow_nominal,
    show_T=true,
    TCon_nominal=TCon_nominal,
    TEva_nominal=TEva_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    etaCarnot_nominal=etaCarnot_nominal,
    TAppCon_nominal=TAppCon_nominal,
    TAppEva_nominal=TAppEva_nominal)
    "Chiller with evaporator leaving water temperature as set point"

  Sources.MassFlowSource_T bouCon(
    nPorts=1,
    redeclare package Medium = Medium,
    m_flow=mCon_flow_nominal,
    T=TCon_nominal - QCon_flow_nominal/cp_default/mCon_flow_nominal)
    "Boundary condition for condenser"
  Sources.MassFlowSource_T bouEva(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=mEva_flow_nominal,
    T=TEva_nominal - QEva_flow_nominal/cp_default/mEva_flow_nominal)
    "Boundary condition for evaporator"

  Modelica.Blocks.Sources.Constant TEvaLvg(k=273.15 + 5)
    "Leaving water temperature"
  Sources.Boundary_pT bou(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"
  Sources.Boundary_pT bou1(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"

  Carnot_y chi_y(
    dp1_nominal=0,
    dp2_nominal=0,
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m1_flow_nominal=mCon_flow_nominal,
    m2_flow_nominal=mEva_flow_nominal,
    show_T=true,
    TCon_nominal=TCon_nominal,
    TEva_nominal=TEva_nominal,
    P_nominal=QEva_flow_nominal + QCon_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    etaCarnot_nominal=etaCarnot_nominal,
    TAppCon_nominal=TAppCon_nominal,
    TAppEva_nominal=TAppEva_nominal)
    "Chiller with control signal as set point"
  Sources.MassFlowSource_T bouCon1(
    nPorts=1,
    redeclare package Medium = Medium,
    m_flow=mCon_flow_nominal,
    T=TCon_nominal - QCon_flow_nominal/cp_default/mCon_flow_nominal)
    "Boundary condition for condenser"
  Sources.MassFlowSource_T bouEva1(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=mEva_flow_nominal,
    T=TEva_nominal - QEva_flow_nominal/cp_default/mEva_flow_nominal)
    "Boundary condition for evaporator"
  Modelica.Blocks.Sources.Constant y(k=1) "Control signal"
  Sources.Boundary_pT bou2(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"
  Sources.Boundary_pT bou3(
    nPorts=1,
    redeclare package Medium = Medium)
    "Pressure boundary condition"

equation
  connect(bouCon.ports[1], chi_TEva.port_a1)
  connect(TEvaLvg.y, chi_TEva.TSet)
  connect(bou.ports[1], chi_TEva.port_b2)
  connect(chi_TEva.port_a2, bouEva.ports[1])
  connect(bou1.ports[1], chi_TEva.port_b1)
  connect(bouCon1.ports[1], chi_y.port_a1)
  connect(bou2.ports[1], chi_y.port_b2)
  connect(chi_y.port_a2, bouEva1.ports[1])
  connect(bou3.ports[1], chi_y.port_b1)
  connect(y.y, chi_y.y)
end CarnotVerifyEtaCarnot;


within Buildings.Fluid.Chillers.Validation;
model Carnot_TEva_2ndLaw
  "Test model to verify that the 2nd law is not violated"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-4
    "Temperature difference evaporator outlet-inlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=4
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";
  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal=-100E3
    "Evaporator heat flow rate";
  final parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=
      QEva_flow_nominal/dTEva_nominal/4200
    "Nominal mass flow rate at chilled water side";

  final parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=-
      m2_flow_nominal/dTCon_nominal*dTEva_nominal
    "Nominal mass flow rate at condenser water side";

  Modelica.Blocks.Sources.Constant TEvaIn(k=273.15 + 20)
    "Evaporator inlet temperature"
  Modelica.Blocks.Sources.Constant dTEva(k=dTEva_nominal)
    "Temperature difference over evaporator"
  Modelica.Blocks.Math.Add TSetEvaLvg
    "Set point for evaporator leaving temperature"
  Modelica.Blocks.Sources.Ramp dTConEva(
    duration=1,
    offset=25,
    height=-25)
               "Temperature lift condenser inlet minus evaporator outlet"
  Modelica.Blocks.Math.Add TConIn "Condenser inlet temperature"
  Chiller chi_b(
    redeclare final package Medium1 = Medium,
    redeclare final package Medium2 = Medium,
    final dTEva_nominal=dTEva_nominal,
    final dTCon_nominal=dTCon_nominal,
    final QEva_flow_nominal=QEva_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final m1_flow_nominal=m1_flow_nominal)
    "Chiller model that uses port_b to compute Carnot efficiency"

protected
  model Chiller "Subsystem model with the chiller"

   replaceable package Medium1 = Modelica.Media.Interfaces.PartialMedium
      "Medium model";
   replaceable package Medium2 = Modelica.Media.Interfaces.PartialMedium
      "Medium model";

    parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal
      "Temperature difference evaporator outlet-inlet";
    parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal
      "Temperature difference condenser outlet-inlet";
    parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal
      "Evaporator heat flow rate";
    parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal
      "Nominal mass flow rate at condenser water side";
    parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal
      "Nominal mass flow rate at chilled water side";

    Buildings.Fluid.Sources.MassFlowSource_T sou1(
      redeclare package Medium = Medium1,
      nPorts=1,
      use_m_flow_in=false,
      use_T_in=true,
      m_flow=m1_flow_nominal)
                     "Mass flow rate source"
    Buildings.Fluid.Sources.Boundary_pT sin1(redeclare package Medium = Medium2, nPorts=1)
      "Pressure source"
    Buildings.Fluid.Chillers.Carnot_TEva chi(
      redeclare package Medium1 = Medium1,
      redeclare package Medium2 = Medium2,
      dTEva_nominal=dTEva_nominal,
      dTCon_nominal=dTCon_nominal,
      m2_flow_nominal=m2_flow_nominal,
      show_T=true,
      QEva_flow_nominal=QEva_flow_nominal,
      allowFlowReversal1=false,
      allowFlowReversal2=false,
      dp1_nominal=0,
      dp2_nominal=0,
      energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
      use_eta_Carnot_nominal=true) "Chiller model"
    Buildings.Fluid.Sources.MassFlowSource_T sou2(
      redeclare package Medium = Medium2,
      m_flow=m2_flow_nominal,
      use_T_in=true,
      T=293.15,
      nPorts=1) "Mass flow rate source"
    Buildings.Fluid.Sensors.EntropyFlowRate S_a1(
      redeclare package Medium = Medium1,
      m_flow_nominal=m1_flow_nominal,
      tau=0) "Entropy flow rate sensor"
    Buildings.Fluid.Sensors.EntropyFlowRate S_a2(
      redeclare package Medium = Medium1,
      m_flow_nominal=m1_flow_nominal,
      tau=0) "Entropy flow rate sensor"
    Buildings.Fluid.Sensors.EntropyFlowRate S_a3(
      redeclare package Medium = Medium1,
      m_flow_nominal=m1_flow_nominal,
      tau=0) "Entropy flow rate sensor"
    Buildings.Fluid.Sensors.EntropyFlowRate S_a4(
      redeclare package Medium = Medium1,
      m_flow_nominal=m1_flow_nominal,
      tau=0) "Entropy flow rate sensor"
    Buildings.Fluid.Sources.Boundary_pT sin2(redeclare package Medium = Medium2, nPorts=1)
      "Pressure source"
    Modelica.Blocks.Math.Add SIn_flow
      "Entropy carried by flow that goes into the chiller"
    Modelica.Blocks.Math.Add SOut_flow
      "Entropy carried by flow that leaves the chiller"
    Modelica.Blocks.Math.Add dS_flow(k1=-1)
      "Change in entropy inflow and outflow"

    Modelica.Blocks.Interfaces.RealInput TSetEvaLea(unit="K")
      "Set point for evaporator leaving temperature"
    Modelica.Blocks.Interfaces.RealOutput SGen_flow "Entropy generated"
    Modelica.Blocks.Interfaces.RealInput TConIn(final unit="K", displayUnit=
          "degC") "Condenser inlet temperature"
    Modelica.Blocks.Interfaces.RealInput TEvaIn(final unit="K", displayUnit=
          "degC") "Evaporator inlet temperature"
  equation
    assert(SGen_flow > 0, "Entropy generated is zero or negative, which violates the 2nd law.
  This is because the model is configured to use the inlet temperatures
  to compute the Carnot efficiency, which can lead to non-physical results.",
    level = AssertionLevel.warning);
    connect(SIn_flow.y, dS_flow.u1)
    connect(sin1.ports[1],S_a2. port_b)
    connect(sou1.ports[1],S_a1. port_a)
    connect(S_a1.port_b,chi. port_a1)
    connect(chi.port_b1,S_a4. port_a)
    connect(S_a4.port_b,sin2. ports[1])
    connect(S_a3.port_a,sou2. ports[1])
    connect(S_a2.port_a,chi. port_b2)
    connect(S_a3.port_b,chi. port_a2)
    connect(S_a4.S_flow,SOut_flow. u2)
    connect(S_a2.S_flow,SOut_flow. u1)
    connect(S_a3.S_flow,SIn_flow. u2)
    connect(S_a1.S_flow,SIn_flow. u1)
    connect(SOut_flow.y,dS_flow. u2)
    connect(TSetEvaLea, chi.TSet)
    connect(SGen_flow, dS_flow.y)
    connect(TConIn, sou1.T_in)
    connect(TEvaIn, sou2.T_in)
  end Chiller;
equation
  connect(TSetEvaLvg.u1, TEvaIn.y)
  connect(dTEva.y, TSetEvaLvg.u2)
  connect(TSetEvaLvg.y, TConIn.u1)
  connect(dTConEva.y, TConIn.u2)
  connect(TEvaIn.y, chi_b.TEvaIn)
  connect(TSetEvaLvg.y, chi_b.TSetEvaLea)
  connect(chi_b.TConIn, TConIn.y)
end Carnot_TEva_2ndLaw;


Test model for the part load efficiency curve with evaporator leaving temperature as input signal. This example extends from

Buildings.Fluid.Chillers.Examples.Carnot_TEva
but has a part load efficiency that varies with the load.

within Buildings.Fluid.Chillers.Validation;
model Carnot_TEva_etaPL
  "Test model for the part load efficiency curve with evaporator leaving temperature as input signal"
  extends Examples.Carnot_TEva(
    chi(a={0.7,0.3},
    QEva_flow_min=-100000));
end Carnot_TEva_etaPL;


Test model for Carnot_TEva with high evaporator temperature. This example extends from

Buildings.Fluid.Chillers.Examples.Carnot_TEva
but increases the set point for the leaving evaporator temperature
to be above its inlet temperature, in which case the model provides no cooling.
Towards the end of the simulation, the inlet temperature of the evaporator is increased
to be above the condenser temperature. In this domain, the model requires cooling
again. While this is not a meaningful operating point for the model, the example
verifies that it robustly simulates this regime.

within Buildings.Fluid.Chillers.Validation;
model Carnot_TEva_HighTemperature
  "Test model for Carnot_TEva with high evaporator temperature"
  extends Examples.Carnot_TEva(TEvaLvg(height=34), sou2(use_T_in=true));
  Modelica.Blocks.Sources.Ramp TEvaEnt(
    startTime=3000,
    height=38,
    offset=273.15 + 22,
    duration=60) "Control signal for evaporator entering temperature"
equation
  connect(TEvaEnt.y, sou2.T_in)
end Carnot_TEva_HighTemperature;


Test model for Carnot_TEva with limited heating capacity. This example extends from

Buildings.Fluid.Chillers.Examples.Carnot_TEva
but limits the cooling capacity.

within Buildings.Fluid.Chillers.Validation;
model Carnot_TEva_LimitedCapacity
  "Test model for Carnot_TEva with limited heating capacity"
  extends Examples.Carnot_TEva(
    chi(QEva_flow_min=-100000));
end Carnot_TEva_LimitedCapacity;


within Buildings.Fluid.Chillers.Validation;
model Carnot_TEva_reverseFlow
  "Test model for chiller based on Carnot efficiency and evaporator outlet temperature control signal"
  extends Modelica.Icons.Example;
 package Medium1 = Buildings.Media.Water "Medium model";
 package Medium2 = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator inlet-outlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";
  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal=-100E3
    "Evaporator heat flow rate";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=QEva_flow_nominal/
      dTEva_nominal/4200 "Nominal mass flow rate at chilled water side";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=m2_flow_nominal*(
      COPc_nominal + 1)/COPc_nominal
    "Nominal mass flow rate at condenser water wide";

  Buildings.Fluid.Chillers.Carnot_TEva chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    use_eta_Carnot_nominal=true,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    show_T=true,
    QEva_flow_nominal=QEva_flow_nominal,
    allowFlowReversal1=true,
    allowFlowReversal2=true,
    dp1_nominal=6000,
    dp2_nominal=6000) "Chiller model"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    m_flow=m1_flow_nominal,
    use_T_in=false,
    use_m_flow_in=true,
    T=298.15)
  Buildings.Fluid.Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    m_flow=m2_flow_nominal,
    use_T_in=false,
    use_m_flow_in=true,
    T=295.15)
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT sin2(nPorts=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.Sources.Constant TEvaLvg(k=273.15 + 10)
    "Control signal for evaporator leaving temperature"
  Modelica.Blocks.Math.Gain mCon_flow(k=-1/cp1_default/dTEva_nominal)
    "Condenser mass flow rate"
  Modelica.Blocks.Math.Add QCon_flow(k2=-1) "Condenser heat flow rate"

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp1_default=
      Medium1.specificHeatCapacityCp(Medium1.setState_pTX(
      Medium1.p_default,
      Medium1.T_default,
      Medium1.X_default))
    "Specific heat capacity of medium 1 at default medium state";
  Modelica.Blocks.Sources.Ramp mEva_flow(
    duration=60,
    startTime=1800,
    height=-2*m2_flow_nominal,
    offset=m2_flow_nominal) "Mass flow rate for evaporator"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTConEnt(
    redeclare final package Medium = Medium1,
    final m_flow_nominal=m1_flow_nominal,
    tau=0) "Temperature sensor for fluid entering condenser"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTConLvg(
    redeclare final package Medium = Medium1,
    final m_flow_nominal=m1_flow_nominal,
    tau=0) "Temperature sensor for fluid leaving condenser"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTEvaEnt(
    redeclare final package Medium = Medium2,
    final m_flow_nominal=m2_flow_nominal,
    tau=0) "Temperature sensor for fluid entering evaporator"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTEvaLvg(
    redeclare final package Medium = Medium2,
    final m_flow_nominal=m2_flow_nominal,
    tau=0) "Temperature sensor for fluid leaving evaporator"
equation
  connect(TEvaLvg.y, chi.TSet)
  connect(chi.P, QCon_flow.u1)
  connect(chi.QEva_flow, QCon_flow.u2)
  connect(QCon_flow.y, mCon_flow.u)
  connect(mCon_flow.y, sou1.m_flow_in)
  connect(mEva_flow.y, sou2.m_flow_in)
  connect(sou1.ports[1], senTConEnt.port_a)
  connect(senTConEnt.port_b, chi.port_a1)
  connect(chi.port_b1, senTConLvg.port_a)
  connect(senTConLvg.port_b, sin1.ports[1])
  connect(sou2.ports[1], senTEvaEnt.port_a)
  connect(senTEvaEnt.port_b, chi.port_a2)
  connect(sin2.ports[1], senTEvaLvg.port_b)
  connect(senTEvaLvg.port_a, chi.port_b2)
end Carnot_TEva_reverseFlow;


Test model for the part load efficiency curve with compressor speed as input signal. This example extends from

Buildings.Fluid.Chillers.Examples.Carnot_y
but uses a part load efficiency curve that is different from 1.

within Buildings.Fluid.Chillers.Validation;
model Carnot_y_etaPL
  "Test model for the part load efficiency curve with compressor speed as input signal"
  extends Examples.Carnot_y(chi(a={0.7,0.3}));
end Carnot_y_etaPL;


within Buildings.Fluid.Chillers;
package Validation "Collection of models that validate the chiller models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


within Buildings.Fluid;
package CHPs "Package with model for combined heat and power device"
  extends Modelica.Icons.VariantsPackage;
end CHPs;


CHP model that can be thermal or electrical load following. This model for combined heat and power device uses empirical data contained within
a \"performance map\" to represent device-specific performance characteristics
coupled with thermally massive elements to characterize the device's dynamic thermal
performance. It was developed based on the specification described in
Beausoleil-Morrison (2007).

within Buildings.Fluid.CHPs;
model ThermalElectricalFollowing "CHP model that can be thermal or electrical load following"
  extends Buildings.Fluid.Interfaces.TwoPortHeatMassExchanger(
    redeclare Buildings.Fluid.MixingVolumes.MixingVolume vol(
      final V=per.capHeaRec/rhoWat/cWat),
    final dp_nominal=3458*m_flow_nominal + 5282 "The correlation between nominal pressure drop and mass flow rate is derived from manufacturers data");

  replaceable parameter Buildings.Fluid.CHPs.Data.Generic per
    "CHP unit performance data"

  parameter Boolean switchThermalElectricalFollowing = true
    "Set to true for switching between thermal and electrical following, to false for electrical following only";
  parameter Modelica.Units.SI.Temperature TEngIni=Medium.T_default
    "Initial engine temperature";
  parameter Modelica.Units.SI.Time waitTime=60
    "Wait time before transition from pump-on mode fires"
  parameter Controls.OBC.CDL.Types.SimpleController watOutCon=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller"
  parameter Real k=1 "Gain of controller"
  parameter Modelica.Units.SI.Time Ti=0.5 "Time constant of integrator block"
  parameter Modelica.Units.SI.Time Td=0.1 "Time constant of derivative block"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TWatOutSet(
    final unit="K",
    displayUnit="degC") if switchThermalElectricalFollowing
    "Water outlet set point temperature, which is input signal for thermal following"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput theFol if switchThermalElectricalFollowing
    "Enable thermal following, false if electrical following"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput PEleDem(
    final unit="W",
    final quantity="Power")
    "Electric power demand"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput avaSig
    "True when the plant is available"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a TRoo
    "Heat port for room temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mWatSet_flow(
    final unit="kg/s",
    final quantity="MassFlowRate") if per.compute_coolingWaterFlowRate
    "Water mass flow rate set point based on internal control"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PCon(
    final unit="W",
    final quantity="Power")
    "Power consumption during stand-by and cool-down modes"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PEleNet(
    final unit="W",
    final quantity="Power")
    "Electric power generation"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mFue_flow(
    final unit="kg/s",
    final quantity="MassFlowRate") "Fuel mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput QWat_flow(
    final unit="W",
    final quantity="HeatFlowRate")
    "Heat transfer rate to the water control volume"
  Buildings.Fluid.CHPs.BaseClasses.EnergyConversion eneCon(
    final per = per) "Energy conversion"
  Buildings.Fluid.CHPs.BaseClasses.EngineTemperature eng(
    final UAHex=per.UAHex,
    final UALos=per.UALos,
    final capEng=per.capEng,
    final TEngIni=TEngIni) "Engine control volume"
  Buildings.Fluid.CHPs.BaseClasses.Controller opeMod(
    final per=per,
    final waitTime=waitTime) "Current operation mode"
  Buildings.Controls.OBC.CDL.Logical.And runSig "Run if avaFlag and PEleDem non zero"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(
    final uLow=per.PEleMax/2*10^(-3),
    final uHigh=per.PEleMax*10^(-3)) "Determine if demand larger than zero"
  Buildings.Fluid.CHPs.BaseClasses.FilterPower fil(
    final PEleMax=per.PEleMax,
    final PEleMin=per.PEleMin,
    final use_powerRateLimit=per.use_powerRateLimit,
    final dPEleMax=per.dPEleMax)
    "Power after applied constraints"
  Buildings.Fluid.CHPs.BaseClasses.WaterFlowControl conWat(final per=per)
    if per.compute_coolingWaterFlowRate
    "Internal controller for water mass flow rate"
  Modelica.Blocks.Sources.RealExpression mWat_flow(
    final y=port_a.m_flow) "Water mass flow rate"
  Modelica.Blocks.Sources.RealExpression TWatIn(
    final y=Medium.temperature(Medium.setState_phX(port_a.p, inStream(port_a.h_outflow))))
    "Water inlet temperature"
  Buildings.Fluid.CHPs.BaseClasses.AssertWaterTemperature assWatTem(
    final TWatMax=per.TWatMax)
    "Assert if water temperature is outside boundaries"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TWatOut
    "Water outlet temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor watHea
    "Heat transfer from the water control volume"
  Buildings.Fluid.CHPs.BaseClasses.PowerConsumption powCon(
    final PStaBy=per.PStaBy,
    final PCooDow=per.PCooDow) "Power consumption during stand-by and cool-down modes"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor QLos
    "Heat transfer to the surrounding"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset cooWatCon(
    final controllerType=watOutCon,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=1,
    final yMin=0) if switchThermalElectricalFollowing
    "Cooling water outlet controller"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter elePowDem(
    final k=per.PEleMax) if switchThermalElectricalFollowing
    "Electric power demand if thermal following"
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    "Switch between thermal and electrical following"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant optFol(
    final k=false) if not switchThermalElectricalFollowing
    "Feed false to switch block if no optional following"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(
    final k=0) if not switchThermalElectricalFollowing "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(final k=-1)
    "Heat transfer to the water control volume"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TRooSen
    "Room temperature"
protected
  constant Modelica.Units.SI.Density rhoWat=1000 "Water density";
  constant Modelica.Units.SI.SpecificHeatCapacity cWat=4180
    "Water specific heat";
equation
  connect(fil.PEle, hys.u)
  connect(runSig.y, opeMod.runSig)
  connect(conWat.PEle, fil.PEle)
  connect(mWat_flow.y, eneCon.mWat_flow)
  connect(eng.TEng, eneCon.TEng)
  connect(mWat_flow.y, opeMod.mWat_flow)
  connect(TWatIn.y, conWat.TWatIn)
  connect(eneCon.TWatIn, TWatIn.y)
  connect(conWat.mWatSet_flow, mWatSet_flow)
  connect(hys.y, runSig.u2)
  connect(opeMod.opeMod, eneCon.opeMod)
  connect(opeMod.avaSig, avaSig)
  connect(runSig.u1, avaSig)
  connect(conWat.opeMod, opeMod.opeMod)
  connect(TWatOut.T, assWatTem.TWat)
  connect(eneCon.mFue_flow, mFue_flow)
  connect(eneCon.PEleNet, PEleNet)
  connect(TWatOut.port, vol.heatPort)
  connect(powCon.opeMod, opeMod.opeMod)
  connect(powCon.PCon, PCon)
  connect(TRoo, QLos.port_b)
  connect(eng.TRoo, QLos.port_a)
  connect(fil.PEle, eneCon.PEle)
  connect(watHea.port_b, eng.TWat)
  connect(vol.heatPort, watHea.port_a)
  connect(eneCon.QGen_flow, eng.QGen_flow)
  connect(eng.TEng, opeMod.TEng)
  connect(TWatOutSet, cooWatCon.u_s)
  connect(cooWatCon.y, elePowDem.u)
  connect(theFol, swi.u2)
  connect(PEleDem, swi.u3)
  connect(TWatOut.T, cooWatCon.u_m)
  connect(watHea.Q_flow, gai.u)
  connect(gai.y, QWat_flow)
  connect(zer1.y, swi.u1)
  connect(optFol.y, swi.u2)
  connect(swi.y, fil.PEleDem)
  connect(eneCon.PEleNet, opeMod.PEleNet)
  connect(PEleDem, opeMod.PEle)
  connect(TRoo, TRooSen.port)
  connect(TRooSen.T, eneCon.TRoo)
  connect(theFol, cooWatCon.trigger)
  connect(elePowDem.y, swi.u1)
end ThermalElectricalFollowing;


Assert whether fuel flow is within boundary. The model sends a warning message if the rate at which the fuel mass flow rate changes
is outside the boundaries defined by the manufacturer.

within Buildings.Fluid.CHPs.BaseClasses;
model AssertFuelFlow "Assert whether fuel flow is within boundary"
  extends Modelica.Blocks.Icons.Block;

  parameter Real dmFueMax_flow(final unit="kg/s2")
    "Maximum rate at which fuel mass flow rate can change";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput mFue_flow(
    final unit="kg/s") "Fuel mass flow rate"
  Buildings.Controls.OBC.CDL.Utilities.Assert assMes(
    final message="Rate of change in the fuel mass flow rate is outside boundaries!")
    "Assert function for checking fuel flow rate"

protected
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Check if fuel flow rate is changing slowly"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(
    final uLow=0.99*dmFueMax_flow,
    final uHigh=1.01*dmFueMax_flow + 1e-6)
    "Check if fuel mass flow rate is changing too much"
  Modelica.Blocks.Continuous.Derivative floChaRat(
    final initType=Modelica.Blocks.Types.Init.InitialOutput)
    "Rate at which fuel mass flow rate changes"
  Buildings.Controls.OBC.CDL.Reals.Abs abs1 "Absolute value"

equation
  connect(abs1.u, floChaRat.y)
  connect(floChaRat.u, mFue_flow)
  connect(not1.y, assMes.u)
  connect(abs1.y, hys.u)
  connect(hys.y, not1.u)
end AssertFuelFlow;


Assert if electric power is outside boundaries. The model sends a warning message if the power demand is outside the boundaries defined by the manufacturer.
Limits can be specified for the minimal and maximal electric power, and for the maximum rate at
which the power can change.

within Buildings.Fluid.CHPs.BaseClasses;
model AssertPower "Assert if electric power is outside boundaries"
  extends Modelica.Blocks.Icons.Block;

  parameter Modelica.Units.SI.Power PEleMax "Maximum power output";
  parameter Modelica.Units.SI.Power PEleMin "Minimum power output";
  parameter Boolean use_powerRateLimit
    "If true, the rate at which net power output can change is limited";
  parameter Real dPEleMax(final unit="W/s")
    "Maximum rate at which net power output can change";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput PEleDem(
    final unit="W")
    "Electric power demand"
  Buildings.Controls.OBC.CDL.Utilities.Assert assMesP(
    final message="Electric power is outside boundaries!")
    "Generate warning when the electric power demand is out of the range"
  Buildings.Controls.OBC.CDL.Utilities.Assert assMesDP(
    final message="Rate of change in power output is outside boundaries!") if use_powerRateLimit
    "Assert function for checking power rate"

protected
  Buildings.Controls.OBC.CDL.Logical.Nor nor
    "Check if the electric power demand is out of the power production range"
  Buildings.Controls.OBC.CDL.Logical.Not not2 if use_powerRateLimit "Logical Nand"
  Modelica.Blocks.Continuous.Derivative demRat(
    final initType=Modelica.Blocks.Types.Init.InitialOutput) if use_powerRateLimit
    "Power demand rate"
  Buildings.Controls.OBC.CDL.Reals.Abs abs1 if use_powerRateLimit "Absolute value"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold maxRat(final t=
        dPEleMax) if use_powerRateLimit
    "Check if demand rate is more than the maximum rate"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis maxPow(
    final uLow=0.99*PEleMax,
    final uHigh=1.01*PEleMax + 1e-6)
    "Check if the electric power demand is more than the maximum power production"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis minPow(
    final uLow=0.99*PEleMin - 1e-6,
    final uHigh=1.01*PEleMin)
    "Check if the electric power demand is larger than the minimum power production"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Check if the electric power demand is less than the minimum power production"

equation
  connect(abs1.u, demRat.y)
  connect(maxRat.u, abs1.y)
  connect(demRat.u, PEleDem)
  connect(nor.y, assMesP.u)
  connect(not2.y, assMesDP.u)
  connect(PEleDem, maxPow.u)
  connect(maxPow.y, nor.u1)
  connect(PEleDem, minPow.u)
  connect(minPow.y, not1.u)
  connect(not1.y, nor.u2)
  connect(maxRat.y, not2.u)
end AssertPower;


Assert if water flow is outside boundaries. The model sends a warning message if the water mass flow rate is lower than the
minimum defined by the manufacturer.

within Buildings.Fluid.CHPs.BaseClasses;
model AssertWaterFlow "Assert if water flow is outside boundaries"
  extends Modelica.Blocks.Icons.Block;

  parameter Modelica.Units.SI.MassFlowRate mWatMin_flow
    "Minimum cooling water mass flow rate";

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput runSig
    "True when electricity or heat demand is larger than zero"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mWat_flow(
    final unit="kg/s")
    "Water mass flow rate"
  Buildings.Controls.OBC.CDL.Utilities.Assert assMes(
    final message="Water flow rate is lower than the minimum!")
    "Assert function for checking water flow rate"

protected
  Buildings.Controls.OBC.CDL.Logical.Nand nand "Logical Nand"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(
    final uLow=0.99*mWatMin_flow - 1e-6,
    final uHigh=1.01*mWatMin_flow)
    "Check if water flow rate is larger than minimum rate"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Check if water flow rate is smaller than minimum rate"

equation
  connect(hys.u, mWat_flow)
  connect(nand.u1, runSig)
  connect(nand.y, assMes.u)
  connect(nand.u2, not1.y)
  connect(not1.u, hys.y)
end AssertWaterFlow;


Assert if water outlet temperature is outside boundaries. The model sends a warning message if the water outlet temperature is higher
than the maximum defined by the manufacturer.

within Buildings.Fluid.CHPs.BaseClasses;
model AssertWaterTemperature
  "Assert if water outlet temperature is outside boundaries"
  extends Modelica.Blocks.Icons.Block;

  parameter Modelica.Units.SI.Temperature TWatMax
    "Maximum cooling water temperature";
  parameter Modelica.Units.SI.TemperatureDifference THys=0.5
    "Hysteresis value to check temperature difference"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TWat(
    final unit="K",
    displayUnit="degC") "Water outlet temperature"
  Buildings.Controls.OBC.CDL.Utilities.Assert assMes(
    final message="Water temperature is higher than the maximum!")
    "Assert function for checking water temperature"

protected
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(
    final uLow=TWatMax -THys,
    final uHigh=TWatMax + THys)
    "Check if water temperature is larger than the maximum temperature"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Check if water temperature is lower than the maximum temperature"

equation
  connect(hys.u, TWat)
  connect(hys.y, not1.u)
  connect(not1.y, assMes.u)
end AssertWaterTemperature;