within AixLib.DataBase.CHP.ModularCHPEngineMedia;
partial package CHPCombustionMixtureGasNasa
    "Medium model of a mixture of ideal gases based on NASA source"

  import Modelica.Math;
  import Modelica.Media.Interfaces.Choices.ReferenceEnthalpy;

  extends Modelica.Media.Interfaces.PartialMixtureMedium(
     ThermoStates=Modelica.Media.Interfaces.Choices.IndependentVariables.pTX,
     substanceNames=data[:].name,
     reducedX = false,
     singleState=false,
     reference_X=fill(1/nX,nX),
     SpecificEnthalpy(start=if referenceChoice==ReferenceEnthalpy.ZeroAt0K then 3e5 else
        if referenceChoice==ReferenceEnthalpy.UserDefined then h_offset else 0, nominal=1.0e5),
     Density(start=10, nominal=10),
     AbsolutePressure(start=10e5, nominal=10e5),
     Temperature(min=200, max=6000, start=500, nominal=500));

    redeclare record extends ThermodynamicState "Thermodynamic state variables"
    end ThermodynamicState;
//   redeclare record extends FluidConstants "Fluid constants"
//   end FluidConstants;

  constant Modelica.Media.IdealGases.Common.DataRecord[:] data
    "Data records of ideal gas substances";
    // ={Common.SingleGasesData.N2,Common.SingleGasesData.O2}

  constant Boolean excludeEnthalpyOfFormation=true
    "If true, enthalpy of formation Hf is not included in specific enthalpy h";
  constant ReferenceEnthalpy referenceChoice=ReferenceEnthalpy.ZeroAt0K
    "Choice of reference enthalpy";
  constant SpecificEnthalpy h_offset=0.0
    "User defined offset for reference enthalpy, if referenceChoice = UserDefined";

