Inertia using a critical damper with variable order. Model that uses a variable order delay to account for inertia.

within Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias;
model VariableOrder
  "Inertia using a critical damper with variable order"
  extends BaseClasses.PartialInertia;

  parameter Modelica.Units.SI.Frequency refIneFreConst
    "Cut off frequency for inertia of refrigerant cycle"
  parameter Integer nthOrd=1 "Order of refrigerant cycle interia"
  parameter Real x_start[nthOrd]=zeros(nthOrd)
    "Initial or guess values of states"
  parameter Real yRefIne_start=0 "Initial or guess value of output (= state)"
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.NoInit
    "Type of initialization (1: no init, 2:
    steady state, 3: initial state, 4: initial output)";
  Modelica.Blocks.Continuous.CriticalDamping criDam(
    final n=nthOrd,
    final f=refIneFreConst,
    initType=initType,
    final x_start=x_start) "Variable order damping model"

equation
  connect(u, criDam.u)
  connect(criDam.y, y)
end VariableOrder;


This package contains partial model for inertia models.

within Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias;
package BaseClasses
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial inertia model. Partial model for inertia.
  This block is identical to

  Modelica.Blocks.Interfaces.SISO
  and is made to constrain the replaceable inertia module
  within other inertia models.

within Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.BaseClasses;
partial model PartialInertia "Partial inertia model"
  extends Modelica.Blocks.Interfaces.SISO;
end PartialInertia;


Calibrated constant Carnot effectiveness. This validation case uses a constant Carnot effectiveness
  to model the efficiency of the heat pump.

within Buildings.Fluid.HeatPumps.ModularReversible.Validation;
model ConstantCarnotEffectiveness
  extends Modelica.Icons.Example;
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.Validation.BaseClasses.PartialValidation(
     heaPum(
      QHea_flow_nominal=etaCarnot_nominal*PEle_nominal*heaPum.TConHea_nominal/(heaPum.TConHea_nominal
           - heaPum.TEvaHea_nominal),
      mCon_flow_nominal=mCon_flow_nominal,
      tauCon=VCon*heaPum.rhoCon/mCon_flow_nominal,
      redeclare model RefrigerantCycleInertia =
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
          (
          refIneFreConst=refIneFreConst,
          nthOrd=2,
          initType=Modelica.Blocks.Types.Init.InitialState),
      redeclare model RefrigerantCycleHeatPumpHeating =
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
          (TAppCon_nominal=0,
           TAppEva_nominal=0,
           etaCarnot_nominal=etaCarnot_nominal)));

  parameter Real etaCarnot_nominal=0.4318 "Calibrated constant Carnot effectiveness";
  parameter Modelica.Units.SI.Power PEle_nominal=1884.218212
    "Calibrated nominal electrical power consumption";

  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal=0.407396
    "Calibrated condenser nominal mass flow rate";
  parameter Modelica.Units.SI.Volume VCon=0.0015972
    "Calibrated condenser volume";
  parameter Modelica.Units.SI.Frequency refIneFreConst=13.2e-3
    "Calibrated cut off frequency for inertia of refrigerant cycle";
end ConstantCarnotEffectiveness;


Collection of validation models

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


Vaillaint_VWL101. This validation case uses table-based data for the heat pump.

within Buildings.Fluid.HeatPumps.ModularReversible.Validation;
model TableData2D
  extends Modelica.Icons.Example;
  extends
    Buildings.Fluid.HeatPumps.ModularReversible.Validation.BaseClasses.PartialValidation(
      heaPum(
      QHea_flow_nominal=heaPum.refCyc.refCycHeaPumHea.QHeaNoSca_flow_nominal,
      mCon_flow_nominal=mCon_flow_nominal,
      tauCon=VCon*heaPum.rhoCon/mCon_flow_nominal,
      redeclare model RefrigerantCycleInertia =
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
          (
          refIneFreConst=refIneFreConst,
          nthOrd=2,
          initType=Modelica.Blocks.Types.Init.InitialState),
      redeclare model RefrigerantCycleHeatPumpHeating =
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
            datTab=
              Buildings.Fluid.HeatPumps.ModularReversible.Data.TableData2D.GenericHeatPump(
              tabPEle=[0,273.15,283.15; 308.15,1300,1500; 328.15,1900,2300],
              mCon_flow_nominal=6100/5/4184,
              mEva_flow_nominal=4800/5/4184,
              dpCon_nominal=0,
              dpEva_nominal=0,
              devIde="Vaillaint_VWL101",
              use_TEvaOutForTab=false,
              use_TConOutForTab=true,
              tabQCon_flow=[0,273.15,283.15; 308.15,6100,8400; 328.15,5700,7600],
              tabUppBou=[-40,70; 40,70]))));

  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal=0.404317
    "Condenser nominal mass flow rate";
  parameter Modelica.Units.SI.Volume VCon=0.004473
    "Condenser volume";
  parameter Modelica.Units.SI.Frequency refIneFreConst=0.011848
    "Cut off frequency for inertia of refrigerant cycle";
end TableData2D;


Partial validation models

within Buildings.Fluid.HeatPumps.ModularReversible.Validation;
package BaseClasses "Partial validation models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Fluid.HeatPumps.ModularReversible.Validation.BaseClasses;
partial model PartialValidation
  "Validation base case for the reversible heat pump model."

  replaceable package MediumSin = Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
      "Medium of sink side"
  replaceable package MediumSou = Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
      "Medium of source side"
  Buildings.Fluid.Sources.MassFlowSource_T souSidMasFlowSou(
    use_m_flow_in=true,
    use_T_in=true,
    m_flow=1,
    nPorts=1,
    redeclare final package Medium = MediumSou,
    T=275.15) "Ideal mass flow source at the inlet of the source side"

  Buildings.Fluid.Sources.Boundary_pT souSidFixBou(
    nPorts=1,
    redeclare package Medium = MediumSou)
    "Fixed boundary at the outlet of the source side"
  Buildings.Fluid.HeatPumps.ModularReversible.Modular heaPum(
    redeclare final package MediumCon = MediumSin,
    redeclare final package MediumEva = MediumSou,
    final use_intSafCtr=false,
    TConHea_nominal=303.15,
    dTCon_nominal=5,
    CCon=0,
    GConOut=0,
    GConIns=0,
    TEvaHea_nominal=290.15,
    dTEva_nominal=5,
    mEva_flow_nominal=0.8,
    dpEva_nominal=0,
    dpCon_nominal=0,
    use_conCap=false,
    final use_rev=false,
    CEva=0,
    GEvaOut=0,
    GEvaIns=0,
    TEva_start=290.15,
    use_evaCap=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    TCon_start=303.15,
    redeclare model RefrigerantCycleHeatPumpCooling =
        Buildings.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.NoCooling)
    "Heat pump"

  Buildings.Fluid.Sources.Boundary_pT sinSidFixBou(redeclare final package Medium =
        MediumSin, nPorts=1) "Fixed boundary at the outlet of the sink side"
  Buildings.Fluid.Sources.MassFlowSource_T sinSidMasFlowSou(
    use_m_flow_in=true,
    use_T_in=true,
    m_flow=1,
    nPorts=1,
    redeclare final package Medium = MediumSin,
    T=275.15) "Ideal mass flow source at the inlet of the source side"

  Modelica.Blocks.Math.Gain mEva_flow(final k=heaPum.mEva_flow_nominal)
    "Gain to scale the time table output to flow rate"
  Modelica.Blocks.Math.Gain mCon_flow(final k=heaPum.mCon_flow_nominal)
    "Gain to scale the time table output to flow rate"
  Modelica.Blocks.Sources.CombiTimeTable tabMea(
    tableOnFile=true,
    tableName="MeasuredData",
    fileName=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/Data/Fluid/HeatPumps/Validation/MeasuredHeatPumpData.txt"),
    columns=2:10,
    extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint)
    "Table with measurement data"

  Modelica.Blocks.Interfaces.RealOutput TConOutMea(unit="K", displayUnit="degC")
    "Measured condenser outlet"
  Modelica.Blocks.Interfaces.RealOutput TEvaOutMea(unit="K", displayUnit="degC")
    "Measured evaporator outlet"
  Modelica.Blocks.Interfaces.RealOutput PEleMea(unit="W")
    "Measured electrical power consumption"
  Modelica.Blocks.Interfaces.RealOutput PEleSim(unit="W")
    "Simulated electrical power consumption"
  Modelica.Blocks.Interfaces.RealOutput TConOutSim(unit="K", displayUnit="degC")
    "Simulated condenser outlet"
  Modelica.Blocks.Interfaces.RealOutput TEvaOutSim(unit="K", displayUnit="degC")
    "Simulated evaporator outlet"
  Modelica.Blocks.Sources.RealExpression reaPEle(y=heaPum.refCyc.PEle)
    "Use of internal heat pump state for PEle"
  Modelica.Blocks.Sources.RealExpression reaTEvaOut(y=heaPum.eva.T)
    "Use of internal heat pump state for TEvaOut"
  Modelica.Blocks.Sources.RealExpression reaTConOut(y=heaPum.con.T)
    "Use of internal heat pump state for TConOut"
