Partial model with components for TableData2D approach for heat pumps and chillers. Partial model for equations and componenents used in both heat pump
  and chiller models using two-dimensional data.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses;
partial model PartialTableData2D
  "Partial model with components for TableData2D approach for heat pumps and chillers"
  parameter Real scaFac "Scaling factor";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal
    "Nominal mass flow rate in secondary condenser side"
  parameter Modelica.Units.SI.MassFlowRate mEva_flow_nominal
    "Nominal mass flow rate in secondary evaporator side"
  parameter Modelica.Blocks.Types.Smoothness smoothness=
    Modelica.Blocks.Types.Smoothness.LinearSegments
    "Smoothness of table interpolation";
  parameter Modelica.Blocks.Types.Extrapolation extrapolation=
    Modelica.Blocks.Types.Extrapolation.LastTwoPoints
    "Extrapolation of data outside the definition range";
  parameter Boolean use_TEvaOutForTab=true
    "=true to use evaporator outlet temperature, false for inlet";
  parameter Boolean use_TConOutForTab=true
    "=true to use condenser outlet temperature, false for inlet";
  Modelica.Blocks.Tables.CombiTable2Ds tabPEle(
    final tableOnFile=false,
    final tableName="NoName",
    final fileName="NoName",
    final verboseRead=true,
    final smoothness=smoothness,
    final u1(unit="K", displayUnit="degC"),
    final u2(unit="K", displayUnit="degC"),
    final y(unit="W"),
    final extrapolation=extrapolation) "Electrical power consumption table"
  Modelica.Blocks.Tables.CombiTable2Ds tabQUse_flow(
    final tableOnFile=false,
    final tableName="NoName",
    final fileName="NoName",
    final verboseRead=true,
    final smoothness=smoothness,
    final u1(unit="K", displayUnit="degC"),
    final u2(unit="K", displayUnit="degC"),
    final y(unit="W"),
    final extrapolation=extrapolation) "Table for useful heat flow rate"
  Modelica.Blocks.Math.Product yMeaTimScaFac
    "Create the product of the scaling factor and relative compressor speed"

  Modelica.Blocks.Math.Product scaFacTimPel "Scale electrical power consumption"
  Modelica.Blocks.Math.Product scaFacTimQUse_flow "Scale useful heat flow rate"
  Modelica.Blocks.Sources.Constant constScaFac(final k=scaFac)
    "Calculates correction of table output based on scaling factor"

  Modelica.Blocks.Routing.RealPassThrough reaPasThrTEvaIn if (not useInRevDev and not use_TEvaOutForTab) or (useInRevDev and not use_TConOutForTab)
    "Used to enable conditional bus connection"
  Modelica.Blocks.Routing.RealPassThrough reaPasThrTConIn if (not useInRevDev and not use_TConOutForTab) or (useInRevDev and not use_TEvaOutForTab)
    "Used to enable conditional bus connection"
  Modelica.Blocks.Routing.RealPassThrough reaPasThrTEvaOut if (not useInRevDev and use_TEvaOutForTab) or (useInRevDev and use_TConOutForTab)
    "Used to enable conditional bus connection"
  Modelica.Blocks.Routing.RealPassThrough reaPasThrTConOut if (not useInRevDev and use_TConOutForTab) or (useInRevDev and use_TEvaOutForTab)
    "Used to enable conditional bus connection"

protected
  parameter Boolean useInRevDev "=true to indicate usage in reversed operation";
  parameter Integer numRow=size(tabPEle.table, 1) "Number of rows in table";
  parameter Integer numCol=size(tabPEle.table, 2) "Number of columns in table";
  parameter Modelica.Units.SI.TemperatureDifference dTMin=3
    "Minimal temperature spread according to EN 14511";
  parameter Modelica.Units.SI.TemperatureDifference dTMax=10
    "Maximal temperature spread according to EN 14511";
  parameter Modelica.Units.SI.Power valTabPEle[numRow-1, numCol - 1]=
    {{tabPEle.table[j, i] for i in 2:numCol} for j in 2:numRow}
    "Table with electrical power values only";
  parameter Modelica.Units.SI.HeatFlowRate valTabQCon_flow[numRow-1, numCol - 1]
    "Table with condenser heat flow values only";
  parameter Modelica.Units.SI.HeatFlowRate valTabQEva_flow[numRow-1, numCol - 1]
    "Table with evaporator heat flow values only";
  parameter Modelica.Blocks.Types.ExternalCombiTable2D tabIdeQUse_flow=
      Modelica.Blocks.Types.ExternalCombiTable2D(
      "NoName",
      "NoName",
      tabQUse_flow.table,
      smoothness,
      extrapolation,
      false) "External table object for nominal useful side conditions";
  parameter Modelica.Blocks.Types.ExternalCombiTable2D tabIdePEle=
      Modelica.Blocks.Types.ExternalCombiTable2D(
      "NoName",
      "NoName",
      tabPEle.table,
      smoothness,
      extrapolation,
      false) "External table object for nominal electrical power consumption";
  parameter Modelica.Units.SI.MassFlowRate mEva_flow_min
    "Minimal evaporator mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mEva_flow_max
    "Maximal evaporator mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_min
    "Minimal evaporator mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_max
    "Maximal evaporator mass flow rate";
