within AixLib.Media.Refrigerants.Validation.RefrigerantsDerivatives;
model RefrigerantsDerivativesR134a
  "Model that checks the implementation of derivatives for R134a"
  extends Modelica.Icons.Example;

  // Definition of the refrigerant that shall be tested
  //
  replaceable package MediumInt =
     AixLib.Media.Refrigerants.R134a.R134a_IIR_P1_395_T233_455_Horner
    "Internal medium model";

  // Definition of parameters and constants
  //
  parameter MediumInt.AbsolutePressure p0 = 20e5
    "Fixed pressure for calculations at initialization";
  parameter MediumInt.Density d0 = 75
    "Fixed density for calculations at initialization";

  constant Real convT(unit="K/s3") = 125
    "Conversion factor to satisfy derivative check";
  constant Real convH(unit="J/(kg.s3)") = 300e3
    "Conversion factor to satisfy derivative check";
  constant Real convS(unit="J/(kg.K.s3)") = 750
    "Conversion factor to satisfy derivative check";

  // Definition of variables used for calculations
  //
  MediumInt.AbsolutePressure p = p0 + 10e5*time^3
    "Pressure used for calculations";
  MediumInt.Temperature T = 273.15 + convT*time^3
    "Temperature used for calculations";
  MediumInt.Density d = d0 + 125*time^3
    "Density used for calculations";
  MediumInt.SpecificEnthalpy h = 200e3 + convH*time^3
    "Specific enthalpy used for calculations";
  MediumInt.SpecificEntropy s = 1e3 + convS*time^3
    "Specific entropy used for calculations";

  // Definition of submodels and connectors
  //
  Modelica.Blocks.Sources.CombiTimeTable extProp(
    tableOnFile=true,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    tableName="External",
    fileName=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Media/Refrigerants/ValidationDerivativesR134a.txt"),
    columns=2:72)
    "Table that contains the results of the external media library"

  // Definition of thermodynamic state record for external medium model
  //
  record TheStaExt
    "Record that contains thermodynamic state properties for external medium"
    Real phase "Phase of the refrigerant";
    Modelica.Units.SI.Density d "Density of the refrigerant";
    Modelica.Units.SI.Temperature T "Temperature of the refrigerant";
    Modelica.Units.SI.AbsolutePressure p "Pressure of the refrigerant";
    Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy of the refrigerant";
  end TheStaExt;

  // Definition of states that include both one-phase and two-phase regions
  //
  record States
    "Record that contains calculated states for further calculations"
    MediumInt.ThermodynamicState dT_Int
      "Thermodynamic state calculated by d and T by the internal medium model";
    MediumInt.ThermodynamicState pT_Int
      "Thermodynamic state calculated by p and T by the internal medium model";
    MediumInt.ThermodynamicState ph_Int
      "Thermodynamic state calculated by p and h by the internal medium model";
    MediumInt.ThermodynamicState ps_Int
      "Thermodynamic state calculated by p and s by the internal medium model";
    TheStaExt dT_Ext
      "Thermodynamic state calculated by d and T by the external medium model";
    TheStaExt pT_Ext
      "Thermodynamic state calculated by p and T by the external medium model";
    TheStaExt ph_Ext
      "Thermodynamic state calculated by p and h by the external medium model";
    TheStaExt ps_Ext
      "Thermodynamic state calculated by p and s by the external medium model";

    MediumInt.SpecificEntropy s_dT_Int
      "Specific entropy calculated by d and T by the internal medium model";
    MediumInt.SpecificEntropy s_dT_Ext
      "Specific entropy calculated by d and T by the external medium model";
    MediumInt.SpecificEntropy s_pT_Int
      "Specific entropy calculated by p and T by the internal medium model";
    MediumInt.SpecificEntropy s_pT_Ext
      "Specific entropy calculated by p and T by the external medium model";
    MediumInt.SpecificEntropy s_ph_Int
      "Specific entropy calculated by p and h by the internal medium model";
    MediumInt.SpecificEntropy s_ph_Ext
      "Specific entropy calculated by p and h by the external medium model";
    MediumInt.SpecificEntropy s_ps_Int
      "Specific entropy calculated by p and s by the internal medium model";
    MediumInt.SpecificEntropy s_ps_Ext
      "Specific entropy calculated by p and s by the external medium model";

    Real phase_dT
      "Actual phase of thermodynamic state calculated by d and T";
    Real phase_ph
      "Actual phase of thermodynamic state calculated by p and h";
    Real phase_ps
      "Actual phase of thermodynamic state calculated by p and s";
  end States;
  States states
    "Record that contains thermodynamic states calculated by
    independent state variables";

  // Definition of properties derived by partial derivatives of the EoS
  //
  record DerProp
    "Record that containts properties derived by partial derivatives of the EoS"
    Modelica.Units.SI.SpecificHeatCapacity cp_Int
      "Isobaric heat capacity calculated by the internal medium model";
    Modelica.Units.SI.SpecificHeatCapacity cp_Ext
      "Isobaric heat capacity calculated by the external medium model";
    Modelica.Units.SI.SpecificHeatCapacity cv_Int
      "Isochoric heat capacity calculated by the internal medium model";
    Modelica.Units.SI.SpecificHeatCapacity cv_Ext
      "Isochoric heat capacity calculated by the external medium model";
    Modelica.Units.SI.VelocityOfSound a_Int
      "Velocity of sound calculated by the internal medium model";
    Modelica.Units.SI.VelocityOfSound a_Ext
      "Velocity of sound calculated by the external medium model";
    MediumInt.IsobaricExpansionCoefficient beta_Int
      "Isobaric expansion coefficient calculated by the internal medium model";
    MediumInt.IsobaricExpansionCoefficient beta_Ext
      "Isobaric expansion coefficient calculated by the external medium model";
    MediumInt.IsentropicExponent gamma_Int
      "Isentropic exponent calculated by the internal medium model";
    MediumInt.IsentropicExponent gamma_Ext
      "Isentropic exponent calculated by the external medium model";
    Modelica.Units.SI.IsothermalCompressibility kappa_Int
      "Isothermal compressibility calculated by the internal medium model";
    Modelica.Units.SI.IsothermalCompressibility kappa_Ext
      "Isothermal compressibility calculated by the external medium model";
    Real delta_T_Int
      "Isothermal throttling coefficient calculated by the internal medium model";
    Real delta_T_Ext
      "Isothermal throttling coefficient by the external medium model";
    Real my_Int
      "Joule Thomson coefficient by the internal medium model";
    Real my_Ext
      "Joule Thomson coefficient calculated by the external medium model";

    Real d_cp =  cp_Int - cp_Ext
      "Difference of the isobaric heat capacity";
    Real d_cv =  cv_Int - cv_Ext
      "Difference of the isochoric heat capacity";
    Real d_a =  a_Int-a_Ext
      "Difference of the velocity of sound";
    Real d_beta =  beta_Int - beta_Ext
      "Difference of the isobaric expansion coefficient";
    Real d_gamma =  gamma_Int-gamma_Ext
      "Difference of the isentropic exponent";
    Real d_kappa =  kappa_Int - kappa_Ext
      "Difference of the isothermal compressibility";
    Real d_delta_T =  delta_T_Int - delta_T_Ext
      "Difference of the isothermal throttling coefficient";
    Real d_my =  my_Int - my_Ext
      "Difference of the Joule Thomson coefficient";
  end DerProp;
  DerProp derProp
    "Record that contains thermodynamic properties derived
    by partial derivatives";

  // Definition of derivatives depending on derivatives of the EoS only
  //
  record ExplDer
    "Record that contains derivatives depending on derivatives of the EoS only"
    Real dpdd_T_Int
      "Derivative (dp/dd)_T=const. calculated by the internal medium model";
    Real dpdd_T_Ext
      "Derivative (dp/dd)_T=const. calculated by the external medium model";
    Real dpdT_d_Int
      "Derivative (dp/dT)_d=const. calculated by the internal medium model";
    Real dpdT_d_Ext
      "Derivative (dp/dT)_d=const. calculated by the external medium model";

    Real dhdT_d_Int
      "Derivative (dh/dT)_d=const. calculated by the internal medium model";
    Real dhdT_d_Ext
      "Derivative (dh/dT)_d=const. calculated by the external medium model";
    Real dhdd_T_Int
      "Derivative (dh/dd)_T=const. calculated by the internal medium model";
    Real dhdd_T_Ext
      "Derivative (dh/dd)_T=const. calculated by the external medium model";

    Real dsdd_T_Int
      "Derivative (ds/dd)_T=const. calculated by the internal medium model";
    Real dsdd_T_Ext
      "Derivative (ds/dd)_T=const. calculated by the external medium model";
    Real dsdT_d_Int
      "Derivative (ds/dT)_d=const. calculated by the internal medium model";
    Real dsdT_d_Ext
      "Derivative (ds/dT)_d=const. calculated by the external medium model";

    Real dudT_d_Int
      "Derivative (du/dT)_d=const. calculated by the internal medium model";
    Real dudT_d_Ext
      "Derivative (du/dT)_d=const. calculated by the external medium model";
    Real dudd_T_Int
      "Derivative (du/dd)_T=const. calculated by the internal medium model";
    Real dudd_T_Ext
      "Derivative (du/dd)_T=const. calculated by the external medium model";

    Real d_dpdd_T =  dpdd_T_Int-dpdd_T_Ext
      "Difference of the derivative (dp/dd)_T=const.";
    Real d_dpdT_d =  dpdT_d_Int-dpdT_d_Ext
      "Difference of the derivative (dp/dT)_d=const.";
    Real d_dhdT_d =  dhdT_d_Int-dhdT_d_Ext
      "Difference of the derivative (dh/dT)_d=const.";
    Real d_dhdd_T =  dhdd_T_Int-dhdd_T_Ext
      "Difference of the derivative (dh/dd)_T=const.";
    Real d_dsdd_T =  dsdd_T_Int-dsdd_T_Ext
      "Difference of the derivative (ds/dd)_T=const.";
    Real d_dsdT_d =  dsdT_d_Int-dsdT_d_Ext
      "Difference of the derivative (ds/dT)_d=const.";
    Real d_dudT_d =  dudT_d_Int-dudT_d_Ext
      "Difference of the derivative (du/dT)_d=const.";
    Real d_dudd_T =  dudd_T_Int-dudd_T_Ext
      "Difference of the derivative (du/dd)_T=const.";
  end ExplDer;
  ExplDer explDer
    "Record that contains partial derivatives wrt. density and temperature";

  // Definition of further derivatives
  //
  record FurDer "Record that contains further derivatives"
    Real dddp_T_Int
      "Derivative (dd/dp)_T=const. calculated by the internal medium model";
    Real dddp_T_Ext
      "Derivative (dd/dp)_T=const. calculated by the external medium model";
    Real dddT_p_Int
      "Derivative (dd/dT)_p=const. calculated by the internal medium model";
    Real dddT_p_Ext
      "Derivative (dd/dT)_p=const. calculated by the external medium model";
    Real dddp_h_Int
      "Derivative (dd/dp)_h=const. calculated by the internal medium model";
    Real dddp_h_Ext
      "Derivative (dd/dp)_h=const. calculated by the external medium model";
    Real dddh_p_Int
      "Derivative (dd/dh)_p=const. calculated by the internal medium model";
    Real dddh_p_Ext
      "Derivative (dd/dh)_p=const. calculated by the external medium model";
    Real dddp_s_Int
      "Derivative (dd/dp)_s=const. calculated by the internal medium model";
    Real dddp_s_Ext
      "Derivative (dd/dp)_s=const. calculated by the external medium model";
    Real ddds_p_Int
      "Derivative (dd/ds)_p=const. calculated by the internal medium model";
    Real ddds_p_Ext
      "Derivative (dd/ds)_p=const. calculated by the external medium model";

    Real dTdp_h_Int
      "Derivative (dT/dp)_h=const. calculated by the internal medium model";
    Real dTdp_h_Ext
      "Derivative (dT/dp)_h=const. calculated by the external medium model";
    Real dTdh_p_Int
      "Derivative (dT/dh)_p=const. calculated by the internal medium model";
    Real dTdh_p_Ext
      "Derivative (dT/dh)_p=const. calculated by the external medium model";
    Real dTdp_s_Int
      "Derivative (dT/dp)_s=const. calculated by the internal medium model";
    Real dTdp_s_Ext
      "Derivative (dT/dp)_s=const. calculated by the external medium model";
    Real dTds_p_Int
      "Derivative (dT/ds)_p=const. calculated by the internal medium model";
    Real dTds_p_Ext
      "Derivative (dT/ds)_p=const. calculated by the external medium model";

    Real dhdp_T_Int
      "Derivative (dh/dp)_T=const. calculated by the internal medium model";
    Real dhdp_T_Ext
      "Derivative (dh/dp)_T=const. calculated by the external medium model";
    Real dhdT_p_Int
      "Derivative (dh/dT)_p=const. calculated by the internal medium model";
    Real dhdT_p_Ext
      "Derivative (dh/dT)_p=const. calculated by the external medium model";
    Real dhds_p_Int
      "Derivative (dh/ds)_p=const. calculated by the internal medium model";
    Real dhds_p_Ext
      "Derivative (dh/ds)_p=const. calculated by the external medium model";
    Real dhdp_s_Int
      "Derivative (dh/dp)_s=const. calculated by the internal medium model";
    Real dhdp_s_Ext
      "Derivative (dh/dp)_s=const. calculated by the external medium model";

    Real d_dddp_T = dddp_T_Int - dddp_T_Ext
      "Difference of the derivative (dd/dp)_T=const.";
    Real d_dddT_p = dddT_p_Int - dddT_p_Ext
      "Difference of the derivative (dd/dT)_p=const.";
    Real d_dddp_h = dddp_h_Int - dddp_h_Ext
      "Difference of the derivative (dd/dp)_h=const.";
    Real d_dddh_p = dddh_p_Int - dddh_p_Ext
      "Difference of the derivative (dd/dh)_p=const.";
    Real d_dddp_s = dddp_s_Int - dddp_s_Ext
      "Difference of the derivative (dd/dp)_s=const.";
    Real d_ddds_p = ddds_p_Int - ddds_p_Ext
      "Difference of the derivative (dd/ds)_p=const.";
    Real d_dTdp_h = dTdp_h_Int - dTdp_h_Ext
      "Difference of the derivative (dT/dp)_h=const.";
    Real d_dTdh_p = dTdh_p_Int - dTdh_p_Ext
      "Difference of the derivative (dT/dh)_p=const.";
    Real d_dTdp_s = dTdp_s_Int - dTdp_s_Ext
      "Difference of the derivative (dT/dp)_s=const.";
    Real d_dTds_p = dTds_p_Int - dTds_p_Ext
      "Difference of the derivative (dT/ds)_p=const.";
    Real d_dhdp_T = dhdp_T_Int - dhdp_T_Ext
      "Difference of the derivative (dh/dp)_T=const.";
    Real d_dhdT_p = dhdT_p_Int - dhdT_p_Ext
      "Difference of the derivative (dh/dT)_p=const.";
    Real d_dhds_p = dhds_p_Int - dhds_p_Ext
      "Difference of the derivative (dh/ds)_p=const.";
    Real d_dhdp_s = dhdp_s_Int - dhdp_s_Ext
      "Difference of the derivative (dh/dp)_s=const.";
  end FurDer;
  FurDer furDer
    "Record that contains further derivatives not wrt. density and temperature";

  // Definition of derivates at bubble and dew state
  //
  record SatDer "Record that contains derivatives at bubble and dew state"
    Real dpdT_Int
      "Derivative (dp/dT)_saturation calculated by the internal medium model";
    Real dpdT_Ext
      "Derivative (dp/dT)_saturation calculated by the external medium model";
    Real dTdp_Int
      "Derivative (dT/dp)_saturation calculated by the internal medium model";
    Real dTdp_Ext
      "Derivative (dT/dp)_saturation  calculated by the external medium model";

    Real dddp_l_Int
      "Derivative (dd_l/dp)_saturation calculated by the internal medium model";
    Real dddp_l_Ext
      "Derivative (dd_l/dp)_saturation calculated by the external medium model";
    Real dddp_v_Int
      "Derivative (dd_v/dp)_saturation calculated by the internal medium model";
    Real dddp_v_Ext
      "Derivative (dd_v/dp)_saturation calculated by the external medium model";
    Real dhdp_l_Int
      "Derivative (dh_l/dp)_saturation calculated by the internal medium model";
    Real dhdp_l_Ext
      "Derivative (dh_l/dp)_saturation calculated by the external medium model";
    Real dhdp_v_Int
      "Derivative (dh_v/dp)_saturation calculated by the internal medium model";
    Real dhdp_v_Ext
      "Derivative (dh_v/dp)_saturation calculated by the external medium model";
    Real dsdp_l_Int
      "Derivative (ds_l/dp)_saturation calculated by the internal medium model";
    Real dsdp_l_Ext
      "Derivative (ds_l/dp)_saturation calculated by the external medium model";
    Real dsdp_v_Int
      "Derivative (ds_v/dp)_saturation calculated by the internal medium model";
    Real dsdp_v_Ext
      "Derivative (ds_v/dp)_saturation calculated by the external medium model";

    Real dddT_l_Int
      "Derivative (dd_l/dT)_saturation calculated by the internal medium model";
    Real dddT_l_Ext
      "Derivative (dd_l/dT)_saturation calculated by the external medium model";
    Real dddT_v_Int
      "Derivative (dd_v/dT)_saturation calculated by the internal medium model";
    Real dddT_v_Ext
      "Derivative (dd_v/dT)_saturation calculated by the external medium model";
    Real dhdT_l_Int
      "Derivative (dh_l/dT)_saturation calculated by the internal medium model";
    Real dhdT_l_Ext
      "Derivative (dh_l/dT)_saturation calculated by the external medium model";
    Real dhdT_v_Int
      "Derivative (dh_v/dT)_saturation calculated by the internal medium model";
    Real dhdT_v_Ext
      "Derivative (dh_v/dT)_saturation calculated by the external medium model";
    Real dudT_l_Int
      "Derivative (du_l/dT)_saturation calculated by the internal medium model";
    Real dudT_l_Ext
      "Derivative (du_l/dT)_saturation calculated by the external medium model";
    Real dudT_v_Int
      "Derivative (du_v/dT)_saturation calculated by the internal medium model";
    Real dudT_v_Ext
      "Derivative (du_v/dT)_saturation calculated by the external medium model";

    Real d_dpdT = dpdT_Int - dpdT_Ext
      "Difference of the derivative (dp/dT)_saturation";
    Real d_dTdp = dTdp_Int - dTdp_Ext
      "Difference of the derivative (dT/dp)_saturation";
    Real d_dddp_l = dddp_l_Int - dddp_l_Ext
      "Difference of the derivative (dd_l/dp)_saturation";
    Real d_dddp_v = dddp_v_Int - dddp_v_Ext
      "Difference of the derivative (dd_v/dp)_saturation ";
    Real d_dhdp_l = dhdp_l_Int - dhdp_l_Ext
      "Difference of the derivative (dh_l/dp)_saturation";
    Real d_dhdp_v = dhdp_v_Int - dhdp_v_Ext
      "Difference of the derivative (dh_v/dp)_saturation";
    Real d_dsdp_l = dsdp_l_Int - dsdp_l_Ext
      "Difference of the derivative (ds_l/dp)_saturation";
    Real d_dsdp_v = dsdp_v_Int - dsdp_v_Ext
      "Difference of the derivative (ds_v/dp)_saturation";
    Real d_dddT_l = dddT_l_Int - dddT_l_Ext
      "Difference of the derivative (dd_l/dT)_saturation";
    Real d_dddT_v = dddT_v_Int - dddT_v_Ext
      "Difference of the derivative (dd_v/dT)_saturation";
    Real d_dhdT_l = dhdT_l_Int - dhdT_l_Ext
      "Difference of the derivative (dh_l/dT)_saturation";
    Real d_dhdT_v = dhdT_v_Int - dhdT_v_Ext
      "Difference of the derivative (dh_v/dT)_saturation";
    Real d_dudT_l = dudT_l_Int - dudT_l_Ext
      "Difference of the derivative (du_l/dT)_saturation";
    Real d_dudT_v = dudT_v_Int - dudT_v_Ext
      "Difference of the derivative (du_v/dT)_saturation";
  end SatDer;
  SatDer satDer
    "Record that contains derivates at bubble and dew state";

