within AixLib.Media.Antifreeze;
package PropyleneGlycolWater
  "Package with model for propylene glycol - water with constant properties"
  extends Modelica.Media.Interfaces.PartialSimpleMedium(
    mediumName="PropyleneGlycolWater(X_a = " + String(X_a) + ", property_T = "
         + String(property_T) + ")",
    final cp_const=specificHeatCapacityCp_TX_a(T=property_T, X_a=X_a),
    final cv_const=cp_const,
    final d_const=density_TX_a(T=property_T, X_a=X_a),
    final eta_const=dynamicViscosity_TX_a(T=property_T, X_a=X_a),
    final lambda_const=thermalConductivity_TX_a(T=property_T, X_a=X_a),
    a_const=1484,
    final T_min=fusionTemperature_TX_a(T=property_T, X_a=X_a),
    T_max=Modelica.Units.Conversions.from_degC(100),
    T0=273.15,
    MM_const=(X_a/simplePropyleneGlycolWaterConstants[1].molarMass + (1 - X_a)/
        0.018015268)^(-1),
    fluidConstants=simplePropyleneGlycolWaterConstants,
    p_default=300000,
    reference_p=300000,
    reference_T=273.15,
    reference_X={1},
    AbsolutePressure(start=p_default),
    Temperature(start=T_default),
    Density(start=d_const));

  constant Modelica.Units.SI.Temperature property_T
    "Temperature for evaluation of constant fluid properties";
  constant Modelica.Units.SI.MassFraction X_a
    "Mass fraction of propylene glycol in water";

  redeclare model BaseProperties "Base properties"
    Temperature T(stateSelect=
      if preferredMediumStates then StateSelect.prefer else StateSelect.default)
      "Temperature of medium";

    InputAbsolutePressure p "Absolute pressure of medium";
    InputMassFraction[nXi] Xi=fill(0, 0)
      "Structurally independent mass fractions";
    InputSpecificEnthalpy h "Specific enthalpy of medium";
    Modelica.Units.SI.SpecificInternalEnergy u
      "Specific internal energy of medium";
    Modelica.Units.SI.Density d=d_const "Density of medium";
    Modelica.Units.SI.MassFraction[nX] X={1}
      "Mass fractions (= (component mass)/total mass  m_i/m)";
    final Modelica.Units.SI.SpecificHeatCapacity R_s=0
      "Gas constant (of mixture if applicable)";
    final Modelica.Units.SI.MolarMass MM=MM_const
      "Molar mass (of mixture or single fluid)";
    ThermodynamicState state
      "Thermodynamic state record for optional functions";
    parameter Boolean preferredMediumStates=false
      "= true if StateSelect.prefer shall be used for the independent property variables of the medium"
    final parameter Boolean standardOrderComponents=true
      "If true, and reducedX = true, the last element of X will be computed from the other ones";
    Modelica.Units.NonSI.Temperature_degC T_degC=
        Modelica.Units.Conversions.to_degC(T) "Temperature of medium in [degC]";
    Modelica.Units.NonSI.Pressure_bar p_bar=Modelica.Units.Conversions.to_bar(p)
      "Absolute pressure of medium in [bar]";

    // Local connector definition, used for equation balancing check
    connector InputAbsolutePressure = input Modelica.Units.SI.AbsolutePressure
      "Pressure as input signal connector";
    connector InputSpecificEnthalpy = input Modelica.Units.SI.SpecificEnthalpy
      "Specific enthalpy as input signal connector";
    connector InputMassFraction = input Modelica.Units.SI.MassFraction
      "Mass fraction as input signal connector";

  equation
  assert(T >= T_min, "
In "   + getInstanceName() + ": Temperature T exceeded its minimum allowed value of " + String(T_min-273.15)
    + " degC (" + String(T_min) + " Kelvin)
as required from medium model \"" + mediumName + "\".");
  assert(T <= T_max, "
In "   + getInstanceName() + ": Temperature T exceeded its maximum allowed value of " + String(T_max-273.15)
    + " degC (" + String(T_max) + " Kelvin)
as required from medium model \"" + mediumName + "\".");

  assert(X_a >= X_a_min, "
In "   + getInstanceName() + ": Mass fraction x_a exceeded its minimum allowed value of " + String(X_a_min) + "
as required from medium model \"" + mediumName + "\".");
  assert(X_a <= X_a_max, "
In "   + getInstanceName() + ": Mass fraction x_a exceeded its maximum allowed value of " + String(X_a_max) + "
as required from medium model \"" + mediumName + "\".");

    h = cp_const*(T-reference_T);
    u = h;
    state.T = T;
    state.p = p;
  end BaseProperties;