//   constant FluidConstants[nX] fluidConstants
//     "Additional data needed for transport properties";
  constant MolarMass[nX] MMX=data[:].MM "Molar masses of components";
  constant Integer methodForThermalConductivity(min=1,max=2)=1;
  redeclare replaceable model extends BaseProperties(
    T(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    p(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    Xi(each stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    final standardOrderComponents=true)
    "Base properties (p, d, T, h, u, R, MM, X, and Xi of NASA mixture gas"
  equation
    assert(T >= 200 and T <= 6000, "
Temperature T (=" + String(T) + " K = 200 K) is not in the allowed range
200 K <= T <= 6000 K
required from medium model \"" + mediumName + "\".");

    MM = molarMass(state);
    h = h_TX(T, X);
    R_s = data.R_s*X;
    u =h - R_s*T;
    d =p/(R_s*T);
    // connect state with BaseProperties
    state.T = T;
    state.p = p;
    state.X = if fixedX then reference_X else X;
  end BaseProperties;

    redeclare function setState_pTX
    "Return thermodynamic state as function of p, T and composition X"
      extends Modelica.Icons.Function;
      input AbsolutePressure p "Pressure";
      input Temperature T "Temperature";
      input MassFraction X[:]=reference_X "Mass fractions";
      output ThermodynamicState state;
    algorithm
      state := if size(X,1) == 0 then ThermodynamicState(p=p,T=T,X=reference_X) else if size(X,1) == nX then ThermodynamicState(p=p,T=T, X=X) else
             ThermodynamicState(p=p,T=T, X=cat(1,X,{1-sum(X)}));
    end setState_pTX;

    redeclare function setState_phX
    "Return 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[:]=reference_X "Mass fractions";
      output ThermodynamicState state;
    algorithm
      state := if size(X,1) == 0 then ThermodynamicState(p=p,T=T_hX(h,reference_X),X=reference_X) else if size(X,1) == nX then ThermodynamicState(p=p,T=T_hX(h,X),X=X) else
             ThermodynamicState(p=p,T=T_hX(h,X), X=cat(1,X,{1-sum(X)}));
    end setState_phX;

    redeclare function setState_psX
    "Return thermodynamic state as function of p, s and composition X"
      extends Modelica.Icons.Function;
      input AbsolutePressure p "Pressure";
      input SpecificEntropy s "Specific entropy";
      input MassFraction X[:]=reference_X "Mass fractions";
      output ThermodynamicState state;
    algorithm
      state := if size(X,1) == 0 then ThermodynamicState(p=p,T=T_psX(p,s,reference_X),X=reference_X) else if size(X,1) == nX then ThermodynamicState(p=p,T=T_psX(p,s,X),X=X) else
             ThermodynamicState(p=p,T=T_psX(p,s,X), X=cat(1,X,{1-sum(X)}));
    end setState_psX;

    redeclare function setState_dTX
    "Return 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;
    algorithm
      state :=if size(X, 1) == 0 then ThermodynamicState(
          p=d*(data.R_s*reference_X)*T,
          T=T,
          X=reference_X) else if size(X, 1) == nX then ThermodynamicState(
          p=d*(data.R_s*X)*T,
          T=T,
          X=X) else ThermodynamicState(
          p=d*(data.R_s*cat(
            1,
            X,
            {1 - sum(X)}))*T,
          T=T,
          X=cat(
            1,
            X,
            {1 - sum(X)}));
    end setState_dTX;

      redeclare function extends setSmoothState
      "Return thermodynamic state so that it smoothly approximates: if x > 0 then state_a else state_b"
      algorithm
      state := ThermodynamicState(
              p=Modelica.Media.Common.smoothStep(
                x,
                state_a.p,
                state_b.p,
                x_small),
              T=Modelica.Media.Common.smoothStep(
                x,
                state_a.T,
                state_b.T,
                x_small),
              X=Modelica.Media.Common.smoothStep(
                x,
                state_a.X,
                state_b.X,
                x_small));
      end setSmoothState;

    redeclare function extends pressure "Return pressure of ideal gas"
    algorithm
      p := state.p;
    end pressure;

    redeclare function extends temperature "Return temperature of ideal gas"
    algorithm
      T := state.T;
    end temperature;

    redeclare function extends density "Return density of ideal gas"
    algorithm
      d :=state.p/((state.X*data.R_s)*state.T);
    end density;

  redeclare function extends specificEnthalpy "Return specific enthalpy"
    extends Modelica.Icons.Function;
  algorithm
    h := h_TX(state.T,state.X);
  end specificEnthalpy;

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

  redeclare function extends specificEntropy "Return specific entropy"
  protected
    Real[nX] Y(unit="mol/mol")=massToMoleFractions(state.X, data.MM)
      "Molar fractions";
  algorithm
  s :=  s_TX(state.T, state.X) - sum(state.X[i]*Modelica.Constants.R/MMX[i]*
      (if state.X[i]<Modelica.Constants.eps then Y[i] else
      Modelica.Math.log(Y[i]*state.p/reference_p)) for i in 1:nX);
  end specificEntropy;

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

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

  function h_TX "Return specific enthalpy"
    import Modelica.Media.Interfaces.Choices;
     extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T "Temperature";
     input MassFraction X[nX]=reference_X
      "Independent Mass fractions of gas mixture";
     input Boolean exclEnthForm=excludeEnthalpyOfFormation
      "If true, enthalpy of formation Hf is not included in specific enthalpy h";
     input Modelica.Media.Interfaces.Choices.ReferenceEnthalpy
                                     refChoice=referenceChoice
      "Choice of reference enthalpy";
    input Modelica.Units.SI.SpecificEnthalpy h_off=h_offset
      "User defined offset for reference enthalpy, if referenceChoice = UserDefined";
    output Modelica.Units.SI.SpecificEnthalpy h
      "Specific enthalpy at temperature T";
  algorithm
    h :=(if fixedX then reference_X else X)*
         {Modelica.Media.IdealGases.Common.Functions.h_T(
                            data[i], T, exclEnthForm, refChoice, h_off) for i in 1:nX};
  end h_TX;

  function h_TX_der "Return specific enthalpy derivative"
    import Modelica.Media.Interfaces.Choices;
     extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T "Temperature";
     input MassFraction X[nX] "Independent Mass fractions of gas mixture";
     input Boolean exclEnthForm=excludeEnthalpyOfFormation
      "If true, enthalpy of formation Hf is not included in specific enthalpy h";
     input Modelica.Media.Interfaces.Choices.ReferenceEnthalpy
                                     refChoice=referenceChoice
      "Choice of reference enthalpy";
    input Modelica.Units.SI.SpecificEnthalpy h_off=h_offset
      "User defined offset for reference enthalpy, if referenceChoice = UserDefined";
    input Real dT "Temperature derivative";
    input Real dX[nX] "Independent mass fraction derivative";
    output Real h_der "Specific enthalpy at temperature T";
  algorithm
    h_der := if fixedX then
      dT*sum((Modelica.Media.IdealGases.Common.Functions.cp_T(
                                 data[i], T)*reference_X[i]) for i in 1:nX) else
      dT*sum((Modelica.Media.IdealGases.Common.Functions.cp_T(
                                 data[i], T)*X[i]) for i in 1:nX)+
      sum((Modelica.Media.IdealGases.Common.Functions.h_T(
                             data[i], T)*dX[i]) for i in 1:nX);
  end h_TX_der;

  redeclare function extends gasConstant "Return gasConstant"
  algorithm
    R_s := data.R_s*state.X;
  end gasConstant;

  redeclare function extends specificHeatCapacityCp
    "Return specific heat capacity at constant pressure"
  algorithm
    cp := {Modelica.Media.IdealGases.Common.Functions.cp_T(
                              data[i], state.T) for i in 1:nX}*state.X;
  end specificHeatCapacityCp;

  redeclare function extends specificHeatCapacityCv
    "Return specific heat capacity at constant volume from temperature and gas data"
  algorithm
    cv :={Modelica.Media.IdealGases.Common.Functions.cp_T(data[i], state.T)
      for i in 1:nX}*state.X - data.R_s*state.X;
  end specificHeatCapacityCv;

  function MixEntropy "Return mixing entropy of ideal gases / R"
    extends Modelica.Icons.Function;
    input Modelica.Units.SI.MoleFraction x[:] "Mole fraction of mixture";
    output Real smix "Mixing entropy contribution, divided by gas constant";
  algorithm
    smix := sum(if x[i] > Modelica.Constants.eps then -x[i]*Modelica.Math.log(x[i]) else
                     x[i] for i in 1:size(x,1));
  end MixEntropy;

  function s_TX
    "Return temperature dependent part of the entropy, expects full entropy vector"
    extends Modelica.Icons.Function;
    input Temperature T "Temperature";
    input MassFraction[nX] X "Mass fraction";
    output SpecificEntropy s "Specific entropy";
  algorithm
    s := sum(Modelica.Media.IdealGases.Common.Functions.s0_T(
                                data[i], T)*X[i] for i in 1:size(X,1));
  end s_TX;

  redeclare function extends isentropicExponent "Return isentropic exponent"
  algorithm
    gamma := specificHeatCapacityCp(state)/specificHeatCapacityCv(state);
  end isentropicExponent;

  redeclare function extends velocityOfSound "Return velocity of sound"
    extends Modelica.Icons.Function;
    input ThermodynamicState state "Properties at upstream location";
  algorithm
    a := sqrt(max(0,gasConstant(state)*state.T*specificHeatCapacityCp(state)/specificHeatCapacityCv(state)));
  end velocityOfSound;

  function isentropicEnthalpyApproximation
    "Approximate method of calculating h_is from upstream properties and downstream pressure"
    extends Modelica.Icons.Function;
    input AbsolutePressure p2 "Downstream pressure";
    input ThermodynamicState state "Thermodynamic state at upstream location";
    output SpecificEnthalpy h_is "Isentropic enthalpy";
  protected
    SpecificEnthalpy h "Specific enthalpy at upstream location";
    SpecificEnthalpy h_component[nX] "Specific enthalpy at upstream location";
    IsentropicExponent gamma =  isentropicExponent(state) "Isentropic exponent";
  protected
    MassFraction[nX] X "Complete X-vector";
  algorithm
    X := if reducedX then cat(1,state.X,{1-sum(state.X)}) else state.X;
    h_component :={Modelica.Media.IdealGases.Common.Functions.h_T(
                                     data[i], state.T, excludeEnthalpyOfFormation,
      referenceChoice, h_offset) for i in 1:nX};
    h :=h_component*X;
    h_is := h + gamma/(gamma - 1.0)*(state.T*gasConstant(state))*
      ((p2/state.p)^((gamma - 1)/gamma) - 1.0);
  end isentropicEnthalpyApproximation;

  redeclare function extends isentropicEnthalpy "Return isentropic enthalpy"
    input Boolean exact = false
      "Flag whether exact or approximate version should be used";
  algorithm
    h_is := if exact then specificEnthalpy_psX(p_downstream,specificEntropy(refState),refState.X) else
           isentropicEnthalpyApproximation(p_downstream,refState);
  end isentropicEnthalpy;

function gasMixtureViscosity
    "Return viscosities of gas mixtures at low pressures (Wilke method)"
  extends Modelica.Icons.Function;
  input MoleFraction[:] yi "Mole fractions";
  input MolarMass[size(yi,1)] M "Mole masses";
  input DynamicViscosity[size(yi,1)] eta "Pure component viscosities";
  output DynamicViscosity etam "Viscosity of the mixture";
  protected
  Real fi[size(yi,1),size(yi,1)];
algorithm
  for i in 1:size(eta,1) loop
    assert(fluidConstants[i].hasDipoleMoment,"Dipole moment for " + fluidConstants[i].chemicalFormula +
       " not known. Can not compute viscosity.");
    assert(fluidConstants[i].hasCriticalData, "Critical data for "+ fluidConstants[i].chemicalFormula +
       " not known. Can not compute viscosity.");
    for j in 1:size(eta,1) loop
      if i==1 then
        fi[i,j] := (1 + (eta[i]/eta[j])^(1/2)*(M[j]/M[i])^(1/4))^2/(8*(1 + M[i]/M[j]))^(1/2);
      elseif j<i then
          fi[i,j] := eta[i]/eta[j]*M[j]/M[i]*fi[j,i];
        else
          fi[i,j] := (1 + (eta[i]/eta[j])^(1/2)*(M[j]/M[i])^(1/4))^2/(8*(1 + M[i]/M[j]))^(1/2);
      end if;
    end for;
  end for;
  etam := sum(yi[i]*eta[i]/sum(yi[j]*fi[i,j] for j in 1:size(eta,1)) for i in 1:size(eta,1));
end gasMixtureViscosity;

    redeclare replaceable function extends dynamicViscosity
    "Return mixture dynamic viscosity"
  protected
      DynamicViscosity[nX] etaX "Component dynamic viscosities";
    algorithm
      for i in 1:nX loop
    etaX[i] := Modelica.Media.IdealGases.Common.Functions.dynamicViscosityLowPressure(
                                                         state.T,
                       fluidConstants[i].criticalTemperature,
                       fluidConstants[i].molarMass,
                       fluidConstants[i].criticalMolarVolume,
                       fluidConstants[i].acentricFactor,
                       fluidConstants[i].dipoleMoment);
      end for;
      eta := gasMixtureViscosity(massToMoleFractions(state.X,
                             fluidConstants[:].molarMass),
                 fluidConstants[:].molarMass,
                 etaX);
    end dynamicViscosity;

  function mixtureViscosityChung
    "Return the viscosity of gas mixtures without access to component viscosities (Chung, et. al. rules)"
  extends Modelica.Icons.Function;

    input Temperature T "Temperature";
    input Temperature[nX] Tc "Critical temperatures";
    input MolarVolume[nX] Vcrit "Critical volumes (m3/mol)";
    input Real[nX] w "Acentric factors";
    input Real[nX] mu "Dipole moments (debyes)";
    input MolarMass[nX] MolecularWeights "Molecular weights (kg/mol)";
    input MoleFraction[nX] y "Molar Fractions";
    input Real[nX] kappa =  zeros(nX) "Association Factors";
    output DynamicViscosity etaMixture "Mixture viscosity (Pa.s)";
  protected
  constant Real[size(y,1)] Vc =  Vcrit*1000000 "Critical volumes (cm3/mol)";
  constant Real[size(y,1)] M =  MolecularWeights*1000
      "Molecular weights (g/mol)";
  Integer n = size(y,1) "Number of mixed elements";
  Real sigmam3 "Mixture sigma3 in Angstrom";
  Real sigma[size(y,1),size(y,1)];
  Real edivkm;
  Real edivk[size(y,1),size(y,1)];
  Real Mm;
  Real Mij[size(y,1),size(y,1)];
  Real wm "Accentric factor";
  Real wij[size(y,1),size(y,1)];
  Real kappam
      "Correlation for highly polar substances such as alcohols and acids";
  Real kappaij[size(y,1),size(y,1)];
  Real mum;
  Real Vcm;
  Real Tcm;
  Real murm "Dimensionless dipole moment of the mixture";
  Real Fcm "Factor to correct for shape and polarity";
  Real omegav;
  Real Tmstar;
  Real etam "Mixture viscosity in microP";
  algorithm
  //combining rules
  for i in 1:n loop
    for j in 1:n loop
      Mij[i,j] := 2*M[i]*M[j]/(M[i]+M[j]);
      if i==j then
        sigma[i,j] := 0.809*Vc[i]^(1/3);
        edivk[i,j] := Tc[i]/1.2593;
        wij[i,j] := w[i];
        kappaij[i,j] := kappa[i];
      else
        sigma[i,j] := (0.809*Vc[i]^(1/3)*0.809*Vc[j]^(1/3))^(1/2);
        edivk[i,j] := (Tc[i]/1.2593*Tc[j]/1.2593)^(1/2);
        wij[i,j] := (w[i] + w[j])/2;
        kappaij[i,j] := (kappa[i]*kappa[j])^(1/2);
      end if;
    end for;
  end for;
  //mixing rules
  sigmam3 := (sum(sum(y[i]*y[j]*sigma[i,j]^3 for j in 1:n) for i in 1:n));
  //(epsilon/k)m
  edivkm := (sum(sum(y[i]*y[j]*edivk[i,j]*sigma[i,j]^3 for j in 1:n) for i in 1:n))/sigmam3;
  Mm := ((sum(sum(y[i]*y[j]*edivk[i,j]*sigma[i,j]^2*Mij[i,j]^(1/2) for j in 1:n) for i in 1:n))/(edivkm*sigmam3^(2/3)))^2;
  wm := (sum(sum(y[i]*y[j]*wij[i,j]*sigma[i,j]^3 for j in 1:n) for i in 1:n))/sigmam3;
  mum := (sigmam3*(sum(sum(y[i]*y[j]*mu[i]^2*mu[j]^2/sigma[i,j]^3 for j in 1:n) for i in 1:n)))^(1/4);
  Vcm := sigmam3/(0.809)^3;
  Tcm := 1.2593*edivkm;
  murm := 131.3*mum/(Vcm*Tcm)^(1/2);
  kappam := (sigmam3*(sum(sum(y[i]*y[j]*kappaij[i,j] for j in 1:n) for i in 1:n)));
  Fcm := 1 - 0.275*wm + 0.059035*murm^4 + kappam;
  Tmstar := T/edivkm;
  omegav := 1.16145*(Tmstar)^(-0.14874) + 0.52487*Math.exp(-0.77320*Tmstar) + 2.16178*Math.exp(-2.43787*Tmstar);
  etam := 26.69*Fcm*(Mm*T)^(1/2)/(sigmam3^(2/3)*omegav);
  etaMixture := etam*1e7;
  end mixtureViscosityChung;

function lowPressureThermalConductivity
    "Return thermal conductivities of low-pressure gas mixtures (Mason and Saxena Modification)"
  extends Modelica.Icons.Function;
  input MoleFraction[:] y "Mole fraction of the components in the gas mixture";
  input Temperature T "Temperature";
  input Temperature[size(y,1)] Tc "Critical temperatures";
  input AbsolutePressure[size(y,1)] Pc "Critical pressures";
  input MolarMass[size(y,1)] M "Molecular weights";
  input ThermalConductivity[size(y,1)] lambda
      "Thermal conductivities of the pure gases";
  output ThermalConductivity lambdam "Thermal conductivity of the gas mixture";
  protected
  MolarMass[size(y,1)] gamma;
  Real[size(y,1)] Tr "Reduced temperature";
  Real[size(y,1),size(y,1)] A "Mason and Saxena Modification";
  constant Real epsilon =  1.0 "Numerical constant near unity";
algorithm
  for i in 1:size(y,1) loop
    gamma[i] := 210*(Tc[i]*M[i]^3/Pc[i]^4)^(1/6);
    Tr[i] := T/Tc[i];
  end for;
  for i in 1:size(y,1) loop
    for j in 1:size(y,1) loop
      A[i,j] := epsilon*(1 + (gamma[j]*(Math.exp(0.0464*Tr[i]) - Math.exp(-0.2412*Tr[i]))/
      (gamma[i]*(Math.exp(0.0464*Tr[j]) - Math.exp(-0.2412*Tr[j]))))^(1/2)*(M[i]/M[j])^(1/4))^2/
      (8*(1 + M[i]/M[j]))^(1/2);
    end for;
  end for;
  lambdam := sum(y[i]*lambda[i]/(sum(y[j]*A[i,j] for j in 1:size(y,1))) for i in 1:size(y,1));
end lowPressureThermalConductivity;

    redeclare replaceable function extends thermalConductivity
    "Return thermal conductivity for low pressure gas mixtures"
      input Integer method=methodForThermalConductivity
      "Method to compute single component thermal conductivity";
  protected
      ThermalConductivity[nX] lambdaX "Component thermal conductivities";
      DynamicViscosity[nX] eta "Component thermal dynamic viscosities";
      SpecificHeatCapacity[nX] cp "Component heat capacity";
    algorithm
      for i in 1:nX loop
    assert(fluidConstants[i].hasCriticalData, "Critical data for "+ fluidConstants[i].chemicalFormula +
       " not known. Can not compute thermal conductivity.");
    eta[i] := Modelica.Media.IdealGases.Common.Functions.dynamicViscosityLowPressure(
                                                        state.T,
                       fluidConstants[i].criticalTemperature,
                       fluidConstants[i].molarMass,
                       fluidConstants[i].criticalMolarVolume,
                       fluidConstants[i].acentricFactor,
                       fluidConstants[i].dipoleMoment);
    cp[i] := Modelica.Media.IdealGases.Common.Functions.cp_T(
                                data[i],state.T);
    lambdaX[i] :=Modelica.Media.IdealGases.Common.Functions.thermalConductivityEstimate(
                                                           Cp=cp[i], eta=
          eta[i], method=method,data=data[i]);
      end for;
      lambda := lowPressureThermalConductivity(massToMoleFractions(state.X,
                                   fluidConstants[:].molarMass),
                           state.T,
                           fluidConstants[:].criticalTemperature,
                           fluidConstants[:].criticalPressure,
                           fluidConstants[:].molarMass,
                           lambdaX);
    end thermalConductivity;

  redeclare function extends isobaricExpansionCoefficient
    "Return isobaric expansion coefficient beta"
  algorithm
    beta := 1/state.T;
  end isobaricExpansionCoefficient;

  redeclare function extends isothermalCompressibility
    "Return isothermal compressibility factor"
  algorithm
    kappa := 1.0/state.p;
  end isothermalCompressibility;

  redeclare function extends density_derp_T
    "Return density derivative by pressure at constant temperature"
  algorithm
    ddpT := 1/(state.T*gasConstant(state));
  end density_derp_T;

  redeclare function extends density_derT_p
    "Return density derivative by temperature at constant pressure"
  algorithm
    ddTp := -state.p/(state.T*state.T*gasConstant(state));
  end density_derT_p;

  redeclare function density_derX "Return density derivative by mass fraction"
    extends Modelica.Icons.Function;
    input ThermodynamicState state "Thermodynamic state record";
    output Density[nX] dddX "Derivative of density w.r.t. mass fraction";
  algorithm
    dddX := {-state.p/(state.T*gasConstant(state))*molarMass(state)/data[
      i].MM for i in 1:nX};
  end density_derX;

  redeclare function extends molarMass "Return molar mass of mixture"
  algorithm
    MM := 1/sum(state.X[j]/data[j].MM for j in 1:size(state.X, 1));
  end molarMass;

  function T_hX "Return temperature from specific enthalpy and mass fraction"
    extends Modelica.Icons.Function;
    input SpecificEnthalpy h "Specific enthalpy";
    input MassFraction[nX] X "Mass fractions of composition";
    input Boolean exclEnthForm=excludeEnthalpyOfFormation
      "If true, enthalpy of formation Hf is not included in specific enthalpy h";
    input Modelica.Media.Interfaces.Choices.ReferenceEnthalpy
                                     refChoice=referenceChoice
      "Choice of reference enthalpy";
    input SpecificEnthalpy h_off=h_offset
      "User defined offset for reference enthalpy, if referenceChoice = UserDefined";
    output Temperature T "Temperature";

  protected
    function f_nonlinear "Solve h_TX(T,X) for T with given h"
      extends Modelica.Math.Nonlinear.Interfaces.partialScalarFunction;
      input SpecificEnthalpy h "Specific enthalpy";
      input MassFraction[nX] X "Mass fractions of composition";
      input Boolean exclEnthForm "If true, enthalpy of formation Hf is not included in specific enthalpy h";
      input Modelica.Media.Interfaces.Choices.ReferenceEnthalpy refChoice "Choice of reference enthalpy";
      input SpecificEnthalpy h_off "User defined offset for reference enthalpy, if referenceChoice = UserDefined";
    algorithm
      y := h_TX(T=u, X=X, exclEnthForm=exclEnthForm, refChoice=refChoice, h_off=h_off) - h;
    end f_nonlinear;

  algorithm
    T := Modelica.Math.Nonlinear.solveOneNonlinearEquation(
      function f_nonlinear(h=h, X=X, exclEnthForm=exclEnthForm, refChoice=refChoice, h_off=h_off), 200, 6000);
  end T_hX;

  function T_psX
    "Return temperature from pressure, specific entropy and mass fraction"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEntropy s "Specific entropy";
    input MassFraction[nX] X "Mass fractions of composition";
    output Temperature T "Temperature";

  protected
    function f_nonlinear "Solve specificEntropyOfpTX(p,T,X) for T with given s"
      extends Modelica.Math.Nonlinear.Interfaces.partialScalarFunction;
      input AbsolutePressure p "Pressure";
      input SpecificEntropy s "Specific entropy";
      input MassFraction[nX] X "Mass fractions of composition";
    algorithm
      y := specificEntropyOfpTX(p=p, T=u, X=X) - s;
    end f_nonlinear;

  algorithm
    T := Modelica.Math.Nonlinear.solveOneNonlinearEquation(
      function f_nonlinear(p=p, s=s, X=X), 200, 6000);
  end T_psX;
//   redeclare function extends specificEnthalpy_psX
//   protected
//     Temperature T "Temperature";
//   algorithm
//     T := temperature_psX(p,s,X);
//     h := specificEnthalpy_pTX(p,T,X);
//   end extends;

//   redeclare function extends density_phX
//     "Compute density from pressure, specific enthalpy and mass fraction"
//     protected
//     Temperature T "Temperature";
//     SpecificHeatCapacity R "Gas constant";
//   algorithm
//     T := temperature_phX(p,h,X);
//     R := if (not reducedX) then
//       sum(data[i].R*X[i] for i in 1:size(substanceNames, 1)) else
//       sum(data[i].R*X[i] for i in 1:size(substanceNames, 1)-1) + data[end].R*(1-sum(X[i]));
//     d := p/(R*T);
//   end density_phX;
end CHPCombustionMixtureGasNasa;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package CHPCoolantPropyleneGlycolWater
  "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 and T <= T_max, "
Temperature T (= " + String(T) + " K) is not
in the allowed range (" + String(T_min) + " K <= T <= " + String(T_max) + " K)
required from medium model \"" + mediumName + "\".
"); assert(X_a >= X_a_min and X_a <= X_a_max, "
    Mass fraction X_a (= " + String(X_a) + " ) is not
in the allowed range (" + String(X_a_min) + " <= X_a <= " + String(X_a_max) + " )
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 CHPCoolantPropyleneGlycolWater;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package CHPFlueGasLambdaOnePlus
  "Simple flue gas for overstoichiometric O2-fuel ratios"
  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="FlueGasLambdaPlus",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.O2,
        Modelica.Media.IdealGases.Common.SingleGasesData.H2O,Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.O2,
        Modelica.Media.IdealGases.Common.FluidData.H2O,Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Oxygen","Water","Carbondioxide"},
    reference_X={0.768,0.232,0.0,0.0});
end CHPFlueGasLambdaOnePlus;


Air as mixture of N2 and O2

within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package EngineCombustionAir "Air as mixture of N2 and O2"
  extends Modelica.Media.IdealGases.Common.MixtureGasNasa(
    mediumName="CombustionAirN2O2",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.O2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.O2},
    substanceNames={"Nitrogen","Oxygen"}, reference_X = {0.768, 0.232});

  //!!For the script calculating the combustion: Nitrogen has to be at first place for the composition of the fuel!!"
    constant ThermodynamicState stateAir = setState_pTX(reference_p, reference_T, reference_X);
    constant MolarMass MM = 1/sum(stateAir.X[j]/data[j].MM for j in 1:size(stateAir.X, 1));
    constant MolarMass MMX[:] = data[:].MM;
    constant Real X[:] = stateAir.X;
    constant MoleFraction moleFractions_Air[:] = massToMoleFractions(X, MMX);
end EngineCombustionAir;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package LiquidFuel_Diesel
  "Simple diesel fuel for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="Just dummy data and no use for calculation",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=DieselFuel() "Needed fuel data for combustion calculations"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MolarMass MM = Fuel.MM_liq "Molar mass of the fuel";
  constant SpecificEnergy H_U = Fuel.H_U "Calorific Value of the fuel gas";
  constant Real l_min = L_st*MM/0.02885;
  constant Real L_st = 4.31034*(2.664*Fuel.Xi_liq[1]+7.937*Fuel.Xi_liq[2]-Fuel.Xi_liq[3]) "Stoichiometric air consumption";
  //Unused information for simulation stability
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;

  record DieselFuel "Data record for simple diesel fuel"
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
    fuelType = "Simple diesel fuel",
    isGasoline = false,
    H_U = 42800000,
    MM_liq = 0.19,
    Xi_liq = {0.86,0.14,0.0});

  end DieselFuel;