initial algorithm
  assert(mCon_flow_nominal >= mCon_flow_min,
    "In " + getInstanceName() + ": The nominal condenser mass flow rate ("
    + String(mCon_flow_nominal) + " kg/s) is smaller than the
    minimal value (" + String(mCon_flow_min) + " kg/s) for the table data
    when assuming a temperature spread between 3 and 10 K, as in EN 14511.",
    AssertionLevel.warning);
  assert(mCon_flow_nominal <= mCon_flow_max,
    "In " + getInstanceName() + ": The nominal condenser mass flow rate ("
    + String(mCon_flow_nominal) + " kg/s) is bigger than the
    maximal value (" + String(mCon_flow_max) + " kg/s) for the table data
    when assuming a temperature spread between 3 and 10 K, as in EN 14511.",
    AssertionLevel.warning);
  assert(mEva_flow_nominal >= mEva_flow_min,
    "In " + getInstanceName() + ": The nominal evaporator mass flow rate ("
    + String(mEva_flow_nominal) + " kg/s) is smaller than the
    minimal value (" + String(mEva_flow_min) + " kg/s) for the table data
    when assuming a temperature spread between 3 and 10 K, as in EN 14511.",
    AssertionLevel.warning);
  assert(mEva_flow_nominal <= mEva_flow_max,
    "In " + getInstanceName() + ": The nominal evaporator mass flow rate ("
    + String(mEva_flow_nominal) + " kg/s) is bigger than the
    maximal value (" + String(mEva_flow_max) + " kg/s) for the table data
    when assuming a temperature spread between 3 and 10 K, as in EN 14511.",
    AssertionLevel.warning);
equation
  connect(constScaFac.y,yMeaTimScaFac. u2)
  connect(scaFacTimPel.u2,yMeaTimScaFac. y)
  connect(tabQUse_flow.y, scaFacTimQUse_flow.u1)
  connect(scaFacTimQUse_flow.u2,yMeaTimScaFac. y)
  connect(tabPEle.y, scaFacTimPel.u1)
end PartialTableData2D;


Partial model with components for TableData3D approach for heat pumps and chillers. Partial model for equations and componenents used in both heat pump
  and chiller models using three-dimensional data.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses;
partial model PartialTableData3D
  "Partial model with components for TableData3D approach for heat pumps and chillers"
  extends AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialTableDataSDF(final
      nDim=3);
  parameter Real y_nominal(final min=0, final max=1, final unit="1")=1
    "Nominal electrical power consumption"
end PartialTableData3D;


Partial model with components for table data using ND SDF tables for heat pumps and chillers. Partial model for equations and componenents used in both heat pump
  and chiller models using SDF based data.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses;