protected
  constant Modelica.Units.SI.MassFraction X_a_min=0.
    "Minimum allowed mass fraction of propylene glycol in water";
  constant Modelica.Units.SI.MassFraction X_a_max=0.6
    "Maximum allowed mass fraction of propylene glycol in water";

  // Fluid constants based on pure Propylene Glycol
  constant Modelica.Media.Interfaces.Types.Basic.FluidConstants[1]
    simplePropyleneGlycolWaterConstants(
    each chemicalFormula="C3H8O2",
    each structureFormula="CH3CH(OH)CH2OH",
    each casRegistryNumber="57-55-6",
    each iupacName="1,2-Propylene glycol",
    each molarMass=0.07609);

  // Coefficients for evaluation of physical properties
  constant AixLib.Media.Antifreeze.BaseClasses.PropertyCoefficients proCoe(
    X_a_ref=0.307031,
    T_ref=Modelica.Units.Conversions.from_degC(32.7083),
    nX_a=6,
    nT={4,4,4,3,2,1},
    nTot=18,
    a_d={1.018e3,-5.406e-1,-2.666e-3,1.347e-5,7.604e-1,-9.450e-3,5.541e-5,-1.343e-7,
        -2.498e-3,2.700e-5,-4.018e-7,3.376e-9,-1.550e-4,2.829e-6,-7.175e-9,-1.131e-6,
        -2.221e-8,2.342e-8},
    a_eta={6.837e-1,-3.045e-2,2.525e-4,-1.399e-6,3.328e-2,-3.984e-4,4.332e-6,-1.860e-8,
        5.453e-5,-8.600e-8,-1.593e-8,-4.465e-11,-3.900e-6,1.054e-7,-1.589e-9,-1.587e-8,
        4.475e-10,3.564e-9},
    a_Tf={-1.325e1,-3.820e-5,7.865e-7,-1.733e-9,-6.631e-1,6.774e-6,-6.242e-8,-7.819e-10,
        -1.094e-2,5.332e-8,-4.169e-9,3.288e-11,-2.283e-4,-1.131e-8,1.918e-10,-3.409e-6,
        8.035e-11,1.465e-8},
    a_cp={3.882e3,2.699e0,-1.659e-3,-1.032e-5,-1.304e1,5.070e-2,-4.752e-5,
        1.522e-6,-1.598e-1,9.534e-5,1.167e-5,-4.870e-8,3.539e-4,3.102e-5,-2.950e-7,
        5.000e-5,-7.135e-7,-4.959e-7},
    a_lambda={4.513e-1,7.955e-4,3.482e-8,-5.966e-9,-4.795e-3,-1.678e-5,8.941e-8,
        1.493e-10,2.076e-5,1.563e-7,-4.615e-9,9.897e-12,-9.083e-8,-2.518e-9,
        6.543e-11,-5.952e-10,-3.605e-11,2.104e-11})
    "Coefficients for evaluation of thermo-physical properties";

  replaceable function density_TX_a
    "Evaluate density of antifreeze-water mixture"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.Density d "Density of antifreeze-water mixture";
  algorithm
    d :=polynomialProperty(
        X_a,
        T,
        proCoe.a_d)

  end density_TX_a;

  replaceable function dynamicViscosity_TX_a
    "Evaluate dynamic viscosity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.DynamicViscosity eta
      "Dynamic Viscosity of antifreeze-water mixture";
  algorithm
    eta :=1e-3*exp(polynomialProperty(
        X_a,
        T,
        proCoe.a_eta));
  end dynamicViscosity_TX_a;

  replaceable function fusionTemperature_TX_a
    "Evaluate temperature of fusion of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.Temperature Tf
      "Temperature of fusion of antifreeze-water mixture";
  algorithm
    Tf :=Modelica.Units.Conversions.from_degC(polynomialProperty(
        X_a,
        T,
        proCoe.a_Tf));
  end fusionTemperature_TX_a;

  replaceable function polynomialProperty
    "Evaluates thermophysical property from 2-variable polynomial"
    extends Modelica.Icons.Function;

    input Real x "First independent variable";
    input Real y "Second independent variable";
    input Real a[sum(proCoe.nT)] "Polynomial coefficients";

    output Real f "Value of thermophysical property";

  protected
    Real dx;
    Real dy;
    Integer n;
  algorithm
    dx := 100*(x - proCoe.X_a_ref);
    dy := y - proCoe.T_ref;

    f := 0;
    n := 0;
    for i in 0:proCoe.nX_a - 1 loop
      for j in 0:proCoe.nT[i+1] - 1 loop
        n := n + 1;
        f := f + a[n]*dx^i*dy^j;
      end for;
    end for;
  end polynomialProperty;

  replaceable function specificHeatCapacityCp_TX_a
    "Evaluate specific heat capacity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.SpecificHeatCapacity cp
      "Specific heat capacity of antifreeze-water mixture";
  algorithm
    cp :=polynomialProperty(
        X_a,
        T,
        proCoe.a_cp);
  end specificHeatCapacityCp_TX_a;

  replaceable function thermalConductivity_TX_a
    "Evaluate thermal conductivity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.ThermalConductivity lambda
      "Thermal conductivity of antifreeze-water mixture";
  algorithm
    lambda :=polynomialProperty(
        X_a,
        T,
        proCoe.a_lambda);
  end thermalConductivity_TX_a;
end PropyleneGlycolWater;


within AixLib.Media.Antifreeze;
package BaseClasses "Base classes for secondary working fluid media packages"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Media.Antifreeze.Validation;
model EthyleneGlycolWater
  "Model that tests the implementation of ethylene glycol-water properties"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Antifreeze.Validation.BaseClasses.FluidProperties(
    redeclare package Medium =
        AixLib.Media.Antifreeze.Validation.BaseClasses.EthyleneGlycolWater (
          property_T=300,
          X_a=0.05),
    nX_a=7,
    X_a={0.05,0.10,0.20,0.30,0.40,0.50,0.60},
    T_min=223.15,
    T_max=373.15);
end EthyleneGlycolWater;


within AixLib.Media.Antifreeze;
package Validation "Validation cases for fluid property evaluations"
extends Modelica.Icons.ExamplesPackage;
end Validation;


within AixLib.Media.Antifreeze.Validation;
model PropyleneGlycolWater
  "Model that tests the implementation of propylene glycol-water properties"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Antifreeze.Validation.BaseClasses.FluidProperties(
    redeclare package Medium =
        AixLib.Media.Antifreeze.Validation.BaseClasses.PropyleneGlycolWater (
          property_T=300,
          X_a=0.05),
    nX_a=7,
    X_a={0.05,0.10,0.20,0.30,0.40,0.50,0.60},
    T_min=223.15,
    T_max=373.15);
end PropyleneGlycolWater;


within AixLib.Media.Antifreeze.Validation.BaseClasses;
package EthyleneGlycolWater
  "EthyleneGlycolWater with publicly accessible medium functions"
  extends AixLib.Media.Antifreeze.EthyleneGlycolWater;

    replaceable function testDensity_TX_a
    "Evaluate density of antifreeze-water mixture"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.Density d "Density of antifreeze-water mixture";
    algorithm
    d := density_TX_a(T = T, X_a = X_a);
    end testDensity_TX_a;

  function testDynamicViscosity_TX_a
    "Evaluate dynamic viscosity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.DynamicViscosity eta
      "Dynamic Viscosity of antifreeze-water mixture";
  algorithm
    eta := dynamicViscosity_TX_a(T = T, X_a = X_a);
  end testDynamicViscosity_TX_a;

  function testFusionTemperature_TX_a
    "Evaluate temperature of fusion of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.Temperature Tf
      "Temperature of fusion of antifreeze-water mixture";
  algorithm
    Tf := fusionTemperature_TX_a(T = T, X_a = X_a);
  end testFusionTemperature_TX_a;

  function testSpecificHeatCapacityCp_TX_a
    "Evaluate specific heat capacity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.SpecificHeatCapacity cp
      "Specific heat capacity of antifreeze-water mixture";
  algorithm
    cp := specificHeatCapacityCp_TX_a(T = T, X_a = X_a);
  end testSpecificHeatCapacityCp_TX_a;

  function testThermalConductivity_TX_a
    "Evaluate thermal conductivity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.ThermalConductivity lambda
      "Thermal conductivity of antifreeze-water mixture";
  algorithm
    lambda := thermalConductivity_TX_a(T = T, X_a = X_a);
  end testThermalConductivity_TX_a;
end EthyleneGlycolWater;