end LiquidFuel_Diesel;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package LiquidFuel_LPG "Simple LPG fuel for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="Just dummy data and no use for calculation",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=LPGFuel()    "Needed fuel data for combustion calculations"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MolarMass MM = Fuel.MM_liq "Molar mass of the fuel";
  constant SpecificEnergy H_U = Fuel.H_U "Calorific Value of the fuel gas";
  constant Real l_min = L_st*MM/0.02885;
  constant Real L_st = 4.31034*(2.664*Fuel.Xi_liq[1]+7.937*Fuel.Xi_liq[2]-Fuel.Xi_liq[3]) "Stoichiometric air consumption";
  //Unused information for simulation stability
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;

  record LPGFuel "Data record for simple LPG fuel"
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
    fuelType = "Simple LPG fuel",
    isGasoline = false,
    H_U = 45330000,
    MM_liq = 0.048,
    Xi_liq = {0.82,0.18,0.00});

  end LPGFuel;
end LiquidFuel_LPG;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package LiquidFuel_Petrol "Simple petrol fuel for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="Just dummy data and no use for calculation",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=PetrolFuel() "Needed fuel data for combustion calculations"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MolarMass MM = Fuel.MM_liq "Molar mass of the fuel";
  constant SpecificEnergy H_U = Fuel.H_U "Calorific Value of the fuel gas";
  constant Real l_min = L_st*MM/0.02885;
  constant Real L_st = 4.31034*(2.664*Fuel.Xi_liq[1]+7.937*Fuel.Xi_liq[2]-Fuel.Xi_liq[3]) "Stoichiometric air consumption";
  //Unused information for simulation stability
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;

  record PetrolFuel "Data record for simple petrol fuel"
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
    fuelType = "Simple petrol fuel",
    isGasoline = false,
    H_U = 42000000,
    MM_liq = 0.098,
    Xi_liq = {0.84,0.14,0.02});

  end PetrolFuel;
