Package with models for heat pumps

within Buildings.Fluid;
package HeatPumps "Package with models for heat pumps"
  extends Modelica.Icons.VariantsPackage;
end HeatPumps;


within Buildings.Fluid.HeatPumps;
model ReciprocatingWaterToWater
  "Model for a reciprocating water to water heat pump"

  extends Buildings.Fluid.HeatPumps.BaseClasses.PartialWaterToWater(
    final UAEva=per.UAEva * scaling_factor,
    final UACon=per.UACon * scaling_factor,
    redeclare HeatPumps.Compressors.ReciprocatingCompressor com(
      redeclare final package ref=ref,
      pisDis=per.pisDis * scaling_factor,
      cleFac=per.cleFac,
      etaEle=per.etaEle,
      PLos=per.PLos * scaling_factor,
      pDro=per.pDro,
      dTSup=per.dTSup));

  parameter Data.ReciprocatingWaterToWater.Generic per
    "Heat pump performance data"
end ReciprocatingWaterToWater;


within Buildings.Fluid.HeatPumps;
model ScrollWaterToWater
  "Model for a scroll water to water heat pump"
  extends Buildings.Fluid.HeatPumps.BaseClasses.PartialWaterToWater(
    final UAEva=datHeaPum.UAEva*scaling_factor,
    final UACon=datHeaPum.UACon*scaling_factor,
    redeclare HeatPumps.Compressors.ScrollCompressor com(
      redeclare final package ref = ref,
      final volRat=datHeaPum.volRat,
      final V_flow_nominal=datHeaPum.V_flow_nominal*scaling_factor,
      final leaCoe=datHeaPum.leaCoe*scaling_factor,
      final etaEle=datHeaPum.etaEle,
      final PLos=datHeaPum.PLos*scaling_factor,
      final dTSup=datHeaPum.dTSup));

  parameter Buildings.Fluid.HeatPumps.Data.ScrollWaterToWater.Generic datHeaPum
    "Heat pump data"
end ScrollWaterToWater;


Equation fit method to compute the performance of the reversable heat pump. Block that implements the equation fit method for the reverse heat pump model

Buildings.Fluid.HeatPumps.EquationFitReversible.

within Buildings.Fluid.HeatPumps.BaseClasses;
block EquationFitReversible
  "Equation fit method to compute the performance of the reversable heat pump"
  extends Modelica.Blocks.Icons.Block;

  parameter Data.EquationFitReversible.Generic per
   "Performance data"
  parameter Real scaling_factor
   "Scaling factor for heat pump capacity";
  parameter Modelica.Units.SI.HeatFlowRate Q_flow_small(min=Modelica.Constants.eps)
     = per.hea.Q_flow*1E-9*scaling_factor
    "Small value for heat flow rate or power, used to avoid division by zero";

  Modelica.Blocks.Interfaces.IntegerInput uMod
   "Control input signal, cooling mode= -1, off=0, heating mode=+1"
  Modelica.Blocks.Interfaces.RealInput TLoaEnt(
    final unit="K",
    displayUnit="degC")
   "Load entering fluid temperature"
  Modelica.Blocks.Interfaces.RealInput TSouEnt(
    final unit="K",
    displayUnit="degC")
   "Source entering fluid temperature"

  Modelica.Blocks.Interfaces.RealInput mLoa_flow(final unit="kg/s")
    "Mass flow rate at load side"

  Modelica.Blocks.Interfaces.RealInput mSou_flow(final unit="kg/s")
    "Mass flow rate at source side"

  Modelica.Blocks.Interfaces.RealInput Q_flow_set(final unit="W")
    "Required heat to meet set point"

  Modelica.Blocks.Interfaces.RealOutput QLoa_flow(final unit="W")
   "Load heat flow rate"

  Modelica.Blocks.Interfaces.RealOutput QSou_flow(final unit="W")
   "Source heat flow rate"

  Modelica.Blocks.Interfaces.RealOutput P(final unit="W")
   "Compressor power"

  Modelica.Blocks.Interfaces.RealOutput COP(
   final min=0,
   final unit="1")
   "Coefficient of performance, assuming useful heat is at the load side (at Medium 1)"

  Modelica.Units.SI.Efficiency QRel_flow "Thermal load ratio";
  Modelica.Units.SI.Efficiency PRel "Power ratio";
  Modelica.Units.SI.HeatFlowRate Q_flow_ava
    "Heat (or cooling) capacity available";
  Real PLR(min=0, nominal=1, unit="1")
   "Part load ratio";

protected
  Real xNor[5] "Normalized inlet variables";

initial equation
  assert(per.hea.Q_flow > 0,
   "Parameter QheaLoa_flow_nominal must be larger than zero.");
  assert(per.coo.Q_flow < 0,
   "Parameter QCooLoa_flow_nominal must be lesser than zero.");
  assert(Q_flow_small > 0,
   "Parameter Q_flow_small must be larger than zero.");

equation
  if (uMod == 0) then
    xNor=fill(0, 5);
  elseif (uMod == -1) then
    xNor={ 1,
           TLoaEnt/per.coo.TRefLoa,
           TSouEnt/per.coo.TRefSou,
           mLoa_flow/(per.coo.mLoa_flow*scaling_factor),
           mSou_flow/(per.coo.mSou_flow*scaling_factor)};
  else // uMod == +1
      xNor={ 1,
           TLoaEnt/per.hea.TRefLoa,
           TSouEnt/per.hea.TRefSou,
           mLoa_flow/(per.hea.mLoa_flow*scaling_factor),
           mSou_flow/(per.hea.mSou_flow*scaling_factor)};

  end if;

  if (uMod==1) then
    QRel_flow = sum(per.hea.coeQ .* xNor);
    Q_flow_ava = QRel_flow*per.hea.Q_flow*scaling_factor;
    QLoa_flow   =Buildings.Utilities.Math.Functions.smoothMin(
      x1=Q_flow_set,
      x2=Q_flow_ava,
      deltaX=Q_flow_small);
    PLR = QLoa_flow / Q_flow_ava;
    PRel =  sum(per.hea.coeP .* xNor);
    P = PLR*PRel*per.hea.P*scaling_factor;
    QSou_flow = -(QLoa_flow -P);
    COP = QLoa_flow/(P+Q_flow_small);
  elseif (uMod==-1) then
    QRel_flow  = sum(per.coo.coeQ .* xNor);
    Q_flow_ava = QRel_flow*per.coo.Q_flow*scaling_factor;
    QLoa_flow =Buildings.Utilities.Math.Functions.smoothMax(
      x1=Q_flow_set,
      x2=Q_flow_ava,
      deltaX=Q_flow_small);
    PLR = QLoa_flow / Q_flow_ava;
    PRel  = sum(per.coo.coeP .* xNor);
    P = PLR*PRel*per.coo.P*scaling_factor;
    QSou_flow = -QLoa_flow + P;
    COP = -QLoa_flow/(P+Q_flow_small);
  else
    QRel_flow=0;
    PRel = 0;
    P = 0;
    Q_flow_ava = 0;
    QLoa_flow = 0;
    QSou_flow = 0;
    PLR=0;
    COP = 0;
  end if;
end EquationFitReversible;


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


within Buildings.Fluid.HeatPumps.BaseClasses;
partial model PartialWaterToWater
  "Partial model for water to water heat pumps and chillers"
  extends Buildings.Fluid.Interfaces.PartialFourPortInterface;
  extends Buildings.Fluid.Interfaces.FourPortFlowResistanceParameters(
    final computeFlowResistance1 = dp1_nominal > 0,
    final computeFlowResistance2 = dp2_nominal > 0);

  replaceable package ref = Buildings.Media.Refrigerants.R410A
    "Refrigerant in the component"

  constant Boolean homotopyInitialization = true "= true, use homotopy method"

  parameter Boolean enable_variable_speed = true
    "Set to true to allow modulating of compressor speed";

  parameter Real scaling_factor = 1.0
    "Scaling factor for heat pump capacity";

  parameter Modelica.Units.SI.ThermalConductance UACon
    "Thermal conductance of condenser";

  parameter Modelica.Units.SI.ThermalConductance UAEva
    "Thermal conductance of evaporator";

  parameter Modelica.Units.SI.Time tau1=60
    "Time constant at nominal flow rate (used if energyDynamics1 <> Modelica.Fluid.Types.Dynamics.SteadyState)"
  parameter Modelica.Units.SI.Time tau2=60
    "Time constant at nominal flow rate (used if energyDynamics2 <> Modelica.Fluid.Types.Dynamics.SteadyState)"

  parameter Modelica.Units.SI.Temperature T1_start=Medium1.T_default
    "Initial or guess value of set point"
  parameter Modelica.Units.SI.Temperature T2_start=Medium2.T_default
    "Initial or guess value of set point"

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

  parameter Boolean enable_temperature_protection = true
    "Enable temperature protection"
  parameter Modelica.Units.SI.Temperature TConMax=ref.TCri - 5
    "Upper bound for condenser temperature"
  parameter Modelica.Units.SI.Temperature TEvaMin=275.15
    "Lower bound for evaporator temperature"
  parameter Real dTHys(unit="K",min=0) = 5
    "Hysteresis interval width"

  Modelica.Blocks.Interfaces.BooleanOutput errLowPre if enable_temperature_protection
    "if true, compressor disabled since evaporator temperature is above upper bound";
  Modelica.Blocks.Interfaces.BooleanOutput errHigPre if enable_temperature_protection
    "if true, compressor disabled since condenser temperature is below lower bound";
  Modelica.Blocks.Interfaces.BooleanOutput errNegTemDif if enable_temperature_protection
    "if true, compressor disabled since condenser temperature is below evaporator temperature";

  Modelica.Blocks.Interfaces.RealInput y(final unit = "1")
 if enable_variable_speed == true
    "Modulating signal for compressor frequency, equal to 1 at full load condition"

  Modelica.Blocks.Interfaces.IntegerInput stage
 if enable_variable_speed == false
    "Current stage of the heat pump, equal to 1 at full load condition"

  Modelica.Blocks.Interfaces.RealOutput QCon_flow(
    min = 0,
    final quantity="HeatFlowRate",
    final unit="W") "Actual heating heat flow rate added to fluid 1"

  Modelica.Blocks.Interfaces.RealOutput P(
    min = 0,
    final quantity="Power",
    final unit="W") "Electric power consumed by compressor"

  Modelica.Blocks.Interfaces.RealOutput QEva_flow(
    max = 0,
    final quantity="HeatFlowRate",
    final unit="W") "Actual cooling heat flow rate removed from fluid 2"

  Buildings.Fluid.HeatExchangers.EvaporatorCondenser con(
    redeclare final package Medium = Medium1,
    final allowFlowReversal=allowFlowReversal1,
    final m_flow_nominal=m1_flow_nominal,
    final m_flow_small=m1_flow_small,
    m_flow(start=m1_flow_nominal),
    final from_dp=from_dp1,
    final dp_nominal=dp1_nominal,
    final linearizeFlowResistance=linearizeFlowResistance1,
    final deltaM=deltaM1,
    final tau=tau1,
    final T_start=T1_start,
    final energyDynamics=energyDynamics,
    final homotopyInitialization=homotopyInitialization,
    final UA=UACon) "Condenser"

  Buildings.Fluid.HeatExchangers.EvaporatorCondenser eva(
    redeclare final package Medium = Medium2,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_nominal=m2_flow_nominal,
    final m_flow_small=m2_flow_small,
    m_flow(start=m2_flow_nominal),
    final from_dp=from_dp2,
    final dp_nominal=dp2_nominal,
    final linearizeFlowResistance=linearizeFlowResistance2,
    final deltaM=deltaM2,
    final tau=tau2,
    final T_start=T2_start,
    final energyDynamics=energyDynamics,
    final homotopyInitialization=homotopyInitialization,
    final UA=UAEva) "Evaporator"

  replaceable Buildings.Fluid.HeatPumps.Compressors.BaseClasses.PartialCompressor com
    "Compressor"