within AixLib.Media.Antifreeze.Validation.BaseClasses;
partial model FluidProperties
  "Partial model that tests the implementation of temperature- and concentration-dependent fluid properties"

  replaceable package Medium =
      AixLib.Media.Antifreeze.Validation.BaseClasses.PropyleneGlycolWater
    "Medium package";

  parameter Integer nX_a
    "Number of mass fractions to evaluate fluid properties";
  parameter Modelica.Units.SI.MassFraction X_a[nX_a]
    "Mass fraction of additive";
  parameter Modelica.Units.SI.Temperature T_min
    "Minimum temperature of mixture";
  parameter Modelica.Units.SI.Temperature T_max
    "Maximum temperature of mixture";
  parameter Modelica.Units.SI.Temperature reference_T=293.15
    "Reference temperature";
  Modelica.Units.SI.Temperature Tf[nX_a] "Fluid temperature";
  Modelica.Units.SI.Density d[nX_a] "Density of fluid mixture";
  Modelica.Units.SI.SpecificHeatCapacity cp[nX_a]
    "Specific heat capacity of fluid mixture";
  Modelica.Units.SI.ThermalConductivity lambda[nX_a] "Density of fluid mixture";
  Modelica.Units.SI.DynamicViscosity eta[nX_a]
    "Dynamic viscosity of fluid mixture";
  Modelica.Units.SI.Temperature T "Temperature of fluid mixture";
  Modelica.Units.NonSI.Temperature_degC T_degC "Celsius temperature";

protected
  parameter Modelica.Units.SI.Time dt=1 "Simulation length";
  parameter Real convT(unit="K/s") = (T_max-T_min)/dt
    "Rate of temperature change";

equation
  T = T_min + convT*time;
  T_degC =Modelica.Units.Conversions.to_degC(T);
  for i in 1:nX_a loop
    Tf[i] =Medium.testFusionTemperature_TX_a(T=T, X_a=X_a[i]);
    d[i] =if T >= Tf[i] then Medium.testDensity_TX_a(T=T, X_a=X_a[i]) else 0.;
    cp[i] =if T >= Tf[i] then Medium.testSpecificHeatCapacityCp_TX_a(T=T, X_a=X_a[i])
       else 0.;
    lambda[i] =if T >= Tf[i] then Medium.testThermalConductivity_TX_a(T=T, X_a=X_a[i]) else 0.;
    eta[i] =if T >= Tf[i] then Medium.testDynamicViscosity_TX_a(T=T, X_a=X_a[i])
       else 0.;
  end for;
end FluidProperties;


within AixLib.Media.Antifreeze.Validation;
package BaseClasses "Package with base classes for AixLib.Media.Antifreeze.Validation"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Media.Antifreeze.Validation.BaseClasses;
package PropyleneGlycolWater
  "PropyleneGlycolWater with publicly accessible medium functions"
  extends AixLib.Media.Antifreeze.PropyleneGlycolWater;

    replaceable function testDensity_TX_a
    "Evaluate density of antifreeze-water mixture"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.Density d "Density of antifreeze-water mixture";
    algorithm
    d := density_TX_a(T = T, X_a = X_a);
    end testDensity_TX_a;

  function testDynamicViscosity_TX_a
    "Evaluate dynamic viscosity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.DynamicViscosity eta
      "Dynamic Viscosity of antifreeze-water mixture";
  algorithm
    eta := dynamicViscosity_TX_a(T = T, X_a = X_a);
  end testDynamicViscosity_TX_a;

  function testFusionTemperature_TX_a
    "Evaluate temperature of fusion of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.Temperature Tf
      "Temperature of fusion of antifreeze-water mixture";
  algorithm
    Tf := fusionTemperature_TX_a(T = T, X_a = X_a);
  end testFusionTemperature_TX_a;

  function testSpecificHeatCapacityCp_TX_a
    "Evaluate specific heat capacity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.SpecificHeatCapacity cp
      "Specific heat capacity of antifreeze-water mixture";
  algorithm
    cp := specificHeatCapacityCp_TX_a(T = T, X_a = X_a);
  end testSpecificHeatCapacityCp_TX_a;

  function testThermalConductivity_TX_a
    "Evaluate thermal conductivity of antifreeze-water mixture"
      extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T
      "Temperature of antifreeze-water mixture";
    input Modelica.Units.SI.MassFraction X_a "Mass fraction of antifreeze";
    output Modelica.Units.SI.ThermalConductivity lambda
      "Thermal conductivity of antifreeze-water mixture";
  algorithm
    lambda := thermalConductivity_TX_a(T = T, X_a = X_a);
  end testThermalConductivity_TX_a;
end PropyleneGlycolWater;


within AixLib.Media.Examples;
model AirDerivativeCheck "Model that tests the derivative implementation"
  extends Modelica.Icons.Example;

   package Medium = AixLib.Media.Air;
  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.MassFraction X[1] "Water vapor mass fraction";

  Modelica.Units.SI.SpecificEnthalpy hLiqSym "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hLiqCod "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hSteSym "Water vapor enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hSteCod "Water vapor enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hAirSym "Dry air enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hAirCod "Dry air enthalpy";
  Modelica.Units.SI.SpecificHeatCapacity cpSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cpCod "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvCod "Specific heat capacity";
    constant Real convT(unit="K/s3") = 270
    "Conversion factor to satisfy unit check";
    constant Real convX(unit="1/s3") = 0.01
    "Conversion factor to satisfy unit check";
initial equation
     hLiqSym = hLiqCod;
     hSteSym = hSteCod;
     hAirSym = hAirCod;
     cpSym   = cpCod;
     cvSym   = cvCod;
equation
    T = 273.15+convT*time^3;
    X = {0.001}+convX*time^3*{1};
    hLiqCod=Medium.enthalpyOfLiquid(T);
    der(hLiqCod)=der(hLiqSym);
    assert(abs(hLiqCod-hLiqSym) < 1E-2, "Model has an error");

    hSteCod=Medium.enthalpyOfCondensingGas(T);
    der(hSteCod)=der(hSteSym);
    assert(abs(hSteCod-hSteSym) < 1E-2, "Model has an error");

    hAirCod=Medium.enthalpyOfNonCondensingGas(T);
    der(hAirCod)=der(hAirSym);
    assert(abs(hAirCod-hAirSym) < 1E-2, "Model has an error");

    cpCod=Medium.specificHeatCapacityCp(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=X));
    der(cpCod)=der(cpSym);
    assert(abs(cpCod-cpSym) < 1E-2, "Model has an error");

     cvCod=Medium.specificHeatCapacityCv(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=X));
    der(cvCod)=der(cvSym);
    assert(abs(cvCod-cvSym) < 1E-2, "Model has an error");
end AirDerivativeCheck;


within AixLib.Media.Examples;
model AirProperties
  "Model that tests the implementation of the fluid properties"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.FluidProperties(
    redeclare package Medium = AixLib.Media.Air,
    TMin=273.15-30,
    TMax=273.15+60);

  Modelica.Units.SI.SpecificEnthalpy hLiq "Specific enthalpy of liquid";