equation
  // Calculation of states
  //
  states.dT_Int = MediumInt.setState_dTX(d=d,T=
    min(T,MediumInt.fluidConstants[1].criticalTemperature-3));
  states.pT_Int = MediumInt.setState_pTX(p=p,T=T);
  states.ph_Int = MediumInt.setState_phX(p=p,h=h);
  states.ps_Int = MediumInt.setState_psX(p=p,s=s);
  states.dT_Ext.phase = extProp.y[1];
  states.dT_Ext.d = extProp.y[2];
  states.dT_Ext.T = extProp.y[3];
  states.dT_Ext.p = extProp.y[4];
  states.dT_Ext.h = extProp.y[5];
  states.pT_Ext.phase = extProp.y[6];
  states.pT_Ext.d = extProp.y[7];
  states.pT_Ext.T = extProp.y[8];
  states.pT_Ext.p = extProp.y[9];
  states.pT_Ext.h = extProp.y[10];
  states.ph_Ext.phase = extProp.y[11];
  states.ph_Ext.d = extProp.y[12];
  states.ph_Ext.T = extProp.y[13];
  states.ph_Ext.p = extProp.y[14];
  states.ph_Ext.h = extProp.y[15];
  states.ps_Ext.phase = extProp.y[16];
  states.ps_Ext.d = extProp.y[17];
  states.ps_Ext.T = extProp.y[18];
  states.ps_Ext.p = extProp.y[19];
  states.ps_Ext.h = extProp.y[20];

  states.s_dT_Int = MediumInt.specificEntropy(states.dT_Int);
  states.s_dT_Ext = extProp.y[21];
  states.s_pT_Int = MediumInt.specificEntropy(states.pT_Int);
  states.s_pT_Ext = extProp.y[22];
  states.s_ph_Int = MediumInt.specificEntropy(states.ph_Int);
  states.s_ph_Ext = extProp.y[23];
  states.s_ps_Int = MediumInt.specificEntropy(states.ps_Int);
  states.s_ps_Ext = extProp.y[24];

  states.phase_dT = extProp.y[25];
  states.phase_ph = extProp.y[26];
  states.phase_ps = extProp.y[27];