protected
  Modelica.Blocks.Math.IntegerToReal intToRea
 if enable_variable_speed == false "Conversion for stage signal"

  Modelica.Blocks.Nonlinear.Limiter lim(final uMin=0, final uMax=1)
 if enable_variable_speed == false "Limiter for control signal"

  Compressors.BaseClasses.TemperatureProtection temPro(
    final TConMax=TConMax,
    final TEvaMin=TEvaMin,
    final dTHys=dTHys) if enable_temperature_protection
    "Disables compressor when outside of allowed operation range"

initial equation
  assert(homotopyInitialization, "In " + getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);

equation
  if enable_temperature_protection then
    connect(errLowPre, temPro.errLowPre);
    connect(errHigPre, temPro.errHigPre);
    connect(errNegTemDif, temPro.errNegTemDif);
  end if;
  connect(port_a1, con.port_a)
  connect(con.port_b, port_b1)
  connect(con.Q_flow, QCon_flow)
  connect(eva.port_a, port_a2)
  connect(eva.port_b, port_b2)
  connect(eva.Q_flow, QEva_flow)
  connect(com.port_b, con.port_ref)
  connect(com.port_a, eva.port_ref)
  connect(com.P, P)
  if enable_variable_speed then
    if enable_temperature_protection then
      connect(y,temPro.u)
    else
      connect(y,com.y)
    end if;
  else
    if enable_temperature_protection then
      connect(lim.y, temPro.u)
    else
      connect(lim.y, com.y)
    end if;
  end if;
  connect(stage, intToRea.u)
  connect(intToRea.y, lim.u)
  connect(temPro.y, com.y)
  connect(temPro.TCon, con.T)
  connect(temPro.TEva, eva.T)
end PartialWaterToWater;


within Buildings.Fluid.HeatPumps.BaseClasses.Validation;
model EquationFitReversible
  "Validation of the equation fit method implemented in the reversible heat pump model"

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

  parameter Modelica.Units.SI.MassFlowRate mSou_flow_nominal=per.hea.mSou_flow
    "Source heat exchanger nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mLoa_flow_nominal=per.hea.mLoa_flow
    "Load heat exchanger nominal mass flow rate";
   parameter Data.EquationFitReversible.Trane_Axiom_EXW240 per
    "Performance data"

  BaseClasses.EquationFitReversible equFit(
    per=per,
    scaling_factor=1)
    "Performance model for equation fit"
  Modelica.Blocks.Math.RealToInteger reaToInt
    "Real to integer conversion"
  Modelica.Blocks.Sources.Sine uMod(amplitude=1, f=1/2600)
    "Heat pump operates in heating mode"
  Modelica.Blocks.Sources.Sine Q_flow_set(amplitude=5000, f=1/2600)
    "Set point for heat flow rate"
  Controls.OBC.CDL.Reals.Sources.Constant mLoa_flow(k=1.89)
    "Mass flow rate entering load heat exchanger side"
  Controls.OBC.CDL.Reals.Sources.Sin TLoaEnt(
    amplitude=10,
    freqHz=1/2600,
    offset=25 + 273.15,
    startTime=0) "Load side entering water temperature"
  Controls.OBC.CDL.Reals.Sources.Constant mSou_flow(k=1.89)
    "Mass flow rate entering source heat exchanger side"
  Controls.OBC.CDL.Reals.Sources.Sin TSouEnt(
    amplitude=5,
    freqHz=1/2600,
    offset=15 + 273.15,
    startTime=0) "Source side entering water temperature"
equation
  connect(reaToInt.u,uMod. y)
  connect(reaToInt.y, equFit.uMod)
  connect(Q_flow_set.y, equFit.Q_flow_set)
  connect(mLoa_flow.y, equFit.mLoa_flow)
  connect(TLoaEnt.y, equFit.TLoaEnt)
  connect(mSou_flow.y, equFit.mSou_flow)
  connect(TSouEnt.y, equFit.TSouEnt)
end EquationFitReversible;


Collection of validation models

within Buildings.Fluid.HeatPumps.BaseClasses;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


within Buildings.Fluid.HeatPumps;
package Calibration "Package for calibration of heat pump models"
extends Modelica.Icons.UtilitiesPackage;
end Calibration;


within Buildings.Fluid.HeatPumps.Calibration;
model ScrollWaterToWater
  "Calibration model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.HeatPumps.Calibration.BaseClasses.PartialWaterToWater(
    redeclare package Medium1 = Buildings.Media.Water,
    redeclare package Medium2 = Buildings.Media.Water,
    redeclare Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum(
      datHeaPum(
        etaEle=etaEle,
        PLos=PLos,
        dTSup=dTSup,
        UACon=UACon,
        UAEva=UAEva,
        volRat=volRat,
        V_flow_nominal=V_flow_nominal,
        leaCoe=leaCoe),
      energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
      enable_temperature_protection=false),
    calDat(tableName="ManufacturerData",
           fileName=Modelica.Utilities.Files.loadResource(
          "modelica://Buildings/Resources/src/fluid/heatpumps/calibration/manufacturerData.txt")),
    UACon = 12000.0,
    UAEva = 12000.0,
    m1_flow_nominal=1.42,
    m2_flow_nominal=1.42);

  parameter Real volRat(min = 1.0, unit = "1") = 2.0
    "Built-in volume ratio";

  parameter Modelica.Units.SI.VolumeFlowRate V_flow_nominal(min=0) = 0.009
    "Refrigerant volume flow rate at suction";

  parameter Modelica.Units.SI.MassFlowRate leaCoe(min=0) = 0.03
    "Leakage coefficient";

  parameter Modelica.Units.SI.Efficiency etaEle=0.696
    "Electro-mechanical efficiency of the compressor";

  parameter Modelica.Units.SI.Power PLos(min=0) = 500.0
    "Constant part of the compressor power losses";

  parameter Modelica.Units.SI.TemperatureDifference dTSup(min=0) = 10.0
    "Superheating at compressor suction";
end ScrollWaterToWater;


within Buildings.Fluid.HeatPumps.Calibration;
package BaseClasses "Base classes for calibration of heat pump models"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Fluid.HeatPumps.Calibration.BaseClasses;
model PartialWaterToWater
  "Partial model for calibration of water to water heat pumps"

  replaceable package Medium1 = Modelica.Media.Interfaces.PartialMedium
    "Medium model at the condenser side";

  replaceable package Medium2 = Modelica.Media.Interfaces.PartialMedium
    "Medium model at the evaporator side";

  replaceable package ref = Buildings.Media.Refrigerants.R410A
    "Refrigerant model";

  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal
    "Nominal mass flow rate on condenser side";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal
    "Nominal mass flow rate on evaporator side";

  parameter Modelica.Units.SI.Pressure dp1_nominal=1000
    "Pressure drop at nominal mass flow rate on condenser side";
  parameter Modelica.Units.SI.Pressure dp2_nominal=1000
    "Pressure drop at nominal mass flow rate on evaporator side";

  parameter Modelica.Units.SI.ThermalConductance UACon
    "Thermal conductance of condenser";

  parameter Modelica.Units.SI.ThermalConductance UAEva
    "Thermal conductance of evaporator";

  Modelica.Blocks.Sources.CombiTimeTable calDat(
    tableOnFile=true,
    columns=2:5)

  Modelica.Blocks.Routing.DeMultiplex4 splDat
    "De-multiplex"

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare final package Medium = Medium2,
    nPorts=1) "Boundary condition"
  Modelica.Fluid.Sources.MassFlowSource_T Sou(
    redeclare final package Medium = Medium2,
    nPorts=1,
    use_m_flow_in=true,
    use_T_in=true)
    "Mass flow source"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare final package Medium = Medium1,
    nPorts=1) "Pressure boundary condition"

  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare final package Medium = Medium1,
    nPorts=1,
    use_m_flow_in=true,
    use_T_in=true) "Mass flow source"

  replaceable Buildings.Fluid.HeatPumps.BaseClasses.PartialWaterToWater heaPum
    constrainedby Buildings.Fluid.HeatPumps.BaseClasses.PartialWaterToWater(
    redeclare final package Medium1 = Medium1,
    redeclare final package Medium2 = Medium2,
    redeclare final package ref = ref,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final dp1_nominal=dp1_nominal,
    final dp2_nominal=dp2_nominal,
    enable_variable_speed=false,
    show_T=true)

  Modelica.Blocks.Sources.IntegerConstant isOn(k=1)
    "Control signal"

equation
  connect(calDat.y, splDat.u)
  connect(splDat.y1[1], Sou.T_in)
  connect(splDat.y3[1], Sou.m_flow_in)
  connect(splDat.y4[1],loa.m_flow_in)
  connect(loa.ports[1], heaPum.port_a1)
  connect(sin2.ports[1], heaPum.port_b2)
  connect(Sou.ports[1], heaPum.port_a2)
  connect(sin1.ports[1], heaPum.port_b1)
  connect(splDat.y2[1],loa.T_in)

  connect(isOn.y, heaPum.stage)
end PartialWaterToWater;


Package with compressor models

within Buildings.Fluid.HeatPumps;
package Compressors "Package with compressor models"
  extends Modelica.Icons.VariantsPackage;
end Compressors;


Model for a reciprocating compressor, based on Jin (2002). Model for a reciprocating processor, as detailed in Jin (2002). The rate of heat transferred to the evaporator is given by:

within Buildings.Fluid.HeatPumps.Compressors;
model ReciprocatingCompressor
  "Model for a reciprocating compressor, based on Jin (2002)"
  extends Buildings.Fluid.HeatPumps.Compressors.BaseClasses.PartialCompressor;

  parameter Modelica.Units.SI.VolumeFlowRate pisDis "Piston displacement";

  parameter Real cleFac(
    min = 0,
    final unit = "1")
    "Clearance factor";

  parameter Modelica.Units.SI.Efficiency etaEle
    "Electro-mechanical efficiency of the compressor";

  parameter Modelica.Units.SI.Power PLos(min=0)
    "Constant part of the compressor power losses";

  parameter Modelica.Units.SI.AbsolutePressure pDro
    "Pressure drop at suction and discharge of the compressor";

  parameter Modelica.Units.SI.TemperatureDifference dTSup(min=0)
    "Superheating at compressor suction";

  Modelica.Units.SI.MassFlowRate m_flow "Refrigerant mass flow rate";

  Modelica.Units.SI.Power PThe "Theoretical power consumed by the compressor";

  Modelica.Units.SI.Efficiency COP(start=5) "Heating COP of the compressor";

protected
  Modelica.Units.SI.IsentropicExponent k(start=1.2)
    "Isentropic exponent of the refrigerant";

  Real pisDis_norm
    "Normalized piston displacement at part load conditions";

equation
  // Limit compressor speed to the full load speed
  pisDis_norm = Buildings.Utilities.Math.Functions.smoothLimit(y, 0.0, 1.0, 0.001);

  if isOn then
    // Suction pressure
    pSuc = Buildings.Utilities.Math.Functions.smoothMin(pEva - pDro, pCon - pDro, 0.01*ref.pCri);
    // Discharge pressure
    pDis = pCon + pDro;
    // Refrigerant mass flow rate
    k = ref.isentropicExponentVap_Tv(TSuc, vSuc);
    m_flow = pisDis_norm*pisDis/vSuc*(1 + cleFac
       - cleFac*(PR)^(1/k));
    // Theoretical power of the compressor
    PThe = k/(k-1) * m_flow*pSuc*vSuc*((PR)^((k-1)/k)-1);
    // Power consumed by the compressor
    P = PThe/etaEle + PLos;
    // Temperature at suction of the compressor
    TSuc = port_a.T + dTSup;
    // Energy balance of the compressor
    port_a.Q_flow = m_flow * (hEva - hCon);
    port_b.Q_flow = - (port_a.Q_flow + P);
    -port_b.Q_flow = P * COP;
  else
    // Heat pump is turned off
    k = 1.0;
    pSuc = pEva;
    pDis = pCon;
    m_flow = 0;
    PThe = 0;
    P = 0;
    TSuc = port_a.T;
    port_a.Q_flow = 0;
    port_b.Q_flow = 0;
    COP = 1.0;
  end if;