equation
  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
  basPro.state.X[1]=X[1];

  hLiq = Medium.enthalpyOfLiquid(T);
  if Medium.nX == 1 then
    assert(abs(h-hLiq) < 1e-8, "Error in enthalpy computation.");
  end if;
end AirProperties;


within AixLib.Media.Examples;
model AirTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.TestTemperatureEnthalpyInversion(
    redeclare package Medium = AixLib.Media.Air);
end AirTemperatureEnthalpyInversion;


within AixLib.Media;
package Examples "Collection of models that test the media models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within AixLib.Media.Examples;
model PropyleneGlycolWaterDerivativeCheck
  "Model that tests the derivative implementation"
  extends Modelica.Icons.Example;

   package Medium = AixLib.Media.Antifreeze.PropyleneGlycolWater (
      X_a=0.60,
      property_T=293.15);

  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy hLiqSym "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hLiqCod "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificHeatCapacity cpSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cpCod "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvCod "Specific heat capacity";
    constant Real convT(unit="K/s3") = 100
      "Conversion factor to satisfy unit check";
initial equation
     hLiqSym = hLiqCod;
     cpSym   = cpCod;
     cvSym   = cvCod;
equation
    T = 273.15+convT*time^3;
    hLiqCod=Medium.cp_const*(T-Medium.reference_T);
    der(hLiqCod)=der(hLiqSym);
    assert(abs(hLiqCod-hLiqSym) < 1E-2, "Model has an error");

    cpCod=Medium.specificHeatCapacityCp(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cpCod)=der(cpSym);
    assert(abs(cpCod-cpSym) < 1E-2, "Model has an error");

     cvCod=Medium.specificHeatCapacityCv(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cvCod)=der(cvSym);
    assert(abs(cvCod-cvSym) < 1E-2, "Model has an error");
end PropyleneGlycolWaterDerivativeCheck;


within AixLib.Media.Examples;
model PropyleneGlycolWaterProperties
  "Model that tests the implementation of the fluid properties"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.FluidProperties(
    redeclare package Medium = AixLib.Media.Antifreeze.PropyleneGlycolWater (
      X_a=0.60,
      property_T=293.15),
    TMin=273.15,
    TMax=373.15);
equation
  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
end PropyleneGlycolWaterProperties;


within AixLib.Media.Examples;
model PropyleneGlycolWaterTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.TestTemperatureEnthalpyInversion(
    redeclare package Medium = AixLib.Media.Antifreeze.PropyleneGlycolWater (
      X_a=0.60,
      property_T=293.15));
end PropyleneGlycolWaterTemperatureEnthalpyInversion;


within AixLib.Media.Examples;
model SteamDerivativeCheck "Model that tests the derivative implementation"
  extends Modelica.Icons.Example;

   package Medium = AixLib.Media.Steam "Medim model";

  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy hVapSym "Vapor phase specific enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hVapCod "Vapor phase specific enthalpy";
  Modelica.Units.SI.SpecificHeatCapacity cpSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cpCod "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvCod "Specific heat capacity";
    constant Real convT(unit="K/s3") = 270
    "Conversion factor to satisfy unit check";
initial equation
     hVapSym = hVapCod;
     cpSym   = cpCod;
     cvSym   = cvCod;