end LiquidFuel_Petrol;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package NaturalGasMixture_GeneralType
  "Simple natural gas mixture for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="NaturalGasMixture_SelectableVolumetricProportions",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=NaturalGas_GeneralDefinition()
    "Needed natural gas data for calculations, manual redefinition of volumetric proportions of the gas components (Xi_mole) required (default:{1/9,1/9,...})!"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;
  constant MolarMass MM = sum(Fuel.Xi_mole[i]*Fuel.MMi[i] for i in 1:size(Fuel.MMi, 1)) "Molar mass of natural gas type from its composition";
  constant MassFraction massFractions_Gas[:] = Modelica.Media.Interfaces.PartialMixtureMedium.moleToMassFractions(Fuel.Xi_mole, Fuel.MMi);
  constant SpecificEnergy H_U = sum(massFractions_Gas[i]*Fuel.H_Ui[i] for i in 1:size(Fuel.MMi, 1)) "Calorific Value of the fuel gas";
  constant Real l_min = sum(Fuel.Xi_mole[i]*Fuel.nue_min[i] for i in 1:size(Fuel.MMi, 1))/0.21;
  constant Real L_st = l_min*0.02885/MM "Stoichiometric air consumption";

  record NaturalGas_GeneralDefinition
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
        fuelType="GeneralTypeForRedefinition",
        isGasoline = true,
        Xi_mole={1/9,1/9,1/9,1/9,
          1/9,1/9,1/9,1/9,1/9});
  end NaturalGas_GeneralDefinition;
end NaturalGasMixture_GeneralType;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package NaturalGasMixture_TypeAachen
  "Simple natural gas mixture (type Aachen) for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="NaturalGasMixtureForAachen",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=NaturalGasTypeAachen() "Needed natural gas data for calculations"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;
  constant MolarMass MM = sum(Fuel.Xi_mole[i]*Fuel.MMi[i] for i in 1:size(Fuel.MMi, 1)) "Molar mass of natural gas type from its composition";
  constant MassFraction massFractions_Gas[:] = Modelica.Media.Interfaces.PartialMixtureMedium.moleToMassFractions(Fuel.Xi_mole, Fuel.MMi);
  constant SpecificEnergy H_U = sum(massFractions_Gas[i]*Fuel.H_Ui[i] for i in 1:size(Fuel.MMi, 1)) "Calorific Value of the fuel gas";
  constant Real l_min = sum(Fuel.Xi_mole[i]*Fuel.nue_min[i] for i in 1:size(Fuel.MMi, 1))/0.21;
  constant Real L_st = l_min*0.02885/MM "Stoichiometric air consumption";

  record NaturalGasTypeAachen
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
        fuelType="TypeAachen",
        isGasoline = true,
        Xi_mole={0.0089,0.9255,0,0.045,0.0063,0.0019,0.0004,0.0001,0.0119});
  end NaturalGasTypeAachen;
end NaturalGasMixture_TypeAachen;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package NaturalGasMixture_TypeH
  "Simple natural gas mixture (type H) for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="NaturalGasMixtureTypeH",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=NaturalGasTypeH() "Needed natural gas data for calculations"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;
  constant MolarMass MM = sum(Fuel.Xi_mole[i]*Fuel.MMi[i] for i in 1:size(Fuel.MMi, 1)) "Molar mass of natural gas type from its composition";
  constant MassFraction massFractions_Gas[:] = Modelica.Media.Interfaces.PartialMixtureMedium.moleToMassFractions(Fuel.Xi_mole, Fuel.MMi);
  constant SpecificEnergy H_U = sum(massFractions_Gas[i]*Fuel.H_Ui[i] for i in 1:size(Fuel.MMi, 1)) "Calorific Value of the fuel gas";
  constant Real l_min = sum(Fuel.Xi_mole[i]*Fuel.nue_min[i] for i in 1:size(Fuel.MMi, 1))/0.21;
  constant Real L_st = l_min*0.02885/MM "Stoichiometric air consumption";

  record NaturalGasTypeH
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
        fuelType="TypeH",
        isGasoline = true,
        Xi_mole={0.007,0.854,0,0.08,0.029,0.01,0,0,
          0.02});
  end NaturalGasTypeH;
end NaturalGasMixture_TypeH;


within AixLib.DataBase.CHP.ModularCHPEngineMedia;
package NaturalGasMixture_TypeL
  "Simple natural gas mixture (type L) for CHP-engine combustion"

  extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa(
    mediumName="NaturalGasMixtureTypeL",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.CH4,
        Modelica.Media.IdealGases.Common.SingleGasesData.C2H4,Modelica.Media.IdealGases.Common.SingleGasesData.C2H6,
        Modelica.Media.IdealGases.Common.SingleGasesData.C3H8,Modelica.Media.IdealGases.Common.SingleGasesData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C5H12_n_pentane,
        Modelica.Media.IdealGases.Common.SingleGasesData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.SingleGasesData.CO2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.CH4,
        Modelica.Media.IdealGases.Common.FluidData.C2H4,Modelica.Media.IdealGases.Common.FluidData.C2H6,
        Modelica.Media.IdealGases.Common.FluidData.C3H8,Modelica.Media.IdealGases.Common.FluidData.C4H10_n_butane,
        Modelica.Media.IdealGases.Common.FluidData.C5H12_n_pentane,Modelica.Media.IdealGases.Common.FluidData.C6H14_n_hexane,
        Modelica.Media.IdealGases.Common.FluidData.CO2},
    substanceNames={"Nitrogen","Methane","Ethene","Ethane","Propane",
        "n-Butane","n-Pentane","n-Hexane","Carbondioxide"});

  constant
    AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord
    Fuel=NaturalGasTypeL() "Needed natural gas data for calculations"

   import Modelica.Units.SI.*;

  constant Boolean isGas = Fuel.isGasoline "True = Gasoline fuel, False = Liquid fuel";
  constant MoleFraction moleFractions_Gas[:] = Fuel.Xi_mole;
  constant MolarMass MM = sum(Fuel.Xi_mole[i]*Fuel.MMi[i] for i in 1:size(Fuel.MMi, 1)) "Molar mass of natural gas type from its composition";
  constant MassFraction massFractions_Gas[:] = Modelica.Media.Interfaces.PartialMixtureMedium.moleToMassFractions(Fuel.Xi_mole, Fuel.MMi);
  constant SpecificEnergy H_U = sum(massFractions_Gas[i]*Fuel.H_Ui[i] for i in 1:size(Fuel.MMi, 1)) "Calorific Value of the fuel gas";
  constant Real l_min = sum(Fuel.Xi_mole[i]*Fuel.nue_min[i] for i in 1:size(Fuel.MMi, 1))/0.21;
  constant Real L_st = l_min*0.02885/MM "Stoichiometric air consumption";

  record NaturalGasTypeL
    extends AixLib.DataBase.CHP.ModularCHPEngineMedia.CombustionEngineFuelDataBaseRecord(
        fuelType="TypeL",
        isGasoline = true,
        Xi_mole={0.126,0.82,0,0.033,0.006,0.003,0,0,
          0.012});
  end NaturalGasTypeL;
end NaturalGasMixture_TypeL;


within AixLib.DataBase;
package Media "Package that provides records describing media properties"
  extends Modelica.Icons.Package;
end Media;


within AixLib.DataBase.Media;
package Refrigerants "Package that provides records describing properties of different refrigerants"
  extends Modelica.Icons.Package;
end Refrigerants;


Base data definition for fitting coefficients of thermodynamic state
  properties. This record is a base data definition for fitting coefficients of the
  thermodynamic state properties depending on two independent state
  variables. These thermodynamic state properties are given as fitted
  formulas in order to reduce the overall computing time of the
  refrigerant model. Therefore, the fitting approach is based on
  \"Fast_Propane\" model developed by Sangi et al..

within AixLib.DataBase.Media.Refrigerants;
record ThermodynamicStatePropertiesBaseDataDefinition
  "Base data definition for fitting coefficients of thermodynamic state
  properties"
  extends Modelica.Icons.Record;

  parameter String name
  "Short description of the record"

  parameter Integer T_phNt[:]
  "Polynomial order for p (SC) | Polynomial order for h (SC) |
   Total number of terms (SC) | Polynomial order for p (SH) |
   Polynomial order for h (SH) | Total number of terms (SH)"
  parameter Real Tl_phA[:]
  "Coefficients a for supercooled regime"
  parameter Real Tl_phB[:]
  "Coefficients b for supercooled regime"
  parameter Real Tl_phC[:]
  "Coefficients c for supercooled regime"
  parameter Real Tl_phD[:]
  "Coefficient d for supercooled regime"
  parameter Real Tv_phA[:]
  "Coefficients a for superheated regime"
  parameter Real Tv_phB[:]
  "Coefficients b for superheated regime"
  parameter Real Tv_phC[:]
  "Coefficients c for superheated regime"
  parameter Real Tv_phD[:]
  "Coefficient d for superheated regime"
  parameter Real T_phIO[:]
  "Mean SC p | Std SC p | Mean SC h | Std SC h | Mean SC T | Std SC T |
   Mean SH p | Std SH p | Mean SH h | Std SH h | Mean SH T | Std SH T"

  parameter Integer T_psNt[:]
  "Polynomial order for p (SC) | Polynomial order for s (SC) |
   Total number of terms (SC) | Polynomial order for p (SH) |
   Polynomial order for s (SH) | Total number of terms (SH)"
  parameter Real Tl_psA[:]
  "Coefficients a for supercooled regime"
  parameter Real Tl_psB[:]
  "Coefficients b for supercooled regime"
  parameter Real Tl_psC[:]
  "Coefficients c for supercooled regime"
  parameter Real Tl_psD[:]
  "Coefficient d for supercooled regime"
  parameter Real Tv_psA[:]
  "Coefficients a for superheated regime"
  parameter Real Tv_psB[:]
  "Coefficients b for superheated regime"
  parameter Real Tv_psC[:]
  "Coefficients c for superheated regime"
  parameter Real Tv_psD[:]
  "Coefficient d for superheated regime"
  parameter Real T_psIO[:]
  "Mean SC p | Std SC p | Mean SC s | Std SC s | Mean SC T | Std SC T |
   Mean SH p | Std SH p | Mean SH s | Std SH s | Mean SH T | Std SH T"

  parameter Integer d_pTNt[:]
  "Polynomial order for p (SC) | Polynomial order for T (SC) |
   Total number of terms (SC) | Polynomial order for p (SH) |
   Polynomial order for T (SH) | Total number of terms (SH)"
  parameter Real dl_pTA[:]
  "Coefficients a for supercooled regime"
  parameter Real dl_pTB[:]
  "Coefficients b for supercooled regime"
  parameter Real dl_pTC[:]
  "Coefficients c for supercooled regime"
  parameter Real dl_pTD[:]
  "Coefficient d for supercooled regime"
  parameter Real dv_pTA[:]
  "Coefficients a for superheated regime"
  parameter Real dv_pTB[:]
  "Coefficients b for superheated regime"
  parameter Real dv_pTC[:]
  "Coefficients c for superheated regime"
  parameter Real dv_pTD[:]
  "Coefficient d for superheated regime"
  parameter Real d_pTIO[:]
  "Mean SC p | Std SC p | Mean SC T | Std SC T | Mean SC d | Std SC d |
   Mean SH p | Std SH p | Mean SH T | Std SH T | Mean SH d | Std SH d"