partial model PartialTableDataSDF
  "Partial model with components for table data using ND SDF tables for heat pumps and chillers"
  parameter Integer nDim=1 "Number of input dimensions";
  parameter Real scaFac "Scaling factor";
  parameter SDF.Types.InterpolationMethod interpMethod=SDF.Types.InterpolationMethod.Linear
    "Interpolation method"
  parameter SDF.Types.ExtrapolationMethod extrapMethod=SDF.Types.ExtrapolationMethod.Hold
    "Extrapolation method"
  Modelica.Blocks.Math.Product scaFacTimPel "Scale electrical power consumption"
  Modelica.Blocks.Math.Product scaFacTimQUse_flow "Scale useful heat flow rate"
  Modelica.Blocks.Sources.Constant constScaFac(final k=scaFac)
    "Calculates correction of table output based on scaling factor"

  Modelica.Blocks.Routing.RealPassThrough reaPasThrTEvaIn if (not useInRevDev and not use_TEvaOutForTab) or (useInRevDev and not use_TConOutForTab)
    "Used to enable conditional bus connection"
  Modelica.Blocks.Routing.RealPassThrough reaPasThrTConIn if (not useInRevDev and not use_TConOutForTab) or (useInRevDev and not use_TEvaOutForTab)
    "Used to enable conditional bus connection"
  Modelica.Blocks.Routing.RealPassThrough reaPasThrTEvaOut if (not useInRevDev and use_TEvaOutForTab) or (useInRevDev and use_TConOutForTab)
    "Used to enable conditional bus connection"
  Modelica.Blocks.Routing.RealPassThrough reaPasThrTConOut if (not useInRevDev and use_TConOutForTab) or (useInRevDev and use_TEvaOutForTab)
    "Used to enable conditional bus connection"

  Modelica.Blocks.Math.Gain facGain[nDim]
    "Convert relative speed n to an absolute value for interpolation in sdf tables"
  SDF.NDTable nDTabQUse_flow(
    final nin=nDim,
    final readFromFile=true,
    final interpMethod=interpMethod,
    final extrapMethod=extrapMethod) "SDF-Table data for condenser heat flow"
  SDF.NDTable nDTabPEle(
    final nin=nDim,
    final readFromFile=true,
    final interpMethod=interpMethod,
    final extrapMethod=extrapMethod) "SDF table data for electrical power"

  Modelica.Blocks.Routing.Multiplex  mux(final n=nDim)
                "Concat all inputs into an array"
  RearrangeInputs ordInp(final nDim=nDim) "Possibly change Input order"
  Modelica.Blocks.Math.Product onOffTimScaFac
    "Create the product of the scaling factor and whether the device is even on"
  Modelica.Blocks.Math.BooleanToReal booToRea(final realTrue=1, final realFalse
      =0) "Convert on/off signal to real"
protected
  parameter Real u_nominal[nDim]
    "Nominal conditions input array";
  parameter Real uOrdSca_nominal[nDim] = {u_nominal[ordInp.outOrd[i]] for i in 1:nDim} .* facGain.k
    "Nominal conditions input array ordered and scaled for sdf";
  parameter Boolean use_TEvaOutForTab=true
    "=true to use evaporator outlet temperature, false for inlet";
  parameter Boolean use_TConOutForTab=true
    "=true to use condenser outlet temperature, false for inlet";

  parameter Boolean useInRevDev "=true to indicate usage in reversed operation";
  parameter SDF.Types.ExternalNDTable extTabQUse_flow=SDF.Types.ExternalNDTable(
       nDTabQUse_flow.nin, SDF.Functions.readTableData(
      Modelica.Utilities.Files.loadResource(nDTabQUse_flow.filename),
      nDTabQUse_flow.dataset,
      nDTabQUse_flow.dataUnit,
      nDTabQUse_flow.scaleUnits));
  parameter SDF.Types.ExternalNDTable extTabPEle=SDF.Types.ExternalNDTable(
       nDTabPEle.nin, SDF.Functions.readTableData(
      Modelica.Utilities.Files.loadResource(nDTabPEle.filename),
      nDTabPEle.dataset,
      nDTabPEle.dataUnit,
      nDTabPEle.scaleUnits));
  function evaluate
    input SDF.Types.ExternalNDTable table;
    input Real[:] params;
    input SDF.Types.InterpolationMethod interpMethod;
    input SDF.Types.ExtrapolationMethod extrapMethod;
    output Real value;
    external "C" value = ModelicaNDTable_evaluate(table, size(params, 1), params, interpMethod, extrapMethod)
  end evaluate;
equation
  connect(nDTabPEle.y, scaFacTimPel.u1)
  connect(nDTabQUse_flow.y, scaFacTimQUse_flow.u1)
  connect(facGain.y, nDTabQUse_flow.u)
  connect(facGain.y, nDTabPEle.u)
  connect(ordInp.y, facGain.u)
  connect(mux.y, ordInp.u)
  connect(onOffTimScaFac.y, scaFacTimPel.u2)
  connect(onOffTimScaFac.y, scaFacTimQUse_flow.u2)
  connect(constScaFac.y, onOffTimScaFac.u2)
  connect(booToRea.y, onOffTimScaFac.u1)