equation
    T = 273.15+110+convT*time^3;
    hVapCod=Medium.specificEnthalpy(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    assert(abs(hVapCod-hVapSym) < 1E-4 * (1+abs(hVapCod)), "Model has an error");
    der(hVapCod)=der(hVapSym);

    cpCod=Medium.specificHeatCapacityCp(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cpCod)=der(cpSym);
    assert(abs(cpCod-cpSym) < 1E-4 * (1+abs(cpCod)), "Model has an error");

     cvCod=Medium.specificHeatCapacityCv(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cvCod)=der(cvSym);
    assert(abs(cvCod-cvSym) < 1E-4 * (1+abs(cvCod)), "Model has an error");
end SteamDerivativeCheck;


within AixLib.Media.Examples;
model SteamProperties
  "Model that tests the implementation of the steam superheated properties"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.PartialProperties(
    redeclare package Medium = AixLib.Media.Steam (
      p_default=200000),
    TMin=273.15 + 100,
    TMax=273.15 + 160,
    p=200000);

  Medium.ThermodynamicState state_phX "Medium state";
  Medium.ThermodynamicState state_psX "Medium state";

  Modelica.Media.Interfaces.Types.DerDensityByEnthalpy ddhp
    "Density derivative w.r.t. enthalpy";
  Modelica.Media.Interfaces.Types.DerDensityByPressure ddph
    "Density derivative w.r.t. pressure";

equation

  // Check setting the states
  state_pTX = Medium.setState_pTX(p=p, T=T, X=X);
  state_phX = Medium.setState_phX(p=p, h=h, X=X);
  state_psX = Medium.setState_psX(p=p, s=s, X=X);
  checkState(state_pTX, state_phX, errAbs, "state_phX");
  checkState(state_pTX, state_psX, errAbs, "state_psX");

  // Check the implementation of the functions
  ddhp = Medium.density_derh_p(state_pTX);
  ddph = Medium.density_derp_h(state_pTX);

  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
end SteamProperties;


within AixLib.Media.Examples;
model SteamSaturationConsistencyCheck
  "Model that checks the consistency of saturated property functions"
  extends Modelica.Icons.Example;

  package MediumSte = AixLib.Media.Steam "Steam medium model";
  package MediumWat = AixLib.Media.Water "Liquid water medium model";

  parameter Modelica.Units.SI.Temperature TMin=273.15 + 100
    "Minimum temperature for the simulation";
  parameter Modelica.Units.SI.Temperature TMax=273.15 + 179.886
    "Maximum temperature for the simulation";
  parameter Real tol = 1E-8 "Numerical tolerance";

  MediumSte.ThermodynamicState sat "Saturation state";
  Modelica.Units.SI.Pressure pSat "Saturation pressure";
  Modelica.Units.SI.Temperature TSat0 "Starting saturation temperature";
  Modelica.Units.SI.Temperature TSat "Saturation temperature";
  Modelica.Units.NonSI.Temperature_degC TSat_degC
    "Celsius saturation temperature";
  Modelica.Units.SI.SpecificEnthalpy hlvIF97
    "Enthalpy of vaporization, IF97 formulation";
  Modelica.Units.SI.SpecificEnthalpy hlvWatSte
    "Enthalpy of vaporization, water and steam medium models";
  Modelica.Units.SI.SpecificEnthalpy hlIF97
    "Enthalpy of saturated liquid, IF97";
  Modelica.Units.SI.SpecificEnthalpy hlWat
    "Enthalpy of saturated liquid, water medium";
  Modelica.Units.SI.SpecificEnthalpy hvIF97 "Enthalpy of saturated vapor, IF97";
  Modelica.Units.SI.SpecificEnthalpy hvSte
    "Enthalpy of saturated vapor, steam medium";

  Real hlvErr "Enthalpy of vaporization percent error";
  Real hlErr "Enthalpy of saturated liquid percent error";
  Real hvErr "Enthalpy of saturated vapor percent error";

protected
  constant Real conv(unit="1/s") = 1 "Conversion factor to satisfy unit check";

function enthalpyOfSaturatedLiquid
  "Return enthalpy of saturated liquid"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.AbsolutePressure p "Pressure";
    output Modelica.Units.SI.SpecificEnthalpy hl "Enthalpy of saturated liquid";
algorithm
  hl := Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hl_p(p);
end enthalpyOfSaturatedLiquid;

function enthalpyOfSaturatedVapor
  "Return enthalpy of saturated liquid"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.AbsolutePressure p "Pressure";
    output Modelica.Units.SI.SpecificEnthalpy hv "Enthalpy of saturated liquid";
algorithm
  hv := Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hv_p(p);
end enthalpyOfSaturatedVapor;

function enthalpyOfVaporization
  "Return enthalpy of vaporization"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.AbsolutePressure p "Pressure";
    output Modelica.Units.SI.SpecificEnthalpy r0 "Vaporization enthalpy";
algorithm
  r0 := Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hv_p(p) -
    Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hl_p(p);
end enthalpyOfVaporization;

equation
  // Compute temperatures that are used as input to the functions
  TSat0 = TMin + conv*time * (TMax-TMin);

  // Set saturation states
  pSat = MediumSte.saturationPressure(TSat0);
  TSat = MediumSte.saturationTemperature(pSat);
  if (time>0.1) then
  assert(abs(TSat-TSat0)<tol, "Error in implementation of functions.\n"
     + "   TSat0 = " + String(TSat0) + "\n"
     + "   TSat  = " + String(TSat) + "\n"
     + "   Absolute error: " + String(abs(TSat-TSat0)) + " K");
  end if;
  TSat_degC =Modelica.Units.Conversions.to_degC(TSat);
  sat = MediumSte.setState_pTX(p=pSat, T=TSat, X=MediumSte.X_default);

  hlvIF97 = enthalpyOfVaporization(pSat);
  hlvWatSte = MediumSte.specificEnthalpy(sat) - MediumWat.specificEnthalpy(sat);
  hlIF97 = enthalpyOfSaturatedLiquid(pSat);
  hlWat = MediumWat.specificEnthalpy(sat);
  hvIF97 = enthalpyOfSaturatedVapor(pSat);
  hvSte = MediumSte.specificEnthalpy(sat);

  hlvErr = abs(hlvIF97 - hlvWatSte)/hlvIF97*100;
  hlErr = abs(hlIF97 - hlWat)/hlIF97*100;
  hvErr = abs(hvIF97 - hvSte)/hvIF97*100;
end SteamSaturationConsistencyCheck;


within AixLib.Media.Examples;
model SteamTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.TestTemperatureEnthalpyInversion(
    redeclare package Medium = AixLib.Media.Steam,
    T0=273.15 + 300);
end SteamTemperatureEnthalpyInversion;


within AixLib.Media.Examples;
model WaterDerivativeCheck "Model that tests the derivative implementation"
  extends Modelica.Icons.Example;

   package Medium = AixLib.Media.Water;

  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy hLiqSym "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hLiqCod "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificHeatCapacity cpSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cpCod "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvCod "Specific heat capacity";
    constant Real convT(unit="K/s3") = 270
    "Conversion factor to satisfy unit check";
initial equation
     hLiqSym = hLiqCod;
     cpSym   = cpCod;
     cvSym   = cvCod;
equation
    T = 273.15+convT*time^3;
    hLiqCod=Medium.enthalpyOfLiquid(T);
    der(hLiqCod)=der(hLiqSym);
    assert(abs(hLiqCod-hLiqSym) < 1E-2, "Model has an error");

    cpCod=Medium.specificHeatCapacityCp(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cpCod)=der(cpSym);
    assert(abs(cpCod-cpSym) < 1E-2, "Model has an error");

     cvCod=Medium.specificHeatCapacityCv(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cvCod)=der(cvSym);
    assert(abs(cvCod-cvSym) < 1E-2, "Model has an error");
end WaterDerivativeCheck;


within AixLib.Media.Examples;
model WaterProperties
  "Model that tests the implementation of the fluid properties"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.FluidProperties(
    redeclare package Medium = AixLib.Media.Water,
    TMin=273.15,
    TMax=373.15);
equation
  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
end WaterProperties;


within AixLib.Media.Examples;
model WaterTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.TestTemperatureEnthalpyInversion(
    redeclare package Medium = AixLib.Media.Water);
end WaterTemperatureEnthalpyInversion;


Model that tests the implementation of the fluid properties. This example checks thermophysical properties of the medium.

within AixLib.Media.Examples.BaseClasses;
partial model FluidProperties
  "Model that tests the implementation of the fluid properties"
  extends PartialProperties;

  Medium.ThermodynamicState state_phX "Medium state";
  Medium.ThermodynamicState state_psX "Medium state";

  Modelica.Media.Interfaces.Types.DerDensityByPressure ddpT
    "Density derivative w.r.t. pressure";
  Modelica.Media.Interfaces.Types.DerDensityByTemperature ddTp
    "Density derivative w.r.t. temperature";
  Modelica.Units.SI.Density[Medium.nX] dddX
    "Density derivative w.r.t. mass fraction";

equation

   // Check setting the states
    state_pTX = Medium.setState_pTX(p=p, T=T, X=X);
    state_phX = Medium.setState_phX(p=p, h=h, X=X);
    state_psX = Medium.setState_psX(p=p, s=s, X=X);
    checkState(state_pTX, state_phX, errAbs, "state_phX");
    checkState(state_pTX, state_psX, errAbs, "state_psX");

    // Check the implementation of the functions
    ddpT = Medium.density_derp_T(state_pTX);
    ddTp = Medium.density_derT_p(state_pTX);
    dddX   = Medium.density_derX(state_pTX);
end FluidProperties;


within AixLib.Media.Examples;
package BaseClasses "Package with base classes for AixLib.Media.Examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Media.Examples.BaseClasses;
partial model PartialProperties
  "Partial model that contains common parameters of the fluid properties"

  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium;

  parameter Modelica.Units.SI.Temperature TMin
    "Minimum temperature for the simulation";
  parameter Modelica.Units.SI.Temperature TMax
    "Maximum temperature for the simulation";
  parameter Modelica.Units.SI.Pressure p=Medium.p_default "Pressure";
  parameter Modelica.Units.SI.MassFraction X[Medium.nX]=Medium.X_default
    "Mass fraction";
  parameter Real errAbs=1E-8 "Absolute error used in the check of the state calculations";
  Medium.Temperature T "Temperature";
  Modelica.Units.NonSI.Temperature_degC T_degC "Celsius temperature";

  Medium.ThermodynamicState state_pTX "Medium state";

  Modelica.Units.SI.Density d "Density";
  Modelica.Units.SI.DynamicViscosity eta "Dynamic viscosity";
  Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy";
  Modelica.Units.SI.SpecificInternalEnergy u "Specific internal energy";
  Modelica.Units.SI.SpecificEntropy s "Specific entropy";
  Modelica.Units.SI.SpecificEnergy g "Specific Gibbs energy";
  Modelica.Units.SI.SpecificEnergy f "Specific Helmholtz energy";

  Modelica.Units.SI.SpecificEnthalpy hIse "Isentropic enthalpy";

  Modelica.Media.Interfaces.Types.IsobaricExpansionCoefficient beta
    "Isobaric expansion coefficient";
  Modelica.Units.SI.IsothermalCompressibility kappa
    "Isothermal compressibility";

  Modelica.Units.SI.SpecificHeatCapacity cp "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cv "Specific heat capacity";
  Modelica.Units.SI.ThermalConductivity lambda "Thermal conductivity";

  Modelica.Units.SI.AbsolutePressure pMed "Pressure";
  Medium.Temperature TMed "Temperature";
  Modelica.Units.SI.MolarMass MM "Mixture molar mass";

  Medium.BaseProperties basPro "Medium base properties";
protected
  constant Real conv(unit="1/s") = 1 "Conversion factor to satisfy unit check";

  function checkState "This function checks the absolute error in the state calculations"
    extends Modelica.Icons.Function;
    input Medium.ThermodynamicState state1 "Medium state";
    input Medium.ThermodynamicState state2 "Medium state";
    input Real errAbs "Absolute error threshold";
    input String message "Message for error reporting";

  protected
              Real TErrAbs=abs(Medium.temperature(state1)-Medium.temperature(state2))
      "Absolute error in temperature";
  protected
              Real pErrAbs=abs(Medium.pressure(state1)-Medium.pressure(state2))
      "Absolute error in pressure";
  algorithm
    assert(TErrAbs < errAbs, "Absolute temperature error: " + String(TErrAbs) +
       " K. Error in temperature of " + message);
    assert(pErrAbs < errAbs, "Absolute pressure error: " + String(pErrAbs) +
       " Pa. Error in pressure of " + message);
  end checkState;

equation
    // Compute temperatures that are used as input to the functions
    T = TMin + conv*time * (TMax-TMin);
    T_degC =Modelica.Units.Conversions.to_degC(T);

    // Check the implementation of the functions
    d = Medium.density(state_pTX);
    eta = Medium.dynamicViscosity(state_pTX);
    h = Medium.specificEnthalpy(state_pTX);

    u = Medium.specificInternalEnergy(state_pTX);
    s = Medium.specificEntropy(state_pTX);
    g = Medium.specificGibbsEnergy(state_pTX);
    f = Medium.specificHelmholtzEnergy(state_pTX);
    hIse = Medium.isentropicEnthalpy(p, state_pTX);
    beta = Medium.isobaricExpansionCoefficient(state_pTX);
    kappa = Medium.isothermalCompressibility(state_pTX);

    cp = Medium.specificHeatCapacityCp(state_pTX);
    cv = Medium.specificHeatCapacityCv(state_pTX);
    lambda = Medium.thermalConductivity(state_pTX);
    pMed = Medium.pressure(state_pTX);
    assert(abs(p-pMed) < errAbs, "Error in pressure computation.");
    TMed = Medium.temperature(state_pTX);
    assert(abs(T-TMed) < errAbs, "Error in temperature computation.");
    MM = Medium.molarMass(state_pTX);
    // Check the implementation of the base properties
    assert(abs(h-basPro.h) < errAbs, "Error in enthalpy computation in BaseProperties.");
    assert(abs(u-basPro.u) < errAbs, "Error in internal energy computation in BaseProperties.");
end PartialProperties;


within AixLib.Media.Examples.BaseClasses;
partial model TestTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse with a controlleable tolerance"
   replaceable package Medium =
        Modelica.Media.Interfaces.PartialMedium;
  parameter Modelica.Units.SI.Temperature T0=273.15 + 20 "Temperature";
     parameter Real tol = 1E-8 "Numerical tolerance";
  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy h "Enthalpy";
     Medium.MassFraction Xi[:] = Medium.reference_X "Mass fraction";
equation
    h = Medium.specificEnthalpy_pTX(p=101325, T=T0, X=Xi);
    T = Medium.temperature_phX(p=101325, h=h,  X=Xi);
    if (time>=0.1) then
    assert(abs(T-T0)<tol, "Error in implementation of functions.\n"
       + "   T0 = " + String(T0) + "\n"
       + "   T  = " + String(T) + "\n"
       + "   Absolute error: " + String(abs(T-T0)) + " K");
    end if;
end TestTemperatureEnthalpyInversion;


within AixLib.Media;
package Refrigerants "Package with functions for refrigerant properties"
  extends Modelica.Icons.Package;
end Refrigerants;


within AixLib.Media.Refrigerants.Examples;
model BranchingDynamicPipes
  "Example model to test dynamic mass and energy equations"
  extends Modelica.Fluid.Examples.BranchingDynamicPipes(
    redeclare package Medium =
        AixLib.Media.Refrigerants.R134a.R134a_IIR_P1_395_T233_455_Horner,
        system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));