end ThermodynamicStatePropertiesBaseDataDefinition;


Record with fitting coefficients calculated for first implementation. In this record, fitting coefficients are provided for thermodynamic
  properties at bubble and dew line. For detailed information of these
  thermodynamic properties as well as the fitting coefficients in
  general, please checkout
  AixLib.DataBase.Media.Refrigerants.BubbleDewStatePropertiesBaseDataDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants.
  For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord.


Record with fitting coefficients calculated for first implementation. In this record, fitting coefficients are provided for the Helmholtz
  equation of state (EoS). For detailed information of the EoS as well
  as the fitting coefficients, please checkout
  AixLib.DataBase.Media.Refrigerants.HelmholtzEquationOfStateBaseDateDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants.
  For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord.


Package provides records for R134a

within AixLib.DataBase.Media.Refrigerants;
package R134a "Package provides records for R134a"
  extends Modelica.Icons.VariantsPackage;
end R134a;


Record with fitting coefficients calculated for first implementation. In this record, fitting coefficients are provided for thermodynamic
  properties calculated from two independent state variables. For
  detailed information of these thermodynamic properties as well as the
  fitting coefficients, please checkout
  AixLib.DataBase.Media.Refrigerants.ThermodynamicStatePropertiesBaseDataDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants.
  For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord.


Record with fitting coefficients taken from the Fast_Propane model. In this record, fitting coefficients are provided for thermodynamic
  properties at bubble and dew line. For detailed information of these
  thermodynamic properties as well as the fitting coefficients, please
  checkout
  AixLib.DataBase.Media.Refrigerants.BubbleDewStatePropertiesBaseDataDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants.
  For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord.


Record with fitting coefficients taken from the Fast_Propane model. In this record, fitting coefficients are provided for the Helmholtz
  equation of state (EoS). For detailed information of the EoS as well
  as the fitting coefficients, please checkout
  AixLib.DataBase.Media.Refrigerants.HelmholtzEquationOfStateBaseDateDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants.
  For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord.


Package provides records for R290

within AixLib.DataBase.Media.Refrigerants;
package R290 "Package provides records for R290"
  extends Modelica.Icons.VariantsPackage;
end R290;


Record with fitting coefficients taken from the Fast_Propane model. In this record, fitting coefficients are provided for thermodynamic
  properties calculated from two independent state variables. For
  detailed information of these thermodynamic properties as well as the
  fitting coefficients, please checkout
  AixLib.DataBase.Media.Refrigerants.ThermodynamicStatePropertiesBaseDataDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants
  . For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord
  .


Record with fitting coefficients calculated for first implementation. In this record, fitting coefficients are provided for thermodynamic
  properties at bubble and dew line. For detailed information of these
  thermodynamic properties as well as the fitting coefficients, please
  checkout
  AixLib.DataBase.Media.Refrigerants.BubbleDewStatePropertiesBaseDataDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants
  . For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord
  .


Record with fitting coefficients calculated for first implementation. In this record, fitting coefficients are provided for the Helmholtz
  equation of state (EoS). For detailed information of the EoS as well
  as the fitting coefficients, please checkout
  AixLib.DataBase.Media.Refrigerants.HelmholtzEquationOfStateBaseDateDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants
  . For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord
  .


Package provides records for R410a

within AixLib.DataBase.Media.Refrigerants;
package R410a "Package provides records for R410a"
  extends Modelica.Icons.VariantsPackage;
end R410a;


Record with fitting coefficients calculated for first implementation. In this record, fitting coefficients are provided for thermodynamic
  properties calculated from two independent state variables. For
  detailed information of these thermodynamic properties as well as the
  fitting coefficients, please checkout
  AixLib.DataBase.Media.Refrigerants.ThermodynamicStatePropertiesBaseDataDefinition
  . The fitting coefficients are used in a hybrid refrigerant model
  provided in AixLib.Media.Refrigerants
  . For detailed information, please checkout
  AixLib.Media.Refrigerants.Interfaces.TemplateHybridTwoPhaseMediumRecord
  .


<html>PE-X (Crosslinked polyethylene) pipes
</html>

within AixLib.DataBase.Pipes;
package PE_X
  extends Modelica.Icons.Package;
end PE_X;


Set water temperature of swimming pool.

within AixLib.DataBase.Pools;
record IndoorSwimmingPoolBaseDataDefinition
  extends Modelica.Icons.Record;

  parameter Modelica.Units.SI.Temperature TPool
    "Set water temperature of swimming pool";
  parameter Modelica.Units.SI.Volume VPool "Volume of pool water";
  parameter Modelica.Units.SI.Area APool(min=0)
    "Area of water surface of swimming pool";
  parameter Modelica.Units.SI.Length depthPool(min=0)
    "Average depth of swimming pool";
  parameter Modelica.Units.SI.Volume VSto
    "Usable Volume of water storage, DIN 19643-1";

  // parameter for pool water circulation
  parameter Modelica.Units.SI.VolumeFlowRate V_flow_nominal(min=0.001)
    "Circulation volume flow rate";
  parameter Modelica.Units.SI.VolumeFlowRate V_flow_par(min=0)
    "In the case of partial load: circulation volume flow rate during non-opening hours, DIN 19643-1";
  parameter Boolean use_parLoa=false  "Partial load operation implemented for non opening hours?";
  parameter Modelica.Units.SI.PressureDifference dpHeaExcPool
    "Pressure drop of heat exchanger, should be zero for an indeal heated pool";
  parameter Boolean use_ideHeaExc=true "Include an ideal heat exchanger into the circulation system";
  parameter Real KHeat "Gain of controller for ideal heater";
  parameter Modelica.Units.SI.Time timeHea "Time constant of Integrator block for ideal heater";
  parameter Real QMaxHeat "Upper limit of output for ideal heater";
  parameter Real QMinHeat "Lower limit of output for ideal heater";

  // parameter for evaporation
  parameter Real betaInUse(unit="m/s") "Water transfer coefficient during opening hours if pool is used, VDI 2089";
  parameter Boolean use_poolCov=false "Pool covered during non opening hours";

  // parameter for fresh water
  parameter Boolean use_watRec= false "Recycled water used for refilling pool water?";
  parameter Real x_rec(min=0) "Percentage of refilling water provided by recycled  pool water, DIN 19643-1: <= 0,8";
  parameter Modelica.Units.SI.MassFlowRate m_flow_out(min=0.0001)
    "Waterexchange due to people in the pool, DIN 19643-1";
  parameter Boolean use_HRS=false "Is a heat recovery system physically integrated?";
  parameter Modelica.Units.SI.Efficiency etaHRS
    "Effieciency of heat recovery system";

 // Wave mode
  parameter Boolean use_wavPool=false "Is there a wave machine installed?";
  parameter Modelica.Units.SI.Length heiWav "Height of generated wave";
  parameter Modelica.Units.SI.Length widWav
    "Width of generated wave/ width of wave machineoutlet";
  parameter Modelica.Units.SI.Time timeWavPul_start
    "Start time of first wave cycle";
  parameter Modelica.Units.SI.Time perWavPul "Time of cycling period";
  parameter Real widWavPul "Fraction of time of wave generation within cycling period";

 // Pool Walls
  parameter Modelica.Units.SI.Area AWalInt "Area of pool walls which is connected to inner rooms (inner pool walls)";
  parameter Modelica.Units.SI.Area AWalExt "Area of pool walls which is connected to the ground (pool wall with earth contact)";
  parameter Modelica.Units.SI.Area AFloInt "Area of pool floors which is connected to inner rooms (inner pool floor)";
  parameter Modelica.Units.SI.Area AFloExt "Area of pool floors which is connected to teh ground (pool floor with earth contact)";
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hConWatHor "Mean value for the heat transfer coefficient of free convection on horizontal pool floors";
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hConWatVer "Mean value for the heat transfer coefficient of free convection on vertical pool walls";
end IndoorSwimmingPoolBaseDataDefinition;


within AixLib.DataBase;
package Profiles "Profiles for ventilation, set temperatures, internal gains"
  extends Modelica.Icons.Package;
end Profiles;


within AixLib.DataBase;
package Pumps "Base definition and parameter set for pumps"
  extends Modelica.Icons.Package;
end Pumps;


within AixLib.DataBase.Pumps;
package PumpPolynomialBased "Configuration data for pump model in Fluid.Movers.PumpPolynomialBased package"
end PumpPolynomialBased;


Definition of pump data.

within AixLib.DataBase.Pumps.PumpPolynomialBased;
record PumpBaseRecord "Definition of pump data"
  extends Modelica.Icons.Record;
  // *****************************************************
  // pumpTableFlowHeadCharacteristicRecord (paramFlowHead)
  // *****************************************************
  parameter Real[:, :] maxMinHeight=[
    -1, 16, 1;
     0, 16, 1;
     5, 12, 0.75;
    10, 0.5, 0.5]
      "maximum and minimum boundaries of pump (Q [m3/h], Hmax [m], Hmin [m])";
  parameter Modelica.Units.NonSI.AngularVelocity_rpm[:,:] maxMinSpeedCurves=[-1,
      nMax,nMin; 0,nMax,nMin; 5,0.5*nMax,nMin; 10,nMin,nMin] "maximum and minimum boundaries of pump speed
     (Q [m3/h], nMax [rev/min], nMin [rev/min])";
  parameter Modelica.Units.NonSI.AngularVelocity_rpm nMin=0
    "minimum pump speed";
  parameter Modelica.Units.NonSI.AngularVelocity_rpm nMax=0
    "maximum pump speed";

  // *****************************************************
  // Coefficients for headFlowRpm function (HeadFlowRpmCharacteristic)
  // *****************************************************
  parameter Real[:, :] cHQN=[
    0, 0, 0;
    0, 0, 0;
    0, 0, 0]
      "coefficients for H = f(Q,n) =
    sum_ij(cHQN[i,j] * Q^i * N^j)";

  // *****************************************************
  // Coefficients for powerCharacteristic function
  // *****************************************************
  parameter Real[:, :] cPQN=[
    0, 0, 0;
    0, 0, 0;
    0, 0, 0]
      "coefficients for P = f(Q,H) = sum_ij(cPQN[i,j] * Q^i * N^j)
    Wilo coefficients:
    c4,  c5,  c6,  c7,  c8;
     0,   0,  c1,   0,   0;
     0,  c2,   0,   0,   0;
    c3,   0,   0,   0,   0";

  // *****************************************************
  // Reference data from measurements
  // *****************************************************
  parameter Real[:, 5] referenceDataQHPN=[
    0, 0, 0, 0, 0;
    0, 0, 0, 0, 0;
    0, 0, 0, 0, 0]
      "Table with measurement and calculated data for reference.
    1. Q in m3/h,
    2. H in m,
    3. P in W,
    4. N in rev/min (power limited pump speed),
    5. N in rev/min (set point for pump speed)";