end PartialTableDataSDF;


Helper model to re-arrange the input order for SDF tables. Re-arranges the input vector based on the provided order.
  For instsance, outOrd={2, 1, 3} switches input
  two and one.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses;
model RearrangeInputs
  "Helper model to re-arrange the input order for SDF tables"
  parameter Integer nDim(min=1)=1
                                "Number of dimensions";
  parameter Integer outOrd[nDim]=1:nDim "Output order";

  Modelica.Blocks.Interfaces.RealInput u[nDim]
    "Connector of Real input signal"
  Modelica.Blocks.Interfaces.RealOutput y[nDim]
    "Connector of Real output signal"

equation
  for i in 1:nDim loop
    connect(u[outOrd[i]], y[i])
  end for;
end RearrangeInputs;


Estimate the frosting supression using a function. Model using functional approaches for calculation of the icing factor.
  The replaceable function uses the inputs on the evaporator side to calculate
  the resulting icing factor.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting;
model FunctionalIcingFactor
  "Estimate the frosting supression using a function"
  extends BaseClasses.PartialIcingFactor;

  replaceable function icingFactor =
      AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.Functions.partialIcingFactor
    constrainedby
    AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.Functions.partialIcingFactor
    "Replaceable function to calculate current icing factor"
protected
  Modelica.Blocks.Routing.RealPassThrough pasThrTEvaIn
    "Enable usage of bus variables in function call"
  Modelica.Blocks.Routing.RealPassThrough pasThrTEvaOut
    "Enable usage of bus variables in function call"
  Modelica.Blocks.Routing.RealPassThrough pasThrMasFlowEva
    "Enable usage of bus variables in function call"

  Modelica.Blocks.Sources.RealExpression ice(
    final y=icingFactor(
      pasThrTEvaIn.y,
      pasThrTEvaOut.y,
      pasThrMasFlowEva.y)) "Icing factor"
equation
  connect(pasThrTEvaOut.u, sigBus.TEvaOutMea)
  connect(pasThrTEvaIn.u, sigBus.TEvaInMea)
  connect(pasThrMasFlowEva.u, sigBus.mEvaMea_flow)
  connect(ice.y, iceFac)
end FunctionalIcingFactor;


Placeholder block to ignore frosting. This block is used to ignore frosting effects by setting the icing factor
to constant <i>1</i>.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting;
model NoFrosting "Placeholder block to ignore frosting"
  extends BaseClasses.PartialIcingFactor;
equation
  iceFac = 1;
end NoFrosting;


within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle;
package Frosting "Package for models and function to estimate influence of frosting on heat pump performance"
end Frosting;


Package with the partial icing factor model.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting;
package BaseClasses
extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model to calculate the icing factor. Partial model to calculate the icing factor based on the data available in the
  signal bus sigBus of the heat pump.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.BaseClasses;
partial model PartialIcingFactor "Partial model to calculate the icing factor"
  extends Modelica.Blocks.Icons.Block;

  AixLib.Fluid.HeatPumps.ModularReversible.BaseClasses.RefrigerantMachineControlBus sigBus
    "Bus-connector used in a heat pump"
  Modelica.Blocks.Interfaces.RealOutput iceFac(final unit="1", min=0, max=1)
    "Icing factor from 0 to 1 to estimate influence of icing"
end PartialIcingFactor;


within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting;
package Functions "Package with functions to calculate current icing factor on evaporator"
end Functions;


No inertia. Placeholder model for no inertia.
  This block is identical to

  Modelica.Blocks.Routing.RealPassThrough
  and is replaceable but constrained by other inertia modules.

within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias;
model NoInertia "No inertia"
  extends BaseClasses.PartialInertia;
equation
  connect(u, y)
end NoInertia;


within AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle;
package Inertias "Package with modules to model inertia of refrigerant cycles"
end Inertias;


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

within AixLib.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 AixLib.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 AixLib.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 AixLib.Fluid.HeatPumps.ModularReversible.Validation;
model ConstantCarnotEffectiveness
  extends Modelica.Icons.Example;
  extends
    AixLib.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 =
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
          (
          refIneFreConst=refIneFreConst,
          nthOrd=2,
          initType=Modelica.Blocks.Types.Init.InitialState),
      redeclare model RefrigerantCycleHeatPumpHeating =
          AixLib.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 AixLib.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 AixLib.Fluid.HeatPumps.ModularReversible.Validation;