end ReciprocatingCompressor;


Model for a scroll compressor, based on Jin (2002). Model for a scroll processor, as detailed in Jin (2002). The rate of heat transferred to the evaporator is given by:

within Buildings.Fluid.HeatPumps.Compressors;
model ScrollCompressor
  "Model for a scroll compressor, based on Jin (2002)"
  extends Buildings.Fluid.HeatPumps.Compressors.BaseClasses.PartialCompressor;

  parameter Real volRat(
    min = 1.0,
    final unit = "1")
    "Built-in volume ratio";

  parameter Modelica.Units.SI.VolumeFlowRate V_flow_nominal(min=0)
    "Refrigerant volume flow rate at suction at full load conditions";

  parameter Modelica.Units.SI.MassFlowRate leaCoe(min=0)
    "Leakage mass flow rate at a pressure ratio of 1";

  parameter Modelica.Units.SI.Efficiency etaEle
    "Electro-mechanical efficiency of the compressor";

  parameter Modelica.Units.SI.Power PLos(min=0)
    "Constant part of the compressor power losses";

  parameter Modelica.Units.SI.TemperatureDifference dTSup(min=0)
    "Superheating at compressor suction";

  Modelica.Units.SI.MassFlowRate m_flow "Refrigerant mass flow rate";

  Modelica.Units.SI.MassFlowRate mLea_flow "Refrigerant leakage mass flow rate";

  Modelica.Units.SI.Power PThe "Theoretical power consumed by the compressor";

  Modelica.Units.SI.Efficiency COP(start=5) "Heating COP of the compressor";

protected
  Modelica.Units.SI.IsentropicExponent k(start=1.2)
    "Isentropic exponent of the refrigerant";

  Real v_norm
    "Normalized refrigerant volume flow rate at
     suction at part load conditions";

  Real PRInt(start = 2.0)
    "Built-in pressure ratio";

equation
  PRInt = volRat^k;

  // Limit compressor speed to the full load speed
  v_norm = Buildings.Utilities.Math.Functions.smoothLimit(y, 0.0, 1.0, 0.001);

  if isOn then
    // Suction pressure
    pSuc = pEva;
    // Discharge pressure
    pDis = pCon;
    // Refrigerant mass flow rate
    mLea_flow = leaCoe*PR;
    m_flow = v_norm*
      Buildings.Utilities.Math.Functions.smoothMax(
      V_flow_nominal/vSuc - mLea_flow,
      1e-5*V_flow_nominal/vSuc,
      1e-6*V_flow_nominal/vSuc);

    // Theoretical power of the compressor
    k = ref.isentropicExponentVap_Tv(TSuc, vSuc);
    // If the external pressure ratio does not match the built-in pressure ratio
    PThe = v_norm * k/(k - 1.0) * pSuc * V_flow_nominal
      * (((k - 1.0)/k) * PR/volRat + 1.0/k * PRInt^((k - 1.0)/k) - 1.0);
    // This equation reduces to the  equation for the built-in pressure ratio
    // if the external pressure ratio matches the built-in pressure ratio:
    // PThe = v_norm * k/(k - 1.0) * pSuc*v_flow * ((PRInt)^((k - 1.0)/k) - 1.0)

    // Temperature at suction of the compressor
    TSuc = port_a.T + dTSup;

    // Power consumed by the compressor
    P = (PThe/etaEle + PLos);

    // Energy balance of the compressor
     port_a.Q_flow = m_flow * (hEva - hCon);
     port_b.Q_flow = - (port_a.Q_flow + P);
     -port_b.Q_flow = P * COP;
  else
    // Heat pump is turned off
    k = 1.0;
    pSuc = pEva;
    pDis = pCon;
    mLea_flow = 0.0;
    m_flow = 0.0;
    PThe = 0.0;
    P = 0.0;
    TSuc = port_a.T;
    port_a.Q_flow = 0.0;
    port_b.Q_flow = 0.0;
    COP = 1.0;
  end if;
end ScrollCompressor;


within Buildings.Fluid.HeatPumps.Compressors;
package BaseClasses "Package with base classes for compressors"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial compressor model

within Buildings.Fluid.HeatPumps.Compressors.BaseClasses;
partial model PartialCompressor "Partial compressor model"

  replaceable package ref = Buildings.Media.Refrigerants.R410A
    "Refrigerant in the component"

    Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a
      "Refrigerant connector a (corresponding to the evaporator)"

    Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port_b
      "Refrigerant connector b (corresponding to the condenser)"

    Modelica.Blocks.Interfaces.RealInput y(final unit = "1")
     "Modulating signal for compressor frequency, equal to 1 at full load conditions"

    Modelica.Blocks.Interfaces.RealOutput P(
      final quantity="Power",
      final unit="W") "Electric power consumed by compressor"

  Modelica.Units.SI.SpecificEnthalpy hEva
    "Specific enthalpy of saturated vapor at evaporator temperature";

  Modelica.Units.SI.SpecificEnthalpy hCon
    "Specific enthalpy of saturated liquid at condenser temperature";

  Modelica.Units.SI.AbsolutePressure pEva(start=100e3)
    "Pressure of saturated vapor at evaporator temperature";

  Modelica.Units.SI.AbsolutePressure pCon(start=1000e3)
    "Pressure of saturated liquid at condenser temperature";

  Modelica.Units.SI.AbsolutePressure pDis(start=1000e3)
    "Discharge pressure of the compressor";

  Modelica.Units.SI.AbsolutePressure pSuc(start=100e3)
    "Suction pressure of the compressor";

  Modelica.Units.SI.Temperature TSuc "Temperature at suction of the compressor";

  Boolean isOn(fixed=false)
    "State of the compressor, true if turned on";

  Modelica.Units.SI.SpecificVolume vSuc(start=1e-4, min=0)
    "Specific volume of the refrigerant at suction of the compressor";

protected
  Real PR(min = 0.0, unit = "1", start = 2.0)
    "Pressure ratio";

initial equation
  pre(isOn) = if y > 0.01 then true else false;