end BranchingDynamicPipes;


within AixLib.Media.Refrigerants;
package Examples "Packages with example models for testing refrigerent models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within AixLib.Media.Refrigerants.Examples;
model RefrigerantProperties
  "Model that tests the implementation of the refrigerant properties"
  extends Modelica.Icons.Example;

  // Define the refrigerant that shall be tested
  //
  package Medium =
      AixLib.Media.Refrigerants.R134a.R134a_IIR_P1_395_T233_455_Horner
      "Internal medium model";

  // Define way of calculating pressure and temperature
  //
  parameter Boolean wayOfCalc = true
    "true = Slowly raise pressure and change temperature | false = Slowly raise
    temperature and change pressure"

  // Define the fluid limits of the medium that shall be tested
  //
  parameter Modelica.Units.SI.SpecificEnthalpy h_min=145e3
    "Fluid limit: Minimum specific enthalpy"
  parameter Modelica.Units.SI.SpecificEnthalpy h_max=480e3
    "Fluid limit: Maximum specific enthalpy"
  parameter Modelica.Units.SI.Density d_min=2 "Fluid limit: Minimum density"
  parameter Modelica.Units.SI.Density d_max=1325 "Fluid limit: Maximum density"
  parameter Modelica.Units.SI.AbsolutePressure p_min=1e5
    "Fluid limit: Minimum absolute pressure"
  parameter Modelica.Units.SI.AbsolutePressure p_max=39e5
    "Fluid limit: Maximum absolute pressure"
  parameter Modelica.Units.SI.Temperature T_min=233.15
    "Fluid limit: Minimum temperature"
  parameter Modelica.Units.SI.Temperature T_max=455.15
    "Fluid limit: Maximum temperature"

  // Define the conversion factor for the test
  //
  Real convT(start = (T_max-T_min)/80)
    "Conversion factor in K/s for temperature to satisfy unit check";
  Real convP(start = (p_max-p_min)/(80*80))
    "Conversion factor in Pa/s for pressure to satisfy unit check";

  // Define variables that shall be tested
  //
  Modelica.Units.SI.Temperature T(start=T_min) "Actual temperature";
  Modelica.Units.SI.AbsolutePressure p(start=p_min) "Actual absolute presure";
  Modelica.Units.SI.Density d(start=d_min) "Actual density";
  Modelica.Units.SI.SpecificEnthalpy h(start=h_min) "Actual specific enthalpy";
  Modelica.Units.SI.SpecificEntropy s "Actual specific entropy";
  Modelica.Units.SI.SpecificInternalEnergy u "Actual specific internal energy";
  Modelica.Units.SI.SpecificEnergy g "Actual specific Gibbs energy";
  Modelica.Units.SI.SpecificEnergy f "Actual specific Helmholtz energy";

  Medium.SaturationProperties satT
    "Actual saturation properties calculated with temperature";
  Medium.SaturationProperties satP
    "Actual saturation properties calculated with pressure";

  Medium.ThermodynamicState bubbleState
    "Actual bubble state";
  Medium.ThermodynamicState dewState
    "Actual dew state";
  Medium.ThermodynamicState state_pT
    "Actual state calculated by p and T";
  Medium.ThermodynamicState state_dT
    "Actual state calculated by d and T";
  Medium.ThermodynamicState state_ph
    "Actual state calculated by p and h";
  Medium.ThermodynamicState state_ps
    "Actual state calculated by p and s";

  // Define records to summarise further variables that shall be tested
  //
  record ThermodynamicProperties
    "Records that contains furhter thermodynamic properties"
    Medium.SpecificHeatCapacity cp
      "Actual specific heat capacity at constant pressure";
    Medium.SpecificHeatCapacity cv
      "Actual specific heat capacity at constant volume";
    Medium.VelocityOfSound w
      "Actual velocity of sound";
    Medium.IsobaricExpansionCoefficient betta
      "Actual isobaric expansion coefficient";
    Modelica.Units.SI.IsothermalCompressibility kappa
      "Actual isothermal compressibility";
    Modelica.Units.SI.IsentropicExponent gamma "Actual isentropic coefficient";
    Real delta_T(unit= "J/(Pa.kg)")
      "Actual isothermal throttling coefficient";
    Real my(unit="K/Pa")
      "Actual joule Thomson Coefficient";
    Medium.DynamicViscosity eta
      "Actual dynamic viscosity";
    Medium.ThermalConductivity lambda
      "Actual thermal conductivity";
    Medium.SurfaceTension sigma
      "Acutal surface tension";
  end ThermodynamicProperties;

  record StateErrors
    "Record that contains errors occuring using the different
    setState functions"
    extends Modelica.Icons.Record;

    Real errorTemperature_dTMax
      "Error of temperature_dT compared to T";
    Real errorPressure_dTMax
      "Error of pressure_dT compared to p";
    Real errorDensity_dTMax
      "Error of density_dT compared to density_pT";
    Real errorSpecificEnthalpy_dTMax
      "Error of specificEnthalpy_dT compared to specificEnthalpy_pT";
    Real errorTemperature_phMax
      "Error of temperature_ph compared to T";
    Real errorPressure_phMax
      "Error of pressure_ph compared to p";
    Real errorDensity_phMax
      "Error of density_ph compared to density_pT";
    Real errorSpecificEnthalpy_phMax
      "Error of specificEnthalpy_ph compared to specificEnthalpy_pT";
    Real errorTemperature_psMax
      "Error of temperature_ps compared to T";
    Real errorPressure_psMax
      "Error of pressure_ps compared to p";
    Real errorDensity_psMax
      "Error of density_ps compared to density_pT";
    Real errorSpecificEnthalpy_psMax
      "Error of specificEnthalpy_ps compared to specificEnthalpy_pT";
    Real relErrorTemperature_dTMax
     "Relative error of temperature_dT compared to T";
    Real relErrorPressure_dTMax
     "Relative error of pressure_dT compared to p";
    Real relErrorDensity_dTMax
     "Relative error of density_dT compared to density_pT";
    Real relErrorSpecificEnthalpy_dTMax
     "Relative error of specificEnthalpy_dT compared to specificEnthalpy_pT";
    Real relErrorTemperature_phMax
     "Relative error of temperature_ph compared to T";
    Real relErrorPressure_phMax
     "Relative error of pressure_ph compared to p";
    Real relErrorDensity_phMax
     "Relative error of density_ph compared to density_pT";
    Real relErrorSpecificEnthalpy_phMax
     "Relative error of specificEnthalpy_ph compared to specificEnthalpy_pT";
    Real relErrorTemperature_psMax
     "Relative error of temperature_ps compared to T";
    Real relErrorPressure_psMax
     "Relative error of pressure_ps compared to p";
    Real relErrorDensity_psMax
     "Relative error of density_ps compared to density_pT";
    Real relErrorSpecificEnthalpy_psMax
     "Relative error of specificEnthalpy_ps compared to specificEnthalpy_pT";
  end StateErrors;

  ThermodynamicProperties thermodynamicProperties
    "Record that contains further thermodynamic properties calculated during
    the test";
  StateErrors stateErros
    "Record that contains errors occuring using the different
    setState functions";