equation

  connect(souSidMasFlowSou.ports[1], heaPum.port_a2)
  connect(heaPum.port_b2, souSidFixBou.ports[1])
  connect(heaPum.port_b1, sinSidFixBou.ports[1])
  connect(heaPum.port_a1, sinSidMasFlowSou.ports[1])
  connect(mEva_flow.y, souSidMasFlowSou.m_flow_in)
  connect(sinSidMasFlowSou.m_flow_in, mCon_flow.y)
  connect(tabMea.y[5], mEva_flow.u)
  connect(tabMea.y[7], mCon_flow.u)
  connect(tabMea.y[6], heaPum.ySet)
  connect(tabMea.y[9], souSidMasFlowSou.T_in)
  connect(sinSidMasFlowSou.T_in, tabMea.y[1])
  connect(tabMea.y[2], TConOutMea)
  connect(tabMea.y[8], TEvaOutMea)
  connect(tabMea.y[3], PEleMea)
  connect(reaPEle.y, PEleSim)
  connect(TEvaOutSim, reaTEvaOut.y)
  connect(TConOutSim, reaTConOut.y)
end PartialValidation;


Example using the Carnot model approach

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

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


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

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


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


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

within Buildings.Fluid.HeatPumps.ModularReversible.Validation.Comparative;
model TableData2D "Validation case for table data approach"
  extends BaseClasses.PartialModularComparison(
    TEva_nominal=TEvaIn_nominal,
    TCon_nominal=TConIn_nominal,
    heaPum(redeclare model RefrigerantCycleHeatPumpHeating =
          Buildings.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
            datTab(
            tabPEle=[0,288.15,298.15; 293.15,12375.1,12375.1; 303.15,12375.1,
                12375.1],
            mCon_flow_nominal=m1_flow_nominal,
            mEva_flow_nominal=m2_flow_nominal,
            dpCon_nominal=0,
            dpEva_nominal=0,
            devIde="CarnotTableData",
            use_TEvaOutForTab=false,
            use_TConOutForTab=false,
            tabQCon_flow=[0,288.15,298.15; 293.15,34084.9,0; 303.15,30000,34620],

            tabUppBou=[273.15,273.15; 273.15,273.15],
            use_TEvaOutForOpeEnv=false,
            use_TConOutForOpeEnv=false))));

  extends Modelica.Icons.Example;
end TableData2D;


Package with partial validation models

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