equation
  isOn = not pre(isOn) and y > 0.01 or pre(isOn) and y >= 0.005;

  PR = max(pDis/pSuc, 0);

  // The specific volume at suction of the compressor is calculated
  // from the Martin-Hou equation of state
  vSuc = ref.specificVolumeVap_pT(pSuc, TSuc);

  // Saturation pressure of refrigerant vapor at condenser temperature
  pCon = ref.pressureSatVap_T(port_b.T);

  // Specific enthalpy of saturated liquid refrigerant at condenser temperature
  hCon = ref.enthalpySatLiq_T(port_b.T);

  // Saturation pressure of refrigerant vapor at evaporator temperature
  pEva = ref.pressureSatVap_T(port_a.T);

  // Specific enthalpy of saturated refrigerant vapor at evaporator temperature
  hEva = ref.enthalpySatVap_T(port_a.T);

  // Assert statements to verify that the refrigerant temperatures are within
  // bounds of the property data in the refrigerant package
  assert(port_b.T > ref.T_min and port_b.T < ref.TCri,
    "Condensing temperature must be above the minimum refrigerant temperature
    and below the critical temperature.");
  assert(port_a.T > ref.T_min and port_a.T < ref.TCri,
    "Evaporating temperature must be above the minimum refrigerant temperature
    and below the critical temperature.");
end PartialCompressor;


Temperature protection for heat pump compressor. Temperature protection block for heat pumps.
This block overrides the heat pump control
signal when the condenser temperature is too high,
the evaporator temperature is too low,
or the temperature difference between
the condenser and evaporator is negative.

within Buildings.Fluid.HeatPumps.Compressors.BaseClasses;
model TemperatureProtection
  "Temperature protection for heat pump compressor"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Temperature TConMax
    "Upper bound for condenser temperature";
  parameter Modelica.Units.SI.Temperature TEvaMin
    "Lower bound for evaporator temperature";
  parameter Real dTHys(
    final unit="K",
    min=Modelica.Constants.small) = 5
    "Hysteresis interval width";
  parameter Boolean pre_y_start=false "Value of pre(y) of hysteresis at initial time";

  Modelica.Blocks.Interfaces.RealInput u "Compressor control signal"

  Modelica.Blocks.Interfaces.RealInput TEva(
    unit="K",
    displayUnit="degC")
    "Evaporator temperature"
  Modelica.Blocks.Interfaces.RealInput TCon(
    unit="K",
    displayUnit="degC")
    "Condenser temperature"

  Modelica.Blocks.Interfaces.RealOutput y "Modified compressor control signal"

  Modelica.Blocks.Interfaces.BooleanOutput errHigPre
    "Error signal condenser upper bound temperature "
  Modelica.Blocks.Interfaces.BooleanOutput errLowPre
    "Error signal evaporator lower bound temperature "
  Modelica.Blocks.Interfaces.BooleanOutput errNegTemDif
    "Error signal if evaporator temperature is above condenser temperature"
protected
  Modelica.Blocks.Logical.Switch switch
    "Switches control signal off when conditions not satisfied"
  Modelica.Blocks.Logical.Hysteresis hysHig(uLow=0, uHigh=dTHys,
    final pre_y_start=pre_y_start)
    "Hysteresis for condenser upper bound temperature"
  Modelica.Blocks.Sources.Constant zero(final k=0)
    "Zero control signal when check fails"
  Modelica.Blocks.Logical.Hysteresis hysLow(uLow=0, uHigh=dTHys,
    final pre_y_start=pre_y_start)
    "Hysteresis for evaporator lower bound temperature"
  Modelica.Blocks.Sources.Constant TMax(final k=TConMax)
    "Condenser maximum temperature"
  Modelica.Blocks.Math.Add dTCon(k2=-1)
    "Difference between condenser temperature and its upper bound"
  Modelica.Blocks.Math.Add dTEva(k1=-1)
    "Difference between evaporator temperature and its lower bound"
  Modelica.Blocks.Sources.Constant TMin(final k=TEvaMin)
    "Evaporator minimum temperature"
  Modelica.Blocks.MathBoolean.And on(nu=3) "Compressor status"

  Modelica.Blocks.Logical.Hysteresis hysdTConEva(
    final uLow=0,
    final uHigh=dTHys,
    final pre_y_start=pre_y_start)
    "Hysteresis for temperature difference between evaporator and condenser"
  Modelica.Blocks.Math.Add dTEvaCon(final k1=-1)
    "Difference between evaporator and condenser"
  Modelica.Blocks.MathBoolean.Not notEva "Negation of signal"
  Modelica.Blocks.MathBoolean.Not notdT "Negation of signal"
  Modelica.Blocks.MathBoolean.Not notCon "Negation of signal"
equation
  connect(zero.y,switch. u3)
  connect(u, switch.u1)
  connect(switch.y, y)
  connect(TMax.y, dTCon.u1)
  connect(TMin.y, dTEva.u1)
  connect(dTEva.u2, TEva)
  connect(dTCon.u2, TCon)
  connect(dTEva.y, hysLow.u)
  connect(hysHig.u, dTCon.y)
  connect(on.y, switch.u2)
  connect(dTEvaCon.y, hysdTConEva.u)
  connect(dTEvaCon.u2, TCon)
  connect(dTEvaCon.u1, TEva)
  connect(hysLow.y, on.u[1])
  connect(hysdTConEva.y, on.u[2])
  connect(hysHig.y, on.u[3])
  connect(hysLow.y, notEva.u)
  connect(notEva.y, errLowPre)
  connect(notdT.u, hysdTConEva.y)
  connect(notdT.y, errNegTemDif)
  connect(notCon.y, errHigPre)
  connect(notCon.u, hysHig.y)
end TemperatureProtection;


Validation package

within Buildings.Fluid.HeatPumps.Compressors.BaseClasses;
package Validation "Validation package"
extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation of temperature protection model. Model that tests temperature protection functionality.

within Buildings.Fluid.HeatPumps.Compressors.BaseClasses.Validation;
model TemperatureProtection
  "Validation of temperature protection model"
  extends Modelica.Icons.Example;

  Buildings.Fluid.HeatPumps.Compressors.BaseClasses.TemperatureProtection
    temPro(TConMax=313.15, TEvaMin=278.15) "Temperature protection block"
  Modelica.Blocks.Sources.Cosine TEva(
    f=1,
    amplitude=10,
    offset=283.15) "Evaporator temperature"
  Modelica.Blocks.Sources.Cosine TCon(
    f=1.2,
    offset=303.15,
    amplitude=20) "Condenser temperature"
  Modelica.Blocks.Sources.Constant one(k=1) "Control signal"
equation
  connect(TEva.y, temPro.TEva)
  connect(temPro.TCon, TCon.y)
  connect(one.y, temPro.u)
end TemperatureProtection;


within Buildings.Fluid.HeatPumps.Compressors;
package Validation "Collection of models that validate the compressor models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Reciprocating compressor

within Buildings.Fluid.HeatPumps.Compressors.Validation;
model ReciprocatingCompressor
  extends Modelica.Icons.Example;
  Buildings.Fluid.HeatPumps.Compressors.ReciprocatingCompressor com(
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    pisDis=0.00162,
    cleFac=0.069,
    etaEle=0.696,
    PLos=100,
    dTSup=9.82,
    pDro=99290) "Reciprocating compressor"
  Buildings.HeatTransfer.Sources.FixedTemperature eva(T=253.15)
    "Evaporating temprature"
  Buildings.HeatTransfer.Sources.FixedTemperature con(T=323.15)
    "Condensing temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloEva
    "Evaporator heat flow rate sensor"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloCon
    "Condenser heat flow rate sensor"
  Modelica.Blocks.Sources.Constant on(k=1) "Compressor control signal"
equation
  connect(eva.port, heaFloEva.port_a)
  connect(heaFloEva.port_b, com.port_a)
  connect(com.port_b, heaFloCon.port_a)
  connect(heaFloCon.port_b, con.port)
  connect(on.y,com.y)
end ReciprocatingCompressor;


Reciprocating compressor

within Buildings.Fluid.HeatPumps.Compressors.Validation;
model ReciprocatingCompressor_ZeroInput
  extends Modelica.Icons.Example;
  Buildings.Fluid.HeatPumps.Compressors.ReciprocatingCompressor com(
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    pisDis=0.00162,
    cleFac=0.069,
    etaEle=0.696,
    PLos=100,
    dTSup=9.82,
    pDro=99290) "Reciprocating compressor"
  Buildings.HeatTransfer.Sources.FixedTemperature eva(T=253.15)
    "Evaporating temprature"
  Buildings.HeatTransfer.Sources.FixedTemperature con(T=323.15)
    "Condensing temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloEva
    "Evaporator heat flow rate sensor"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloCon
    "Condenser heat flow rate sensor"
  Modelica.Blocks.Sources.Constant on(k=0) "Compressor control signal"
equation
  connect(eva.port, heaFloEva.port_a)
  connect(heaFloEva.port_b, com.port_a)
  connect(com.port_b, heaFloCon.port_a)
  connect(heaFloCon.port_b, con.port)
  connect(on.y,com.y)
end ReciprocatingCompressor_ZeroInput;


Evaporating temperature

within Buildings.Fluid.HeatPumps.Compressors.Validation;
model ScrollCompressor
  extends Modelica.Icons.Example;
  Buildings.HeatTransfer.Sources.FixedTemperature eva(T=253.15)
    "Evaporating temperature"
  Buildings.HeatTransfer.Sources.FixedTemperature con(T=323.15)
    "Condensing temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloEva
    "Evaporator heat flow rate sensor"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloCon
    "Condenser heat flow rate sensor"
  Buildings.Fluid.HeatPumps.Compressors.ScrollCompressor com(
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    V_flow_nominal=0.003,
    leaCoe=0.005,
    etaEle=0.85,
    PLos=500,
    dTSup=3,
    volRat=2.1) "Scroll compressor"
  Modelica.Blocks.Sources.Constant on(k=1) "Compressor control signal"
equation
  connect(eva.port, heaFloEva.port_a)
  connect(heaFloCon.port_b, con.port)
  connect(com.port_b, heaFloCon.port_a)
  connect(heaFloEva.port_b, com.port_a)
  connect(on.y, com.y)
end ScrollCompressor;


Evaporating temperature

within Buildings.Fluid.HeatPumps.Compressors.Validation;
model ScrollCompressor_ZeroInput
  extends Modelica.Icons.Example;
  Buildings.HeatTransfer.Sources.FixedTemperature eva(T=253.15)
    "Evaporating temperature"
  Buildings.HeatTransfer.Sources.FixedTemperature con(T=323.15)
    "Condensing temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloEva
    "Evaporator heat flow rate sensor"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloCon
    "Condenser heat flow rate sensor"
  Buildings.Fluid.HeatPumps.Compressors.ScrollCompressor com(
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    V_flow_nominal=0.003,
    leaCoe=0.005,
    etaEle=0.85,
    PLos=500,
    dTSup=3,
    volRat=2.1) "Scroll compressor"
  Modelica.Blocks.Sources.Constant on(k=0) "Compressor control signal"
equation
  connect(eva.port, heaFloEva.port_a)
  connect(heaFloCon.port_b, con.port)
  connect(com.port_b, heaFloCon.port_a)
  connect(heaFloEva.port_b, com.port_a)
  connect(on.y, com.y)
end ScrollCompressor_ZeroInput;


within Buildings.Fluid.HeatPumps;
package Data "Package with model parameters for heat pumps"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Base classes for package Data

within Buildings.Fluid.HeatPumps.Data;
package BaseClasses "Base classes for package Data"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Fluid.HeatPumps.Data;
package EquationFitReversible "Package with model parameters for reverse heat pumps using the equation fit model"
  extends Modelica.Icons.MaterialPropertiesPackage;
end EquationFitReversible;


Base classes for package Data

within Buildings.Fluid.HeatPumps.Data.EquationFitReversible;
package BaseClasses "Base classes for package Data"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Fluid.HeatPumps.Data;
package ReciprocatingWaterToWater "Package with model parameters for reciprocating water to water heat pumps"
  extends Modelica.Icons.MaterialPropertiesPackage;
end ReciprocatingWaterToWater;


within Buildings.Fluid.HeatPumps.Data;
package ScrollWaterToWater "Package with model parameters for scroll water to water heat pumps"
  extends Modelica.Icons.MaterialPropertiesPackage;
end ScrollWaterToWater;


within Buildings.Fluid.HeatPumps.Data.ScrollWaterToWater;
package Heating "Records for scroll water to water heat pumps in heating mode"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Heating;


within Buildings.Fluid.HeatPumps.Examples;
model Carnot_TCon
  "Test model for heat pump based on Carnot efficiency and condenser 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=-5
    "Temperature difference evaporator inlet-outlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Modelica.Units.SI.HeatFlowRate QCon_flow_nominal=100E3
    "Evaporator heat flow rate";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=QCon_flow_nominal/
      dTCon_nominal/4200 "Nominal mass flow rate at condenser";

  Buildings.Fluid.HeatPumps.Carnot_TCon heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m1_flow_nominal=m1_flow_nominal,
    show_T=true,
    allowFlowReversal1=false,
    allowFlowReversal2=false,
    use_eta_Carnot_nominal=true,
    QCon_flow_nominal=QCon_flow_nominal,
    dp1_nominal=6000,
    dp2_nominal=6000) "Heat pump"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    m_flow=m1_flow_nominal,
    T=293.15)
  Buildings.Fluid.Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    use_T_in=false,
    use_m_flow_in=true,
    T=288.15)
  Modelica.Blocks.Sources.Ramp TConLvg(
    duration=60,
    startTime=1800,
    height=15,
    offset=273.15 + 35) "Control signal for condenser leaving temperature"
  Modelica.Blocks.Math.Gain mEva_flow(k=-1/cp2_default/dTEva_nominal)
    "Evaporator mass flow rate"
  Modelica.Blocks.Math.Add QEva_flow(k2=-1) "Evaporator heat flow rate"
  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1)

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp2_default=
      Medium2.specificHeatCapacityCp(Medium2.setState_pTX(
      Medium2.p_default,
      Medium2.T_default,
      Medium2.X_default))
    "Specific heat capacity of medium 2 at default medium state";

equation
  connect(sou1.ports[1], heaPum.port_a1)
  connect(sou2.ports[1], heaPum.port_a2)
  connect(QEva_flow.y,mEva_flow. u)
  connect(TConLvg.y, heaPum.TSet)
  connect(mEva_flow.y, sou2.m_flow_in)
  connect(QEva_flow.u1, heaPum.QCon_flow)
  connect(QEva_flow.u2, heaPum.P)
  connect(sin2.ports[1], heaPum.port_b2)
  connect(heaPum.port_b1, sin1.ports[1])
end Carnot_TCon;


within Buildings.Fluid.HeatPumps.Examples;
model Carnot_y "Test model for heat pump based on Carnot efficiency"
  extends Modelica.Icons.Example;
 package Medium1 = Buildings.Media.Water "Medium model";
 package Medium2 = Buildings.Media.Water "Medium model";
  parameter Real COP_nominal = 6 "Nominal COP";

  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 Modelica.Units.SI.MassFlowRate m2_flow_nominal=-P_nominal*(
      COP_nominal - 1)/cp2_default/dTEva_nominal
    "Nominal mass flow rate at chilled water side";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=P_nominal*
      COP_nominal/cp1_default/dTCon_nominal
    "Nominal mass flow rate at condenser water wide";
  Buildings.Fluid.HeatPumps.Carnot_y heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    P_nominal=P_nominal,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    dp1_nominal=6000,
    dp2_nominal=6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    use_eta_Carnot_nominal=false,
    COP_nominal=COP_nominal,
    TCon_nominal=303.15,
    TEva_nominal=278.15) "Heat pump 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"
  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 2 at default medium state";

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp2_default=
      Medium2.specificHeatCapacityCp(Medium2.setState_pTX(
      Medium2.p_default,
      Medium2.T_default,
      Medium2.X_default))
    "Specific heat capacity of medium 2 at default medium state";
equation
  connect(sou1.ports[1], heaPum.port_a1)
  connect(sou2.ports[1], heaPum.port_a2)
  connect(heaPum.port_b1, sin1.ports[1])
  connect(sin2.ports[1], heaPum.port_b2)
  connect(TCon_in.y, sou1.T_in)
  connect(TEva_in.y, sou2.T_in)
  connect(uCom.y, heaPum.y)
end Carnot_y;