algorithm
  // Calculation of properties based on derivatives
  //
  derProp.cp_Int := MediumInt.specificHeatCapacityCp(states.ph_Int);
  derProp.cp_Ext := extProp.y[28];
  derProp.cv_Int := MediumInt.specificHeatCapacityCv(states.ph_Int);
  derProp.cv_Ext := extProp.y[29];
  derProp.a_Int := MediumInt.velocityOfSound(states.ph_Int);
  derProp.a_Ext := extProp.y[30];
  derProp.beta_Int := MediumInt.isobaricExpansionCoefficient(states.ph_Int);
  derProp.beta_Ext := extProp.y[31];
  derProp.gamma_Int := MediumInt.isentropicExponent(states.ph_Int);
  derProp.gamma_Ext := extProp.y[32];
  derProp.kappa_Int := MediumInt.isothermalCompressibility(states.ph_Int);
  derProp.kappa_Ext :=extProp.y[33];
  derProp.delta_T_Int :=
    MediumInt.isothermalThrottlingCoefficient(states.ph_Int);
  derProp.delta_T_Ext := extProp.y[34];
  derProp.my_Int := MediumInt.jouleThomsonCoefficient(states.ph_Int);
  derProp.my_Ext := extProp.y[35];

  // Calculate derivatives that depend on derivatives of the EoS only
  //
  explDer.dpdd_T_Int := MediumInt.pressure_derd_T(states.ph_Int);
  explDer.dpdd_T_Ext := extProp.y[36];
  explDer.dpdT_d_Int := MediumInt.pressure_derT_d(states.ph_Int);
  explDer.dpdT_d_Ext := extProp.y[37];

  explDer.dhdT_d_Int := MediumInt.specificEnthalpy_derT_d(states.ph_Int);
  explDer.dhdT_d_Ext := extProp.y[38];
  explDer.dhdd_T_Int := MediumInt.specificEnthalpy_derd_T(states.ph_Int);
  explDer.dhdd_T_Ext := extProp.y[39];

  explDer.dsdd_T_Int := MediumInt.specificEntropy_derd_T(states.ph_Int);
  explDer.dsdd_T_Ext := extProp.y[40]; // no two-phase region
  explDer.dsdT_d_Int := MediumInt.specificEntropy_derT_d(states.ph_Int);
  explDer.dsdT_d_Ext := extProp.y[41]; // no two-phase region

  explDer.dudT_d_Int := MediumInt.specificInternalEnergy_derT_d(states.ph_Int);
  explDer.dudT_d_Ext := extProp.y[42]; // no two-phase region
  explDer.dudd_T_Int := MediumInt.specificInternalEnergy_derd_T(states.ph_Int);
  explDer.dudd_T_Ext := extProp.y[43]; // no two-phase region

  // Calculate further derivatives
  //
  furDer.dddp_T_Int := MediumInt.density_derp_T(states.ph_Int);
  furDer.dddp_T_Ext := extProp.y[44];
  furDer.dddT_p_Int := MediumInt.density_derT_p(states.ph_Int);
  furDer.dddT_p_Ext := extProp.y[45];
  furDer.dddp_h_Int := MediumInt.density_derp_h(states.ph_Int);
  furDer.dddp_h_Ext := extProp.y[46];
  furDer.dddh_p_Int := MediumInt.density_derh_p(states.ph_Int);
  furDer.dddh_p_Ext := extProp.y[47];
  furDer.dddp_s_Int := MediumInt.density_derp_s(states.ph_Int);
  furDer.dddp_s_Ext := extProp.y[48]; // no two-phase region
  furDer.ddds_p_Int := MediumInt.density_ders_p(states.ph_Int);
  furDer.ddds_p_Ext := extProp.y[49];

  furDer.dTdp_h_Int := MediumInt.temperature_derp_h(states.ph_Int);
  furDer.dTdp_h_Ext := extProp.y[50];
  furDer.dTdh_p_Int := MediumInt.temperature_derh_p(states.ph_Int);
  furDer.dTdh_p_Ext := extProp.y[51];
  furDer.dTdp_s_Int := MediumInt.temperature_derp_s(states.ph_Int);
  furDer.dTdp_s_Ext := extProp.y[52];
  furDer.dTds_p_Int := MediumInt.temperature_ders_p(states.ph_Int);
  furDer.dTds_p_Ext := extProp.y[53];

  furDer.dhdp_T_Int := MediumInt.specificEnthalpy_derp_T(states.ph_Int);
  furDer.dhdp_T_Ext := extProp.y[54];
  furDer.dhdT_p_Int := MediumInt.specificEnthalpy_derT_p(states.ph_Int);
  furDer.dhdT_p_Ext := extProp.y[55];
  furDer.dhds_p_Int := MediumInt.specificEnthalpy_ders_p(states.ph_Int);
  furDer.dhds_p_Ext := extProp.y[56];
  furDer.dhdp_s_Int := MediumInt.specificEnthalpy_derp_s(states.ph_Int);
  furDer.dhdp_s_Ext := extProp.y[57];

  // Calculate derivatives at bubble and dew line
  //
  satDer.dpdT_Int := MediumInt.saturationPressure_derT(min(
    MediumInt.temperature(states.ph_Int),
    MediumInt.fluidConstants[1].criticalTemperature-3));
  satDer.dpdT_Ext := extProp.y[58];
  satDer.dTdp_Int := MediumInt.saturationTemperature_derp(
    MediumInt.pressure(states.dT_Int));
  satDer.dTdp_Ext := extProp.y[59];

  satDer.dddp_l_Int := MediumInt.dBubbleDensity_dPressure(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dddp_l_Ext := extProp.y[60];
  satDer.dddp_v_Int := MediumInt.dDewDensity_dPressure(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dddp_v_Ext := extProp.y[61];
  satDer.dhdp_l_Int := MediumInt.dBubbleEnthalpy_dPressure(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dhdp_l_Ext := extProp.y[62];
  satDer.dhdp_v_Int := MediumInt.dDewEnthalpy_dPressure(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dhdp_v_Ext := extProp.y[63];
  satDer.dsdp_l_Int := MediumInt.dBubbleEntropy_dPressure(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dsdp_l_Ext := extProp.y[64];
  satDer.dsdp_v_Int := MediumInt.dDewEntropy_dPressure(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dsdp_v_Ext := extProp.y[65];

  satDer.dddT_l_Int := MediumInt.dBubbleDensity_dTemperature(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dddT_l_Ext :=extProp.y[66];
  satDer.dddT_v_Int := MediumInt.dDewDensity_dTemperature(MediumInt.setSat_p(
    MediumInt.pressure(states.dT_Int)));
  satDer.dddT_v_Ext :=extProp.y[67];
  satDer.dhdT_l_Int := MediumInt.dBubbleEnthalpy_dTemperature(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dhdT_l_Ext := extProp.y[68];
  satDer.dhdT_v_Int := MediumInt.dDewEnthalpy_dTemperature(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dhdT_v_Ext :=extProp.y[69];
  satDer.dudT_l_Int := MediumInt.dBubbleInternalEnergy_dTemperature(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dudT_l_Ext := extProp.y[70];
  satDer.dudT_v_Int := MediumInt.dDewInternalEnergy_dTemperature(
    MediumInt.setSat_p(MediumInt.pressure(states.dT_Int)));
  satDer.dudT_v_Ext := extProp.y[71];
end RefrigerantsDerivativesR134a;


within AixLib.Media.Refrigerants.Validation.RefrigerantsDerivatives;
model RefrigerantsDerivativesR290
  "Model that checks the implementation of derivatives for R134a"
  extends RefrigerantsDerivativesR134a(
    redeclare package MediumInt =
      AixLib.Media.Refrigerants.R290.R290_IIR_P05_30_T263_343_Horner,
    extProp(fileName=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Media/Refrigerants/ValidationDerivativesR290.txt")),
    convT=70);
end RefrigerantsDerivativesR290;


within AixLib.Media.Refrigerants.Validation;
package RefrigerantsFittedFormulas "Package that contains validation models to check refrigerants' fitted formulas"
extends Modelica.Icons.ExamplesPackage;
end RefrigerantsFittedFormulas;


within AixLib.Media.Refrigerants.Validation.RefrigerantsFittedFormulas;
model RefrigerantsFittedFormulasR134a
  "Model that checks the fitted formulas of R134a"
  extends Modelica.Icons.Example;

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

  // Define parameters that define the range for calculating the fitted formulas
  //
  parameter Modelica.Units.SI.SpecificEnthalpy h_min=180e3
    "Fluid limit: Minimum specific enthalpy"
  parameter Modelica.Units.SI.SpecificEnthalpy h_max=550e3
    "Fluid limit: Maximum specific enthalpy"
  parameter Modelica.Units.SI.SpecificEntropy s_min=1.0e3
    "Fluid limit: Minimum specific entropy"
  parameter Modelica.Units.SI.SpecificEntropy s_max=1.8e3
    "Fluid limit: Maximum specific entropy"
  parameter Modelica.Units.SI.Density d_min=2.0 "Fluid limit: Minimum density"
  parameter Modelica.Units.SI.Density d_max=1425 "Fluid limit: Maximum density"
  parameter Modelica.Units.SI.AbsolutePressure p_min=1e5
    "Fluid limit: Minimum absolute pressure"
  parameter Modelica.Units.SI.AbsolutePressure p_max=38.5e5
    "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 submodels and connectors
  //
  Modelica.Blocks.Sources.CombiTimeTable extProp(
    tableOnFile=true,
    tableName="External",
    fileName=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Media/Refrigerants/ValidationFittedFormulasR134a.txt"),
    columns=2:26,
    extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint,
    smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments,
    startTime=-0.000001)
    "Table that contains the results of the external media library"

  // 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 convD(start = (d_max-d_min)/(80*80))
    "Conversion factor in kg/m³/s for density to satisfy unit check";
  Real convH(start = (h_max-h_min)/(80*80))
    "Conversion factor in J/kg/s for specific enthalpy to satisfy unit check";
  Real convS(start = (s_max-s_min)/(80*80))
    "Conversion factor in J/kg/K/s for specific entropy to satisfy unit check";

  // Defines state variables
  //
  Modelica.Units.SI.AbsolutePressure p_sat
    "Actual pressure for calculating saturation properties";
  Modelica.Units.SI.Temperature T "Actual pulsating temperature";
  Modelica.Units.SI.Temperature T_sat
    "Actual temperature for calculating saturation properties";
  Modelica.Units.SI.Density d "Actual raising density";
  Modelica.Units.SI.SpecificEnthalpy h
    "Actual pulsating specific enthalpy for calculating state properties";
  Modelica.Units.SI.SpecificEntropy s
    "Actual pulsating specific enthalpy for calculating state properties";
  Real tauInt "Actual dimensionless temperature of internal medium";
  Real deltaInt "Actual dimensionless density of internal medium";

  // Define variables for the derivates of the EoS
  //
  record EoS "Record that contains calculated properties of the EoS"
    Real f_iInt "Ideal part of the internal Helmholtz energy";
    Real f_iExt "Ideal part of the external Helmholtz energy";
    Real f_rInt "Residual part of the internal Helmholtz energy";
    Real f_rExt "Residual part of the external Helmholtz energy";
    Real f_itInt "Derivative di/dt of the internal Helmholtz energy";
    Real f_itExt "Derivative di/dt of the external Helmholtz energy";
    Real f_ittInt "Derivative ddi/dtt of the internal Helmholtz energy";
    Real f_ittExt "Derivative ddi/dtt of the external Helmholtz energy";
    Real f_itttInt "Derivative dddi/dttt of the internal Helmholtz energy";
    Real f_itttExt "Derivative dddi/dttt of the external Helmholtz energy";
    Real f_rtInt "Derivative dr/dt of the internal Helmholtz energy";
    Real f_rtExt "Derivative dr/dt of the external Helmholtz energy";
    Real f_rttInt "Derivative ddr/dtt of the internal Helmholtz energy";
    Real f_rttExt "Derivative ddr/dtt of the external Helmholtz energy";
    Real f_rtttInt "Derivative dddr/dttt of the internal Helmholtz energy";
    Real f_rtttExt "Derivative dddr/dttt of the external Helmholtz energy";
    Real f_rdInt "Derivative dr/dd of the internal Helmholtz energy";
    Real f_rdExt "Derivative dr/dd of the external Helmholtz energy";
    Real f_rddInt "Derivative ddr/ddd of the internal Helmholtz energy";
    Real f_rddExt "Derivative ddr/ddd of the external Helmholtz energy";
    Real f_rdddInt "Derivative dddr/dddd of the internal Helmholtz energy";
    Real f_rdddExt "Derivative dddr/dddd of the external Helmholtz energy";
    Real f_rtdInt "Derivative ddr/dtd of the internal Helmholtz energy";
    Real f_rtdExt "Derivative ddr/dtd of the external Helmholtz energy";
    Real f_rtddInt "Derivative dddr/dtdd of the internal Helmholtz energy";
    Real f_rtddExt "Derivative dddr/dtdd of the external Helmholtz energy";
    Real f_rttdInt "Derivative dddr/dttd of the internal Helmholtz energy";
    Real f_rttdExt "Derivative dddr/dttd of the external Helmholtz energy";
  end EoS;

  record Saturation
    "Record that contains calculated saturation properties"
    Modelica.Units.SI.AbsolutePressure p_satInt
      "Saturation pressure of internal medium";
    Modelica.Units.SI.AbsolutePressure p_satExt
      "Saturation pressure of external medium";
    Modelica.Units.SI.Temperature T_satInt
      "Saturation temperature of internal medium";
    Modelica.Units.SI.Temperature T_satExt
      "Saturation temperature of external medium";
    Modelica.Units.SI.Density d_lInt "Bubble density of internal medium";
    Modelica.Units.SI.Density d_lExt "Bubble density of external medium";
    Modelica.Units.SI.Density d_vInt "Dew density of internal medium";
    Modelica.Units.SI.Density d_vExt "Dew density of external medium";
    Modelica.Units.SI.SpecificEnthalpy h_lInt
      "Specific bubble enthalpy of internal medium";
    Modelica.Units.SI.SpecificEnthalpy h_lExt
      "Specific bubble enthalpy of external medium";
    Modelica.Units.SI.SpecificEnthalpy h_vInt
      "Specific dew enthalpy internal medium";
    Modelica.Units.SI.SpecificEnthalpy h_vExt
      "Specific dew enthalpy of external medium";
    Modelica.Units.SI.SpecificEntropy s_lInt
      "Specific bubble entropy of internal medium";
    Modelica.Units.SI.SpecificEntropy s_lExt
      "Specific bubble entropy of external medium";
    Modelica.Units.SI.SpecificEntropy s_vInt
      "Specific dew entropy of internal medium";
    Modelica.Units.SI.SpecificEntropy s_vExt
      "Specific dew entropy of external medium";
    Real dp_sat "Relative difference of saturation pressure";
    Real dT_sat "Relative difference of saturation temperature";
    Real dd_l "Relative difference of bubble density";
    Real dd_v "Relative difference of dew density";
    Real dh_l "Relative difference of specific bubble enthalpy";
    Real dh_v "Relative difference of specific dew enthalpy";
    Real ds_l "Relative difference of specific bubble entropy";
    Real ds_v "Relative difference of specific dew entropyy";
  end Saturation;

  record Properties "Record that contains state properties"
    Real d_ptInt "Density of internal medium";
    Real d_ptExt "Density of external medium";
    Real T_phInt "Temperature calculated by p and h of internal medium";
    Real T_phExt "Temperature calculated by p and h of external medium";
    Real T_psInt "Temperature calculated by p and s of internal medium";
    Real T_psExt "Temperature calculated by p and s of external medium";
  end Properties;

  EoS eos "Record that contains calculated properties of the EoS";
  Saturation saturation "Record that contains calculated saturation properties";
  Properties properties "Record that contains calculated state properties";

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

algorithm
    convT := (T_max - T_min)/80;
    convH := (h_max - h_min)/80;
    convS := (s_max - s_min)/80;
    convD := (d_max - d_min)/(80*80);
    convChange := if noEvent(delay(T,1)) >= T_max-convT then
      time else convChangeTmp;

equation

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

  // Change independent thermodynamic state properties
  //
  T =  T_min + convT * (time - convChange);
  h =  h_min + convH * (time - convChange);
  s =  s_min + convS * (time - convChange);
  d =  d_min + convD * time;

  // Calculate dimensionless thermydynamic state properties
  //
  tauInt = MediumInt.fluidConstants[1].criticalTemperature/T;
  deltaInt = d/(MediumInt.fluidConstants[1].molarMass/
    MediumInt.fluidConstants[1].criticalMolarVolume);

  // Calculate state properties for calculating saturation properties
  //
  T_sat = T_min + (min(MediumInt.fluidConstants[1].criticalTemperature-2,
    T_max)-T_min)/(80*80) * time;
  p_sat = p_min + (min(MediumInt.fluidConstants[1].criticalPressure-1000,
    p_max)-p_min)/(80*80) * time;

  // Calculate derivatives of the EoS
  //
  eos.f_iInt = MediumInt.f_Idg(deltaInt,tauInt);
  eos.f_iExt = extProp.y[1];
  eos.f_rInt = MediumInt.f_Res(deltaInt,tauInt);
  eos.f_rExt = extProp.y[2];
  eos.f_itInt = MediumInt.t_fIdg_t(tauInt)/tauInt;
  eos.f_itExt = extProp.y[3];
  eos.f_ittInt = MediumInt.tt_fIdg_tt(tauInt)/tauInt^2;
  eos.f_ittExt = extProp.y[4];
  eos.f_itttInt = MediumInt.ttt_fIdg_ttt(tauInt)/tauInt^3;
  eos.f_itttExt = extProp.y[5];
  eos.f_rtInt = MediumInt.t_fRes_t(deltaInt,tauInt)/tauInt;
  eos.f_rtExt =extProp.y[6];
  eos.f_rttInt = MediumInt.tt_fRes_tt(deltaInt,tauInt)/tauInt^2;
  eos.f_rttExt = extProp.y[7];
  eos.f_rtttInt = MediumInt.ttt_fRes_ttt(deltaInt,tauInt)/tauInt^3;
  eos.f_rtttExt = extProp.y[8];
  eos.f_rdInt = MediumInt.d_fRes_d(deltaInt,tauInt)/deltaInt;
  eos.f_rdExt = extProp.y[9];
  eos.f_rddInt = MediumInt.dd_fRes_dd(deltaInt,tauInt)/deltaInt^2;
  eos.f_rddExt = extProp.y[10];
  eos.f_rdddInt = MediumInt.ddd_fRes_ddd(deltaInt,tauInt)/deltaInt^3;
  eos.f_rdddExt = extProp.y[11];
  eos.f_rtdInt = MediumInt.td_fRes_td(deltaInt,tauInt)/tauInt/deltaInt;
  eos.f_rtdExt = extProp.y[12];
  eos.f_rtddInt = MediumInt.tdd_fRes_tdd(deltaInt,tauInt)/tauInt/deltaInt^2;
  eos.f_rtddExt = extProp.y[13];
  eos.f_rttdInt = MediumInt.ttd_fRes_ttd(deltaInt,tauInt)/tauInt^2/deltaInt;
  eos.f_rttdExt = extProp.y[14];

  // Calculate saturation properties
  //
  saturation.p_satInt = MediumInt.saturationPressure(T_sat);
  saturation.p_satExt =extProp.y[15];
  saturation.T_satInt = MediumInt.saturationTemperature(p_sat);
  saturation.T_satExt = extProp.y[16];
  saturation.d_lInt = MediumInt.bubbleDensity(MediumInt.setSat_T(T_sat));
  saturation.d_lExt = extProp.y[17];
  saturation.d_vInt = MediumInt.dewDensity(MediumInt.setSat_T(T_sat));
  saturation.d_vExt = extProp.y[18];
  saturation.h_lInt = MediumInt.bubbleEnthalpy(MediumInt.setSat_p(p_sat));
  saturation.h_lExt = extProp.y[19];
  saturation.h_vInt = MediumInt.dewEnthalpy(MediumInt.setSat_p(p_sat));
  saturation.h_vExt = extProp.y[20];
  saturation.s_lInt = MediumInt.bubbleEntropy(MediumInt.setSat_p(p_sat));
  saturation.s_lExt = extProp.y[21];
  saturation.s_vInt = MediumInt.dewEntropy(MediumInt.setSat_p(p_sat));
  saturation.s_vExt = extProp.y[22];

  saturation.dp_sat = (saturation.p_satInt-saturation.p_satExt)
      /saturation.p_satExt*100;
  saturation.dT_sat = (saturation.T_satInt-saturation.T_satExt)
      /saturation.T_satExt*100;
  saturation.dd_l = (saturation.d_lInt-saturation.d_lExt)
      /saturation.d_lExt*100;
  saturation.dd_v = (saturation.d_vInt-saturation.d_vExt)
      /saturation.d_vExt*100;
  saturation.dh_l = (saturation.h_lInt-saturation.h_lExt)
      /saturation.h_lExt*100;
  saturation.dh_v = (saturation.h_vInt-saturation.h_vExt)
      /saturation.h_vExt*100;
  saturation.ds_l = (saturation.s_lInt-saturation.s_lExt)
      /saturation.s_lExt*100;
  saturation.ds_v = (saturation.s_vInt-saturation.s_vExt)
      /saturation.s_vExt*100;

  // Calculate further state properties
  //
  properties.d_ptInt = MediumInt.density_pT(p_sat, T);
  properties.d_ptExt = extProp.y[23];
  properties.T_phInt = MediumInt.temperature_ph(p_sat,h);
  properties.T_phExt = extProp.y[24];
  properties.T_psInt = MediumInt.temperature_ps(p_sat,s);
  properties.T_psExt = extProp.y[25];
end RefrigerantsFittedFormulasR134a;


within AixLib.Media.Refrigerants.Validation.RefrigerantsFittedFormulas;
model RefrigerantsFittedFormulasR290
  "Model that checks the fitted formulas of R290"
  extends RefrigerantsFittedFormulasR134a(
    redeclare package MediumInt =
      AixLib.Media.Refrigerants.R290.R290_IIR_P05_30_T263_343_Horner,
    extProp(fileName=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Media/Refrigerants/ValidationFittedFormulasR290.txt")),
    h_min = 180e3,
    h_max = 550e3,
    s_min = 1.0e3,
    s_max = 1.8e3,
    d_min = 2.0,
    d_max = 525,
    p_min = 1e5,
    p_max = 30e5,
    T_min = 263.15,
    T_max = 343.15);
end RefrigerantsFittedFormulasR290;


within AixLib.Media.Refrigerants.Validation.RefrigerantsFittedFormulas;
model RefrigerantsFittedFormulasR410a
  "Model that checks the fitted formulas of R410a"
  extends RefrigerantsFittedFormulasR134a(
    redeclare package MediumInt =
      AixLib.Media.Refrigerants.R410A_HEoS.R410a_IIR_P1_48_T233_473_Horner,
    extProp(fileName=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Media/Refrigerants/ValidationFittedFormulasR410a.txt")),
    h_min = 155e3,
    h_max = 600e3,
    s_min = 0.75e3,
    s_max = 2e3,
    d_min = 2.0,
    d_max = 1325,
    p_min = 1e5,
    p_max = 48e5,
    T_min = 233.15,
    T_max = 473.15);
end RefrigerantsFittedFormulasR410a;


within AixLib.Media;
package Specialized "Package with specialized media implementations"
  extends Modelica.Icons.Package;
end Specialized;


Specialized implementation of air

within AixLib.Media.Specialized;
package Air "Specialized implementation of air"
  extends Modelica.Icons.Package;
end Air;


Model for air as a perfect gas

within AixLib.Media.Specialized.Air;
package PerfectGas "Model for air as a perfect gas"
  extends Modelica.Media.Interfaces.PartialCondensingGases(
     mediumName="Moist air unsaturated perfect gas",
     substanceNames={"water", "air"},
     final reducedX=true,
     final singleState=false,
     reference_X={0.01,0.99},
     reference_T=273.15,
     reference_p=101325,
     fluidConstants = {Modelica.Media.IdealGases.Common.FluidData.H2O,
                       Modelica.Media.IdealGases.Common.FluidData.N2},
     AbsolutePressure(start=p_default),
     Temperature(start=T_default));

  extends Modelica.Icons.Package;

  constant Integer Water=1
    "Index of water (in substanceNames, massFractions X, etc.)";
  constant Integer Air=2
    "Index of air (in substanceNames, massFractions X, etc.)";

  redeclare record extends ThermodynamicState(
    p(start=p_default),
    T(start=T_default),
    X(start=X_default)) "ThermodynamicState record for moist air"
  end ThermodynamicState;

  redeclare replaceable model extends BaseProperties(
    p(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    Xi(
      nominal={0.01},
      each stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    final standardOrderComponents=true)

    /* p, T, X = X[Water] are used as preferred states, since only then all
     other quantities can be computed in a recursive sequence.
     If other variables are selected as states, static state selection
     is no longer possible and non-linear algebraic equations occur.
      */
  protected
    constant Modelica.Units.SI.MolarMass[2] MMX={steam.MM,dryair.MM}
      "Molar masses of components";

    MassFraction X_steam "Mass fraction of steam water";
    MassFraction X_air "Mass fraction of air";
  equation
    assert(T >= 200.0, "
In "   + getInstanceName() + ": Temperature T exceeded its minimum allowed value of -73.15 degC (200 Kelvin)
as required from medium model \"" + mediumName + "\".");
    assert(T <= 423.15, "
In "   + getInstanceName() + ": Temperature T exceeded its maximum allowed value of 150 degC (423.15 Kelvin)
as required from medium model \"" + mediumName + "\".");

    MM = 1/(Xi[Water]/MMX[Water]+(1.0-Xi[Water])/MMX[Air]);

    X_steam  = Xi[Water];
    X_air    = 1-Xi[Water];

    h = (T - reference_T)*dryair.cp * (1 - Xi[Water]) +
        ((T-reference_T) * steam.cp + h_fg) * Xi[Water];

    R_s = dryair.R*(1 - X_steam) + steam.R*X_steam;
    //
    u =h - R_s*T;
    d =p/(R_s*T);
    /* Note, u and d are computed under the assumption that the volume of the liquid
         water is negligible with respect to the volume of air and of steam
      */
    state.p = p;
    state.T = T;
    state.X = X;
  end BaseProperties;

  function Xsaturation = Modelica.Media.Air.MoistAir.Xsaturation
    "Steam water mass fraction of saturation boundary in kg_water/kg_moistair"
  redeclare function setState_pTX
    "Thermodynamic state as function of p, T and composition X"
      extends Modelica.Media.Air.MoistAir.setState_pTX;
  end setState_pTX;

  redeclare function setState_phX
    "Thermodynamic state as function of p, h and composition X"
  extends Modelica.Icons.Function;
  input AbsolutePressure p "Pressure";
  input SpecificEnthalpy h "Specific enthalpy";
  input MassFraction X[:] "Mass fractions";
  output ThermodynamicState state;
  algorithm
  state := if size(X,1) == nX then
         ThermodynamicState(p=p,T=temperature_phX(p,h,X),X=X) else
        ThermodynamicState(p=p,T=temperature_phX(p,h,X), X=cat(1,X,{1-sum(X)}));
  end setState_phX;

  redeclare function setState_dTX
    "Thermodynamic state as function of d, T and composition X"
  extends Modelica.Icons.Function;
  input Density d "Density";
  input Temperature T "Temperature";
  input MassFraction X[:]=reference_X "Mass fractions";
  output ThermodynamicState state "Thermodynamic state";
  algorithm
  state := if size(X, 1) == nX then ThermodynamicState(
        p=d*({steam.R,dryair.R}*X)*T,
        T=T,
        X=X) else ThermodynamicState(
        p=d*({steam.R,dryair.R}*cat(
          1,
          X,
          {1 - sum(X)}))*T,
        T=T,
        X=cat(
          1,
          X,
          {1 - sum(X)}));
  end setState_dTX;

redeclare function extends gasConstant "Gas constant"
algorithm
    R_s := dryair.R*(1 - state.X[Water]) + steam.R*state.X[Water];
end gasConstant;

function saturationPressureLiquid
    "Return saturation pressure of water as a function of temperature T in the range of 273.16 to 373.16 K"

  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature Tsat "saturation temperature";
    output Modelica.Units.SI.AbsolutePressure psat "saturation pressure";
  // This function is declared here explicitly, instead of referencing the function in its
  // base class, since otherwise Dymola 7.3 does not find the derivative for the model
  // AixLib.Fluid.Sensors.Examples.MassFraction
algorithm
  psat := 611.657*Modelica.Math.exp(17.2799 - 4102.99/(Tsat - 35.719));
end saturationPressureLiquid;

function saturationPressureLiquid_der
    "Time derivative of saturationPressureLiquid"

  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature Tsat "Saturation temperature";
  input Real dTsat(unit="K/s") "Saturation temperature derivative";
  output Real psat_der(unit="Pa/s") "Saturation pressure";

algorithm
  psat_der:=611.657*Modelica.Math.exp(17.2799 - 4102.99/(Tsat - 35.719))*4102.99*dTsat/(Tsat - 35.719)/(Tsat - 35.719);
end saturationPressureLiquid_der;

  function sublimationPressureIce =
      Modelica.Media.Air.MoistAir.sublimationPressureIce
    "Saturation curve valid for 223.16 <= T <= 273.16. Outside of these limits a (less accurate) result is returned"
  function sublimationPressureIce_der =
      Modelica.Media.Air.MoistAir.sublimationPressureIce_der
    "Derivative function for 'sublimationPressureIce'"
redeclare function extends saturationPressure
    "Saturation curve valid for 223.16 <= T <= 373.16 (and slightly outside with less accuracy)"

algorithm
  psat := AixLib.Utilities.Math.Functions.regStep(
            y1=saturationPressureLiquid(Tsat),
            y2=sublimationPressureIce(Tsat),
            x=Tsat-273.16,
            x_small=1.0);
end saturationPressure;

 redeclare function extends pressure "Gas pressure"
 algorithm
  p := state.p;
 end pressure;

 redeclare function extends temperature "Gas temperature"
 algorithm
  T := state.T;
 end temperature;

 redeclare function extends density "Gas density"
 algorithm
  d := state.p/(gasConstant(state)*state.T);
 end density;

 redeclare function extends specificEntropy
    "Specific entropy (liquid part neglected, mixing entropy included)"
 algorithm
  s := s_pTX(
        state.p,
        state.T,
        state.X);
 end specificEntropy;

 redeclare function extends enthalpyOfVaporization
    "Enthalpy of vaporization of water"
 algorithm
  r0 := h_fg;
 end enthalpyOfVaporization;

function HeatCapacityOfWater
    "Specific heat capacity of water (liquid only) which is constant"
    extends Modelica.Icons.Function;
    input Temperature T;
    output SpecificHeatCapacity cp_fl;
algorithm
    cp_fl := cpWatLiq;
end HeatCapacityOfWater;

redeclare replaceable function extends enthalpyOfLiquid
    "Enthalpy of liquid (per unit mass of liquid) which is linear in the temperature"

algorithm
  h := (T - reference_T)*cpWatLiq;
end enthalpyOfLiquid;

replaceable function der_enthalpyOfLiquid
    "Temperature derivative of enthalpy of liquid per unit mass of liquid"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of liquid enthalpy";
algorithm
  der_h := cpWatLiq*der_T;
end der_enthalpyOfLiquid;

redeclare function enthalpyOfCondensingGas
    "Enthalpy of steam per unit mass of steam"
  extends Modelica.Icons.Function;

  input Temperature T "temperature";
  output SpecificEnthalpy h "steam enthalpy";
algorithm
  h := (T-reference_T) * steam.cp + enthalpyOfVaporization(T);
end enthalpyOfCondensingGas;

replaceable function der_enthalpyOfCondensingGas
    "Derivative of enthalpy of steam per unit mass of steam"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of steam enthalpy";
algorithm
  der_h := steam.cp*der_T;
end der_enthalpyOfCondensingGas;

redeclare function enthalpyOfNonCondensingGas
    "Enthalpy of non-condensing gas per unit mass of steam"
  extends Modelica.Icons.Function;

  input Temperature T "temperature";
  output SpecificEnthalpy h "enthalpy";
algorithm
  h := enthalpyOfDryAir(T);
end enthalpyOfNonCondensingGas;

replaceable function der_enthalpyOfNonCondensingGas
    "Derivative of enthalpy of non-condensing gas per unit mass of steam"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of steam enthalpy";
algorithm
  der_h := der_enthalpyOfDryAir(T, der_T);
end der_enthalpyOfNonCondensingGas;

redeclare replaceable function extends enthalpyOfGas
    "Enthalpy of gas mixture per unit mass of gas mixture"
algorithm
  h := enthalpyOfCondensingGas(T)*X[Water]
       + enthalpyOfDryAir(T)*(1.0-X[Water]);
end enthalpyOfGas;

replaceable function enthalpyOfDryAir
    "Enthalpy of dry air per unit mass of dry air"
  extends Modelica.Icons.Function;

  input Temperature T "temperature";
  output SpecificEnthalpy h "dry air enthalpy";
algorithm
  h := (T - reference_T)*dryair.cp;
end enthalpyOfDryAir;

replaceable function der_enthalpyOfDryAir
    "Derivative of enthalpy of dry air per unit mass of dry air"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of dry air enthalpy";
algorithm
  der_h := dryair.cp*der_T;
end der_enthalpyOfDryAir;

redeclare replaceable function extends specificHeatCapacityCp
    "Specific heat capacity of gas mixture at constant pressure"
algorithm
  cp := dryair.cp*(1-state.X[Water]) +steam.cp*state.X[Water];
end specificHeatCapacityCp;

replaceable function der_specificHeatCapacityCp
    "Derivative of specific heat capacity of gas mixture at constant pressure"
    input ThermodynamicState state;
    input ThermodynamicState der_state;
    output Real der_cp(unit="J/(kg.K.s)");
algorithm
  der_cp := (steam.cp-dryair.cp)*der_state.X[Water];
end der_specificHeatCapacityCp;

redeclare replaceable function extends specificHeatCapacityCv
    "Specific heat capacity of gas mixture at constant volume"
algorithm
  cv:= dryair.cv*(1-state.X[Water]) +steam.cv*state.X[Water];
end specificHeatCapacityCv;

replaceable function der_specificHeatCapacityCv
    "Derivative of specific heat capacity of gas mixture at constant volume"
    input ThermodynamicState state;
    input ThermodynamicState der_state;
    output Real der_cv(unit="J/(kg.K.s)");
algorithm
  der_cv := (steam.cv-dryair.cv)*der_state.X[Water];
end der_specificHeatCapacityCv;

redeclare function extends dynamicViscosity "dynamic viscosity of dry air"
algorithm
  eta := 1.85E-5;
end dynamicViscosity;

redeclare function extends thermalConductivity
    "Thermal conductivity of dry air as a polynomial in the temperature"
algorithm
  lambda :=Modelica.Math.Polynomials.evaluate({(-4.8737307422969E-008),
      7.67803133753502E-005,0.0241814385504202},
      Modelica.Units.Conversions.to_degC(state.T));
end thermalConductivity;

redeclare function extends specificEnthalpy "Specific enthalpy"
algorithm
  h := specificEnthalpy_pTX(state.p, state.T, state.X);
end specificEnthalpy;

redeclare replaceable function specificEnthalpy_pTX "Specific enthalpy"
  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Pressure p "Pressure";
    input Modelica.Units.SI.Temperature T "Temperature";
    input Modelica.Units.SI.MassFraction X[:] "Mass fractions of moist air";
    output Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy at p, T, X";

  protected
    Modelica.Units.SI.SpecificEnthalpy hDryAir "Enthalpy of dry air";
algorithm
  hDryAir := (T - reference_T)*dryair.cp;
  h := hDryAir * (1 - X[Water]) +
       ((T-reference_T) * steam.cp + h_fg) * X[Water];
end specificEnthalpy_pTX;

redeclare function extends specificInternalEnergy "Specific internal energy"
  extends Modelica.Icons.Function;
algorithm
  u := specificEnthalpy_pTX(state.p,state.T,state.X) - gasConstant(state)*state.T;
end specificInternalEnergy;

redeclare function extends specificGibbsEnergy "Specific Gibbs energy"
  extends Modelica.Icons.Function;
algorithm
  g := specificEnthalpy_pTX(state.p,state.T,state.X) - state.T*specificEntropy(state);
end specificGibbsEnergy;

redeclare function extends specificHelmholtzEnergy "Specific Helmholtz energy"
  extends Modelica.Icons.Function;
algorithm
  f := specificEnthalpy_pTX(state.p,state.T,state.X) - gasConstant(state)*state.T - state.T*specificEntropy(state);
end specificHelmholtzEnergy;

redeclare replaceable function temperature_phX
    "Compute temperature from specific enthalpy and mass fraction"
    extends Modelica.Icons.Function;
  input AbsolutePressure p "Pressure";
  input SpecificEnthalpy h "specific enthalpy";
  input MassFraction[:] X "mass fractions of composition";
  output Temperature T "temperature";
algorithm
  T := reference_T + (h - h_fg * X[Water])
       /((1 - X[Water])*dryair.cp + X[Water] * steam.cp);
end temperature_phX;
//////////////////////////////////////////////////////////////////////
// Protected classes.
// These classes are only of use within this medium model.
// Equipment models generally have no need to access them.
// Therefore, they are made protected. This also allows to redeclare the
// medium model with another medium model that does not provide an
// implementation of these classes.
protected
  record GasProperties
    "Coefficient data record for properties of perfect gases"
    extends Modelica.Icons.Record;

    Modelica.Units.SI.MolarMass MM "Molar mass";
    Modelica.Units.SI.SpecificHeatCapacity R "Gas constant";
    Modelica.Units.SI.SpecificHeatCapacity cp
      "Specific heat capacity at constant pressure";
    Modelica.Units.SI.SpecificHeatCapacity cv=cp - R
      "Specific heat capacity at constant volume";
  end GasProperties;
  // In the assignments below, we compute cv as OpenModelica
  // cannot evaluate cv=cp-R as defined in GasProperties.
  constant GasProperties dryair(
    R=Modelica.Media.IdealGases.Common.SingleGasesData.Air.R_s,
    MM=Modelica.Media.IdealGases.Common.SingleGasesData.Air.MM,
    cp=AixLib.Utilities.Psychrometrics.Constants.cpAir,
    cv=AixLib.Utilities.Psychrometrics.Constants.cpAir - Modelica.Media.IdealGases.Common.SingleGasesData.Air.R_s)
    "Dry air properties";
  constant GasProperties steam(
    R=Modelica.Media.IdealGases.Common.SingleGasesData.H2O.R_s,
    MM=Modelica.Media.IdealGases.Common.SingleGasesData.H2O.MM,
    cp=AixLib.Utilities.Psychrometrics.Constants.cpSte,
    cv=AixLib.Utilities.Psychrometrics.Constants.cpSte - Modelica.Media.IdealGases.Common.SingleGasesData.H2O.R_s)
    "Steam properties";

  constant Real k_mair =  steam.MM/dryair.MM "Ratio of molar weights";

  constant Modelica.Units.SI.SpecificEnergy h_fg=AixLib.Utilities.Psychrometrics.Constants.h_fg
    "Latent heat of evaporation of water";

  constant Modelica.Units.SI.SpecificHeatCapacity cpWatLiq=AixLib.Utilities.Psychrometrics.Constants.cpWatLiq
    "Specific heat capacity of liquid water";

  function s_pTX = Modelica.Media.Air.MoistAir.s_pTX
    "Return specific entropy of moist air as a function of pressure p, temperature T and composition X (only valid for phi<1)";
  function s_pTX_der = Modelica.Media.Air.MoistAir.s_pTX_der
    "Return specific entropy of moist air as a function of pressure p, temperature T and composition X (only valid for phi<1)";
end PerfectGas;


within AixLib.Media.Specialized.Air;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Temperature

within AixLib.Media.Specialized.Air.Examples;
model PerfectGasDerivativeCheck
  extends Modelica.Icons.Example;

   package Medium = AixLib.Media.Specialized.Air.PerfectGas;

  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.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";
    constant Real convT(unit="K/s3") = 270
    "Conversion factor to satisfy unit check";
initial equation
     hLiqSym = hLiqCod;
     hSteSym = hSteCod;
     hAirSym = hAirCod;
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");

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

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


within AixLib.Media.Specialized.Air.Examples;
model PerfectGasTemperatureEnthalpyInversion
  "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.Specialized.Air.PerfectGas);
end PerfectGasTemperatureEnthalpyInversion;


Specialized implementation of water

within AixLib.Media.Specialized;
package Water "Specialized implementation of water"
  extends Modelica.Icons.Package;
end Water;


within AixLib.Media.Specialized.Water;
package TemperatureDependentDensity
  "Package with model for liquid water with temperature-dependent density"
   extends Modelica.Media.Interfaces.PartialPureSubstance(
     mediumName="WaterDetailed",
     p_default=300000,
     reference_p=300000,
     reference_T=273.15,
     reference_X={1},
     final singleState=true,
     ThermoStates=Modelica.Media.Interfaces.Choices.IndependentVariables.T,
     AbsolutePressure(start=p_default),
     Temperature(start=T_default));
   extends Modelica.Icons.Package;

  redeclare record FluidConstants =
    Modelica.Media.Interfaces.Types.Basic.FluidConstants (
    each chemicalFormula="H2O",
    each structureFormula="H2O",
    each casRegistryNumber="7732-18-5",
    each iupacName="oxidane",
    each molarMass=MM_const);
  redeclare record extends ThermodynamicState "Thermodynamic state variables"
    Temperature T(start=T_default) "Temperature of medium";
    AbsolutePressure p(start=p_default) "Pressure of medium";
  end ThermodynamicState;
  constant Modelica.Units.SI.SpecificHeatCapacity cp_const=4184
    "Specific heat capacity at constant pressure";

  redeclare model extends BaseProperties(
     preferredMediumStates=true) "Base properties"
  equation
    h = (T - reference_T)*cp_const;
    u = h-reference_p/d;
    d = density(state);
    state.T = T;
    state.p = p;
    R_s = 0;
    MM=MM_const;
  end BaseProperties;

redeclare function extends density "Return the density"
algorithm
  d := smooth(1,
    if state.T < 278.15 then
      -0.042860825*state.T + 1011.9695761
    elseif state.T < 373.15 then
      0.000015009*state.T^3 - 0.01813488505*state.T^2 + 6.5619527954075*state.T
      + 254.900074971947
    else
     -0.7025109*state.T + 1220.35045233);
end density;

redeclare function extends dynamicViscosity "Return the dynamic viscosity"
algorithm
  eta := density(state)*kinematicViscosity(state.T);
end dynamicViscosity;

redeclare function extends specificEnthalpy "Return the specific enthalpy"
algorithm
  h := (state.T - reference_T)*cp_const;
end specificEnthalpy;

function enthalpyOfLiquid "Return the specific enthalpy of liquid"
  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T "Temperature";
    output Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy";
algorithm
  h := (T - reference_T)*cp_const;
end enthalpyOfLiquid;

redeclare function extends specificInternalEnergy
    "Return the specific enthalpy"
algorithm
  u := specificEnthalpy(state) - reference_p/density(state);
end specificInternalEnergy;

redeclare function extends specificEntropy "Return the specific entropy"
  extends Modelica.Icons.Function;
algorithm
  s := cv_const*Modelica.Math.log(state.T/reference_T);
end specificEntropy;

redeclare function extends specificGibbsEnergy
    "Return the specific Gibbs energy"
  extends Modelica.Icons.Function;
algorithm
  g := specificEnthalpy(state) - state.T*specificEntropy(state);
end specificGibbsEnergy;

redeclare function extends specificHelmholtzEnergy
    "Return the specific Helmholtz energy"
  extends Modelica.Icons.Function;
algorithm
  f := specificInternalEnergy(state) - state.T*specificEntropy(state);
end specificHelmholtzEnergy;

redeclare function extends isentropicEnthalpy "Return the isentropic enthalpy"
algorithm
  h_is := specificEnthalpy(setState_psX(
            p=p_downstream,
            s=specificEntropy(refState),
            X={1}));
end isentropicEnthalpy;

redeclare function extends isobaricExpansionCoefficient
    "Return the isobaric expansion coefficient"
algorithm
    beta := -smooth(0,
    if state.T < 278.15 then
      0.042860825*(0.042860825*state.T - 1011.9695761)/(-0.042860825*state.T +
      1011.9695761)^2
    elseif state.T < 373.15 then
      (4.5027e-5*state.T^2 - 0.0362697701*state.T + 6.5619527954075)/
        (1.5009e-5*state.T^3 - 0.01813488505*state.T^2 + 6.5619527954075*state.T + 254.900074971947)
    else
       0.7025109*(0.7025109*state.T - 1220.35045233)/(-0.7025109*state.T +
       1220.35045233)^2);
        // Symbolic conversion of degC to Kelvin
//        ((4.5027e-05)*T_degC^2 - 0.01167152*state.T +
//               3.202446788)/((1.5009e-05)*T_degC^3 - 0.00583576*T_degC^2 +
//               0.0143711*state.T + 996.194534035)
end isobaricExpansionCoefficient;

redeclare function extends isothermalCompressibility
    "Return the isothermal compressibility factor"
algorithm
  kappa := 0;
end isothermalCompressibility;

redeclare function extends density_derp_T
    "Return the partial derivative of density with respect to pressure at constant temperature"
algorithm
  ddpT := 0;
end density_derp_T;

redeclare function extends density_derT_p
    "Return the partial derivative of density with respect to temperature at constant pressure"
algorithm
  ddTp := if state.T < 278.15 then
            -0.042860825
          elseif state.T < 373.15 then
            (0.0000450270000000000*state.T^2 - 0.0362697701000000*state.T +
            6.56195279540750)
          else
           -0.7025109;
end density_derT_p;

redeclare function extends density_derX
    "Return the partial derivative of density with respect to mass fractions at constant pressure and temperature"
algorithm
  dddX := fill(0, nX);
end density_derX;

redeclare replaceable function extends specificHeatCapacityCp
    "Return the specific heat capacity at constant pressure"
algorithm
  cp := cp_const;
end specificHeatCapacityCp;

redeclare replaceable function extends specificHeatCapacityCv
    "Return the specific heat capacity at constant volume"
algorithm
  cv := cv_const;
end specificHeatCapacityCv;

redeclare function extends thermalConductivity
    "Return the thermal conductivity"
algorithm
  lambda :=0.6065*(-1.48445 + 4.12292*(state.T/298.15) - 1.63866*(state.T/298.15)^2);
end thermalConductivity;

redeclare function extends pressure "Return the pressure"
algorithm
    p := state.p;
end pressure;

redeclare function extends temperature "Return the temperature"
algorithm
    T := state.T;
end temperature;

redeclare function extends molarMass "Return the molar mass"
algorithm
    MM := MM_const;
end molarMass;

redeclare function setState_dTX
    "Return thermodynamic state from d, T, and X or Xi"
    extends Modelica.Icons.Function;
    input Density d "Density";
    input Temperature T "Temperature";
    input MassFraction X[:]=reference_X "Mass fractions";
    output ThermodynamicState state "Thermodynamic state record";
algorithm
    assert(false,
      "Pressure can not be computed from temperature and density for an incompressible fluid!");
end setState_dTX;

redeclare function extends setState_phX
    "Return the thermodynamic state as function of pressure p, specific enthalpy h and composition X or Xi"
algorithm
  state := ThermodynamicState(p=p, T=reference_T + h/cp_const);
end setState_phX;

redeclare function extends setState_pTX
    "Return the thermodynamic state as function of p, T and composition X or Xi"
algorithm
    state := ThermodynamicState(p=p, T=T);
end setState_pTX;

redeclare function extends setState_psX
    "Return the thermodynamic state as function of p, s and composition X or Xi"
algorithm
  // The temperature is obtained from symbolic solving the
  // specificEntropy function for T, i.e.,
  // s := cv_const*Modelica.Math.log(state.T/reference_T)
  state := ThermodynamicState(p=p, T=reference_T * Modelica.Math.exp(s/cv_const));
end setState_psX;
//////////////////////////////////////////////////////////////////////
// Protected classes.
// These classes are only of use within this medium model.
// Equipment models generally have no need to access them.
// Therefore, they are made protected. This also allows to redeclare the
// medium model with another medium model that does not provide an
// implementation of these classes.
protected
  final constant Modelica.Units.SI.SpecificHeatCapacity cv_const=cp_const
    "Specific heat capacity at constant volume";

  constant Modelica.Units.SI.VelocityOfSound a_const=1484
    "Constant velocity of sound";
  constant Modelica.Units.SI.MolarMass MM_const=0.018015268 "Molar mass";

replaceable function der_specificHeatCapacityCp
    "Return the derivative of the specific heat capacity at constant pressure"
  extends Modelica.Icons.Function;
  input ThermodynamicState state "Thermodynamic state";
  input ThermodynamicState der_state "Derivative of thermodynamic state";
  output Real der_cp(unit="J/(kg.K.s)") "Derivative of specific heat capacity";
algorithm
  der_cp := 0;
end der_specificHeatCapacityCp;

replaceable function der_enthalpyOfLiquid
    "Temperature derivative of enthalpy of liquid per unit mass of liquid"
  extends Modelica.Icons.Function;
  input Temperature T "Temperature";
  input Real der_T "Temperature derivative";
  output Real der_h "Derivative of liquid enthalpy";
algorithm
  der_h := cp_const*der_T;
end der_enthalpyOfLiquid;

function kinematicViscosity "Return the kinematic viscosity"
  extends Modelica.Icons.Function;

    input Modelica.Units.SI.Temperature T "Temperature";
    output Modelica.Units.SI.KinematicViscosity kinVis "Kinematic viscosity";
algorithm
  kinVis := smooth(1,
  if T < 278.15 then
    -(4.63023776563e-08)*T + 1.44011135763e-05
  else
    1.0e-6*Modelica.Math.exp(
      -(7.22111000000000e-7)*T^3 + 0.000809102858950000*T^2
      - 0.312920238272193*T + 40.4003044106506));

This has been converted to Kelvin, which resulted in the above expression.
In addition, at 5 °C the kinematic viscosity is linearly extrapolated
to avoid a large gradient at very low temperatures.
We selected the same point for the linearization as we used for the density,
as the density and the kinematic viscosity are combined in

AixLib.Media.Specialized.Water.TemperatureDependentDensity.dynamicViscosity.

",
revisions="

April 11, 2016 by Michael Wetter:

Corrected wrong hyperlink in documentation for
issue 450.

December 18, 2013, by Michael Wetter:

First implementation, based on the IDA implementation in therpro.nmf,
but converted from Celsius to Kelvin.

"));
end kinematicViscosity;
end TemperatureDependentDensity;


within AixLib.Media.Specialized.Water;
package ConstantProperties_pT "Package with model for liquid water with constant properties at user-provided nominal conditions"

  extends AixLib.Media.Water(
    mediumName="ConstantPropertyWater(p="+String(p_nominal)+",T="+String(T_nominal)+")",
    p_default=p_nominal,
    reference_p=p_nominal,
    cp_const=cp_nominal,
    d_const=d_nominal,
    eta_const=eta_nominal,
    lambda_const=lambda_nominal,
    a_const=a_nominal,
    T_max=T_max_nominal);

constant Modelica.Units.SI.Temperature T_max_nominal=
    Modelica.Media.Water.IF97_Utilities.BaseIF97.Basic.tsat(p_nominal)
  "Maximum temperature valid for medium model";

constant Modelica.Units.SI.Temperature T_nominal=273.15 + 20
  "Nominal temperature for calculation of water properties";

constant Modelica.Units.SI.VelocityOfSound a_nominal=
    Modelica.Media.Water.IF97_Utilities.velocityOfSound_pT(p_nominal, T_nominal)
  "Constant velocity of sound";

constant Modelica.Units.SI.SpecificHeatCapacity cp_nominal=
    Modelica.Media.Water.IF97_Utilities.cp_pT(p_nominal, T_nominal)
  "Specific heat capacity at nominal water conditions";

constant Modelica.Units.SI.Density d_nominal=
    Modelica.Media.Water.IF97_Utilities.rho_pT(p_nominal, T_nominal)
  "Density at nominal water conditions";

constant Modelica.Units.SI.DynamicViscosity eta_nominal=
    Modelica.Media.Water.IF97_Utilities.dynamicViscosity(
    d_nominal,
    T_nominal,
    p_nominal) "Constant dynamic viscosity";

constant Modelica.Units.SI.ThermalConductivity lambda_nominal=
    Modelica.Media.Water.IF97_Utilities.thermalConductivity(
    d_nominal,
    T_nominal,
    p_nominal) "Constant thermal conductivity";

constant Modelica.Units.SI.AbsolutePressure p_nominal=101325
  "Nominal pressure for calculation of water properties";

", revisions="

September 20, 2016, by Michael Wetter:

Reordered constants to conform with the order in package.order.

This is for
issue 518.

September 14, 2016, by Michael Wetter:

Revised implementation.

September 8, 2016, by Marcus Fuchs:

First implementation.

"),
    Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}),
        graphics={
        Polygon(
          points={{16,-28},{32,-42},{26,-48},{10,-36},{16,-28}},
          lineColor={95,95,95},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Polygon(
          points={{10,34},{26,44},{30,36},{14,26},{10,34}},
          lineColor={95,95,95},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Ellipse(
          extent={{-82,52},{24,-54}},
          lineColor={95,95,95},
          fillPattern=FillPattern.Sphere,
          fillColor={0,0,0}),
        Ellipse(
          extent={{22,82},{80,24}},
          lineColor={0,0,0},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Ellipse(
          extent={{20,-30},{78,-88}},
          lineColor={0,0,0},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Text(
          extent={{-110,40},{50,-36}},
          textColor={238,46,47},
          textString="pT")}));
end ConstantProperties_pT;


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


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

   package Medium =
      AixLib.Media.Specialized.Water.TemperatureDependentDensity
    "Medium model";

  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 TemperatureDependentDensityDerivativeCheck;


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


within AixLib.Media.Specialized.Water.Examples;
model TemperatureDependentDensityTemperatureEnthalpyInversion
  "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.Specialized.Water.TemperatureDependentDensity);
end TemperatureDependentDensityTemperatureEnthalpyInversion;


within AixLib.Media.Specialized.Water.Examples;
model WaterProperties_pT
  "Model that tests the implementation of the fluid properties at nominal conditions"
  extends Modelica.Icons.Example;
  extends AixLib.Media.Examples.BaseClasses.FluidProperties(
    redeclare package Medium =
      AixLib.Media.Specialized.Water.ConstantProperties_pT (
        T_nominal=273.15+100,
        p_nominal=5e5),
    TMin=273.15,
    TMax=273.15+150);
equation
  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
end WaterProperties_pT;


within AixLib.Obsolete.Year2019;
package Fluid "Package with models for fluid flow systems"
  extends Modelica.Icons.Package;
end Fluid;


within AixLib.Obsolete.Year2019.Fluid.HeatPumps;
model HeatPumpDetailed
  "Heat pump model with good level of detail. Mainly fed with manufacturing data."
  extends AixLib.Obsolete.BaseClasses.ObsoleteModel;
  import      Modelica.Units.SI;
  parameter Boolean HPctrlType=true "Capacity control type"
  parameter Integer capCalcType=1 "Type of capacity calculation"
  replaceable package Medium_con = Modelica.Media.Interfaces.PartialMedium
    "Medium outside the refrigerant cycle (Condenser)"
  parameter SI.PressureDifference dp_conNominal=0
    "Pressure loss at nominal mass flow in condenser"

  replaceable package Medium_eva = Modelica.Media.Interfaces.PartialMedium
    "Medium outside the refrigerant cycle (Evaporator)"

  parameter SI.PressureDifference dp_evaNominal=0
    "Pressure loss at nominal mass flow in evaporator"

  parameter SI.Volume volume_eva=0.004
    "External medium volume in heat exchanger"
  parameter SI.Volume volume_con=0.004
    "External medium volume in heat exchanger"
  parameter AixLib.Obsolete.Year2024.DataBase.HeatPump.HeatPumpBaseDataDefinition
    dataTable=AixLib.Obsolete.Year2024.DataBase.HeatPump.EN255.Vitocal350BWH113()
    "Look-up table data for on/off heat pump according to EN255 or EN14511"

  replaceable function data_poly =
      AixLib.Obsolete.Year2024.DataBase.HeatPump.Functions.Characteristics.ConstantQualityGrade
    constrainedby
    AixLib.Obsolete.Year2024.DataBase.HeatPump.Functions.Characteristics.PartialBaseFct
    "Polynomial heat pump characteristics for inverter heat pump"

  parameter SI.Temperature T_startEva=273.15 "Initial evaporator temperature"
  parameter SI.Temperature T_startCon=308.15 "Initial condenser temperature"
  replaceable function Corr_icing =
      AixLib.Obsolete.Year2024.DataBase.HeatPump.Functions.DefrostCorrection.NoModel
    constrainedby
    AixLib.Obsolete.Year2024.DataBase.HeatPump.Functions.DefrostCorrection.PartialBaseFct
    "Frost/Defrost model (only air-to-water heat pumps)"

  parameter Real N_max=4200
    "Maximum speed of compressor in 1/min (only used if used in polynom)"
  parameter Real N_min=1500
    "Minimum speed of compressor in 1/min (only used if used in polynom)"
  parameter Real N_nom=3600
    "Nominal speed of compressor in 1/min (only used if used in polynom)"
  parameter Boolean P_eleOutput=false "Electric power consumption"
  parameter Boolean CoP_output=false "CoP"
  parameter Boolean PT1_cycle=false "First Order model for capacity"
  parameter SI.Time timeConstantCycle=1 "Time constant for first order model"

  parameter Real eta_ele=1
    "Assumption of P_tech/P_el (for calculation of Evaporator load)"
  parameter Real factorScale=1
    "Scaling factor (Attention: not physically correct)"
  parameter SI.Power P_eleAdd=0
    "Additional electric power when heat pump is on (not influenced through
    scaling factor)"

  parameter Boolean CorrFlowCo=false
    "Correction of mass flow different from nominal flow in condenser
    (polynomials: make sure mass flow rate is not corrected in polynomials)"
  parameter SI.MassFlowRate mFlow_conNominal=0.5
    "Nominal mass flow rate in condenser (only with polynomials, as already
    given in data tables)"

  parameter Boolean CorrFlowEv=false
    "Correction of mass flow different from nominal flow in evaporator
    (polynomials: make sure mass flow rate is not corrected in polynomials)"
  parameter SI.MassFlowRate mFlow_evaNominal=0.5
    "Nominal mass flow rate in evaporator (only for polynomials, as already
    given in data tables)"

  Modelica.Fluid.Interfaces.FluidPort_b port_evaOut(redeclare package Medium =
        Medium_eva) "Evaporator fluid output port"
  Modelica.Fluid.Interfaces.FluidPort_a port_evaIn(redeclare package Medium =
        Medium_eva) "Evaporator fluid input port"
  AixLib.Fluid.Sensors.TemperatureTwoPort T_evaIn(
    redeclare package Medium = Medium_eva,
    m_flow_nominal=mFlow_evaNominal,
    T_start=T_startEva) "Temperature sensor at inlet of the evaporator"
  AixLib.Fluid.Sensors.TemperatureTwoPort T_conIn(
    redeclare package Medium = Medium_con,
    m_flow_nominal=mFlow_conNominal,
    T_start=T_startCon) "Temperature sensor at inlet of the condenser"
  Modelica.Fluid.Interfaces.FluidPort_a port_conIn(redeclare package Medium =
        Medium_con) "Condenser fluid input port"
  Modelica.Fluid.Interfaces.FluidPort_b port_conOut(redeclare package Medium =
        Medium_con) "Condenser fluid ouput port"
  AixLib.Fluid.Sensors.TemperatureTwoPort T_conOut(
    redeclare package Medium = Medium_con,
    m_flow_nominal=mFlow_conNominal,
    T_start=T_startCon) "Temperature sensor at outlet of the condenser"
  AixLib.Fluid.Sensors.TemperatureTwoPort T_evaOut(
    redeclare package Medium = Medium_eva,
    m_flow_nominal=mFlow_evaNominal,
    T_start=T_startEva) "Temperature sensor at outlet of the evaporator"
  AixLib.Fluid.Sensors.MassFlowRate mFlow_con(redeclare package Medium =
        Medium_con) "Mass flow sensor at the condenser"
  Modelica.Blocks.Interfaces.RealOutput P_eleOut(unit="W")
                                                if P_eleOutput
    "Electical power consumption"
  Modelica.Blocks.Interfaces.RealOutput CoP_out if CoP_output
    "Coefficient of Performance"

  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heatFlowRate_con
    "Heat flow rate of the condenser"

public
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heatFlowRate_eva
    "Heat flow rate of the evaporator"

  parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
    "Smoothness of table interpolation"

  AixLib.Fluid.Sensors.MassFlowRate mFlow_eva(redeclare package Medium =
        Medium_eva) "Mass flow sensor at the evaporator"
  AixLib.Fluid.HeatPumps.BaseClasses.CycleHP cycle(
    HPctrlType=HPctrlType,
    capCalcType=capCalcType,
    dataTable=dataTable,
    redeclare function data_poly = data_poly,
    N_max=N_max,
    N_min=N_min,
    N_nom=N_nom,
    Corr_icing=Corr_icing,
    eta_ele=eta_ele,
    factorScale=factorScale,
    P_eleAdd=P_eleAdd,
    CorrFlowCo=CorrFlowCo,
    CorrFlowEv=CorrFlowEv,
    timeConstantCycle=timeConstantCycle,
    smoothness=smoothness,
    PT1_cycle=PT1_cycle,
    mFlow_conNominal=mFlow_conNominal,
    mFlow_evaNominal=mFlow_evaNominal,
    T_conMax=T_conMax) "Heat pump refrigerant circuit black box model"
  Modelica.Blocks.Interfaces.BooleanInput onOff_in
    "Enable or disable heat pump"
  Modelica.Blocks.Interfaces.RealInput N_in if not HPctrlType
    "Rotational speed of compressor"

  parameter Boolean heatLosses_con=false
    "Consider heat losses of condenser to ambient"
  parameter SI.ThermalConductance R_loss=1
    "Thermal conductance of heat loss to ambient"
protected
  Modelica.Blocks.Interfaces.RealInput N_inInternal
    "Needed to connect to conditional connector";
  Modelica.Blocks.Interfaces.RealInput T_ambInternal
    "Needed to connect to conditional connector";
public
  Modelica.Blocks.Sources.RealExpression dummyZero(y=0)
    "Dummy value used for rotational speed"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor heatConv(G=R_loss)
    "Heat flow through condenser casing with a given conductance"
  Modelica.Blocks.Interfaces.RealInput T_amb
                                            if heatLosses_con
    "Ambient temperatur input signal"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature varTemp
    "Foreces heat losses according to ambient temperature"
  parameter SI.Temperature T_conMax=338.15
    "Maximum condenser outlet temperature"
  Modelica.Blocks.Math.Gain gainMinusOne(k=-1)
    "Calculated heat flow in evaporator has to be withdrawn"
  AixLib.Fluid.MixingVolumes.MixingVolume evaporator(
    nPorts=2,
    T_start(displayUnit="K") = T_startEva,
    m_flow_nominal=mFlow_evaNominal,
    redeclare package Medium = Medium_eva,
    V=volume_eva) "Volume of evaporator"
  AixLib.Fluid.FixedResistances.PressureDrop hydRes_eva(
    redeclare package Medium = Medium_eva,
    m_flow_nominal=mFlow_evaNominal,
    m_flow(start=mFlow_evaNominal),
    dp_nominal=dp_evaNominal)
    "The pressure drop caused by flow resistance in the evaporator"
  AixLib.Fluid.MixingVolumes.MixingVolume condenser(
    nPorts=2,
    redeclare package Medium = Medium_con,
    T_start(displayUnit="K") = T_startCon,
    m_flow_nominal=mFlow_conNominal,
    V=volume_con) "Volume of condenser"
  AixLib.Fluid.FixedResistances.PressureDrop hydRes_con(
    redeclare package Medium = Medium_con,
    m_flow_nominal=mFlow_conNominal,
    m_flow(start=mFlow_conNominal),
    dp_nominal=dp_conNominal)
    "The pressure drop caused by flow resistance in the condenser"
equation

  if HPctrlType then
    connect(N_inInternal, dummyZero.y);
  else
    connect(N_in, N_inInternal);
  end if;
  connect(N_inInternal, cycle.N_in);

  if heatLosses_con then
    connect(T_ambInternal, T_amb);
    connect(heatConv.port_b, condenser.heatPort);
  else
    connect(T_ambInternal, dummyZero.y);
  end if;
  connect(varTemp.T, T_ambInternal);
  connect(varTemp.port, heatConv.port_a)

  //fluid connections evaporator
  connect(T_evaOut.port_b, port_evaOut)
  connect(port_evaIn, mFlow_eva.port_a)
  connect(mFlow_eva.port_b, T_evaIn.port_a)

  //fluid connections condenser
  connect(mFlow_con.port_a, port_conIn)
  connect(mFlow_con.port_b, T_conIn.port_a)
  connect(T_conOut.port_b, port_conOut)
  // other connections

  connect(cycle.CoP_out, CoP_out)

  connect(heatFlowRate_eva.Q_flow, gainMinusOne.y)
  connect(T_conOut.T, cycle.T_conOut)
  connect(cycle.Qdot_conOut, heatFlowRate_con.Q_flow)
  connect(cycle.T_conIn, T_conIn.T)
  connect(cycle.mFlow_con, mFlow_con.m_flow)
  connect(cycle.T_evaOut, T_evaOut.T)
  connect(cycle.mFlow_eva, mFlow_eva.m_flow)
  connect(gainMinusOne.u, cycle.Qdot_evaOut)
  connect(T_evaIn.T, cycle.T_evaIn)
  connect(cycle.P_eleOut, P_eleOut)
  connect(cycle.onOff_in, onOff_in)
  connect(T_evaIn.port_b, evaporator.ports[1])
  connect(heatFlowRate_eva.port, evaporator.heatPort)
  connect(heatFlowRate_con.port, condenser.heatPort)
  connect(T_conIn.port_b, condenser.ports[1])
  connect(condenser.ports[2], hydRes_con.port_a)
  connect(hydRes_con.port_b, T_conOut.port_a)
  connect(hydRes_eva.port_a, evaporator.ports[2])
  connect(hydRes_eva.port_b, T_evaOut.port_a)
end HeatPumpDetailed;


Heat pump inlet on the source side

within AixLib.Obsolete.Year2019.Fluid.HeatPumps;
model HeatPumpSimple
  extends AixLib.Obsolete.BaseClasses.ObsoleteModel;
  replaceable package Medium =
     Modelica.Media.Water.ConstantPropertyLiquidWater
     constrainedby Modelica.Media.Interfaces.PartialMedium;

  Modelica.Fluid.Interfaces.FluidPort_a
                    port_a_source(redeclare package Medium = Medium)
                    "Heat pump inlet on the source side"
  Modelica.Fluid.Interfaces.FluidPort_b
                    port_b_source(redeclare package Medium = Medium)
                    "Heat pump outlet on the source side"
  Modelica.Fluid.Interfaces.FluidPort_a
                    port_a_sink(redeclare package Medium = Medium)
                    "Heat pump inlet on the sink side"
  Modelica.Fluid.Interfaces.FluidPort_b
                    port_b_sink(redeclare package Medium = Medium)
                    "Heat pump outlet on the sink side"
  AixLib.Fluid.MixingVolumes.MixingVolume volumeEvaporator(
    V=VolumeEvaporator,
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=0.01) "Water volume of the evaporator on the source side"
  AixLib.Fluid.MixingVolumes.MixingVolume volumeCondenser(
    V=VolumeCondenser,
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=0.01) "Water volume of the condenser on the sink side"
  AixLib.Fluid.Sensors.TemperatureTwoPort temperatureSinkOut(redeclare package Medium =
               Medium, m_flow_nominal=0.01)
    "Temperature sensor at outlet on the sink side"
  Modelica.Blocks.Interfaces.BooleanInput OnOff
                    "On Off input signal of the heat pump"
  AixLib.Fluid.Sensors.TemperatureTwoPort temperatureSourceIn(redeclare package
                                                                                Medium =
               Medium, m_flow_nominal=0.01)
    "Temperature sensor at inlet on the source side"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow HeatFlowCondenser
                    "Heat flow on the sink side"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow HeatFlowEvaporator
                    "Heat flow on the source side"
  Modelica.Blocks.Tables.CombiTable2Ds PowerTable(table=tablePower)
    "Calculates electric power based on temperature in source and sink"
  Modelica.Blocks.Tables.CombiTable2Ds HeatFlowCondenserTable(table=
        tableHeatFlowCondenser)
    "Calculates heat flow based on temperature in source and sink"
  Modelica.Blocks.Logical.Switch SwitchHeatFlowCondenser
                    "Switch to deactivate heat flow when off"
  Modelica.Blocks.Sources.Constant constZero2(k = 0)
                    "Zero heat flow, when heat pump off"
  Modelica.Blocks.Logical.Switch SwitchPower
                    "Switch to deactivate Power when off"
  Modelica.Blocks.Sources.Constant constZero1(k = 0)
                    "Zero power, when heat pump off"
  Modelica.Blocks.Math.Feedback feedbackHeatFlowEvaporator
                    "Calculates evaporator heat flow with total energy balance"
  Modelica.Blocks.Interfaces.RealOutput Power "Connector of Real output signal"
  parameter Modelica.Units.SI.Volume VolumeEvaporator=0.01 "Volume im m3";
  parameter Modelica.Units.SI.Volume VolumeCondenser=0.01 "Volume im m3";
  parameter Real tablePower[:, :] = fill(0.0, 0, 2)
    "Table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real tableHeatFlowCondenser[:, :] = fill(0.0, 0, 2)
    "Table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  Modelica.Blocks.Math.Gain gain(k=-1)
equation
  connect(temperatureSourceIn.port_a, port_a_source)
  connect(temperatureSinkOut.port_b, port_b_sink)
  connect(HeatFlowEvaporator.port, volumeEvaporator.heatPort)
  connect(HeatFlowCondenser.port, volumeCondenser.heatPort)
  connect(OnOff, SwitchHeatFlowCondenser.u2)
  connect(HeatFlowCondenserTable.y, SwitchHeatFlowCondenser.u1)
  connect(constZero2.y, SwitchHeatFlowCondenser.u3)
  connect(SwitchHeatFlowCondenser.y, HeatFlowCondenser.Q_flow)
  connect(constZero1.y, SwitchPower.u3)
  connect(SwitchPower.u2, SwitchHeatFlowCondenser.u2)
  connect(PowerTable.y, SwitchPower.u1)
  connect(SwitchPower.y, Power)
  connect(SwitchPower.y, feedbackHeatFlowEvaporator.u2)
  connect(SwitchHeatFlowCondenser.y, feedbackHeatFlowEvaporator.u1)
  connect(gain.y, HeatFlowEvaporator.Q_flow)
  connect(gain.u, feedbackHeatFlowEvaporator.y)
  connect(temperatureSourceIn.port_b, volumeEvaporator.ports[1])
  connect(port_a_sink, volumeCondenser.ports[1])
  connect(volumeCondenser.ports[2], temperatureSinkOut.port_a)

  connect(temperatureSourceIn.T, PowerTable.u2)
  connect(temperatureSourceIn.T, HeatFlowCondenserTable.u2)
  connect(temperatureSinkOut.T, PowerTable.u1)
  connect(temperatureSinkOut.T, HeatFlowCondenserTable.u1)
  connect(volumeEvaporator.ports[2], port_b_source)
end HeatPumpSimple;


Package with models for heat pumps

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