within Buildings.Fluid.HeatPumps.ModularReversible.Validation.Comparative.BaseClasses;
partial model PartialComparison
  "Partial model to allow heat pump and chiller model comparison"
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.HeatFlowRate QUse_flow_nominal = 30E3
    "Nominal capacity";

  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.Pressure dp1_nominal=6000
    "Pressure difference over condenser";
  parameter Modelica.Units.SI.Pressure dp2_nominal=6000
    "Pressure difference over evaporator";
  parameter Real etaCarnot_nominal=0.3
    "Carnot effectiveness (=COP/COP_Carnot) used during simulation if use_eta_Carnot_nominal = true";
  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.Temperature T1_start=303.15
    "Initial or guess value of set point";
  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 T2_start=278.15
    "Initial or guess value of set point";

  parameter Modelica.Units.SI.Temperature TConIn_nominal=303.15
    "Nominal condenser inlet temperature";
  parameter Modelica.Units.SI.Temperature TEvaIn_nominal=288.15
    "Nominal condenser inlet temperature";

  parameter Modelica.Units.SI.Temperature TCon_nominal=TConIn_nominal + dTCon_nominal
    "Nominal condenser temperature";
  parameter Modelica.Units.SI.Temperature TEva_nominal=TEvaIn_nominal -
      dTEva_nominal
    "Nominal evaporator temperature";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal
    "Nominal mass flow rate at chilled water side";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal
    "Nominal mass flow rate at condenser water wide";
  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium1,
    use_T_in=true,
    m_flow=m1_flow_nominal,
    T=298.15) "Condenser mass flow source"
  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = Medium2,
    use_T_in=true,
    m_flow=m2_flow_nominal,
    T=291.15) "Evaporator mass flow source"
  Buildings.Fluid.Sources.Boundary_pT sin1(redeclare package Medium = Medium1)
  Buildings.Fluid.Sources.Boundary_pT sin2(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=TConIn_nominal - 10,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEva_in(
    height=10,
    duration=60,
    startTime=900,
    offset=TEvaIn_nominal) "Evaporator inlet temperature"
equation
  connect(TCon_in.y,sou1. T_in)
  connect(TEva_in.y,sou2. T_in)
end PartialComparison;


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

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

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


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

Buildings.Fluid.HeatPumps.Examples.Carnot_TCon
but has a part load efficiency that varies with the load.

within Buildings.Fluid.HeatPumps.Validation;
model Carnot_TCon_etaPL
  "Test model for the part load efficiency curve with condenser leaving temperature as input signal"
  extends Examples.Carnot_TCon(
    heaPum(a={0.7,0.3}),
    TConLvg(height=10, offset=273.15 + 25));
end Carnot_TCon_etaPL;


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

Buildings.Fluid.HeatPumps.Examples.Carnot_TCon
but limits the heating capacity.

within Buildings.Fluid.HeatPumps.Validation;
model Carnot_TCon_LimitedCapacity
  "Test model for Carnot_TCon with limited heating capacity"
  extends Examples.Carnot_TCon(heaPum(QCon_flow_max=250000));
end Carnot_TCon_LimitedCapacity;


Test model for Carnot_TCon with low condenser leaving water temperature. This example extends from

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

within Buildings.Fluid.HeatPumps.Validation;
model Carnot_TCon_LowTemperature
  "Test model for Carnot_TCon with low condenser leaving water temperature"
  extends Examples.Carnot_TCon(TConLvg(height=-32), sou1(use_T_in=true));
  Modelica.Blocks.Sources.Ramp TConEnt(
    duration=60,
    offset=273.15 + 20,
    startTime=3000,
    height=-19) "Control signal for condenser entering temperature"
equation
  connect(TConEnt.y, sou1.T_in)
end Carnot_TCon_LowTemperature;


within Buildings.Fluid.HeatPumps.Validation;
model Carnot_TCon_reverseFlow
  "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=-10
    "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";

  Modelica.Blocks.Sources.Constant TConLvg(k=273.15 + 40)
    "Control signal for condenser leaving temperature"

  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";
  Modelica.Blocks.Sources.Ramp mCon_flow(
    duration=60,
    startTime=1800,
    height=-2*m1_flow_nominal,
    offset=m1_flow_nominal) "Mass flow rate for condenser"
  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,
    use_eta_Carnot_nominal=true,
    QCon_flow_nominal=QCon_flow_nominal,
    allowFlowReversal1=true,
    allowFlowReversal2=true,
    dp1_nominal=6000,
    dp2_nominal=6000) "Heat pump"
  Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    use_m_flow_in=true,
    T=293.15)
  Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    use_T_in=false,
    use_m_flow_in=true,
    T=288.15)
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT sin2(
    nPorts=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.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.Sensors.TemperatureTwoPort senTConEnt(
    redeclare final package Medium = Medium1,
    final m_flow_nominal=m1_flow_nominal,
    tau=0) "Temperature sensor for fluid entering condenser"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTConLvg(
    redeclare final package Medium = Medium1,
    final m_flow_nominal=m1_flow_nominal,
    tau=0) "Temperature sensor for fluid leaving condenser"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTEvaLvg(
    redeclare final package Medium = Medium2,
    final m_flow_nominal=heaPum.m2_flow_nominal,
    tau=0) "Temperature sensor for fluid leaving evaporator"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTEvaEnt(
    redeclare final package Medium = Medium2,
    final m_flow_nominal=heaPum.m2_flow_nominal,
    tau=0) "Temperature sensor for fluid entering evaporator"
equation
  connect(QEva_flow.y,mEva_flow. u)
  connect(mEva_flow.y, sou2.m_flow_in)
  connect(TConLvg.y, heaPum.TSet)
  connect(mCon_flow.y, sou1.m_flow_in)
  connect(heaPum.QCon_flow, QEva_flow.u1)
  connect(QEva_flow.u2, heaPum.P)
  connect(sou1.ports[1], senTConEnt.port_a)
  connect(senTConEnt.port_b, heaPum.port_a1)
  connect(heaPum.port_b1, senTConLvg.port_a)
  connect(senTConLvg.port_b, sin1.ports[1])
  connect(sin2.ports[1], senTEvaLvg.port_b)
  connect(senTEvaLvg.port_a, heaPum.port_b2)
  connect(sou2.ports[1], senTEvaEnt.port_a)
  connect(senTEvaEnt.port_b, heaPum.port_a2)
end Carnot_TCon_reverseFlow;


Test model for heat pump based on Carnot efficiency with etaCar as parameter. This example extends from

Buildings.Fluid.HeatPumps.Examples.Carnot_y
but uses the parameter etaCar instead of COP_nominal.

within Buildings.Fluid.HeatPumps.Validation;
model Carnot_y_etaCar
  "Test model for heat pump based on Carnot efficiency with etaCar as parameter"
  extends Buildings.Fluid.HeatPumps.Examples.Carnot_y(
    heaPum(use_eta_Carnot_nominal=true,
           etaCarnot_nominal=0.494805));
end Carnot_y_etaCar;


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

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

within Buildings.Fluid.HeatPumps.Validation;
model Carnot_y_etaPL
  "Test model for the part load efficiency curve with compressor speed as input signal"
  extends Examples.Carnot_y(heaPum(a={0.7,0.3},
      T1_start=303.15,
      T2_start=278.15));

end Carnot_y_etaPL;


Validation with EnergyPlus model

within Buildings.Fluid.HeatPumps.Validation;
model EquationFitReversible_EnergyPlus "Validation with EnergyPlus model"

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

  parameter Data.EquationFitReversible.EnergyPlus perEP
    "EnergyPlus heat pump performance"
  parameter Modelica.Units.SI.MassFlowRate mSou_flow_nominal=perEP.hea.mSou_flow
    "Source heat exchanger nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mLoa_flow_nominal=perEP.hea.mLoa_flow
    "Load heat exchanger nominal mass flow rate";
  Buildings.Fluid.HeatPumps.EquationFitReversible heaPum(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    per=perEP,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Water to Water heat pump"
  Sources.MassFlowSource_T loaPum(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    m_flow=1.89,
    T=328.15,
    nPorts=1,
    use_T_in=true) "Load water pump"
  Sources.MassFlowSource_T souPum(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    m_flow=1.89,
    T=280.65,
    nPorts=1,
    use_T_in=true) "Source side water pump"
  Buildings.Fluid.Sources.Boundary_pT cooVol(
    redeclare package Medium = Medium, nPorts=1)
    "Volume for cooling load"
  Buildings.Fluid.Sources.Boundary_pT heaVol(
    redeclare package Medium = Medium, nPorts=1)
    "Volume for heating load"

  Modelica.Blocks.Sources.CombiTimeTable datRea(
    tableOnFile=true,
    fileName=ModelicaServices.ExternalReferences.loadResource(
    "modelica://Buildings//Resources/Data/Fluid/HeatPumps/Validation/EquationFitReversible_EnergyPlus/GSHPSimple-GLHE-ReverseHeatPump.dat"),
    verboseRead=false,
    tableName="EnergyPlus",
    columns=2:8,
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments)
    "Reader for \"GSHPSimple-GLHE-ReverseHeatPump.IDF\" energy plus example results"

  Controls.OBC.CDL.Integers.Sources.Constant uMod(k=1)
    "Heat pump operational mode"
  Buildings.Controls.OBC.UnitConversions.From_degC TLoaEnt
    "Block that converts entering water temperature of the load side"
  Buildings.Controls.OBC.UnitConversions.From_degC TSouEnt
    "Block that converts entering water temperature of the source side"
  Buildings.Controls.OBC.UnitConversions.From_degC TSetHea
    "Block that converts set point for leaving heating water temperature "
  Modelica.Blocks.Sources.RealExpression QSou_flow_EP(y=datRea.y[2])
    "EnergyPlus results: source side heat flow rate [W]"
  Modelica.Blocks.Sources.RealExpression QLoa_flow_EP(y=-datRea.y[3])
    "EnergyPlus results: load side heat flow rate [W]"
  Modelica.Blocks.Sources.RealExpression P_EP(y=datRea.y[1])
    "EnergyPlus results: compressr power [W]"
equation
  connect(heaPum.port_a1,loaPum. ports[1])
  connect(souPum.ports[1], heaPum.port_a2)
  connect(cooVol.ports[1], heaPum.port_b2)
  connect(heaPum.port_b1, heaVol.ports[1])
  connect(loaPum.T_in, TLoaEnt.y)
  connect(TSouEnt.y, souPum.T_in)
  connect(TSetHea.y, heaPum.TSet)
  connect(datRea.y[5], TLoaEnt.u)
  connect(datRea.y[4],TSetHea. u)
  connect(datRea.y[6], TSouEnt.u)
  connect(heaPum.uMod, uMod.y)
end EquationFitReversible_EnergyPlus;


within Buildings.Fluid.HeatPumps.Validation;
model EquationFitReversible_ScalingFactor
  "Test model for scaling up the reversible heat pump"
 extends Modelica.Icons.Example;
 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";
  parameter Real scaling_factor=2
    "Scaling factor for heat pump capacity";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium, nPorts=2)
    "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium, nPorts=2)
    "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium,
    m_flow=mLoa_flow_nominal,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1)
    "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    m_flow=mSou_flow_nominal,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1)
    "Source side flow source"
  EquationFitReversible heaPum(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    per=per,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Equation fit reverse heat pump"
  EquationFitReversible heaPum1(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    per=per,
    scaling_factor=scaling_factor,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Scaled equation fit reverse heat pump"
  Modelica.Fluid.Sources.MassFlowSource_T loa1(
    redeclare package Medium = Medium,
    m_flow=mLoa_flow_nominal,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1)
    "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium,
    m_flow=mSou_flow_nominal,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1)
    "Source side flow source"
  Modelica.Blocks.Sources.Constant TLoa(k=323.15)
    "Load side fluid temperature"
  Modelica.Blocks.Sources.Constant TSou(k=285.15)
    "Source side fluid temperature"
  Modelica.Blocks.Sources.RealExpression capErr(y=(heaPum1.QLoa_flow -
        scaling_factor*heaPum.QLoa_flow))
    "Apparent capacity of the heat pump"
  Modelica.Blocks.Sources.RealExpression mLoa(y=mLoa_flow_nominal)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=mSou_flow_nominal)
    "Source side mass flow rate"
  Modelica.Blocks.Math.RealToInteger reaToInt
    "Real to integer conversion"
  Controls.OBC.CDL.Reals.Sources.Ramp TLoaEntHea(
    height=4,
    duration(displayUnit="h") = 14400,
    offset=50 + 273.15,
    startTime=0) "Load side entering water temperature in heating mode"
  Modelica.Blocks.Sources.Pulse uMod(
    amplitude=1,
    width=70,
    period=500,
    offset=0,
    startTime=0) "Heat pump signal to operate in heating mode"
  Modelica.Blocks.Sources.RealExpression mSou1(y=mSou_flow_nominal*
        scaling_factor)
    "Source side mass flow rate"
  Modelica.Blocks.Sources.RealExpression mLoa1(y=mLoa_flow_nominal*
        scaling_factor)
    "Load side mass flwo rate"