within Buildings.Fluid.HeatPumps.Examples;
model EquationFitReversible
  "Test model for reverse heat pump based on performance curves"
 package Medium = Buildings.Media.Water "Medium model";

  parameter Data.EquationFitReversible.Trane_Axiom_EXW240 per
   "Reverse heat pump performance data"
  parameter Modelica.Units.SI.MassFlowRate mSou_flow_nominal=per.hea.mSou_flow
    "Source heat exchanger nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mLoa_flow_nominal=per.hea.mLoa_flow
    "Load heat exchanger nominal mass flow rate";

  Buildings.Fluid.HeatPumps.EquationFitReversible heaPum(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T1_start=281.4,
    per=per)
   "Water to Water heat pump"
  Modelica.Blocks.Math.RealToInteger reaToInt
   "Real to integer conversion"
  Sources.MassFlowSource_T loaPum(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    m_flow=mLoa_flow_nominal,
    use_T_in=true,
    nPorts=1)
   "Load Side water pump"
  Sources.MassFlowSource_T souPum(
    redeclare package Medium = Medium,
    m_flow=mSou_flow_nominal,
    nPorts=1,
    use_T_in=true)
   "Source side water pump"
  Modelica.Fluid.Sources.FixedBoundary loaVol(
     redeclare package Medium = Medium,
     nPorts=1)
   "Volume for the load side"
  Modelica.Fluid.Sources.FixedBoundary souVol(
     redeclare package Medium = Medium,
     nPorts=1)
   "Volume for source side"
  Controls.OBC.CDL.Reals.Sources.Ramp THeaLoaSet(
    height=5,
    duration(displayUnit="h") = 14400,
    offset=55 + 273.15)
   "Heating load side setpoint water temperature"
  Controls.OBC.CDL.Reals.Sources.Ramp TCooLoaSet(
    height=1,
    duration(displayUnit="h") = 14400,
    offset=6 + 273.15) "Cooling load setpoint water temperature"
  Controls.OBC.CDL.Integers.GreaterThreshold intGreThr(t=-1)
    "Integer threshold"
  Controls.OBC.CDL.Reals.Switch swi "Switch for set point temperature"
  Controls.OBC.CDL.Reals.Sources.Ramp TSouEntCoo(
    height=5,
    duration(displayUnit="h") = 14400,
    offset=28 + 273.15)
  "Source side entering water temperature in cooling mode"
  Modelica.Blocks.Sources.Ramp uMod(
    height=2,
    duration(displayUnit="h") = 14400,
    offset=-1) "Heat pump operates in heating mode"
  Controls.OBC.CDL.Reals.Switch swi1
   "Switch for set point temperature"
  Controls.OBC.CDL.Reals.Switch swi2
   "Switch for set point temperature"
  Controls.OBC.CDL.Reals.Sources.Ramp TSouEntHea(
    height=2,
    duration(displayUnit="h") = 14400,
    offset=12 + 273.15)
   "Source side entering water temperature in heating mode"
  Controls.OBC.CDL.Reals.Sources.Ramp TLoaEntHea(
    height=5,
    duration(displayUnit="h") = 14400,
    offset=50 + 273.15)
   "Load side entering water temperature  in heating mode"
  Controls.OBC.CDL.Reals.Sources.Ramp TLoaEntCoo(
    height=5,
    duration(displayUnit="h") = 14400,
    offset=10 + 273.15)
   "Load side entering water temperature in cooling mode"
equation
  connect(souPum.ports[1], heaPum.port_a2)
  connect(heaPum.port_b1, loaVol.ports[1])
  connect(heaPum.port_b2, souVol.ports[1])
  connect(swi.u2,intGreThr. y)
  connect(intGreThr.u, reaToInt.y)
  connect(reaToInt.u, uMod.y)
  connect(swi2.u3, TSouEntCoo.y)
  connect(TSouEntHea.y, swi2.u1)
  connect(intGreThr.y, swi2.u2)
  connect(swi1.y, loaPum.T_in)
  connect(intGreThr.y, swi1.u2)
  connect(TLoaEntCoo.y, swi1.u3)
  connect(TLoaEntHea.y, swi1.u1)
  connect(swi.y, heaPum.TSet)
  connect(swi2.y, souPum.T_in)
  connect(loaPum.ports[1], heaPum.port_a1)
  connect(THeaLoaSet.y, swi.u1)
  connect(TCooLoaSet.y, swi.u3)
  connect(reaToInt.y, heaPum.uMod)
end EquationFitReversible;


within Buildings.Fluid.HeatPumps.Examples;
model EquationFitReversible_CoolingClosedLoop
  "Test model for a closed loop of a reverse heat pump based on performance curves"
 package Medium = Buildings.Media.Water "Medium model";

  parameter Data.EquationFitReversible.Trane_Axiom_EXW240 per
   "Reversible heat pump performance data"
  parameter Modelica.Units.SI.MassFlowRate mSou_flow_nominal=per.hea.mSou_flow
    "Source heat exchanger nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mLoa_flow_nominal=per.hea.mLoa_flow
    "Load heat exchanger nominal mass flow rate";

  Buildings.Fluid.HeatPumps.EquationFitReversible heaPum(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    per=per,
    scaling_factor=1)
   "Reversible water to water heat pump"
  Modelica.Blocks.Math.RealToInteger reaToInt
   "Real to integer conversion"
  Sources.MassFlowSource_T souPum(
    redeclare package Medium = Medium,
    m_flow=mSou_flow_nominal,
    nPorts=1,
    use_T_in=true)
   "Source side water pump"
  Modelica.Fluid.Sources.FixedBoundary souVol(
     redeclare package Medium = Medium,
     nPorts=1)
   "Volume for source side"
  Controls.OBC.CDL.Reals.Sources.Pulse uMod(
    amplitude=-1,
    width=0.7,
    period=200,
    offset=0)
   "heat pump operational mode input signal"
  Controls.OBC.CDL.Reals.Sources.Pulse pulse(
    amplitude=1,
    width=0.7,
    period(displayUnit="s") = 200,
    offset=0)
  Modelica.Blocks.Math.Gain Q_flow(k=4200)
    "Heat input to volume"
  Modelica.Blocks.Math.Gain m_flow(k=mLoa_flow_nominal)
    "Pump mass flow rate"
  HeatTransfer.Sources.PrescribedHeatFlow heaFlo
    "Prescribed heat flow rate"
  Movers.FlowControlled_m_flow pum(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mLoa_flow_nominal,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true)
    "Chilled water pump"
  MixingVolumes.MixingVolume vol(
    redeclare package Medium = Medium,
    massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=285.15,
    m_flow_nominal=mLoa_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    V=0.1*3600*mLoa_flow_nominal/1000,
    nPorts=2)
    "Mixing volume mimics a room to be cooled"
  Controls.OBC.CDL.Reals.Sources.Pulse TSouEnt(
    amplitude=3,
    width=0.7,
    period=200,
    offset=25 + 273.15)
    "Source side entering water temperature"
  Controls.OBC.CDL.Reals.Sources.Pulse TLoaSet(
    y(final unit="K", displayUnit="degC"),
    amplitude=1,
    width=0.7,
    period=200,
    offset=6 + 273.15)
    "Set point chilled water temperature"
  Sources.Boundary_pT pre(
    redeclare package Medium = Medium,
    nPorts=1) "Pressure source."
equation
  connect(souPum.ports[1], heaPum.port_a2)
  connect(uMod.y, reaToInt.u)
  connect(reaToInt.y, heaPum.uMod)
  connect(heaPum.port_b2, souVol.ports[1])
  connect(pulse.y,m_flow. u)
  connect(m_flow.y,Q_flow. u)
  connect(heaFlo.port, vol.heatPort)
  connect(pum.port_a, vol.ports[1])
  connect(vol.ports[2], heaPum.port_b1)
  connect(pum.port_b, heaPum.port_a1)
  connect(m_flow.y, pum.m_flow_in)
  connect(Q_flow.y, heaFlo.Q_flow)
  connect(souPum.T_in, TSouEnt.y)
  connect(TLoaSet.y, heaPum.TSet)
  connect(pum.port_a, pre.ports[1])
end EquationFitReversible_CoolingClosedLoop;


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


within Buildings.Fluid.HeatPumps.Examples;
model ScrollWaterToWater_OneRoomRadiator
  "Heat pump with scroll compressor connected to a simple room model with radiator"
  extends Modelica.Icons.Example;
  replaceable package MediumA =
      Buildings.Media.Air "Medium model for air";
  replaceable package MediumW =
      Buildings.Media.Water "Medium model for water";

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=20000
    "Nominal heat flow rate of radiator";
  parameter Modelica.Units.SI.Temperature TRadSup_nominal=273.15 + 50
    "Radiator nominal supply water temperature";
  parameter Modelica.Units.SI.Temperature TRadRet_nominal=273.15 + 45
    "Radiator nominal return water temperature";
  parameter Modelica.Units.SI.MassFlowRate mHeaPum_flow_nominal=Q_flow_nominal/
      4200/5 "Heat pump nominal mass flow rate";
  parameter Modelica.Units.SI.Volume V=6*10*3 "Room volume";
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=V*1.2*6/3600
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=4000
    "Internal heat gains of the room";
//------------------------------------------------------------------------------//

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mA_flow_nominal,
    V=V)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20000/40)
    "Thermal conductance with the ambient"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea
    "Prescribed heat flow"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(C=2*V*1.2*1006)
    "Heat capacity for furniture and walls"
  Modelica.Blocks.Sources.CombiTimeTable timTab(
      extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
      smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
      table=[-6*3600, 0;
              8*3600, QRooInt_flow;
             18*3600, 0]) "Time table for internal heat gain"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=Q_flow_nominal,
    T_a_nominal=TRadSup_nominal,
    T_b_nominal=TRadRet_nominal,
    m_flow_nominal=mHeaPum_flow_nominal,
    T_start=TRadSup_nominal)     "Radiator"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(
    redeclare package Medium = MediumW,
    m_flow_nominal=mHeaPum_flow_nominal,
    T_start=TRadSup_nominal)            "Supply water temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temRoo
    "Room temperature"

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

  Buildings.Fluid.Movers.FlowControlled_m_flow pumHeaPum(
    redeclare package Medium = MediumW,
    m_flow_nominal=mHeaPum_flow_nominal,
    m_flow_start=0.85,
    T_start=TRadSup_nominal,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump for radiator side"
//----------------------------------------------------------------------------//

  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(
    redeclare package Medium = MediumW,
    m_flow_nominal=mHeaPum_flow_nominal,
    T_start=TRadSup_nominal) "Return water temperature"

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

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

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

  ScrollWaterToWater heaPum(
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    dp1_nominal=2000,
    dp2_nominal=2000,
    tau1=15,
    tau2=15,
    show_T=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m1_flow_nominal=mHeaPum_flow_nominal,
    m2_flow_nominal=mHeaPum_flow_nominal,
    datHeaPum=Data.ScrollWaterToWater.Heating.Daikin_WRA072_24kW_4_30COP_R410A(),
    T1_start=TRadSup_nominal)
    "Heat pump"

  Buildings.Fluid.Movers.FlowControlled_m_flow pumHeaPumSou(
    redeclare package Medium = MediumW,
    m_flow_start=0.85,
    m_flow_nominal=mHeaPum_flow_nominal,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump for heat pump source side"
  Modelica.Blocks.Logical.Hysteresis hysteresis(
    uLow=273.15 + 19,
    uHigh=273.15 + 21) "Hysteresis controller"
  Modelica.Blocks.Logical.Not not2 "Negate output of hysteresis"
  Modelica.Blocks.Math.BooleanToReal booToReaPum(realTrue=1, y(start=0))
    "Pump signal"
  Modelica.Blocks.Logical.And and1
  Modelica.Blocks.Logical.And and2
  Modelica.Blocks.Math.BooleanToReal booToReaPum1(
    realTrue=1,
    y(start=0))
    "Pump signal"
  Modelica.Blocks.Logical.Hysteresis tesConHea(
    uHigh=0.25*mHeaPum_flow_nominal,
    uLow=0.20*mHeaPum_flow_nominal) "Test for flow rate of condenser pump"
  Modelica.Blocks.Logical.Hysteresis tesEvaPum(
    uLow=0.20*mHeaPum_flow_nominal,
    uHigh=0.25*mHeaPum_flow_nominal) "Test for flow rate of evaporator pump"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = MediumW,
    T=281.15,
    nPorts=1) "Fluid source on source side"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = MediumW,
    T=283.15,
    nPorts=1) "Fluid sink on source side"
  Buildings.Fluid.Sources.Boundary_pT preSou(
    redeclare package Medium = MediumW,
    T=TRadSup_nominal,
    nPorts=1)
    "Source for pressure and to account for thermal expansion of water"