end PumpBaseRecord;


within AixLib.DataBase.Pumps.PumpPolynomialBased;
package Examples "Contains tests to check the parameters of the records."
extends Modelica.Icons.ExamplesPackage;

end Examples;


Testing the max and min height curves from that table.. This test can be used to display the maximum and minimum pump curves
  as defined in the maxMinHeight parameter matrix.

within AixLib.DataBase.Pumps.PumpPolynomialBased.Examples;
model testMaxMinHeightTable
  "Testing the max and min height curves from that table."
  extends Modelica.Icons.Example;
  parameter AixLib.DataBase.Pumps.PumpPolynomialBased.PumpBaseRecord param=
      AixLib.DataBase.Pumps.PumpPolynomialBased.Pump_DN30_H1_12_V13()
    "select the parameter record that you want to check here";
  parameter Real maxQ(unit="m3/h", displayUnit="m3/h") = param.maxMinHeight[
    size(param.maxMinHeight, 1), 1];
  Modelica.Blocks.Sources.Ramp Q(
    height=maxQ,
    duration=1,
    offset=0,
    startTime=0) "volume flow rate"
  Modelica.Blocks.Interfaces.RealOutput HmaxCurve
  Modelica.Blocks.Interfaces.RealOutput HminCurve
  Modelica.Blocks.Tables.CombiTable1Dv maxMinTable(
    columns={2,3},
    tableName="NoName",
    tableOnFile=false,
    table=param.maxMinHeight)
    "Outputs static head (H). Maximum, minimum and freely selectable pump curve"
initial equation
  assert(
    (sum(abs(param.maxMinHeight)) > 0),
    "In a pump model parameter record
    parameter matrix 'maxMinHeight' was all zero.",
    level=AssertionLevel.error);
equation

  connect(Q.y, maxMinTable.u[1])
  connect(maxMinTable.y[1], HmaxCurve)
  connect(maxMinTable.y[2], HminCurve)
  connect(Q.y, maxMinTable.u[2])
end testMaxMinHeightTable;


Calculates pump head from volume flow rate and pump speed.. simulate and plot script

within AixLib.DataBase.Pumps.PumpPolynomialBased.Examples;
model testPumpHeadCalculation
  "Calculates pump head from volume flow rate and pump speed."
  extends Modelica.Icons.Example;

  // **************************************************
  //           Select pump record here:
  //
  parameter AixLib.DataBase.Pumps.PumpPolynomialBased.PumpBaseRecord param=
      AixLib.DataBase.Pumps.PumpPolynomialBased.Pump_DN25_H1_6_V4()
    "new pump record with coefficients.";
  //
  // **************************************************

  function headFlowSpeedFuncNew =
      AixLib.Fluid.Movers.PumpsPolynomialBased.BaseClasses.polynomial2D
    "polynomial evaluator using new aproach with coefficient matrix";

  function headFlowSpeedFuncNewABC =
      AixLib.Fluid.Movers.PumpsPolynomialBased.BaseClasses.polynomialABC
    "polynomial evaluator using new aproach with coefficient matrix";

  parameter Real maxQ(unit="m3/h", displayUnit="m3/h") = param.maxMinHeight[
    size(param.maxMinHeight, 1), 1];

  Modelica.Blocks.Sources.TimeTable speedTable(table=[
    0.00, param.nMin + (param.nMax - param.nMin)*0;
    0.99, param.nMin + (param.nMax - param.nMin)*0;
    1.00, param.nMin + (param.nMax - param.nMin)*0.25;
    1.99, param.nMin + (param.nMax - param.nMin)*0.25;
    2.00, param.nMin + (param.nMax - param.nMin)*0.5;
    2.99, param.nMin + (param.nMax - param.nMin)*0.5;
    3.00, param.nMin + (param.nMax - param.nMin)*0.75;
    3.99, param.nMin + (param.nMax - param.nMin)*0.75;
    4.00, param.nMin + (param.nMax - param.nMin)*1.0;
    4.99, param.nMin + (param.nMax - param.nMin)*1.0])
    "selects different pump speeds"
  Modelica.Blocks.Sources.TimeTable volumeFlowTable(table=[
    0.0,  0.0;
    0.99, maxQ;
    1,    0.0;
    1.99, maxQ;
    2,    0.0;
    2.99, maxQ;
    3,    0.0;
    3.99, maxQ;
    4,    0.0;
    4.99, maxQ]) "selects different pump speeds"
  Modelica.Blocks.Sources.RealExpression headNew(y=headFlowSpeedFuncNew(
        param.cHQN,
        volumeFlowTable.y,
        speedTable.y)) if sum(abs(param.cHQN)) > 0

  Modelica.Blocks.Sources.RealExpression headNewABC(y=headFlowSpeedFuncNewABC(
        {param.cHQN[3,1], param.cHQN[2,2], param.cHQN[1,3]},
        volumeFlowTable.y,
        speedTable.y)) if sum(abs({param.cHQN[3,1], param.cHQN[2,2],
          param.cHQN[1,3]})) > 0
end testPumpHeadCalculation;


Calculates pump power from volume flow rate and pump speed.. simulate and plot script

within AixLib.DataBase.Pumps.PumpPolynomialBased.Examples;
model testPumpPowerCalculation
  "Calculates pump power from volume flow rate and pump speed."
  extends Modelica.Icons.Example;

  // **************************************************
  //           Select pump record here:
  //
  parameter AixLib.DataBase.Pumps.PumpPolynomialBased.PumpBaseRecord param=
      AixLib.DataBase.Pumps.PumpPolynomialBased.Pump_DN25_H1_6_V4()
    "new pump record with coefficients.";
  //
  // **************************************************

  function headFlowSpeedFuncNew =
      AixLib.Fluid.Movers.PumpsPolynomialBased.BaseClasses.polynomial2D
    "polynomial evaluator using new aproach with coefficient matrix";

  parameter Real maxQ(unit="m3/h", displayUnit="m3/h") = param.maxMinHeight[
    size(param.maxMinHeight, 1), 1];

  Modelica.Blocks.Sources.TimeTable speedTable(table=[
    0.00, param.nMin + (param.nMax - param.nMin)*0;
    0.99, param.nMin + (param.nMax - param.nMin)*0;
    1.00, param.nMin + (param.nMax - param.nMin)*0.25;
    1.99, param.nMin + (param.nMax - param.nMin)*0.25;
    2.00, param.nMin + (param.nMax - param.nMin)*0.5;
    2.99, param.nMin + (param.nMax - param.nMin)*0.5;
    3.00, param.nMin + (param.nMax - param.nMin)*0.75;
    3.99, param.nMin + (param.nMax - param.nMin)*0.75;
    4.00, param.nMin + (param.nMax - param.nMin)*1.0;
    4.99, param.nMin + (param.nMax - param.nMin)*1.0])
    "selects different pump speeds"
  Modelica.Blocks.Sources.TimeTable volumeFlowTable(table=[
    0.0,  0.0;
    0.99, maxQ;
    1,    0.0;
    1.99, maxQ;
    2,    0.0;
    2.99, maxQ;
    3,    0.0;
    3.99, maxQ;
    4,    0.0;
    4.99, maxQ]) "selects different pump speeds"

  Modelica.Blocks.Sources.RealExpression power(y=headFlowSpeedFuncNew(
        param.cPQN,
        volumeFlowTable.y,
        speedTable.y)) if sum(abs(param.cPQN)) > 0
end testPumpPowerCalculation;


test the functions to calculate pump speed from volume flow rate and pump head.. simulate and plot script

within AixLib.DataBase.Pumps.PumpPolynomialBased.Examples;
model testPumpSpeedCalculation
  "test the functions to calculate pump speed from volume flow rate and pump head."
  extends Modelica.Icons.Example;

  // **************************************************
  //           Select pump record here:
  //
  parameter AixLib.DataBase.Pumps.PumpPolynomialBased.PumpBaseRecord param=
      AixLib.DataBase.Pumps.PumpPolynomialBased.Pump_DN25_H1_6_V4()
    "New pump record with coefficients.";
  //
  // **************************************************

  function speedFlowHeadFunc =
      AixLib.Fluid.Movers.PumpsPolynomialBased.BaseClasses.polynomial2D
    "polynomial evaluator using new aproach with coefficient matrix";
  function speedFlowHeadFuncABC =
      AixLib.Fluid.Movers.PumpsPolynomialBased.BaseClasses.polynomialABCinverse
    "polynomial evaluator using new aproach with coefficient matrix";

  parameter Real maxQ(unit="m3/h", displayUnit="m3/h") = param.maxMinHeight[
    size(param.maxMinHeight, 1), 1];
  parameter Modelica.Units.SI.Length maxHead=max(param.maxMinHeight[:, 2])
    "maximum static head of the pump";
  parameter Modelica.Units.SI.Length minHead=max(param.maxMinHeight[:, 3])
    "aprox. minimum static head of the pump";

  Modelica.Blocks.Sources.TimeTable headTable(table=[
    0.0,  minHead+(maxHead-minHead)*0.0;
    0.99, minHead+(maxHead-minHead)*0.0;
    1,    minHead+(maxHead-minHead)*0.25;
    1.99, minHead+(maxHead-minHead)*0.25;
    2,    minHead+(maxHead-minHead)*0.5;
    2.99, minHead+(maxHead-minHead)*0.5;
    3,    minHead+(maxHead-minHead)*0.75;
    3.99, minHead+(maxHead-minHead)*0.75;
    4,    minHead+(maxHead-minHead)*1.0;
    4.99, minHead+(maxHead-minHead)*1.0])
    "selects different pump speeds"
  Modelica.Blocks.Sources.TimeTable volumeFlowTable(table=[
    0.0,  0.0;
    0.99, maxQ;
    1,    0;
    1.99, maxQ;
    2,    0;
    2.99, maxQ;
    3,    0;
    3.99, maxQ;
    4,    0;
    4.99, maxQ]) "selects different volume flows"
//   Modelica.Blocks.Sources.RealExpression speed(y=speedFlowHeadFunc(
//         param.cNQH,
//         volumeFlowTable.y,
//         headTable.y)) if sum(abs(param.cNQH)) > 0
//
  Modelica.Blocks.Sources.RealExpression speedABC(y=speedFlowHeadFuncABC(
        {param.cHQN[3,1], param.cHQN[2,2], param.cHQN[1,3]},
        volumeFlowTable.y,
        headTable.y)) if sum(abs({param.cHQN[3,1], param.cHQN[2,2],
          param.cHQN[1,3]})) > 0
end testPumpSpeedCalculation;


within AixLib.DataBase;
package Radiators "Base record definition of radiators and some ready-to-use parameter sets"
  extends Modelica.Icons.VariantsPackage;