equation
  connect(heaPum.port_a2, sou.ports[1])
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a1, loa.ports[1])
  connect(heaPum.port_b2, sin2.ports[1])
  connect(sin2.ports[2], heaPum1.port_b2)
  connect(sou1.ports[1], heaPum1.port_a2)
  connect(TSou.y, sou1.T_in)
  connect(sou.T_in, sou1.T_in)
  connect(TLoa.y, loa1.T_in)
  connect(TLoa.y, loa.T_in)
  connect(loa1.ports[1], heaPum1.port_a1)
  connect(heaPum1.port_b1, sin1.ports[2])
  connect(mLoa.y, loa.m_flow_in)
  connect(mSou.y, sou.m_flow_in)
  connect(TLoaEntHea.y, heaPum.TSet)
  connect(reaToInt.y, heaPum.uMod)
  connect(reaToInt.y, heaPum1.uMod)
  connect(reaToInt.u, uMod.y)
  connect(TLoaEntHea.y, heaPum1.TSet)
  connect(sou1.m_flow_in, mSou1.y)
  connect(loa1.m_flow_in, mLoa1.y)
end EquationFitReversible_ScalingFactor;


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


within Buildings.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_Dynamic
  "Test model for variable speed reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2,
    nPorts=2) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=2) "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flow rate"
  Buildings.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    show_T=true,
    enable_variable_speed=false,
    per=Buildings.Fluid.HeatPumps.Data.ReciprocatingWaterToWater.Generic(
        etaEle=0.696,
        PLos=100,
        dTSup=9.82,
        UACon=2210,
        UAEva=1540,
        pisDis=0.00162,
        cleFac=0.069,
        pDro=99290),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    enable_temperature_protection=false)
    "Reciprocating water to water heat pump"

  Buildings.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum1(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    tau1=15,
    tau2=15,
    enable_variable_speed=false,
    per=Buildings.Fluid.HeatPumps.Data.ReciprocatingWaterToWater.Generic(
        etaEle=0.696,
        PLos=100,
        dTSup=9.82,
        UACon=2210,
        UAEva=1540,
        pisDis=0.00162,
        cleFac=0.069,
        pDro=99290),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    enable_temperature_protection=false)
    "Reciprocating water to water heat pump with transient effects"

  Modelica.Blocks.Sources.Pulse N(width=60, period=500)
    "Heat pump control signal"
  Modelica.Fluid.Sources.MassFlowSource_T loa1(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.Constant TLoa(k=285.15) "Load side fluid temperature"
  Modelica.Blocks.Sources.Constant TSou(k=283.15)
    "Source side fluid temperature"
  Modelica.Blocks.Sources.RealExpression appCap(y=heaPum1.port_a1.m_flow*(
        heaPum1.port_b1.h_outflow - loa1.ports[1].h_outflow))
    "Apparent capacity of the heat pump"
  Modelica.Blocks.Math.RealToInteger realToInteger
equation
  connect(mSou.y, sou.m_flow_in)
  connect(heaPum.port_a2, sou.ports[1])
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a1, loa.ports[1])
  connect(heaPum.port_b2, sin2.ports[1])
  connect(sin2.ports[2], heaPum1.port_b2)
  connect(mLoa.y, loa.m_flow_in)
  connect(mLoa.y, loa1.m_flow_in)
  connect(sou1.ports[1], heaPum1.port_a2)
  connect(mSou.y, sou1.m_flow_in)
  connect(TSou.y, sou1.T_in)
  connect(sou.T_in, sou1.T_in)
  connect(TLoa.y, loa1.T_in)
  connect(TLoa.y, loa.T_in)
  connect(loa1.ports[1], heaPum1.port_a1)
  connect(heaPum1.port_b1, sin1.ports[2])
  connect(N.y, realToInteger.u)
  connect(realToInteger.y, heaPum.stage)
  connect(realToInteger.y, heaPum1.stage)
end ReciprocatingWaterToWater_Dynamic;


within Buildings.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_ScalingFactor
  "Test model for variable speed reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

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

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=2) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=2) "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad*scaling_factor)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource*scaling_factor)
    "Source side mass flow rate"
  Buildings.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    enable_variable_speed=false,
    per=Buildings.Fluid.HeatPumps.Data.ReciprocatingWaterToWater.Generic(
        etaEle=0.696,
        PLos=100,
        dTSup=9.82,
        UACon=2210,
        UAEva=1540,
        pisDis=0.00162,
        cleFac=0.069,
        pDro=99290),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    enable_temperature_protection=false)
    "Reciprocating water to water heat pump"

  Buildings.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum1(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    enable_variable_speed=false,
    scaling_factor=scaling_factor,
    m1_flow_nominal=m1_flow_nominal*scaling_factor,
    m2_flow_nominal=m2_flow_nominal*scaling_factor,
    per=Buildings.Fluid.HeatPumps.Data.ReciprocatingWaterToWater.Generic(
        etaEle=0.696,
        PLos=100,
        dTSup=9.82,
        UACon=2210,
        UAEva=1540,
        pisDis=0.00162,
        cleFac=0.069,
        pDro=99290),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    enable_temperature_protection=false)
    "Reciprocating water to water heat pump with transient effects"
  Modelica.Blocks.Sources.Pulse N(width=60, period=500)
    "Heat pump control signal"
  Modelica.Fluid.Sources.MassFlowSource_T loa1(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.Constant TLoa(k=285.15) "Load side fluid temperature"
  Modelica.Blocks.Sources.Constant TSou(k=283.15)
    "Source side fluid temperature"
  Modelica.Blocks.Sources.RealExpression capErr(y=(heaPum1.QCon_flow -
        scaling_factor*heaPum.QCon_flow))
    "Apparent capacity of the heat pump"
  Modelica.Blocks.Math.RealToInteger realToInteger
  Modelica.Blocks.Sources.RealExpression mLoa1(y=flowLoad)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou1(y=flowSource)
    "Source side mass flow rate"
equation
  connect(heaPum.port_a2, sou.ports[1])
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a1, loa.ports[1])
  connect(heaPum.port_b2, sin2.ports[1])
  connect(sin2.ports[2], heaPum1.port_b2)
  connect(mLoa.y, loa1.m_flow_in)
  connect(sou1.ports[1], heaPum1.port_a2)
  connect(mSou.y, sou1.m_flow_in)
  connect(TSou.y, sou1.T_in)
  connect(sou.T_in, sou1.T_in)
  connect(TLoa.y, loa1.T_in)
  connect(TLoa.y, loa.T_in)
  connect(loa1.ports[1], heaPum1.port_a1)
  connect(heaPum1.port_b1, sin1.ports[2])
  connect(N.y, realToInteger.u)
  connect(realToInteger.y, heaPum.stage)
  connect(realToInteger.y, heaPum1.stage)
  connect(mLoa1.y, loa.m_flow_in)
  connect(mSou1.y, sou.m_flow_in)
end ReciprocatingWaterToWater_ScalingFactor;


within Buildings.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_Static
  "Test model for static, reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum(
    per=Data.ReciprocatingWaterToWater.Generic(
        etaEle=0.696,
        PLos=100,
        dTSup=9.82,
        UACon=2210,
        UAEva=1540,
        pisDis=0.00162,
        cleFac=0.069,
        pDro=99290),
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=100,
    dp2_nominal=100,
    show_T=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    enable_temperature_protection=false)
    "Reciprocating water to water heat pump"

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=1) "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Sourc side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flow rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flow rate"
  Modelica.Blocks.Sources.Ramp yLoa(
    height=20,
    duration=750,
    offset=293.15,
    startTime=250) "Load side fluid temperature"
  Modelica.Blocks.Sources.Ramp ySou(
    height=20,
    duration=750,
    offset=283.15,
    startTime=0) "Source side fluid temperature"
  Modelica.Blocks.Sources.Constant          isOn(k=1)
    "Heat pump control signal"
equation
  connect(mSou.y, sou.m_flow_in)
  connect(mLoa.y, loa.m_flow_in)
  connect(yLoa.y, loa.T_in)
  connect(ySou.y, sou.T_in)
  connect(isOn.y,heaPum.y)
  connect(loa.ports[1], heaPum.port_a1)
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a2, sou.ports[1])
  connect(sin2.ports[1], heaPum.port_b2)
end ReciprocatingWaterToWater_Static;


within Buildings.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_VariableSpeed
  "Test model for reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=1) "Load side sink"

  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"

  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"

  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flow rate"

  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flow rate"

  Buildings.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    show_T=true,
    per=Buildings.Fluid.HeatPumps.Data.ReciprocatingWaterToWater.Generic(
        etaEle=0.696,
        PLos=100,
        dTSup=9.82,
        UACon=2210,
        UAEva=1540,
        pisDis=0.00162,
        cleFac=0.069,
        pDro=99290),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    enable_temperature_protection=false)
    "Reciprocating water to water heat pump"

  Modelica.Blocks.Sources.Trapezoid N(
    startTime=100,
    offset=0.0,
    rising=200,
    width=200,
    falling=200,
    period=1000) "Heat pump control signal"
  Modelica.Blocks.Sources.Constant TLoa(k=285.15) "Load side temperature"
  Modelica.Blocks.Sources.Constant TSou(k=283.15) "Source side temeprature"