equation
  connect(theCon.port_b, vol.heatPort)
  connect(preHea.port, vol.heatPort)
  connect(heaCap.port, vol.heatPort)
  connect(timTab.y[1], preHea.Q_flow)
  connect(temSup.port_b, rad.port_a)
  connect(temRoo.port, vol.heatPort)
  connect(rad.heatPortCon, vol.heatPort)
  connect(rad.heatPortRad, vol.heatPort)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.TDryBul, TOut.T)
  connect(TOut.port, theCon.port_a)
  connect(temRet.port_b, heaPum.port_a1)
  connect(pumHeaPumSou.port_b, heaPum.port_a2)
  connect(hysteresis.y, not2.u)
  connect(temRoo.T, hysteresis.u)
  connect(pumHeaPum.port_b, temSup.port_a)
  connect(temRet.port_a, rad.port_b)
  connect(booToReaPum1.y, heaPum.y)
  connect(tesConHea.y, and1.u1)
  connect(tesEvaPum.y, and1.u2)
  connect(heaPum.port_b1, pumHeaPum.port_a)
  connect(booToReaPum.y, pumHeaPum.m_flow_in)
  connect(booToReaPum.y, pumHeaPumSou.m_flow_in)
  connect(not2.y, and2.u1)
  connect(not2.y, booToReaPum.u)
  connect(sou.ports[1], pumHeaPumSou.port_a)
  connect(sin.ports[1], heaPum.port_b2)
  connect(pumHeaPum.m_flow_actual, tesConHea.u)
  connect(and1.y, and2.u2)
  connect(pumHeaPumSou.m_flow_actual, tesEvaPum.u)
  connect(and2.y, booToReaPum1.u)
  connect(preSou.ports[1], temRet.port_b)
end ScrollWaterToWater_OneRoomRadiator;


within Buildings.Fluid.HeatPumps.ModularReversible;
model AirToWaterTableData2D
  "Reversible air to water heat pump based on 2D manufacturer data in Europe"
  extends Buildings.Fluid.HeatPumps.ModularReversible.TableData2D(
    redeclare replaceable package MediumEva = Buildings.Media.Air,
    redeclare replaceable package MediumCon = Buildings.Media.Water,
    redeclare replaceable Buildings.Fluid.HeatPumps.ModularReversible.Data.TableData2D.GenericAirToWater datTabHea
      constrainedby Buildings.Fluid.HeatPumps.ModularReversible.Data.TableData2D.GenericAirToWater,
    redeclare replaceable Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic datTabCoo
      constrainedby Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic);
end AirToWaterTableData2D;


Heat pump using the Carnot approach, but with added reversibility and losses (heat, frost, inertia). Model of a reversible heat pump.

within Buildings.Fluid.HeatPumps.ModularReversible;
model CarnotWithLosses
  "Heat pump using the Carnot approach, but with added reversibility and losses (heat, frost, inertia)"
  extends Buildings.Fluid.HeatPumps.ModularReversible.Modular(
    QCoo_flow_nominal=-PEle_nominal*refCyc.refCycHeaPumCoo.EER_nominal,
    redeclare model RefrigerantCycleHeatPumpCooling =
        Buildings.Fluid.Chillers.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 RefrigerantCycleHeatPumpHeating =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (
        redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.FunctionalIcingFactor
          iceFacCal(redeclare function icingFactor =
              Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.Functions.wetterAfjei1997),
        etaCarnot_nominal=etaCarnot_nominal,
        TAppCon_nominal=TAppCon_nominal,
        TAppEva_nominal=TAppEva_nominal),
    final allowDifferentDeviceIdentifiers=false,
    final use_evaCap,
    final use_conCap,
    redeclare model RefrigerantCycleInertia =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
        (
        final refIneFreConst=1/refIneTimCon,
        final nthOrd=nthOrd,
        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(min=1)=1 "Order of refrigerant cycle interia"

initial algorithm
  assert(use_rev and (abs(refCyc.refCycHeaPumCoo.PEle_nominal - PEle_nominal) / PEle_nominal < limWarSca),
    "In " + getInstanceName() + ": Nominal electrical powers for heating and cooling
    operation differ by " + String((refCyc.refCycHeaPumCoo.PEle_nominal - PEle_nominal) / PEle_nominal * 100) +
    " %. The simulated nominal heating and cooling
    capacities may not be realistic for a single device.",
    AssertionLevel.warning);
end CarnotWithLosses;


within Buildings.Fluid.HeatPumps.ModularReversible;
model LargeScaleWaterToWater
  "Model with automatic parameter estimation for large scale water-to-water heat pumps"
  extends Buildings.Fluid.HeatPumps.ModularReversible.TableData2D(
    redeclare replaceable package MediumCon = Buildings.Media.Water,
    redeclare replaceable package MediumEva = Buildings.Media.Water,
    final mCon_flow_nominal=autCalMasCon_flow,
    final mEva_flow_nominal=autCalMasEva_flow,
    final tauCon=autCalVCon*rhoCon/autCalMasCon_flow,
    final tauEva=autCalVEva*rhoEva/autCalMasEva_flow);

  extends Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.LargeScaleWaterToWaterDeclarations(
    final autCalMasCon_flow=max(4E-5*QHea_flow_nominal - 0.6162, autCalMMin_flow),
    final autCalMasEva_flow=max(4E-5*QHea_flow_nominal - 0.3177, autCalMMin_flow),
    final autCalVCon=max(1E-7*QHea_flow_nominal - 94E-4, autCalVMin),
    final autCalVEva=max(1E-7*QHea_flow_nominal - 75E-4, autCalVMin));
end LargeScaleWaterToWater;


Grey-box model for reversible and non-reversible heat pumps. Model of a reversible, modular heat pump.
  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.HeatPumps.ModularReversible;
model Modular
  "Grey-box model for reversible and non-reversible heat pumps"
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.PartialReversibleRefrigerantMachine(
    final use_COP=true,
    final use_EER=use_rev,
    con(preDro(m_flow(nominal=QHea_flow_nominal/1000/10))),
    eva(preDro(m_flow(nominal=QHea_flow_nominal/1000/10))),
    final PEle_nominal=refCyc.refCycHeaPumHea.PEle_nominal,
    mCon_flow_nominal=QHea_flow_nominal/(dTCon_nominal*cpCon),
    mEva_flow_nominal=(QHea_flow_nominal - PEle_nominal)/(dTEva_nominal*cpEva),
    use_rev=false,
    redeclare final Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.RefrigerantCycle refCyc(
      redeclare model RefrigerantCycleHeatPumpHeating =
          RefrigerantCycleHeatPumpHeating,
      redeclare model RefrigerantCycleHeatPumpCooling =
          RefrigerantCycleHeatPumpCooling,
      final allowDifferentDeviceIdentifiers=allowDifferentDeviceIdentifiers));
  parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal(min=Modelica.Constants.eps)
    "Nominal heating capacity"
  parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal(max=0)=0
    "Nominal cooling capacity"

  replaceable model RefrigerantCycleHeatPumpHeating =
    Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle
      (PEle_nominal=0)
       constrainedby
    Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle(
       final useInHeaPum=true,
       final QHea_flow_nominal=QHea_flow_nominal,
       final TCon_nominal=TConHea_nominal,
       final TEva_nominal=TEvaHea_nominal,
       final cpCon=cpCon,
       final cpEva=cpEva)
  "Refrigerant cycle module for the heating mode"

  replaceable model RefrigerantCycleHeatPumpCooling =
      Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.NoCooling
      constrainedby
    Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
       final useInChi=false,
       final cpCon=cpCon,
       final cpEva=cpEva,
       final TCon_nominal=TEvaCoo_nominal,
       final TEva_nominal=TConCoo_nominal,
       QCoo_flow_nominal=QCoo_flow_nominal)
  "Refrigerant cycle module for the cooling mode"
  parameter Modelica.Units.SI.Temperature TConHea_nominal
    "Nominal temperature of the heated fluid"
  parameter Modelica.Units.SI.Temperature TEvaHea_nominal
    "Nominal temperature of the cooled fluid"
  parameter Modelica.Units.SI.Temperature TConCoo_nominal
    "Nominal temperature of the cooled fluid"
  parameter Modelica.Units.SI.Temperature TEvaCoo_nominal
    "Nominal temperature of the heated fluid"

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


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


Reversible heat pump based on 2D manufacturer data. Heat pump based on
  two-dimensional data from manufacturer data, (e.g. based on EN 14511),
  using the

  Buildings.Fluid.HeatPumps.ModularReversible.Modular approach.

within Buildings.Fluid.HeatPumps.ModularReversible;
model TableData2D
  "Reversible heat pump based on 2D manufacturer data"
  extends Buildings.Fluid.HeatPumps.ModularReversible.Modular(
    final use_rev=true,
    QCoo_flow_nominal=refCyc.refCycHeaPumCoo.QCooNoSca_flow_nominal*scaFacHea,
    dpEva_nominal=datTabHea.dpEva_nominal*scaFacHea^2,
    dpCon_nominal=datTabHea.dpCon_nominal*scaFacHea^2,
    redeclare replaceable
      Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar constrainedby
      Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Generic(
      final tabUppHea=datTabHea.tabUppBou,
      final tabLowCoo=datTabCoo.tabLowBou,
      final use_TConOutHea=datTabHea.use_TConOutForOpeEnv,
      final use_TEvaOutHea=datTabHea.use_TEvaOutForOpeEnv,
      final use_TConOutCoo=datTabCoo.use_TConOutForOpeEnv,
      final use_TEvaOutCoo=datTabCoo.use_TEvaOutForOpeEnv),
    dTEva_nominal=(QHea_flow_nominal - PEle_nominal)/cpEva/mEva_flow_nominal,
    mEva_flow_nominal=datTabHea.mEva_flow_nominal*scaFacHea,
    mCon_flow_nominal=datTabHea.mCon_flow_nominal*scaFacHea,
    dTCon_nominal=QHea_flow_nominal/cpCon/mCon_flow_nominal,
    GEvaIns=0,
    GEvaOut=0,
    CEva=0,
    use_evaCap=false,
    GConIns=0,
    GConOut=0,
    CCon=0,
    use_conCap=false,
    redeclare model RefrigerantCycleHeatPumpCooling =
        Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D (
        redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal,
        final mCon_flow_nominal=mCon_flow_nominal,
        final mEva_flow_nominal=mEva_flow_nominal,
        final smoothness=smoothness,
        final extrapolation=extrapolation,
        final datTab=datTabCoo),
    redeclare model RefrigerantCycleHeatPumpHeating =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
        redeclare
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal,
        final mCon_flow_nominal=mCon_flow_nominal,
        final mEva_flow_nominal=mEva_flow_nominal,
        final smoothness=smoothness,
        final extrapolation=extrapolation,
        final datTab=datTabHea),
    redeclare model RefrigerantCycleInertia =
        Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.NoInertia);
  final parameter Real scaFacHea=refCyc.refCycHeaPumHea.scaFac
    "Scaling factor of heat pump";
  final parameter Real scaFacCoo=refCyc.refCycHeaPumCoo.scaFac
    "Scaling factor for cooling mode";

  replaceable parameter
    Buildings.Fluid.HeatPumps.ModularReversible.Data.TableData2D.GenericHeatPump datTabHea
    constrainedby
    Buildings.Fluid.HeatPumps.ModularReversible.Data.TableData2D.GenericHeatPump
    "Data table of heat pump"
  replaceable parameter Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic datTabCoo(
      use_TEvaOutForTab=true, use_TConOutForTab=true)
    constrainedby
    Buildings.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic
    "Data table of chiller"

  parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
    "Smoothness of table interpolation"
  parameter Modelica.Blocks.Types.Extrapolation extrapolation=Modelica.Blocks.Types.Extrapolation.LastTwoPoints
    "Extrapolation of data outside the definition range"