protected
  Modelica.Units.SI.Time convChange(start=0)
    "Time to reset calculation of actual temperature or pressure";
  Modelica.Units.SI.Time convChangeTmp(start=0)
    "Temporary time to reset calculation of actual temperature or pressure";

algorithm
  if wayOfCalc then
    convT := (T_max - T_min)/80;
    convP := (p_max - p_min)/(80*80);
    convChange := if noEvent(delay(T,1)) >=
      T_max-convT then time else convChangeTmp;
  else
    convT := (T_max - T_min)/(80*80);
    convP := (p_max - p_min)/80;
    convChange := if noEvent(delay(p,1)) >=
      p_max-convP then time else convChangeTmp;
  end if;

equation

  // Change correction factors for temperature and pressure calculation
  //
  convChangeTmp = convChange;

  // Change independent thermodynamic state properties acording to time
  //
  if wayOfCalc then
    T =  min((T_min + convT * (time - convChange)),T_max);
    p =  min((p_min + convP * time),p_max);
  else
    T =  min((T_min + convT * time),T_max);
    p =  min((p_min + convP * (time - convChange)),p_max);
  end if;

  // Calculate furhter thermodynamic state properties
  //
  d = Medium.density(state_pT);
  h = Medium.specificEnthalpy(state_pT);
  s = Medium.specificEntropy(state_pT);
  u = h - p/d;
  g = h - T*s;
  f = h - p/d -T*s;

  // Calculate and check saturation properties
  //
  satT = Medium.setSat_T(min(max(243.15,T),
    Medium.fluidConstants[1].criticalTemperature-3));
  satP = Medium.setSat_p(satT.psat);

  // Calculate and check state functions
  //
  bubbleState = Medium.setBubbleState(satT,1);
  dewState = Medium.setDewState(satT,1);
  state_pT = Medium.setState_pT(p,T);
  state_dT = Medium.setState_dT(d,T);
  state_ph = Medium.setState_ph(p,h);
  state_ps = Medium.setState_ps(p,s);

  // Calculate further properties
  //
  thermodynamicProperties.cp = Medium.specificHeatCapacityCp(state_pT);
  thermodynamicProperties.cv = Medium.specificHeatCapacityCv(state_pT);
  thermodynamicProperties.w = Medium.velocityOfSound(state_pT);
  thermodynamicProperties.betta =
    Medium.isobaricExpansionCoefficient(state_pT);
  thermodynamicProperties.kappa = Medium.isothermalCompressibility(state_pT);
  thermodynamicProperties.gamma = Medium.isentropicExponent(state_pT);
  thermodynamicProperties.delta_T =
    Medium.isothermalThrottlingCoefficient(state_pT);
  thermodynamicProperties.my = Medium.jouleThomsonCoefficient(state_pT);
  thermodynamicProperties.eta = Medium.dynamicViscosity(state_pT);
  thermodynamicProperties.lambda = Medium.thermalConductivity(state_pT);
  thermodynamicProperties.sigma = Medium.surfaceTension(satT);

  // Calculate errors of thermodynamic state properties
  //
  stateErros.errorTemperature_dTMax =  abs(state_dT.T - state_pT.T);
  stateErros.errorPressure_dTMax =  abs(state_dT.p - state_pT.p);
  stateErros.errorDensity_dTMax = abs(state_dT.d - state_pT.d);
  stateErros.errorSpecificEnthalpy_dTMax = abs(state_dT.h - state_pT.h);
  stateErros.errorTemperature_phMax = abs(state_ph.T - state_pT.T);
  stateErros.errorPressure_phMax = abs(state_ph.p - state_pT.p);
  stateErros.errorDensity_phMax = abs(state_ph.d - state_pT.d);
  stateErros.errorSpecificEnthalpy_phMax = abs(state_ph.h - state_pT.h);
  stateErros.errorTemperature_psMax = abs(state_ps.T - state_pT.T);
  stateErros.errorPressure_psMax = abs(state_ps.p - state_pT.p);
  stateErros.errorDensity_psMax = abs(state_ps.d - state_pT.d);
  stateErros.errorSpecificEnthalpy_psMax = abs(state_ps.h - state_pT.h);

  stateErros.relErrorTemperature_dTMax =  abs(state_dT.T - state_pT.T) /
    abs(state_pT.T)*100;
  stateErros.relErrorPressure_dTMax =  abs(state_dT.p - state_pT.p) /
    abs(state_pT.p)*100;
  stateErros.relErrorDensity_dTMax = abs(state_dT.d - state_pT.d) /
    abs(state_pT.d)*100;
  stateErros.relErrorSpecificEnthalpy_dTMax = abs(state_dT.h - state_pT.h) /
    abs(state_pT.h)*100;
  stateErros.relErrorTemperature_phMax = abs(state_ph.T - state_pT.T) /
    abs(state_pT.T)*100;
  stateErros.relErrorPressure_phMax = abs(state_ph.p - state_pT.p) /
    abs(state_pT.p)*100;
  stateErros.relErrorDensity_phMax = abs(state_ph.d - state_pT.d) /
    abs(state_pT.d)*100;
  stateErros.relErrorSpecificEnthalpy_phMax = abs(state_ph.h - state_pT.h) /
    abs(state_pT.h)*100;
  stateErros.relErrorTemperature_psMax = abs(state_ps.T - state_pT.T) /
    abs(state_pT.T)*100;
  stateErros.relErrorPressure_psMax = abs(state_ps.p - state_pT.p) /
    abs(state_pT.p)*100;
  stateErros.relErrorDensity_psMax = abs(state_ps.d - state_pT.d) /
    abs(state_pT.d)*100;
  stateErros.relErrorSpecificEnthalpy_psMax = abs(state_ps.h - state_pT.h) /
    abs(state_pT.h)*100;