equation
  connect(mSou.y, sou.m_flow_in)
  connect(mLoa.y, loa.m_flow_in)
  connect(N.y,heaPum.y)
  connect(TSou.y, sou.T_in)
  connect(TLoa.y, loa.T_in)
  connect(sin2.ports[1], heaPum.port_b2)
  connect(heaPum.port_a1, loa.ports[1])
  connect(heaPum.port_b1, sin1.ports[1])
  connect(sou.ports[1], heaPum.port_a2)
end ReciprocatingWaterToWater_VariableSpeed;


within Buildings.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_Dynamic
  "Test model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=2) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=2) "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flow rate"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    enable_variable_speed=false,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    enable_temperature_protection=false) "Scroll water to water heat pump"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum1(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    tau1=15,
    tau2=15,
    enable_variable_speed=false,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    enable_temperature_protection=false)
    "Scroll water to water heat pump with transient effects"
  Modelica.Blocks.Sources.Pulse N(width=60, period=500)
    "Heat pump control signal"
  Modelica.Fluid.Sources.MassFlowSource_T loa1(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.Constant TLoa(k=285.15) "Load side fluid temperature"
  Modelica.Blocks.Sources.Constant TSou(k=283.15)
    "Source side fluid temperature"
  Modelica.Blocks.Sources.RealExpression appCap(y=heaPum1.port_a1.m_flow*(
        heaPum1.port_b1.h_outflow - loa1.ports[1].h_outflow))
    "Apparent capacity of the heat pump"
  Modelica.Blocks.Math.RealToInteger realToInteger
equation
  connect(mSou.y, sou.m_flow_in)
  connect(heaPum.port_a2, sou.ports[1])
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a1, loa.ports[1])
  connect(heaPum.port_b2, sin2.ports[1])
  connect(sin2.ports[2], heaPum1.port_b2)
  connect(mLoa.y, loa.m_flow_in)
  connect(mLoa.y, loa1.m_flow_in)
  connect(sou1.ports[1], heaPum1.port_a2)
  connect(mSou.y, sou1.m_flow_in)
  connect(TSou.y, sou1.T_in)
  connect(sou.T_in, sou1.T_in)
  connect(TLoa.y, loa1.T_in)
  connect(TLoa.y, loa.T_in)
  connect(loa1.ports[1], heaPum1.port_a1)
  connect(heaPum1.port_b1, sin1.ports[2])
  connect(N.y, realToInteger.u)
  connect(realToInteger.y, heaPum.stage)
  connect(realToInteger.y, heaPum1.stage)
end ScrollWaterToWater_Dynamic;


within Buildings.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_ScalingFactor
  "Test model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

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

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=2) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=2) "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    enable_variable_speed=false,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    enable_temperature_protection=false) "Scroll water to water heat pump"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum1(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    enable_variable_speed=false,
    m1_flow_nominal=m1_flow_nominal*scaling_factor,
    m2_flow_nominal=m2_flow_nominal*scaling_factor,
    scaling_factor=scaling_factor,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    enable_temperature_protection=false)
    "Scroll water to water heat pump with transient effects"
  Modelica.Blocks.Sources.Pulse N(width=60, period=500)
    "Heat pump control signal"
  Modelica.Fluid.Sources.MassFlowSource_T loa1(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.Constant TLoa(k=285.15) "Load side fluid temperature"
  Modelica.Blocks.Sources.Constant TSou(k=283.15)
    "Source side fluid temperature"
  Modelica.Blocks.Math.RealToInteger realToInteger
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource*scaling_factor)
    "Source side mass flow rate"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad*scaling_factor)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mLoa1(
                                              y=flowLoad)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou1(
                                              y=flowSource)
    "Source side mass flow rate"
  Modelica.Blocks.Sources.RealExpression capErr(y=(heaPum1.QCon_flow -
        scaling_factor*heaPum.QCon_flow))
    "Apparent capacity of the heat pump"
equation
  connect(heaPum.port_a2, sou.ports[1])
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a1, loa.ports[1])
  connect(heaPum.port_b2, sin2.ports[1])
  connect(sin2.ports[2], heaPum1.port_b2)
  connect(sou1.ports[1], heaPum1.port_a2)
  connect(TSou.y, sou1.T_in)
  connect(sou.T_in, sou1.T_in)
  connect(TLoa.y, loa1.T_in)
  connect(TLoa.y, loa.T_in)
  connect(loa1.ports[1], heaPum1.port_a1)
  connect(heaPum1.port_b1, sin1.ports[2])
  connect(N.y, realToInteger.u)
  connect(realToInteger.y, heaPum.stage)
  connect(realToInteger.y, heaPum1.stage)
  connect(mLoa.y, loa1.m_flow_in)
  connect(mSou.y, sou1.m_flow_in)
  connect(mSou1.y, sou.m_flow_in)
  connect(mLoa1.y, loa.m_flow_in)
end ScrollWaterToWater_ScalingFactor;


within Buildings.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_Static
  "Test model for static scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=1) "Load side sink"
  Modelica.Blocks.Sources.Constant isOn(k=1)
    "Heat pump control signal"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flow rate"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    show_T=true,
    enable_variable_speed=true,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    enable_temperature_protection=false) "Scroll water to water heat pump"
  Modelica.Blocks.Sources.Ramp yLoa(
    height=20,
    duration=750,
    offset=293.15,
    startTime=250) "Load side fluid temperature"
  Modelica.Blocks.Sources.Ramp ySou(
    height=20,
    duration=750,
    offset=283.15,
    startTime=0) "Source side fluid temperature"
equation
  connect(mSou.y, sou.m_flow_in)
  connect(mLoa.y, loa.m_flow_in)
  connect(yLoa.y, loa.T_in)
  connect(ySou.y, sou.T_in)
  connect(isOn.y,heaPum.y)
  connect(sin2.ports[1], heaPum.port_b2)
  connect(sou.ports[1], heaPum.port_a2)
  connect(sin1.ports[1], heaPum.port_b1)
  connect(loa.ports[1], heaPum.port_a1)
end ScrollWaterToWater_Static;


within Buildings.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_TemperatureProtection
  "Test model for temperature protection of scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=1) "Load side sink"
  Modelica.Blocks.Sources.Constant isOn(k=1)
    "Heat pump control signal"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flwo rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flow rate"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    show_T=true,
    enable_variable_speed=true,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    TConMax=273.15 + 60,
    enable_temperature_protection=true) "Scroll water to water heat pump"
  Modelica.Blocks.Sources.Sine yLoa(
    startTime=250,
    f=1/600,
    amplitude=30,
    offset=313.15) "Load side fluid temperature"
  Modelica.Blocks.Sources.Cosine ySou(
    startTime=0,
    amplitude=20,
    offset=293.15,
    f=1/400) "Source side fluid temperature"
equation
  connect(mSou.y, sou.m_flow_in)
  connect(mLoa.y, loa.m_flow_in)
  connect(yLoa.y, loa.T_in)
  connect(ySou.y, sou.T_in)
  connect(isOn.y,heaPum.y)
  connect(sin2.ports[1], heaPum.port_b2)
  connect(sou.ports[1], heaPum.port_a2)
  connect(sin1.ports[1], heaPum.port_b1)
  connect(loa.ports[1], heaPum.port_a1)
end ScrollWaterToWater_TemperatureProtection;