model TableData2D
  extends Modelica.Icons.Example;
  extends
    AixLib.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 =
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
          (
          refIneFreConst=refIneFreConst,
          nthOrd=2,
          initType=Modelica.Blocks.Types.Init.InitialState),
      redeclare model RefrigerantCycleHeatPumpHeating =
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
            datTab=
              AixLib.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 AixLib.Fluid.HeatPumps.ModularReversible.Validation;
package BaseClasses "Partial validation models"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


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

  replaceable package MediumSin = AixLib.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
      "Medium of sink side"
  replaceable package MediumSou = AixLib.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
      "Medium of source side"
  AixLib.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"

  AixLib.Fluid.Sources.Boundary_pT souSidFixBou(
    nPorts=1,
    redeclare package Medium = MediumSou)
    "Fixed boundary at the outlet of the source side"
  AixLib.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 =
        AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.NoCooling)
    "Heat pump"

  AixLib.Fluid.Sources.Boundary_pT sinSidFixBou(redeclare final package Medium =
        MediumSin, nPorts=1) "Fixed boundary at the outlet of the sink side"
  AixLib.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://AixLib/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 AixLib.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;
  AixLib.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
AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness.

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


within AixLib.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
AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D.

within AixLib.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 =
          AixLib.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 AixLib.Fluid.HeatPumps.ModularReversible.Validation.Comparative;
package BaseClasses "Package with partial validation models"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Fluid.HeatPumps.ModularReversible.Validation.Comparative.BaseClasses;
partial model PartialComparison
  "Partial model to allow heat pump and chiller model comparison"
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";
  AixLib.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"
  AixLib.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"
  AixLib.Fluid.Sources.Boundary_pT sin1(redeclare package Medium = Medium1)
  AixLib.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 AixLib.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));

  AixLib.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 =
        AixLib.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

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

within AixLib.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

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

within AixLib.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

AixLib.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 AixLib.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 AixLib.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 = AixLib.Media.Water "Medium model";
 package Medium2 = AixLib.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)
  AixLib.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1)
  AixLib.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"
equation
  connect(sou1.ports[1],heaPum. port_a1)
  connect(sou2.ports[1],heaPum. port_a2)
  connect(sin2.ports[1],heaPum. port_b2)
  connect(QEva_flow.y,mEva_flow. u)
  connect(heaPum.port_b1,sin1. ports[1])
  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)
end Carnot_TCon_reverseFlow;


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

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

within AixLib.Fluid.HeatPumps.Validation;
model Carnot_y_etaCar
  "Test model for heat pump based on Carnot efficiency with etaCar as parameter"
  extends AixLib.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

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

within AixLib.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;


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