end RefrigerantProperties;


within AixLib.Media.Refrigerants.Examples;
model RefrigerantTestImplementation
  "Model to test the refrigerant implementation"
  extends Modelica.Icons.Example;
  extends Modelica.Media.Examples.Tests.Components.PartialTestModel2(
    redeclare package Medium =
        AixLib.Media.Refrigerants.R410A_HEoS.R410a_IIR_P1_48_T233_340_Record,
    h_start=151000,
    p_start=150000,
    T_start=333.15,
    fixedMassFlowRate(use_T_ambient=true),
    volume(use_T_start=true),
    ambient(use_T_ambient=true));
end RefrigerantTestImplementation;


Types, constants to define menu choices

within AixLib.Media.Refrigerants.Interfaces;
package Choices
  "Types, constants to define menu choices"
  extends Modelica.Media.Interfaces.Choices;

  type InputChoice = enumeration(
      pT "(p,T) as inputs",
      dT "(d,T) as inputs",
      ph "(p,h) as inputs",
      ps "(p,s) as inputs")
     "Enumeration to define input choice of calculating thermodynamic state"
end Choices;


within AixLib.Media.Refrigerants;
package Interfaces "Package with interfaces for refrigerant models"
  extends Modelica.Icons.InterfacesPackage;
end Interfaces;