end Radiators;


<html><p>
  Just one Appartmen, in the first floor, the middle antracne, which
  means adiabatic conditions on all walls towards neighbouring rooms,
  with the exception of the staircase.
</p>
</html>

within AixLib.DataBase.Radiators;
package Standard_MFD_WSchV1984_OneAppartment
  extends Modelica.Icons.VariantsPackage;
end Standard_MFD_WSchV1984_OneAppartment;


within AixLib.DataBase;
package SolarThermal "Properties of different solar thermal collectors"
  extends Modelica.Icons.Package;
end SolarThermal;


Outside surfaces of walls

within AixLib.DataBase;
package Surfaces "Outside surfaces of walls"
  extends Modelica.Icons.Package;
end Surfaces;


Roughness coefficents for heat transfer

within AixLib.DataBase.Surfaces;
package RoughnessForHT "Roughness coefficents for heat transfer"
      extends Modelica.Icons.Package;
end RoughnessForHT;


within AixLib.DataBase;
package ThermalZones "Package with records for reduced order thermal zone models"
  extends Modelica.Icons.VariantsPackage;

end ThermalZones;


within AixLib.DataBase.ThermalZones;
package OfficePassiveHouse "Contains records for an office as passive house"
  extends Modelica.Icons.MaterialPropertiesPackage;

end OfficePassiveHouse;


Database for different types of walls

within AixLib.DataBase;
package Walls "Database for different types of walls"
  extends Modelica.Icons.Package;
end Walls;


Walls records

within AixLib.DataBase.Walls;
package ASHRAE140 "Walls records"

end ASHRAE140;


Collections with multiple wall types

within AixLib.DataBase.Walls;
package Collections "Collections with multiple wall types"
end Collections;


Records describing weather conditions

within AixLib.DataBase;
package Weather "Records describing weather conditions"
  extends Modelica.Icons.Package;
end Weather;


Collection of surface orientation data

within AixLib.DataBase.Weather;
package SurfaceOrientation "Collection of surface orientation data"
  extends Modelica.Icons.Package;
end SurfaceOrientation;


Windows and doors definition package

within AixLib.DataBase;
package WindowsDoors "Windows and doors definition package"
  extends Modelica.Icons.Package;
end WindowsDoors;


Window base definition. Overview

within AixLib.DataBase.WindowsDoors.Simple;
record OWBaseDataDefinition_Simple
  "Window base definition"
  extends Modelica.Icons.Record;
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer Uw
    "Thermal transmission coefficient of whole window: glass + frame";
  parameter Real frameFraction(min=0.0, max=1.0) = 0.2
    "frame fraction from total fenestration area";
  parameter Real g = 0.7 "coefficient of solar energy transmission";
end OWBaseDataDefinition_Simple;


Collection of simple window records

within AixLib.DataBase.WindowsDoors;
package Simple "Collection of simple window records"
  extends Modelica.Icons.Package;

end Simple;


within AixLib;
package Electrical "Package with models for electrical systems"
  extends Modelica.Icons.Package;
end Electrical;


Electrical package user's guide

within AixLib.Electrical;
package UsersGuide "Electrical package user's guide"
  extends Modelica.Icons.Information;
end UsersGuide;


within AixLib.Electrical;
package AC "Package for electrical systems in which the frequency is modeled as quasi-stationary"
  extends Modelica.Icons.Package;

package UsersGuide "User's Guide"
  extends Modelica.Icons.Information;
end UsersGuide;
end AC;


within AixLib.Electrical.AC;
package Interfaces "Package that contains some useful interfaces"
extends Modelica.Icons.InterfacesPackage;
end Interfaces;


One phase AC systems

within AixLib.Electrical.AC;
package OnePhase "One phase AC systems"
extends Modelica.Icons.VariantsPackage;
end OnePhase;


Ground connection

within AixLib.Electrical.AC.OnePhase.Basics;
model Ground "Ground connection"
  extends AixLib.Electrical.Interfaces.Ground(
    redeclare package PhaseSystem = PhaseSystems.OnePhase,
    redeclare Interfaces.Terminal_n terminal);
end Ground;


Package with basic models

within AixLib.Electrical.AC.OnePhase;
package Basics "Package with basic models"
extends Modelica.Icons.BasesPackage;
end Basics;


AC AC converter single phase systems

within AixLib.Electrical.AC.OnePhase.Conversion;
model ACACConverter "AC AC converter single phase systems"
  extends AixLib.Electrical.Icons.RefAngleConversion;
  extends AixLib.Electrical.Interfaces.PartialConversion(
    redeclare package PhaseSystem_p = PhaseSystems.OnePhase,
    redeclare package PhaseSystem_n = PhaseSystems.OnePhase,
    redeclare replaceable Interfaces.Terminal_n terminal_n
      constrainedby Interfaces.Terminal_n(
      i(start = zeros(PhaseSystem_n.n),
      each stateSelect = StateSelect.prefer)),
    redeclare replaceable Interfaces.Terminal_p terminal_p
      constrainedby Interfaces.Terminal_p(
      i(start = zeros(PhaseSystem_p.n),
      each stateSelect = StateSelect.prefer)));
  parameter Real conversionFactor(min = Modelica.Constants.eps)
    "Ratio of QS rms voltage on side 2 / QS rms voltage on side 1";
  parameter Real eta(min=0, max=1)
    "Converter efficiency, pLoss = (1-eta) * Ptr";
  parameter Boolean ground_1 = false
    "If true, connect side 1 of converter to ground"
  parameter Boolean ground_2 = true
    "If true, connect side 2 of converter to ground"
  Modelica.Units.SI.Power LossPower[2] "Loss power";
protected
  Modelica.Units.SI.Power P_p[2]=PhaseSystem_p.phasePowers_vi(terminal_p.v,
      terminal_p.i) "Power transmitted at pin p";
  Modelica.Units.SI.Power P_n[2]=PhaseSystem_n.phasePowers_vi(terminal_n.v,
      terminal_n.i) "Power transmitted at pin n";
equation

  // Ideal transformation
  terminal_p.v = conversionFactor*terminal_n.v;

  // Power loss term
  terminal_p.i[1] = terminal_n.i[1]/conversionFactor*
    AixLib.Utilities.Math.Functions.spliceFunction(eta-2, 1/(eta-2), P_p[1], deltax=0.1);
  terminal_p.i[2] = terminal_n.i[2]/conversionFactor*
    AixLib.Utilities.Math.Functions.spliceFunction(eta-2, 1/(eta-2), P_p[1], deltax=0.1);
  LossPower = P_p + P_n;

  // The two sides have the same reference angle
  terminal_p.theta = terminal_n.theta;

  if ground_1 then
    Connections.potentialRoot(terminal_n.theta);
  end if;
  if ground_2 then
    Connections.root(terminal_p.theta);
  end if;
end ACACConverter;


within AixLib.Electrical.AC.OnePhase.Conversion;
model ACACTransformer "AC AC transformer simplified equivalent circuit"
  extends AixLib.Electrical.Icons.RefAngleConversion;
  extends AixLib.Electrical.Interfaces.PartialConversion(
    redeclare package PhaseSystem_p = PhaseSystems.OnePhase,
    redeclare package PhaseSystem_n = PhaseSystems.OnePhase,
    redeclare replaceable Interfaces.Terminal_n terminal_n
      constrainedby Interfaces.Terminal_n(
      i(start = zeros(PhaseSystem_n.n),
      each stateSelect = StateSelect.prefer)),
    redeclare replaceable Interfaces.Terminal_p terminal_p
      constrainedby Interfaces.Terminal_p(
      i(start = zeros(PhaseSystem_p.n),
      each stateSelect = StateSelect.prefer)));
  parameter Modelica.Units.SI.Voltage VHigh
    "Rms voltage on side 1 of the transformer (primary side)";
  parameter Modelica.Units.SI.Voltage VLow
    "Rms voltage on side 2 of the transformer (secondary side)";
  parameter Modelica.Units.SI.ApparentPower VABase
    "Nominal power of the transformer";
  parameter Real XoverR
    "Ratio between the complex and real components of the impedance (XL/R)";
  parameter Real Zperc "Short circuit impedance";
  parameter Boolean ground_1 = false
    "If true, connect side 1 of converter to ground"
  parameter Boolean ground_2 = true
    "If true, connect side 2 of converter to ground"
  parameter Modelica.Units.SI.Angle phi_1=0
    "Angle of the voltage side 1 at initialization"
  parameter Modelica.Units.SI.Angle phi_2=phi_1
    "Angle of the voltage side 2 at initialization"
  Modelica.Units.SI.Efficiency eta "Efficiency";
  Modelica.Units.SI.Power PLoss[2] "Loss power";

  Modelica.Units.SI.Voltage V1[2](start=PhaseSystem_n.phaseVoltages(VHigh,
        phi_1)) "Voltage at the winding - primary side";
  Modelica.Units.SI.Voltage V2[2](start=PhaseSystem_p.phaseVoltages(VLow, phi_2))
    "Voltage at the winding - secondary side";
protected
  Real N = VHigh/VLow "Winding ratio";
  Modelica.Units.SI.Current IHigh=VABase/VHigh
    "Nominal current on primary side";
  Modelica.Units.SI.Current ILow=VABase/VLow
    "Nominal current on secondary side";
  Modelica.Units.SI.Current IscHigh=IHigh/Zperc
    "Short circuit current on primary side";
  Modelica.Units.SI.Current IscLow=ILow/Zperc
    "Short circuit current on secondary side";
  Modelica.Units.SI.Impedance Zp=VHigh/IscHigh
    "Impedance of the primary side (module)";
  Modelica.Units.SI.Impedance Z1[2]={Zp*cos(atan(XoverR)),Zp*sin(atan(XoverR))}
    "Impedance of the primary side of the transformer";
  Modelica.Units.SI.Impedance Zs=VLow/IscLow
    "Impedance of the secondary side (module)";
  Modelica.Units.SI.Impedance Z2[2]={Zs*cos(atan(XoverR)),Zs*sin(atan(XoverR))}
    "Impedance of the secondary side of the transformer";
  Modelica.Units.SI.Power P_p[2]=PhaseSystem_p.phasePowers_vi(terminal_p.v,
      terminal_p.i) "Power transmitted at pin p (secondary)";
  Modelica.Units.SI.Power P_n[2]=PhaseSystem_n.phasePowers_vi(terminal_n.v,
      terminal_n.i) "Power transmitted at pin n (primary)";
  Modelica.Units.SI.Power S_p=Modelica.Fluid.Utilities.regRoot(P_p[1]^2 + P_p[2]
      ^2, delta=0.1) "Apparent power at terminal p";
  Modelica.Units.SI.Power S_n=Modelica.Fluid.Utilities.regRoot(P_n[1]^2 + P_n[2]
      ^2, delta=0.1) "Apparent power at terminal n";