within AixLib.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_Dynamic
  "Test model for variable speed reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2,
    nPorts=2) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.Media.Refrigerants.R410A,
    show_T=true,
    enable_variable_speed=false,
    per=AixLib.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"

  AixLib.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 = AixLib.Media.Refrigerants.R410A,
    tau1=15,
    tau2=15,
    enable_variable_speed=false,
    per=AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_ScalingFactor
  "Test model for variable speed reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=2) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.Media.Refrigerants.R410A,
    enable_variable_speed=false,
    per=AixLib.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"

  AixLib.Fluid.HeatPumps.ReciprocatingWaterToWater heaPum1(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = AixLib.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=AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_Static
  "Test model for static, reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.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 = AixLib.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"

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ReciprocatingWaterToWater_VariableSpeed
  "Test model for reciprocating water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  AixLib.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"

  AixLib.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 = AixLib.Media.Refrigerants.R410A,
    show_T=true,
    per=AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_Dynamic
  "Test model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=2) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.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"
  AixLib.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 = AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_ScalingFactor
  "Test model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=2) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.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"
  AixLib.Fluid.HeatPumps.ScrollWaterToWater heaPum1(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dp1_nominal=1000,
    dp2_nominal=1000,
    redeclare package ref = AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_Static
  "Test model for static scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_TemperatureProtection
  "Test model for temperature protection of scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.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 AixLib.Fluid.HeatPumps.Validation;
model ScrollWaterToWater_VariableSpeed
  "Test model for scroll water to water heat pump"
  extends Modelica.Icons.Example;
  package Medium1 = AixLib.Media.Water "Medium model";
  package Medium2 = AixLib.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";

  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium2, nPorts=1) "Source side sink"
  AixLib.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"
  AixLib.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 = AixLib.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 AixLib.Fluid.Humidifiers;
model GenericHumidifier_u
  "Steam or adiabatic humidifier with relative mass flow rate as input"
  extends AixLib.Fluid.Interfaces.TwoPortHeatMassExchanger(
    redeclare replaceable package Medium =
        Modelica.Media.Interfaces.PartialCondensingGases,
    redeclare final AixLib.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";

  parameter Modelica.Units.SI.Temperature TLiqWat_in
    "Temperature of liquid water that is vaporized";

  parameter Boolean steamHumidifier=true  "True: steam humidifier, false: adiabatic (water) humidifier";

  parameter Boolean TVapFixed = true "True: fixed vaporization temperature, false: vaporization temperature from pressure"

  parameter Modelica.Units.SI.Temperature TVap=373.15
    "Vaporization temperature of steam"

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

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

  Modelica.Blocks.Interfaces.RealOutput powerEva if steamHumidifier
    "Consumed power for evaporization"
  Modelica.Blocks.Sources.RealExpression steamEnthalpyFlow(y=
        Medium.enthalpyOfCondensingGas(T=Tsteam_intern)*mWat_flow) if steamHumidifier
  Modelica.Blocks.Sources.RealExpression waterEnthalpyFlow(y=Medium.enthalpyOfLiquid(T=TLiqWat_in)*mWat_flow)
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow prescribedHeatFlow
  Modelica.Blocks.Sources.RealExpression TVapPoint(y=
        AixLib.Utilities.Psychrometrics.Functions.TDewPoi_pW(vol.p)) if not TVapFixed and steamHumidifier
  Modelica.Blocks.Sources.RealExpression TVapPointFix(y=TVap) if TVapFixed and steamHumidifier
  Modelica.Blocks.Routing.RealPassThrough Tsteam if steamHumidifier
  Modelica.Blocks.Sources.RealExpression realExpression(y = mWat_flow_nominal)
  Modelica.Blocks.Math.Product product
protected
  Modelica.Blocks.Interfaces.RealInput Tsteam_intern;
  Modelica.Blocks.Nonlinear.Limiter limiter(uMax=1, uMin=0)

  Modelica.Blocks.Math.Add add(k2=-1) if steamHumidifier
equation
  if not steamHumidifier then
    Tsteam_intern = 273.15;
  end if;

  connect(Tsteam.y, Tsteam_intern);
  connect(product.y, vol.mWat_flow)
  connect(u, limiter.u)
  connect(prescribedHeatFlow.port, vol.heatPort)

  connect(steamEnthalpyFlow.y, add.u1)
  connect(waterEnthalpyFlow.y, add.u2)
  connect(add.y, powerEva)
  if steamHumidifier then
      connect(steamEnthalpyFlow.y, prescribedHeatFlow.Q_flow)
  else
    connect(waterEnthalpyFlow.y, prescribedHeatFlow.Q_flow)
  end if;
  connect(TVapPoint.y, Tsteam.u)
  connect(TVapPointFix.y, Tsteam.u)
  connect(limiter.y, product.u1)
  connect(realExpression.y, product.u2)
  connect(product.y, mWat_flow)
end GenericHumidifier_u;


within AixLib.Fluid.Humidifiers;
model Humidifier_u
  "Ideal humidifier or dehumidifier with prescribed water mass flow rate addition or subtraction"
  extends AixLib.Fluid.Interfaces.TwoPortHeatMassExchanger(
    redeclare replaceable package Medium =
        Modelica.Media.Interfaces.PartialCondensingGases,
    redeclare final AixLib.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 AixLib.Fluid;
package Humidifiers "Package with humidifier models"
  extends Modelica.Icons.Package;
end Humidifiers;


within AixLib.Fluid.Humidifiers;
model SprayAirWasher_X
  "Spray air washer with leaving water mass fraction as input"
  extends AixLib.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 AixLib.Fluid.Humidifiers;
model SteamHumidifier_X
  "Steam humidifier with leaving water mass fraction as input"
  extends AixLib.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 AixLib.Fluid.Humidifiers.Examples;
model GenericHumidifier_u
  "Model that demonstrates the steam and adiabtic humidifier"
  extends Modelica.Icons.Example;

  package Medium = AixLib.Media.Air;

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

  AixLib.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    use_T_in=false,
    nPorts=3,
    m_flow=3*m_flow_nominal,
    T=303.15) "Source"
  AixLib.Fluid.Humidifiers.GenericHumidifier_u steamHum(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    mWat_flow_nominal=m_flow_nominal*0.003,
    TLiqWat_in=293.15) "Steam humidifier"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal) "Temperature sensor"
  AixLib.Fluid.Humidifiers.GenericHumidifier_u adiabHum(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    mWat_flow_nominal=m_flow_nominal*0.003,
    TLiqWat_in=293.15,
    steamHumidifier=false) "Adiabatic humidifier"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem2(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal) "Temperature sensor"
  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_T_in=false,
    p(displayUnit="Pa") = Medium.p_default + 10000,
    T=303.15,
    nPorts=3) "Sink"
  Modelica.Blocks.Sources.Ramp ramp(duration=1200, startTime=100)
  Sensors.RelativeHumidityTwoPort senRelHum(redeclare package Medium = Medium,
      m_flow_nominal=m_flow_nominal)
  Sensors.RelativeHumidityTwoPort senRelHum2(redeclare package Medium = Medium,
      m_flow_nominal=m_flow_nominal)
  AixLib.Fluid.Humidifiers.GenericHumidifier_u steamHum1(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    mWat_flow_nominal=m_flow_nominal*0.003,
    TLiqWat_in=293.15,
    TVapFixed=false) "Steam humidifier"
  Sensors.TemperatureTwoPort              senTem1(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal) "Temperature sensor"
  Sensors.RelativeHumidityTwoPort senRelHum1(redeclare package Medium = Medium,
      m_flow_nominal=m_flow_nominal)