within Buildings.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_VariableSpeed
  "Test model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water "Medium model";
  package Medium2 = Buildings.Media.Water "Medium model";

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

  parameter Modelica.Units.SI.MassFlowRate flowSource=0.79
    "Mass flow rate on the condenser side";
  parameter Modelica.Units.SI.MassFlowRate flowLoad=0.47
    "Mass flow rate on the evaporator side";

  Buildings.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1, nPorts=1) "Load side sink"
  Modelica.Fluid.Sources.MassFlowSource_T loa(
    redeclare package Medium = Medium1,
    m_flow=flowLoad,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Load side flow source"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium2,
    m_flow=flowSource,
    use_m_flow_in=true,
    use_T_in=true,
    nPorts=1) "Source side flow source"
  Modelica.Blocks.Sources.RealExpression mLoa(y=flowLoad)
    "Load side mass flow rate"
  Modelica.Blocks.Sources.RealExpression mSou(y=flowSource)
    "Source side mass flwo rate"
  Buildings.Fluid.HeatPumps.ScrollWaterToWater heaPum(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = Buildings.Media.Refrigerants.R410A,
    show_T=true,
    datHeaPum(
      etaEle=0.696,
      PLos=500,
      dTSup=10,
      UACon=4400,
      UAEva=4400,
      volRat=2,
      V_flow_nominal=0.003,
      leaCoe=0.01),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    enable_temperature_protection=false) "Scroll water to water heat pump"
  Modelica.Blocks.Sources.Ramp N(
    duration=800,
    startTime=100,
    height=1.0,
    offset=0.0) "Heat pump control signal"
  Modelica.Blocks.Sources.Constant TLoa(k=285.15) "Load side fluid temperature"
  Modelica.Blocks.Sources.Constant TSou(k=283.15)
    "Source side fluid temperature"
equation
  connect(mSou.y, sou.m_flow_in)
  connect(mLoa.y, loa.m_flow_in)
  connect(N.y,heaPum.y)
  connect(TSou.y, sou.T_in)
  connect(TLoa.y, loa.T_in)
  connect(sin2.ports[1], heaPum.port_b2)
  connect(loa.ports[1], heaPum.port_a1)
  connect(heaPum.port_b1, sin1.ports[1])
  connect(heaPum.port_a2, sou.ports[1])
end ScrollWaterToWater_VariableSpeed;


within Buildings.Fluid.Humidifiers;
model Humidifier_u
  "Ideal humidifier or dehumidifier with prescribed water mass flow rate addition or subtraction"
  extends Buildings.Fluid.Interfaces.TwoPortHeatMassExchanger(
    redeclare replaceable package Medium =
        Modelica.Media.Interfaces.PartialCondensingGases,
    redeclare final Buildings.Fluid.MixingVolumes.MixingVolumeMoistAir vol(
    final prescribedHeatFlowRate=true));

  parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal
    "Water mass flow rate at u=1, positive for humidification";

  Modelica.Blocks.Interfaces.RealInput u(unit="1") "Control input"

  Modelica.Blocks.Interfaces.RealOutput mWat_flow(unit="kg/s")
    "Water added to the fluid"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat port for total heat exchange with the control volume"

protected
  Modelica.Blocks.Math.Gain gai(final k=mWat_flow_nominal) "Gain"

equation
  connect(u, gai.u)
  connect(gai.y, vol.mWat_flow)
  connect(vol.heatPort, heatPort)

  connect(gai.y, mWat_flow)
end Humidifier_u;


Package with humidifier models

within Buildings.Fluid;
package Humidifiers "Package with humidifier models"
  extends Modelica.Icons.Package;
end Humidifiers;


within Buildings.Fluid.Humidifiers;
model SprayAirWasher_X
  "Spray air washer with leaving water mass fraction as input"
  extends Buildings.Fluid.HeatExchangers.BaseClasses.PartialPrescribedOutlet(
    redeclare replaceable package Medium =
        Modelica.Media.Interfaces.PartialCondensingGases,
    outCon(
      final T_start=293.15,
      final X_start=X_start,
      final use_TSet = true,
      final use_X_wSet = true,
      final QMax_flow = Modelica.Constants.inf,
      final QMin_flow = -Modelica.Constants.inf,
      final mWatMax_flow = mWatMax_flow,
      final mWatMin_flow = 0));

  parameter Modelica.Units.SI.MassFlowRate mWatMax_flow(min=0) = Modelica.Constants.inf
    "Maximum water mass flow rate addition (positive)"

  parameter Modelica.Units.SI.MassFraction X_start[Medium.nX]=Medium.X_default
    "Start value of mass fractions m_i/m"

  // Set maximum to a high value to avoid users mistakenly entering relative humidity.
  Modelica.Blocks.Interfaces.RealInput X_w(
    unit="1",
    min=0,
    max=0.03)
    "Set point for water vapor mass fraction in kg/kg total air of the fluid that leaves port_b"

  Modelica.Blocks.Interfaces.RealOutput mWat_flow(unit="kg/s")
    "Water added to the fluid (if flow is from port_a to port_b)"

protected
  constant Modelica.Units.SI.SpecificEnthalpy hSte=Medium.enthalpyOfLiquid(T=
      283.15) "Enthalpy of water at 10 degree Celsius";

  Modelica.Units.SI.SpecificEnthalpy hLea=inStream(port_a.h_outflow) + {hSte}*(
      port_b.Xi_outflow - inStream(port_a.Xi_outflow))
    "Approximation of leaving enthalpy, based on dh/dx=h_fg";

  Modelica.Blocks.Sources.RealExpression TLea(y=
    Medium.temperature_phX(p = port_b.p,
                           h = hLea,
                           X = port_b.Xi_outflow)) "Leaving air temperature"
equation
  connect(X_w, outCon.X_wSet)
  connect(outCon.mWat_flow, mWat_flow)

  connect(TLea.y, outCon.TSet)
end SprayAirWasher_X;


Steam humidifier with leaving water mass fraction as input. Model for a steam humidifier with a prescribed outlet water vapor mass fraction
in kg/kg total air.

within Buildings.Fluid.Humidifiers;
model SteamHumidifier_X
  "Steam humidifier with leaving water mass fraction as input"
  extends Buildings.Fluid.HeatExchangers.BaseClasses.PartialPrescribedOutlet(
    outCon(
      final T_start=293.15,
      final X_start=X_start,
      final use_TSet = true,
      final use_X_wSet = true,
      final QMax_flow = Modelica.Constants.inf,
      final QMin_flow = -Modelica.Constants.inf,
      final mWatMax_flow = mWatMax_flow,
      final mWatMin_flow = 0));

  parameter Modelica.Units.SI.MassFlowRate mWatMax_flow(min=0) = Modelica.Constants.inf
    "Maximum water mass flow rate addition (positive)"

  parameter Modelica.Units.SI.MassFraction X_start[Medium.nX]=Medium.X_default
    "Start value of mass fractions m_i/m"

  // Set maximum to a high value to avoid users mistakenly entering relative humidity.
  Modelica.Blocks.Interfaces.RealInput X_w(
    unit="1",
    min=0,
    max=0.03)
    "Set point for water vapor mass fraction in kg/kg total air of the fluid that leaves port_b"

  Modelica.Blocks.Interfaces.RealOutput mWat_flow(unit="kg/s")
    "Water added to the fluid (if flow is from port_a to port_b)"

  Modelica.Blocks.Interfaces.RealOutput Q_flow(unit="W")
    "Heat flow rate added to the fluid (if flow is from port_a to port_b)"
protected
  constant Modelica.Units.SI.SpecificEnthalpy hSte=
      Medium.enthalpyOfCondensingGas(T=373.15)
    "Enthalpy of steam at 100 degree Celsius";

  Modelica.Units.SI.SpecificEnthalpy hLea=inStream(port_a.h_outflow) + {hSte}*(
      port_b.Xi_outflow - inStream(port_a.Xi_outflow))
    "Approximation of leaving enthalpy, based on dh/dx=h_fg";

  Modelica.Blocks.Sources.RealExpression TLea(y=
    Medium.temperature_phX(p = port_b.p,
                           h = hLea,
                           X = port_b.Xi_outflow)) "Leaving air temperature"
equation
  connect(X_w, outCon.X_wSet)
  connect(outCon.mWat_flow, mWat_flow)

  connect(Q_flow, outCon.Q_flow)
  connect(TLea.y, outCon.TSet)
end SteamHumidifier_X;