equation
  // Efficiency
  eta = AixLib.Utilities.Math.Functions.smoothMin(
        x1=
        Modelica.Fluid.Utilities.regRoot(P_p[1]^2 + P_p[2]^2, delta=0.01)/
        Modelica.Fluid.Utilities.regRoot(P_n[1]^2 + P_n[2]^2 + 1e-6, delta=0.01),
        x2=
        Modelica.Fluid.Utilities.regRoot(P_n[1]^2 + P_n[2]^2, delta=0.01)/
        Modelica.Fluid.Utilities.regRoot(P_p[1]^2 + P_p[2]^2 + 1e-6, delta=0.01),
        deltaX = 0.01);

  // Ideal transformation
  V2 = V1/N;
  terminal_p.i[1] + terminal_n.i[1]*N = 0;
  terminal_p.i[2] + terminal_n.i[2]*N = 0;

  // Losses due to the impedance
  terminal_n.v = V1 + AixLib.Electrical.PhaseSystems.OnePhase.product(
    terminal_n.i, Z1);
  V2 = terminal_p.v;

  // Loss of power
  PLoss = P_p + P_n;

  // The two sides have the same reference angle
  terminal_p.theta = terminal_n.theta;

  if ground_1 then
    Connections.potentialRoot(terminal_n.theta);
  end if;
  if ground_2 then
    Connections.root(terminal_p.theta);
  end if;
end ACACTransformer;


within AixLib.Electrical.AC.OnePhase.Conversion;
model ACACTransformerFull "AC AC transformer with detailed equivalent circuit"
  extends AixLib.Electrical.Icons.RefAngleConversion;
  extends AixLib.Electrical.Interfaces.PartialConversion(
    redeclare package PhaseSystem_p = PhaseSystems.OnePhase,
    redeclare package PhaseSystem_n = PhaseSystems.OnePhase,
    redeclare replaceable Interfaces.Terminal_n terminal_n
      constrainedby Interfaces.Terminal_n(
      i(start = zeros(PhaseSystem_n.n),
      each stateSelect = StateSelect.prefer)),
    redeclare replaceable Interfaces.Terminal_p terminal_p
      constrainedby Interfaces.Terminal_p(
      i(start = zeros(PhaseSystem_p.n),
      each stateSelect = StateSelect.prefer)));
  parameter Modelica.Units.SI.Voltage VHigh
    "RMS voltage on side 1 of the transformer (primary side)";
  parameter Modelica.Units.SI.Voltage VLow
    "RMS voltage on side 2 of the transformer (secondary side)";
  parameter Modelica.Units.SI.ApparentPower VABase
    "Nominal power of the transformer";
  parameter Modelica.Units.SI.Frequency f(start=60) "Nominal frequency";
  parameter AixLib.Electrical.Types.PerUnit R1(min=0)
    "Resistance on side 1 of the transformer (pu)";
  parameter AixLib.Electrical.Types.PerUnit L1(min=0)
    "Inductance on side 1 of the transformer (pu)";
  parameter AixLib.Electrical.Types.PerUnit R2(min=0)
    "Resistance on side 2 of the transformer (pu)";
  parameter AixLib.Electrical.Types.PerUnit L2(min=0)
    "Inductance on side 2 of the transformer (pu)";
  parameter Boolean magEffects = false
    "If true, introduce magnetization effects"
  parameter AixLib.Electrical.Types.PerUnit Rm(min=0)
    "Magnetization resistance (pu)"
  parameter AixLib.Electrical.Types.PerUnit Lm(min=0)
    "Magnetization inductance (pu)"
  parameter Boolean ground_1 = false "Connect side 1 of converter to ground"
  parameter Boolean ground_2 = true "Connect side 2 of converter to ground"
  parameter Modelica.Units.SI.Angle phi_1=0
    "Angle of the voltage side 1 at initialization"
  parameter Modelica.Units.SI.Angle phi_2=phi_1
    "Angle of the voltage side 2 at initialization"
  Modelica.Units.SI.Efficiency eta "Efficiency";
  Modelica.Units.SI.Power PLoss[2] "Loss power";

  Modelica.Units.SI.Voltage V1[2](start=PhaseSystem_n.phaseVoltages(VHigh,
        phi_1)) "Voltage at the winding - primary side";
  Modelica.Units.SI.Voltage V2[2](start=PhaseSystem_n.phaseVoltages(VLow, phi_2))
    "Voltage at the winding - secondary side";
protected
  parameter Modelica.Units.SI.AngularVelocity omega_n=2*Modelica.Constants.pi*f;
  parameter Real N = VHigh/VLow "Winding ratio";
  parameter Modelica.Units.SI.Resistance RBaseHigh=VHigh^2/VABase
    "Base impedance of the primary side";
  parameter Modelica.Units.SI.Resistance RBaseLow=VLow^2/VABase
    "Base impedance of the secondary side";
  Modelica.Units.SI.Impedance Z1[2]={RBaseHigh*R1,omega*L1*RBaseHigh/omega_n}
    "Impedance of the primary side of the transformer";
  Modelica.Units.SI.Impedance Z2[2]={RBaseLow*R2,omega*L2*RBaseLow/omega_n}
    "Impedance of the secondary side of the transformer";
  Modelica.Units.SI.Impedance Zrm[2]={RBaseHigh*Rm,0}
    "Magnetization impedance - resistance";
  Modelica.Units.SI.Impedance Zlm[2]={0,omega*Lm*RBaseHigh/omega_n}
    "Magnetization impedance - impedence";
  Modelica.Units.SI.Power P_p[2]=PhaseSystem_p.phasePowers_vi(terminal_p.v,
      terminal_p.i) "Power transmitted at pin p (secondary)";
  Modelica.Units.SI.Power P_n[2]=PhaseSystem_n.phasePowers_vi(terminal_n.v,
      terminal_n.i) "Power transmitted at pin n (primary)";
  Modelica.Units.SI.Power S_p=Modelica.Fluid.Utilities.regRoot(P_p[1]^2 + P_p[2]
      ^2, delta=0.1) "Apparent power at terminal p";
  Modelica.Units.SI.Power S_n=Modelica.Fluid.Utilities.regRoot(P_n[1]^2 + P_n[2]
      ^2, delta=0.1) "Apparent power at terminal n";
  Modelica.Units.SI.AngularVelocity omega "Angular velocity";
  Modelica.Units.SI.Current Im[2] "Magnetization current";
  Modelica.Units.SI.Angle theRef "Absolute angle of rotating reference system";
equation
  assert(sqrt(P_p[1]^2 + P_p[2]^2) <= VABase*1.01,
    "The load power of the transformer is higher than VABase");

  // Angular velocity
  theRef = PhaseSystem_p.thetaRef(terminal_p.theta);
  omega = der(theRef);

  // Efficiency
  eta = AixLib.Utilities.Math.Functions.smoothMin(
        x1=
        Modelica.Fluid.Utilities.regRoot(P_p[1]^2 + P_p[2]^2, delta=0.01)/
        Modelica.Fluid.Utilities.regRoot(P_n[1]^2 + P_n[2]^2 + 1e-6, delta=0.01),
        x2=
        Modelica.Fluid.Utilities.regRoot(P_n[1]^2 + P_n[2]^2, delta=0.01)/
        Modelica.Fluid.Utilities.regRoot(P_p[1]^2 + P_p[2]^2 + 1e-6, delta=0.01),
        deltaX = 0.01);

  // Ideal transformation
  V2 = V1/N;
  terminal_p.i[1] + (terminal_n.i[1] - Im[1])*N = 0;
  terminal_p.i[2] + (terminal_n.i[2] - Im[2])*N = 0;

  // Magnetization current
  if magEffects then
    Im = AixLib.Electrical.PhaseSystems.OnePhase.divide(V1, Zrm) +
         AixLib.Electrical.PhaseSystems.OnePhase.divide(V1, Zlm);
  else
    Im = zeros(2);
  end if;

  // Losses due to the impedance - primary side
  terminal_n.v = V1 + AixLib.Electrical.PhaseSystems.OnePhase.product(
    terminal_n.i, Z1);

  // Losses due to the impedance - secondary side
  terminal_p.v = V2 + AixLib.Electrical.PhaseSystems.OnePhase.product(
    terminal_p.i, Z2);

  // Loss of power
  PLoss = P_p + P_n;

  // The two sides have the same reference angle
  terminal_p.theta = terminal_n.theta;

  if ground_1 then
    Connections.potentialRoot(terminal_n.theta);
  end if;
  if ground_2 then
    Connections.root(terminal_p.theta);
  end if;
end ACACTransformerFull;


AC DC converter

within AixLib.Electrical.AC.OnePhase.Conversion;
model ACDCConverter "AC DC converter"
  extends AixLib.Electrical.Interfaces.PartialConversion(
    redeclare package PhaseSystem_p = PhaseSystems.TwoConductor,
    redeclare package PhaseSystem_n = PhaseSystems.OnePhase,
    redeclare replaceable Interfaces.Terminal_n terminal_n
      constrainedby Interfaces.Terminal_n(
        i(start = zeros(PhaseSystem_n.n),
        each stateSelect = StateSelect.prefer)),
    redeclare DC.Interfaces.Terminal_p terminal_p(
        i(start = zeros(PhaseSystem_p.n),
        each stateSelect = StateSelect.prefer)));
  parameter Real conversionFactor(min = Modelica.Constants.eps)
    "Ratio of DC voltage / AC RMS voltage";
  parameter Real eta(min=0, max=1)
    "Converter efficiency, pLoss = (1-eta) * Ptr";
  Modelica.Units.SI.Power PLoss "Loss power";
  parameter Boolean ground_AC = false "Connect AC side of converter to ground"
  parameter Boolean ground_DC = true "Connect DC side of converter to ground"
protected
  PhaseSystem_p.Current i_dc "DC current";
  PhaseSystem_p.Voltage v_dc "DC voltage";
  Modelica.Units.SI.Power P_p[2]=PhaseSystem_p.phasePowers_vi(terminal_p.v,
      terminal_p.i) "Power transmitted at pin p (secondary)";
  Modelica.Units.SI.Power P_n[2](each start=0) = PhaseSystem_n.phasePowers_vi(
    terminal_n.v, terminal_n.i) "Power transmitted at pin n (primary)";
equation
  //voltage relation
  v_p = v_n*conversionFactor;

  // Power losses
  PLoss = (1-eta)*
    AixLib.Utilities.Math.Functions.spliceFunction(P_p[1], P_n[1], i_p, deltax=0.1);
  P_n + P_p = {PLoss, 0};

  if ground_AC then
    Connections.potentialRoot(terminal_n.theta);
  end if;

  if ground_DC then
    v_dc = 0;
    Connections.root(terminal_p.theta);
  else
    i_dc = 0;
    Connections.potentialRoot(terminal_p.theta);
  end if;

  v_dc = terminal_p.v[2];
  sum(terminal_p.i) + i_dc = 0;
end ACDCConverter;