initial algorithm
  assert(use_rev and (abs(scaFacHea - scaFacCoo) / scaFacHea < limWarSca),
    "In " + getInstanceName() + ": Scaling factors for heating and cooling
    operation differ by " + String((scaFacHea - scaFacCoo) / scaFacHea * 100) +
    " %. The simulated nominal heating and cooling
    capacities may not be realistic for a single device",
    AssertionLevel.warning);
end TableData2D;


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

  They may be on/off and inverter driven;

  They are able reverse the operation between heating to cooling;

  They operate in a limited characteristic range (operational envelope);

  The design depends on various nominal boundary conditions;

  Safety features are part of their control sequence.

  To what extend all these effects need to be modeled depends
  on the simulation aim. Sometimes a simple Carnot approach is
  sufficient, sometimes a more detailed performance data
  and a realistic control behaviour is required.

  The modular approach allows to disable any irrelevant features,
  select readily made functional modules, and
  easily add new model modules.
  Relevant components are declared as replaceable.
  Replaceable models are constrainedby partial models
  which one is free to extend. Thus, new model approaches can be inserted
  into the framework of the modular reversible model approach.
  For users not familiar with replaceable models,
  there are readily assembled models as well.

Package and model structure

  This section explains the inheritance and model package structure
  to help navigate through all options and to check out the
  detailed documentation of each model for further information.

  All modular heat pump or chiller models base on the model

  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle.
  This partial model declares all common interfaces, parameters, etc.

Heat pump models

For heat pumps, the model
Buildings.Fluid.HeatPumps.ModularReversible.Modular extends the partial model and adds
the connector hea to choose
between the operation modes of the heat pump:

hea = true: Main operation mode (heating)

hea = false: Reversed operation mode (cooling)

Furthermore, the refrigerant cycle is redeclared to use the one for
the heat pump

Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.RefrigerantCycle.
This refrigerant cycle in turn contains replaceable models for the
heating and cooling operation of the heat pump.
Available modules can be found in the package:

Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle
For more information on the refrigerant cycle models, refer
to the section Refrigerant cycle models.

  There are a number of preconfigured models provided in the package.
  Please check out the documentation of each approach
  to check if this approach is suitable.

  Buildings.Fluid.HeatPumps.ModularReversible.LargeScaleWaterToWater

  Buildings.Fluid.HeatPumps.ModularReversible.AirToWaterTableData2D

  Buildings.Fluid.HeatPumps.ModularReversible.CarnotWithLosses

Chiller models

For chillers, the model
Buildings.Fluid.Chillers.ModularReversible.Modular extends the partial model and adds
the connector coo to choose
between the operation mode of the chiller:

coo = true: Main operation mode (cooling)

coo = false: Reversed operation mode (heating)

Furthermore, the refrigerant cycle is redeclared to use the one for
the chiller

Buildings.Fluid.Chillers.ModularReversible.BaseClasses.RefrigerantCycle.
This refrigerant cycle in turn contains replaceable models for the
cooling and heating operation of the chiller.
Available modules can be found in the package:

Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.
For more information on the refrigerant cycle models, refer
to the section Refrigerant cycle models.

  There are a number of preconfigured models provided in the package.
  Please check out the documentation of each approach
  to check if this approach is suitable.

  Buildings.Fluid.Chillers.ModularReversible.LargeScaleWaterToWater

  Buildings.Fluid.Chillers.ModularReversible.CarnotWithLosses

Naming and reversible operation

Simulating reversible heat pumps and chillers can get confusing, as the same heat
exchanger model has to be used for both condensation and evaporation.

In most cases, heat pumps and chillers extract/exhaust heat from/to
an ambient source (air, soil, ground-water, etc.),
and, consuming electrical energy, provide heating or cooling
on the useful or load side.
For building applications, this useful / load side is inside the building.
The ambient heat is outside of the building, on the ambient / source side.
However, vapor compression machines can also be used to provide heating
and cooling simultaneously.
In this case, both sides provide utility to the energy system.
Hence, both sides are useful / load sides.

What always stays the same is that there is one heated fluid, and
one cooled fluid. Thus, specifying the nominal temperatures, users have
to specify the temperatures of both heated and cooled fluids, for both cooling
and heating operation. Note, that the heated fluid will be the cooled fluid in
reversed operation, and vice versa.

Because of this, we decided on a naming scheme which is based on the main operation
of the heat pump or chiller. The main operation of a heat pump is heating, for
a chiller, it is cooling. When reversed, the condenser becomes the evaporator and
vice versa. As renaming instances after translation is not possible, users always
have to think about the names con and eva in terms of
the main operation of the device.
This applies to the instance and variable names,
such as the heat exchangers con and eva,
as well as sensors such as TConOutMea and TEvaInMea,
or nominal conditions TConHea_nominal and TConCoo_nominal.

As the nominal temperatures may be used table-based performance data
and the operational envelope model,
users also have to think about the useful / load
and ambient / source side and how they translate to
heat pumps and chillers in both main and reversed operation
when adding new datasheets.
Thinking about the heated and cooled fluid helps.

The following tables summarizes the possible options.

      Heat pump main
      Heat pump reversed
      Chiller main
      Chiller reversed

      Heating / cooling?
      heating
      cooling
      cooling
      heating

      Table-data: column 1: useful / load side
      con
      con 1
      eva
      eva 2

      Table-data - row 1: ambient / source side
      eva
      eva 2
      con
      con 1

      Operational envelope - column 1: ambient / source side
      eva
      eva 2
      con
      con 1

      Operational envelope - column 2: useful / load side
      con
      con 1
      eva
      eva 2

Footnotes:

1 In reality, the condenser, e.g. a plate heat exchanger, of the main operation is used for evaporation.
2 In reality, the evaporator, e.g. fin-tube heat exchanger, of the main operation is used for condensation.

Connectors

  Aside from the aforementioned Boolean signals
  hea and coo, the following
  connectors are relevant to understanding how the model works:
  Compressor speed and the expandable bus connector.

  The ambient temperatures TEvaAmb and TConAmb are
  only relevant for the heat losses.
  The fluid ports are explained in more detail here:
Buildings.Fluid.UsersGuide.

Compressor speed

  The input ySet represents the relative compressor speed.
  To model both on/off and inverter controlled refrigerant machines,
  the compressor speed is normalised to a relative value between 0 and 1.
  To model heat pumps other than inverter driven,
  other signal limits can be used.

  If data is in Hz or similar, consider converting
  the input according to the maximum allowed value.

  We use the notation Set to indicate a set value.
  It may be modified by the safety control blocks which produces a signal
  with the Mea notation. For example, the compressor
  speed ySet is modified by the safety
  control block to yMea. If no safety violations
  occur, ySet equals yMea.

Expandable bus connector

  As the modular approach may require different information to model
  the refrigerant cycle depending on configuration, all available states and outputs
  are aggregated in the expandable bus connector sigBus.
  For instance, in order to control both chillers and heat pumps,
  both flow and return temperature are relevant.

Refrigerant cycle models

  A replaceable refrigerant cycle model for heating or
  cooling calculates the electrical power consumption
  PEle, condenser heat flow rate QCon_flow
  and evaporator heat flow rate QEva_flow based on the
  values in the sigBus.
  Heat pumps models extend

  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle
  and chiller models extend

  Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle.

  Currently, two modules for refrigerant cycle are implemented.
  First, the
  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness model
  uses the same equations as the Carnot models, i.e.
  Buildings.Fluid.HeatPumps.Carnot_y.
  Second, the
  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D provides performance data
  based on different condenser outlet and evaporator inlet temperatures using 2D-tables.

  Two additional modules exist in the AixLib library.
  These approaches require the use of the SDF-library, as
  the compressor speed influences the model output as a third
  dimension. Currently, tables with more than two dimensions are not supported in
  the Modelica Standard Library.
  The first approach is similar to
  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D
  approach buts adds the 3rd dimension of compressor speed.
  The second approach is based on white-box stationary Python models
  for closed-loop refrigerant cycles. The model has been empirically
  validated and can take up to n-dimensions.
  If your simulation aim requires more detailed data, be sure
  to check out the models in the AixLib.

Parameterization and naming

  The refrigerant cycle models will output
  varying heat flow rates and electrical power consumptions.
  This is based on the fact that refrigerant cycle performance
  depend heavily on the boundary conditions.

  Still, the user needs to size the device or the system
  according to some reference points. Accordingly, we follow
  the basic Buildings concept for nominal conditions, explained in
  detail here:
  Buildings.Fluid.UsersGuide

  The nominal heat flow rate of the device is distinct for
  heat pumps and chillers.
  For heat pumps, it is the nominal
  condenser heat flow rate QHea_flow_nominal.
  For chillers, it is the nominal
  evaporator heat flow rate QCoo_flow_nominal (negative).
  This nominal heat flow rate is only valid at the
  nominal conditions. Whether parameters influence the nominal heat flow rates
  depends on the model approach used to estimate the heat flow rate and efficiencies.
  Typically, at least nominal source and sink temperatures will influence the
  nominal conditions:

  condenser temperature TCon_nominal,

  evaporator temperature TEva_nominal,

  Depending on the model in use, this may be inlet or outlet.

  Another example would be inverter driven devices.
  Here, the compressor speed influences the
  refrigerant mass flow rate and compressor efficiencies.
  If the performance data is dependent on the compressor speed,
  y_nominal influences the nominal efficiencies.
  In such cases, specifying additional nominal parameters will
  be nessary.

  Using the nominal conditions and the specified heat flow rate,
  the nominal electrical power consumption PEle_nominal is calculated.
  As reversible devices have typically a four-way-valve and a single
  compressor, you have to make sure that the values for PEle_nominal
  are similar between heating and cooling. The pre-configured models
  warn about deviations if they are too large.

  To change the capacity of the model, users should change
  QHea_flow_nominal for heating operation and
  QCoo_flow_nominal for cooling operation. This will then also
  update the electricity use PEle_nominal.

  For models with table-based performance curves, changing these values will also scale
  the design mass flow rates and pressure drops.
  The documentation of

  Buildings.Fluid.HeatPumps.ModularReversible.TableData2D
  further explains the scaling.

Safety controls

  Refrigerant machines contain internal safety controls,
  prohibiting operations in possibly unsafe points.
  All ModularReversible models account for those.
  All options can be disabled as described in the model description

  Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.Safety

  An important safety control with regard to
  system interaction is the operation envelope. Read the documentation of

  Buildings.Fluid.HeatPumps.ModularReversible.Controls.Safety.BaseClasses.PartialOperationalEnvelope
  for more information on this model and how it affects device operation.

Refrigerant cycle inertia

  The refrigerant cycle models
  are based on stationary data points, any inertia
  (mass and thermal) of components inside the refrigerant cycle
  (compressor, pipes, expansion valve, fluid, etc.) is neglected.
  To overcome this issue, replaceable SISO blocks that are connected to the
  output of the refrigerant cycle (instance refCyc)
  can approximate the refrigerant cycle inertia.

  The package

  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias
  contains implemented inertia models. In the
  contribution, an empirical
  validation showed that a third-order critical damping element
  fits the inertia most closely. At the same time, models in literature
  often use first-order delay blocks.
  Additionally, higher-order elements require more computation time.
  At the end, the requirements on the analysis will define the required level
  of detail of the model.

  The effect of the inertia can be removed by setting NoInertia.

  If a user finds in real data that another approach might be better suited
  (e.g. a deadband), then the model

  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.BaseClasses.PartialInertia

  can be extended to implement a costum model.

Frost

  To simulate possible icing of the evaporator on air-source devices, the
  icing factor iceFac is used to modify the outputs.
  The factor models the reduction of heat transfer between refrigerant
  and source. Thus, the factor is implemented as follows:

  QEva_flow = iceFac * (QConNoIce_flow - PEle)

  With iceFac as a relative value between 0 and 1:

iceFac = kA/kA_noIce

Finally, the energy balance must still hold:

QCon_flow = PEle + QEva_flow

  Different options can be selected for the modeling of the icing factor, or
  a custom model can be implemented by extending

  Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.BaseClasses.PartialIcingFactor

  Note however, that this only simulates the efficiency reduction
  due to frost. If a user-provided frost module enables the simulation
  of a defrost cycle, the user needs to implement the corresponding external controls.
  The iceFac approach was already used by Vering et al., 2021,
  to account for reverse cycle defrost based on validated literature-data.
  However, as no empirical validation was performed, the model was not
  added to the Buildings library.

Heat losses

  Most refrigerant cycle models that calculate
  PEle, QCon_flow, and QEva_flow
  assume the device to be adiabatic, following the equation:

  QCon_flow = PEle + QEva_flow

  Depending on the application, one may need to model
  the heat losses to the ambient, as those may
  impact the overall efficiency of the heat pump or chiller.
  Thus, the heat exchangers in the models adds
  thermal capacities to the adiabatic heat exchanger.
  The parameterization may be challenging, as datasheets
  do not contain parameters for the required values.
  Besides empirical calibration, simplified
  assumptions (e.g. 2% heat loss) may be used to
  parameterize the required values.
  For more information, see the description of

  Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.EvaporatorCondenserWithCapacity

References

  Fabian Wuellhorst, David Jansen, Philipp Mehrfeld and Dirk Müller.

  A Modular Model of Reversible Heat Pumps and Chillers for System Applications.

  Proceedings of 14th Modelica Conference 2021. Linköping, Sweden, September, 2021.

  doi:10.3384/ecp21181561.

Christian Vering, Fabian Wüllhorst, Philipp Mehrfeld and Dirk Müller.

Towards an integrated design of heat pump systems: Application of process intensification using two-stage optimization.

Energy Conversion and Management, Volume 250, 2021.

doi:10.1016/j.enconman.2021.114888.

"));

end UsersGuide;


Calculate the COP or EER of a device. This model is used to calculate the COP or the EER of a device. As
  the electrical power can get zero, a lower boundary is used to
  avoid division by zero.

within Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses;
model CalculateEfficiency
  "Calculate the COP or EER of a device"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Power PEleMin(min=Modelica.Constants.eps)
    "If eletrical power consumption falls below this value, COP will be set to zero";

  Modelica.Blocks.Interfaces.RealInput PEle(final unit="W", displayUnit="W")
    "Electrical power consumed by the system"
  Modelica.Blocks.Interfaces.RealInput QUse_flow(final unit="W", displayUnit="W")
    "Useful heat flow"
  Modelica.Blocks.Interfaces.RealOutput COP(min=0, final unit="1")
    "Output for calculated COP value"
  Modelica.Blocks.Logical.Hysteresis hys(
    uLow=PEleMin,
    uHigh=PEleMin*1.1)
    "Hysteresis to switch between calculation and no calculation"
  Modelica.Blocks.Interfaces.BooleanInput hea
    "=true for heating, false for cooling"
  Modelica.Blocks.Interfaces.RealOutput EER(min=0, final unit="1")
    "Output for calculated EER value"
  Buildings.Utilities.Math.InverseXRegularized invXReg(delta=PEleMin)
    "Inverse of electrical power"
protected
  Modelica.Blocks.Math.Product  copCom "Computes COP"
  Modelica.Blocks.Logical.Switch swi
    "Outputs COP or zero depending on electricity use"
  Modelica.Blocks.Sources.Constant zer(final k=0) "Outputs zero"
  Modelica.Blocks.Logical.Switch swiCoo "Switch for cooling and EER calculation"
  Modelica.Blocks.Logical.Switch swiHea "Switch for heating and COP calculation"
protected
  Modelica.Blocks.Math.Abs absQEva_flow
    "Negates possibly negative usefule flow rates"
initial equation
  assert(PEleMin > 0,
    "In " + getInstanceName() + ": PEleMin must be greater than zero. Disable efficiency calculation using
    calEff=false to debug why PEle_nominal is lower than zero.",
    AssertionLevel.error);

equation

  connect(hys.u, PEle)
  connect(hys.y, swi.u2)
  connect(copCom.y, swi.u1)
  connect(zer.y, swi.u3)
  connect(swiCoo.y, EER)
  connect(swiHea.y, COP)
  connect(hea, swiHea.u2)
  connect(swi.y, swiHea.u1)
  connect(swiHea.u3, zer.y)
  connect(hea, swiCoo.u2)
  connect(swi.y, swiCoo.u3)
  connect(zer.y, swiCoo.u1)
  connect(QUse_flow, absQEva_flow.u)
  connect(absQEva_flow.y, copCom.u1)
  connect(copCom.u2, invXReg.y)
  connect(invXReg.u, PEle)
end CalculateEfficiency;


Evaporaotr or condenser model with added capacity for heat losses to the ambient. Model for an evaporator or condenser with the use of a capacity to
  simulate heat losses.

within Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses;
model EvaporatorCondenserWithCapacity
  "Evaporaotr or condenser model with added capacity for heat losses to the ambient"
  extends Buildings.Fluid.Interfaces.TwoPortHeatMassExchanger(
    redeclare final Buildings.Fluid.MixingVolumes.MixingVolume vol(final V=
          m_flow_nominal*tau/rho_default,
    final prescribedHeatFlowRate=true));

  parameter Boolean isCon "=true for condenser, false for evaporator"
  parameter Boolean use_cap=true
    "False if capacity and heat losses are neglected"
  parameter Modelica.Units.SI.HeatCapacity C
    "Capacity of heat exchanger, set to zero to ignore its dry mass"
  parameter Modelica.Units.SI.Temperature TCap_start=Medium.T_default
    "Initial temperature of heat capacity"
  Modelica.Units.SI.ThermalConductance GOut
    "Exterior heat transfer coefficient,
    set to zero to ignore external heat loss but keep the dry mass"
  Modelica.Blocks.Interfaces.RealOutput GInn
    "Interior heat transfer coefficient"
  Modelica.Thermal.HeatTransfer.Components.Convection conIns if use_cap
    "Convection between the wall and the working fluid"
  Modelica.Thermal.HeatTransfer.Components.Convection conOut if use_cap
    "Convection and conduction between the wall and ambient air"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heaCap(
    final C=C,
    final T(final fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial),
        final start=TCap_start),
    final der_T(final fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial),
        start=0)) if use_cap "Heat Capacity"
  Modelica.Blocks.Sources.RealExpression heaLosInt(final y=GInn) if use_cap
    "Nominal heat loss coefficient to the interior"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_out if use_cap
    "Temperature and heat flow to the ambient"
  Modelica.Blocks.Sources.RealExpression heaLosExt(final y=GOut) if use_cap
    "Nominal heat loss coefficient to the exterior"

  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea(final alpha=0,
      final T_ref=293.15) "Heat flow rate of the condenser"
  Modelica.Blocks.Interfaces.RealInput Q_flow
    "Heat flow rate from the refrigerant to the medium"

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senT
    "Temperature sensor for the condenser volume"
  Modelica.Blocks.Interfaces.RealOutput T(
    final unit="K",
    displayUnit="degC")
    "Temperature of the condenser volume"
equation
  connect(conIns.fluid, heaCap.port)
  connect(heaCap.port, conOut.solid)
  connect(conIns.Gc, heaLosInt.y)
  connect(conOut.fluid, port_out)
  connect(conOut.Gc, heaLosExt.y)
  connect(vol.heatPort, conIns.solid)
  connect(vol.heatPort, preHea.port)
  connect(preHea.Q_flow, Q_flow)
  connect(senT.port, vol.heatPort)
  connect(senT.T, T)
end EvaporatorCondenserWithCapacity;


Model with parameters for large scale water-to-water heat pump. This model provides declarations that auto-populate nominal mass flow rates
  and time constants (i.e. volumes) of the heat exchange based on
  the nominal electric power consumption of the chiller or heat pump.
  It is based on more than 20 datasets of water-to-water heat pumps
  from multiple manufacturers ranging from about 25 kW
  to 1 MW in nominal electric power consumption. The linear regressions with coefficients
  of determination above 91% give a good approximation of these
  parameters. Nevertheless, estimates for machines outside
  the given range should be checked for plausibility during simulation.

within Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses;
partial model LargeScaleWaterToWaterDeclarations
  "Model with parameters for large scale water-to-water heat pump"

  //Automatic calculation of mass flow rates and volumes of the evaporator
  // and condenser using linear regressions from data sheets of
  // heat pumps and chillers (water to water)

protected
  parameter Modelica.Units.SI.MassFlowRate autCalMMin_flow=0.3
    "Realistic mass flow minimum for simulation plausibility";
  parameter Modelica.Units.SI.Volume autCalVMin=0.003
    "Realistic volume minimum for simulation plausibility";

  parameter Modelica.Units.SI.MassFlowRate autCalMasEva_flow
    "Automatically calculated evaporator mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate autCalMasCon_flow
    "Automatically calculated condenser mass flow rate";
  parameter Modelica.Units.SI.Volume autCalVEva
    "Automatically calculated evaporator volume";
  parameter Modelica.Units.SI.Volume autCalVCon
    "Automatically calculated condenser volume";

initial equation
  //Control and feedback for the auto-calculation of condenser and evaporator data
  assert(
    autCalMasEva_flow > autCalMMin_flow and autCalMasEva_flow < 90,
    "In " + getInstanceName() + ": Given nominal heat output for auto-calculation of
    evaporator and condenser data is outside the range of data sheets
    considered. Verify the auto-calculated mass flows.",
    level=AssertionLevel.warning);
  assert(
    autCalVEva > autCalVMin and autCalVEva < 0.43,
  "In " + getInstanceName() + ": Given nominal heat output for auto-calculation of evaporator
  and condenser data is outside the range of data sheets considered.
  Verify the auto-calculated volumes.",
    level=AssertionLevel.warning);
end LargeScaleWaterToWaterDeclarations;


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


Partial refrigerant cycle model. Partial modular refrigerant cycle models for data and
  equation based approaches used in the model

  Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.PartialReversibleRefrigerantMachine.

within Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses;
partial model PartialModularRefrigerantCycle
  "Partial refrigerant cycle model"

  parameter Boolean use_rev=true
    "True if the refrigerant machine is reversible";

  Buildings.Fluid.HeatPumps.ModularReversible.BaseClasses.RefrigerantMachineControlBus sigBus
    "Signal bus with data for refrigerant models"
  Modelica.Blocks.Interfaces.RealOutput QCon_flow(
    final unit="W")
    "Heat flow rate from the refrigerant to the condenser medium"
  Modelica.Blocks.Interfaces.RealOutput QEva_flow(
    final unit="W")
    "Heat flow rate from the evaporator medium to the refrigerant"
  Modelica.Blocks.Logical.Switch swiQEva(
    u1(final unit="W"),
    u3(final unit="W"),
    y(final unit="W"))
    "Routing block that picks the component acting as evaporator"
  Modelica.Blocks.Logical.Switch swiQCon(
    y(final unit="W"),
    u1(final unit="W"),
    u3(final unit="W"))
    "Routing block that picks the component acting as condenser"
  Modelica.Blocks.Interfaces.RealOutput PEle(final unit="W")
    "Routing block that picks the component for electric power consumption"

  Modelica.Blocks.Logical.Switch swiPEle(
    u1(final unit="W"),
    u3(final unit="W"),
    y(final unit="W"))
    "Whether to use cooling or heating power output"
protected
  Modelica.Blocks.Routing.BooleanPassThrough pasTrhModSet
    "Pass through to enable assertion for non-reversible device";
equation
  assert(
    use_rev or (use_rev == false and pasTrhModSet.y == true),
    "In " + getInstanceName() + ": Can't turn to reversible operation mode on
    irreversible refrigerant machine.",
    level=AssertionLevel.error);

  connect(swiQEva.y, QEva_flow)
  connect(swiPEle.y, PEle)
  connect(swiQCon.y, QCon_flow)
end PartialModularRefrigerantCycle;