within Buildings.Fluid.Humidifiers.Examples;
model Humidifier_u "Model that demonstrates the ideal humidifier model"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Air;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=3000/1000/20
    "Nominal mass flow rate";

  Buildings.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    use_T_in=false,
    nPorts=2,
    m_flow=2*m_flow_nominal,
    T=303.15) "Source"
  Buildings.Fluid.Humidifiers.Humidifier_u humSte(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=6000,
    tau=0,
    mWat_flow_nominal=m_flow_nominal*0.005,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Steady-state model of the humidifier"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTem1(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal) "Temperature sensor"
  Modelica.Blocks.Sources.TimeTable TSet(table=[0, 273.15 + 30; 120, 273.15 +
        30; 120, 273.15 + 25; 1200, 273.15 + 25]) "Setpoint"
  Buildings.Controls.Continuous.LimPID con1(
    Td=1,
    k=1,
    Ti=10,
    reverseActing=false) "Controller"
  Buildings.Fluid.Humidifiers.Humidifier_u humDyn(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=6000,
    mWat_flow_nominal=m_flow_nominal*0.005,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=303.15) "Dynamic model of the humidifier"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTem2(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal) "Temperature sensor"
  Buildings.Controls.Continuous.LimPID con2(
    Td=1,
    Ti=10,
    k=0.1,
    reverseActing=false) "Controller"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_T_in=false,
    p(displayUnit="Pa"),
    T=303.15,
    nPorts=2) "Sink"
equation
  connect(senTem1.T, con1.u_m)
  connect(TSet.y, con1.u_s)
  connect(con1.y, humSte.u)
  connect(humSte.port_b, senTem1.port_a)
  connect(senTem2.T, con2.u_m)
  connect(TSet.y, con2.u_s)
  connect(con2.y, humDyn.u)
  connect(humDyn.port_b, senTem2.port_a)

  connect(sou.ports[1], humSte.port_a)
  connect(sou.ports[2], humDyn.port_a)
  connect(senTem1.port_b, sin.ports[1])
  connect(senTem2.port_b, sin.ports[2])
end Humidifier_u;


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


Collection of validation models

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


within Buildings.Fluid.Humidifiers.Validation;
model SprayAirWasher_X
  "Model that demonstrates the spray air washer model, configured as steady-state"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Air;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.1
    "Nominal mass flow rate";

  parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal=m_flow_nominal*
      0.004 "Maximum humidification water mass flow rate";

  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_T_in=false,
    p(displayUnit="Pa"),
    T=293.15,
    nPorts=1) "Sink"

  replaceable Buildings.Fluid.Humidifiers.SprayAirWasher_X hum(
    mWatMax_flow=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
      constrainedby Buildings.Fluid.Humidifiers.SprayAirWasher_X(
        redeclare package Medium = Medium,
        m_flow_nominal=m_flow_nominal,
        dp_nominal=6000,
        show_T=true) "Humidifier with capacity limitation"

  Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=m_flow_nominal,
    T=293.15) "Flow source"

  Modelica.Blocks.Sources.CombiTimeTable XSet(
    tableOnFile=false,
    table=[
      0.0,   0.01;
      1*180, 0.012;
      2*180, 0.015;
      3*180, 0.01;
      4*180, 0.008;
      5*180, 0.004;
      6*180, 0.01],
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
    "Set point for humidity"

  Buildings.Fluid.Sensors.MassFractionTwoPort senHum(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0) "Mass fraction sensor"

equation
  connect(sou1.ports[1], hum.port_a)
  connect(XSet.y[1], hum.X_w)
  connect(hum.port_b, senHum.port_a)
  connect(senHum.port_b, sin.ports[1])
end SprayAirWasher_X;


Model that demonstrates the spray air washer model, configured as dynamic model. Model that validates the use of a spray air washer
configured as a dynamic model with limits on the maximum water mass flow rate
that is added to the air stream.

within Buildings.Fluid.Humidifiers.Validation;
model SprayAirWasher_X_dynamic
  "Model that demonstrates the spray air washer model, configured as dynamic model"
  extends Buildings.Fluid.Humidifiers.Validation.SprayAirWasher_X(
    hum(
     mWatMax_flow=mWat_flow_nominal,
     energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));
end SprayAirWasher_X_dynamic;


Model that demonstrates the steam humidifier model, configured as steady-state model. Model that validates the use of a spray air washer
configured as a steady-state model with limits on the maximum water mass flow rate
that is added to the air stream.

within Buildings.Fluid.Humidifiers.Validation;
model SteamHumidifier_X
  "Model that demonstrates the steam humidifier model, configured as steady-state model"
  extends Buildings.Fluid.Humidifiers.Validation.SprayAirWasher_X(
    redeclare Buildings.Fluid.Humidifiers.SteamHumidifier_X hum(
      mWatMax_flow=mWat_flow_nominal));
end SteamHumidifier_X;


Model that demonstrates the steam humidifier model, configured as dynamic model. Model that validates the use of a spray air washer
configured as a dynamic model with limits on the maximum water mass flow rate
that is added to the air stream.

within Buildings.Fluid.Humidifiers.Validation;
model SteamHumidifier_X_dynamic
  "Model that demonstrates the steam humidifier model, configured as dynamic model"
  extends Buildings.Fluid.Humidifiers.Validation.SprayAirWasher_X(
    redeclare Buildings.Fluid.Humidifiers.SteamHumidifier_X hum(
      mWatMax_flow=mWat_flow_nominal,
      energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));
end SteamHumidifier_X_dynamic;


within Buildings.Fluid;
package HydronicConfigurations "Package with common hydronic configurations"
  extends Modelica.Icons.VariantsPackage;
end HydronicConfigurations;


Package with type definitions

within Buildings.Fluid.HydronicConfigurations;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;
  type Control = enumeration(
      ChangeOver
    "Change-over",
      Cooling
    "Cooling",
      Heating
    "Heating",
      None
    "No built-in controls")
    "Enumeration to specify the type of valve controls"
  type ControlVariable = enumeration(
      ReturnTemperature
    "Consumer circuit return temperature",
      SupplyTemperature
    "Consumer circuit supply temperature")
    "Enumeration to specify the controlled variable"
  type Pump = enumeration(
      None
      "No pump",
      NoVariableInput
      "Constant input signal",
      VariableInput
      "Variable input signal")
    "Enumeration to specify the type of pump"
  type PumpModel = enumeration(
      Head
      "Pump with ideally controlled head as input",
      MassFlowRate
      "Pump with ideally controlled mass flow rate as input",
      Speed
      "Pump with ideally controlled normalized speed as input")
    "Enumeration to specify the type of pump model"
  type Valve = enumeration(
      None
    "No valve",
      ThreeWay
    "Three-way valve",
      TwoWay
    "Two-way valve")
    "Enumeration to specify the type of control valve"
  type ValveCharacteristic = enumeration(
      EqualPercentage
      "Equal percentage - Equal percentage and linear for three-way valves",
      Linear
      "Linear",
      PressureIndependent
      "Pressure independent (mass flow rate only dependent of input signal)",
      Table
      "Table-specified")
    "Enumeration to specify the control valve characteristic"
end Types;


User's Guide

within Buildings.Fluid.HydronicConfigurations;
package UsersGuide "User's Guide"
  extends Modelica.Icons.Information;

  class Overview "Overview of the configuration models"
    extends Modelica.Icons.Information;

  end Overview;

  class ModelParameters "Description of the model parameters"
    extends Modelica.Icons.Information;
  end ModelParameters;

  class ControlValves "About control valves"
    extends Modelica.Icons.Information;

  end ControlValves;

  class NomenclatureSymbols "Nomenclature and symbols"
    extends Modelica.Icons.Information;
  end NomenclatureSymbols;
end UsersGuide;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model Decoupling "Decoupling circuit with self-acting Delta-p control valve"
  extends Fluid.HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    dpBal3_nominal=if typCtl<>Buildings.Fluid.HydronicConfigurations.Types.Control.None
      then 1e4 else 0,
    dpValve_nominal=dp1_nominal/2,
    m1_flow_nominal(min=(1+1e-2)*m2_flow_nominal)=1.05 * m2_flow_nominal,
    k=5,
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.P,
    final typVal=Buildings.Fluid.HydronicConfigurations.Types.Valve.TwoWay,
    final have_set=false,
    final have_typVar=false,
    final use_dp1=use_siz,
    final use_dp2=use_siz and typPum<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None);

  FixedResistances.Junction junBypSup(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final m_flow_nominal=m1_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3))
    "Junction"
  FixedResistances.Junction junBypRet(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final m_flow_nominal=m1_flow_nominal .* {1,-1,1},
    final dp_nominal=fill(0, 3))
    "Junction"

  Components.TwoWayValve val(
    redeclare final package Medium = Medium,
    final typCha=typCha,
    use_strokeTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=if use_lumFloRes then dpBal1_nominal else 0,
    final flowCharacteristics=flowCharacteristics)
    "Control valve"

  FixedResistances.PressureDrop res1(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dp_nominal=if use_lumFloRes then 0 else dpBal1_nominal)
    "Primary balancing valve"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dp_nominal=dpBal2_nominal)
    "Secondary balancing valve"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(
    final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
  Components.Pump pum(
    redeclare final package Medium = Medium,
    final typ=typPum,
    final typMod=typPumMod,
    final m_flow_nominal=mPum_flow_nominal,
    final dp_nominal=dpPum_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final per=perPum) "Pump"
  Sensors.TemperatureTwoPort T2Sup(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit supply temperature sensor"
  Controls.PIDWithOperatingMode ctl(
    r=dpBal3_nominal,
    final reverseActing=true,
    final yMin=0,
    final yMax=1,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti)
    if typCtl <> Buildings.Fluid.HydronicConfigurations.Types.Control.None
    "Controller"
  Sensors.TemperatureTwoPort T2Ret(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
    else 1)
    "Consumer circuit return temperature sensor"
  FixedResistances.PressureDrop res3(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal-m2_flow_nominal,
    final dp_nominal=dpBal3_nominal)
    "Bypass balancing valve"
  Sensors.RelativePressure dp3(
    redeclare final package Medium = Medium)
    "Pressure drop across bypass balancing valve"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dp3Set(
    y(final unit="Pa"),
    final k=dpBal3_nominal)
    "Pressure differential set point"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger enaCtl
    "Enable signal for control loop"
equation
  connect(port_a1, junBypSup.port_1)
  connect(val.port_b, res1.port_a)
  connect(res1.port_b, port_b1)
  connect(mode, isEna.u)
  connect(junBypSup.port_2, pum.port_a)
  connect(pum.port_b, T2Sup.port_a)
  connect(T2Sup.port_b, port_b2)
  connect(ctl.y, val.y)
  connect(yVal, val.y)
  connect(val.y_actual, yVal_actual)
  connect(pum.y_actual, yPum_actual)
  connect(pum.P, PPum)
  connect(junBypRet.port_2, val.port_a)
  connect(res2.port_b, junBypRet.port_1)
  connect(port_a2, T2Ret.port_a)
  connect(T2Ret.port_b, res2.port_a)
  connect(junBypSup.port_3, res3.port_a)
  connect(res3.port_b, junBypRet.port_3)
  connect(dp3.port_a, res3.port_a)
  connect(dp3.port_b, res3.port_b)
  connect(dp3.p_rel, ctl.u_m)
  connect(dp3Set.y, ctl.u_s)
  connect(enaCtl.y, ctl.mode)
  connect(isEna.y, enaCtl.u)
  connect(isEna.y, pum.y1)
  connect(yPum, pum.y)
end Decoupling;


Diversion circuit

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model Diversion "Diversion circuit"
  extends Fluid.HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    dpValve_nominal=dp2_nominal,
    final m1_flow_nominal=m2_flow_nominal,
    final dpBal2_nominal=0,
    final typVal=Buildings.Fluid.HydronicConfigurations.Types.Valve.ThreeWay,
    final typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.None,
    final typCtl=Buildings.Fluid.HydronicConfigurations.Types.Control.None,
    final have_typVar=false,
    final use_dp1=false,
    final use_dp2=use_lumFloRes or use_siz);

  Buildings.Fluid.HydronicConfigurations.Components.ThreeWayValve val(
    redeclare final package Medium=Medium,
    final typCha=typCha,
    final energyDynamics=energyDynamics,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final portFlowDirection_1=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Entering,
    final m_flow_nominal=m2_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=if use_lumFloRes then {dp2_nominal, dpBal3_nominal} else
      {0, 0},
    final flowCharacteristics1=flowCharacteristics1,
    final flowCharacteristics3=flowCharacteristics3)
    "Control valve"
  Buildings.Fluid.FixedResistances.Junction jun(
    redeclare final package Medium=Medium,
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final m_flow_nominal=m2_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3))
    "Junction"
  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dp_nominal=dpBal1_nominal)
    "Primary balancing valve"
  FixedResistances.PressureDrop res3(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dp_nominal=if use_lumFloRes then 0 else dpBal3_nominal)
    "Bypass balancing valve"