equation
  connect(steamHum.port_b, senTem.port_a)
  connect(adiabHum.port_b, senTem2.port_a)

  connect(sou.ports[1], steamHum.port_a)
  connect(ramp.y, steamHum.u)
  connect(ramp.y, adiabHum.u)
  connect(senTem.port_b, senRelHum.port_a)
  connect(senTem2.port_b, senRelHum2.port_a)
  connect(steamHum1.port_b, senTem1.port_a)
  connect(ramp.y, steamHum1.u)
  connect(senTem1.port_b, senRelHum1.port_a)
  connect(steamHum1.port_a, sou.ports[2])
  connect(adiabHum.port_a, sou.ports[3])
  connect(senRelHum.port_b, sin.ports[1])
  connect(senRelHum1.port_b, sin.ports[2])
  connect(senRelHum2.port_b, sin.ports[3])
end GenericHumidifier_u;


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

  package Medium = AixLib.Media.Air;

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

  AixLib.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"
  AixLib.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"
  AixLib.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"
  AixLib.Controls.Continuous.LimPID con1(
    Td=1,
    k=1,
    Ti=10,
    reverseActing=false) "Controller"
  AixLib.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"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem2(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal) "Temperature sensor"
  AixLib.Controls.Continuous.LimPID con2(
    Td=1,
    Ti=10,
    k=0.1,
    reverseActing=false) "Controller"
  AixLib.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 AixLib.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 AixLib.Fluid.Humidifiers;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


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

  package Medium = AixLib.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";

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

  replaceable AixLib.Fluid.Humidifiers.SprayAirWasher_X hum(
    mWatMax_flow=mWat_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
      constrainedby AixLib.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"

  AixLib.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 AixLib.Fluid.Humidifiers.Validation;
model SprayAirWasher_X_dynamic
  "Model that demonstrates the spray air washer model, configured as dynamic model"
  extends AixLib.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 AixLib.Fluid.Humidifiers.Validation;
model SteamHumidifier_X
  "Model that demonstrates the steam humidifier model, configured as steady-state model"
  extends AixLib.Fluid.Humidifiers.Validation.SprayAirWasher_X(
    redeclare AixLib.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 AixLib.Fluid.Humidifiers.Validation;
model SteamHumidifier_X_dynamic
  "Model that demonstrates the steam humidifier model, configured as dynamic model"
  extends AixLib.Fluid.Humidifiers.Validation.SprayAirWasher_X(
    redeclare AixLib.Fluid.Humidifiers.SteamHumidifier_X hum(
      mWatMax_flow=mWat_flow_nominal,
      energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));
end SteamHumidifier_X_dynamic;