equation
  connect(port_a2, val.port_1)
  connect(val.port_2,res1. port_a)
  connect(res1.port_b, port_b1)
  connect(jun.port_1, port_a1)
  connect(jun.port_2, port_b2)
  connect(yVal, val.y)
  connect(val.y_actual, yVal_actual)
  connect(jun.port_3, res3.port_a)
  connect(res3.port_b, val.port_3)
end Diversion;


Injection circuit with three-way valve

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model InjectionThreeWay "Injection circuit with three-way valve"
  extends Fluid.HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    dpValve_nominal=3e3,
    set(final unit="K", displayUnit="degC"),
    final dpBal3_nominal=0,
    final typVal=Buildings.Fluid.HydronicConfigurations.Types.Valve.ThreeWay,
    final have_typVar=true,
    final use_dp1=false,
    final use_dp2=use_siz and typPum<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None);

  Buildings.Fluid.HydronicConfigurations.Components.ThreeWayValve val(
    redeclare final package Medium=Medium,
    final typCha=typCha,
    final energyDynamics=energyDynamics,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final portFlowDirection_1=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Entering,
    final m_flow_nominal=m1_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal={0, 0},
    final flowCharacteristics1=flowCharacteristics1,
    final flowCharacteristics3=flowCharacteristics3)
    "Control valve"
  FixedResistances.Junction jun(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final m_flow_nominal=m1_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3)) "Junction"
  FixedResistances.Junction junBypSup(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final m_flow_nominal=m2_flow_nominal .* {1,-1,1},
    final dp_nominal=fill(0, 3))
    "Junction"
  FixedResistances.Junction junBypRet(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final m_flow_nominal=m2_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3))
    "Junction"
  FixedResistances.PressureDrop res1(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dp_nominal=dpBal1_nominal)
    "Primary balancing valve"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dp_nominal=dpBal2_nominal) "Secondary balancing valve"
  Buildings.Fluid.HydronicConfigurations.Components.Pump pum(
    redeclare final package Medium = Medium,
    final typ=typPum,
    final typMod=typPumMod,
    final m_flow_nominal=mPum_flow_nominal,
    final dp_nominal=dpPum_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final per=perPum) "Pump"
  Sensors.TemperatureTwoPort T2Sup(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit supply temperature sensor"
  Controls.PIDWithOperatingMode ctl(
    u_s(final unit="K", displayUnit="degC"),
    u_m(final unit="K", displayUnit="degC"),
    final reverseActing=typCtl == Buildings.Fluid.HydronicConfigurations.Types.Control.Heating,
    final yMin=0,
    final yMax=1,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti)
    if typCtl <> Buildings.Fluid.HydronicConfigurations.Types.Control.None
    "Controller"

  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(
    final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
  Sensors.TemperatureTwoPort T2Ret(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit return temperature sensor"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig(final nin=2)
    "Select measured signal"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant ctlVar(
    final k=Integer(typVar))
    "Controlled variable selector"
equation
  connect(jun.port_3, val.port_3)
  connect(junBypRet.port_2, val.port_1)
  connect(junBypSup.port_3, junBypRet.port_3)
  connect(jun.port_2, junBypSup.port_1)
  connect(port_a1, jun.port_1)
  connect(port_b1,res1. port_b)
  connect(res1.port_a, val.port_2)
  connect(res2.port_b, junBypRet.port_1)
  connect(junBypSup.port_2, pum.port_a)
  connect(pum.port_b, T2Sup.port_a)
  connect(T2Sup.port_b, port_b2)
  connect(mode, ctl.mode)
  connect(set, ctl.u_s)
  connect(yVal, val.y)
  connect(mode, isEna.u)
  connect(port_a2, T2Ret.port_a)
  connect(T2Ret.port_b,res2. port_a)
  connect(extIndSig.y, ctl.u_m)
  connect(T2Sup.T, extIndSig.u[2])
  connect(T2Ret.T, extIndSig.u[1])
  connect(ctl.y, val.y)
  connect(ctlVar.y, extIndSig.index)
  connect(val.y_actual, yVal_actual)
  connect(pum.P, PPum)
  connect(pum.y_actual, yPum_actual)
  connect(yPum, pum.y)
  connect(isEna.y, pum.y1)
end InjectionThreeWay;