within AixLib.Media.Refrigerants.Interfaces;
partial package PartialHybridTwoPhaseMediumRecord
  "Base class for two phase medium using a hybrid approach with records"
  extends AixLib.Media.Refrigerants.Interfaces.PartialHybridTwoPhaseMediumFormula;

  /*Provide records that contain the fitting coefficients for all fitted
    formula (e.g. Helmholtz equation of state). These records must be
    redeclared within the template to provide the coefficients.
  */
  replaceable record EoS
    "Record that contains fitting coefficients of the Helmholtz EoS"
    extends AixLib.DataBase.Media.Refrigerants.HelmholtzEquationOfStateBaseDateDefinition;
  end EoS;

  replaceable record BDSP
    "Record that contains fitting coefficients of the state properties at
    bubble and dew lines"
    extends AixLib.DataBase.Media.Refrigerants.BubbleDewStatePropertiesBaseDataDefinition;
  end BDSP;

  replaceable record TSP
    "Record that contains fitting coefficients of the state properties
    calculated with two independent state properties"
    extends AixLib.DataBase.Media.Refrigerants.ThermodynamicStatePropertiesBaseDataDefinition;
  end TSP;
  /*Provide Helmholtz equations of state (EoS). These EoS must be fitted to
    different refrigerants. However, the structure will not change and,
    therefore, the coefficients, which are obtained during the fitting
    procedure, are provided by a record. These coefficients have to be
    provided within the template.
    Just change if needed.
  */
  redeclare function extends f_Idg
    "Dimensionless Helmholtz energy (Ideal gas contribution f_Idg)"
  protected
    EoS cf;

  algorithm
    f_Idg := log(delta);
    if not cf.f_IdgNl == 0 then
      for k in 1:cf.f_IdgNl loop
        f_Idg := f_Idg + cf.f_IdgL1[k]*log(tau^cf.f_IdgL2[k]);
      end for;
    end if;
    if not cf.f_IdgNp == 0 then
      for k in 1:cf.f_IdgNp loop
        f_Idg := f_Idg + cf.f_IdgP1[k]*tau^cf.f_IdgP2[k];
      end for;
    end if;
    if not cf.f_IdgNe == 0 then
      for k in 1:cf.f_IdgNe loop
        f_Idg := f_Idg + cf.f_IdgE1[k]*log(1-exp(-cf.f_IdgE2[k]*tau));
      end for;
    end if;
  end f_Idg;

  redeclare function extends f_Res
    "Dimensionless Helmholtz energy (Residual part f_Res)"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
          f_Res := f_Res + cf.f_ResP1[k]*delta^cf.f_ResP2[k]*tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        f_Res := f_Res + cf.f_ResB1[k]*delta^cf.f_ResB2[k]*tau^cf.f_ResB3[k]*
                 exp(-delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        f_Res := f_Res + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^cf.f_ResG3[k]*
                 exp(-cf.f_ResG4[k]*(delta - cf.f_ResG5[k])^2 -
                 cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2);
      end for;
    end if;
  end f_Res;

  redeclare function extends t_fIdg_t
    "Short form for tau*(dalpha_0/dtau)_delta=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_IdgNl == 0 then
      for k in 1:cf.f_IdgNl loop
        t_fIdg_t := t_fIdg_t + cf.f_IdgL1[k]*cf.f_IdgL2[k];
      end for;
    end if;
    if not cf.f_IdgNp == 0 then
      for k in 1:cf.f_IdgNp loop
        t_fIdg_t := t_fIdg_t + cf.f_IdgP1[k]*cf.f_IdgP2[k]*tau^cf.f_IdgP2[k];
      end for;
    end if;
    if not cf.f_IdgNe == 0 then
      for k in 1:cf.f_IdgNe loop
        t_fIdg_t := t_fIdg_t + tau*cf.f_IdgE1[k]*cf.f_IdgE2[k]/
                    (exp(cf.f_IdgE2[k]*tau)-1);
      end for;
    end if;
  end t_fIdg_t;

  redeclare function extends tt_fIdg_tt
    "Short form for tau*tau*(ddalpha_0/(dtau*dtau))_delta=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_IdgNl == 0 then
      for k in 1:cf.f_IdgNl loop
        tt_fIdg_tt := tt_fIdg_tt - cf.f_IdgL1[k]*cf.f_IdgL2[k];
      end for;
    end if;
    if not cf.f_IdgNp == 0 then
      for k in 1:cf.f_IdgNp loop
        tt_fIdg_tt := tt_fIdg_tt + cf.f_IdgP1[k]*cf.f_IdgP2[k]*
                      (cf.f_IdgP2[k]-1)*tau^cf.f_IdgP2[k];
      end for;
    end if;
    if not cf.f_IdgNe == 0 then
      for k in 1:cf.f_IdgNe loop
        tt_fIdg_tt := tt_fIdg_tt - tau^2*cf.f_IdgE1[k]*cf.f_IdgE2[k]^2*
                      exp(-cf.f_IdgE2[k]*tau)/((1-exp(-cf.f_IdgE2[k]*tau))^2);
      end for;
    end if;
  end tt_fIdg_tt;

  redeclare function extends t_fRes_t
    "Short form for tau*(dalpha_r/dtau)_delta=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        t_fRes_t := t_fRes_t + cf.f_ResP1[k]*cf.f_ResP3[k]*delta^cf.f_ResP2[k]*
                    tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        t_fRes_t := t_fRes_t + cf.f_ResB1[k]*cf.f_ResB3[k]*delta^cf.f_ResB2[k]*
                    tau^cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        t_fRes_t := t_fRes_t + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                    cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta - cf.f_ResG5[k])^2 -
                    cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2)*(cf.f_ResG3[k]-2*
                    cf.f_ResG6[k]*tau*(tau-cf.f_ResG7[k]));
      end for;
    end if;
  end t_fRes_t;

  redeclare function extends tt_fRes_tt
    "Short form for tau*tau*(ddalpha_r/(dtau*dtau))_delta=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        tt_fRes_tt := tt_fRes_tt + cf.f_ResP1[k]*cf.f_ResP3[k]*(cf.f_ResP3[k]-1)*
                      delta^cf.f_ResP2[k]*tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        tt_fRes_tt := tt_fRes_tt + cf.f_ResB1[k]*cf.f_ResB3[k]*(cf.f_ResB3[k]-1)*
                      delta^cf.f_ResB2[k]*tau^cf.f_ResB3[k]*
                      exp(-delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        tt_fRes_tt := tt_fRes_tt + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                      cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta - cf.f_ResG5[k])^
                      2 - cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2)*
                      ((cf.f_ResG3[k]-2*cf.f_ResG6[k]*tau*(tau-cf.f_ResG7[k]))^
                      2-cf.f_ResG3[k]-2*
          cf.f_ResG6[k]*tau^2);
      end for;
    end if;
  end tt_fRes_tt;

  redeclare function extends d_fRes_d
    "Short form for delta*(dalpha_r/(ddelta))_tau=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        d_fRes_d := d_fRes_d + cf.f_ResP1[k]*cf.f_ResP2[k]*delta^cf.f_ResP2[k]*
                    tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        d_fRes_d := d_fRes_d + cf.f_ResB1[k]*delta^cf.f_ResB2[k]*tau^
                    cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k])*(cf.f_ResB2[k]-
                    cf.f_ResB4[k]*delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        d_fRes_d := d_fRes_d + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                    cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta - cf.f_ResG5[k])^2 -
                    cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2)*(cf.f_ResG2[k]-2*
                    cf.f_ResG4[k]*delta*(delta-cf.f_ResG5[k]));
      end for;
    end if;
  end d_fRes_d;

  redeclare function extends dd_fRes_dd
    "Short form for delta*delta(ddalpha_r/(ddelta*delta))_tau=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        dd_fRes_dd := dd_fRes_dd + cf.f_ResP1[k]*cf.f_ResP2[k]*(cf.f_ResP2[k]-1)*
                      delta^cf.f_ResP2[k]*tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        dd_fRes_dd := dd_fRes_dd + cf.f_ResB1[k]*delta^cf.f_ResB2[k]*tau^
                      cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k])*((cf.f_ResB2[k]-1-
                      cf.f_ResB4[k]*delta^cf.f_ResB4[k])*(cf.f_ResB2[k]-
                      cf.f_ResB4[k]*delta^cf.f_ResB4[k])-cf.f_ResB4[k]^2*
                      delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        dd_fRes_dd := dd_fRes_dd + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                      cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta - cf.f_ResG5[k])^
                      2 - cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2)*((cf.f_ResG2[k]-
                      2*cf.f_ResG4[k]*delta*(delta-cf.f_ResG5[k]))^2-
                      cf.f_ResG2[k]-2*cf.f_ResG4[k]*delta^2);
      end for;
    end if;
  end dd_fRes_dd;

  redeclare function extends td_fRes_td
    "Short form for tau*delta*(ddalpha_r/(dtau*ddelta))"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        td_fRes_td := td_fRes_td + cf.f_ResP1[k]*cf.f_ResP2[k]*cf.f_ResP3[k]*
                      delta^cf.f_ResP2[k]*tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        td_fRes_td := td_fRes_td + cf.f_ResB1[k]*cf.f_ResB3[k]*delta^
                      cf.f_ResB2[k]*tau^cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k])*
                      (cf.f_ResB2[k]-cf.f_ResB4[k]*delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        td_fRes_td := td_fRes_td + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                      cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta - cf.f_ResG5[k])^
                      2 - cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2)*(cf.f_ResG3[k]-
                      2*cf.f_ResG6[k]*tau*(tau-cf.f_ResG7[k]))*(cf.f_ResG2[k]-2*
                      cf.f_ResG4[k]*delta*(delta-cf.f_ResG5[k]));
      end for;
    end if;
  end td_fRes_td;

  redeclare function extends ttt_fIdg_ttt
    "Short form for tau*tau*tau*(dddalpha_0/(dtau*dtau*dtau))_delta=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_IdgNl == 0 then
      for k in 1:cf.f_IdgNl loop
        ttt_fIdg_ttt := ttt_fIdg_ttt + 2*cf.f_IdgL1[k]*cf.f_IdgL2[k];
      end for;
    end if;
    if not cf.f_IdgNp == 0 then
      for k in 1:cf.f_IdgNp loop
        ttt_fIdg_ttt := ttt_fIdg_ttt + cf.f_IdgP1[k]*cf.f_IdgP2[k]*
                        (cf.f_IdgP2[k]-1)*(cf.f_IdgP2[k]-2)*tau^cf.f_IdgP2[k];
      end for;
    end if;
    if not cf.f_IdgNe == 0 then
      for k in 1:cf.f_IdgNe loop
        ttt_fIdg_ttt := ttt_fIdg_ttt + tau^3*cf.f_IdgE1[k]*cf.f_IdgE2[k]^3*
                        exp(cf.f_IdgE2[k]*tau)*(exp(cf.f_IdgE2[k]*tau)+1)/
                        ((exp(cf.f_IdgE2[k]*tau)-1)^3);
      end for;
    end if;
  end ttt_fIdg_ttt;

  redeclare function extends ttt_fRes_ttt
    "Short form for tau*tau*tau*(dddalpha_r/(dtau*dtau*dtau))_delta=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        ttt_fRes_ttt := ttt_fRes_ttt + cf.f_ResP1[k]*cf.f_ResP3[k]*
                        (cf.f_ResP3[k]-1)*(cf.f_ResP3[k]-2)*delta^cf.f_ResP2[k]*
                        tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        ttt_fRes_ttt := ttt_fRes_ttt + cf.f_ResB1[k]*cf.f_ResB3[k]*
                        (cf.f_ResB3[k]-1)*(cf.f_ResB3[k]-2)*delta^cf.f_ResB2[k]*
                        tau^cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNG loop
        ttt_fRes_ttt := ttt_fRes_ttt - cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                        cf.f_ResG3[k]*(8*cf.f_ResG6[k]^3*tau^6-24*cf.f_ResG6[k]^
                        3*cf.f_ResG7[k]*tau^5+12*cf.f_ResG6[k]^2*(2*
                        cf.f_ResG6[k]*cf.f_ResG7[k]^2-cf.f_ResG3[k]-1)*tau^4-4*
                        cf.f_ResG6[k]^2*cf.f_ResG7[k]*(2*cf.f_ResG6[k]*
                        cf.f_ResG7[k]^2-6*cf.f_ResG3[k]-3)*tau^3-6*cf.f_ResG3[k]*
                        cf.f_ResG6[k]*(2*cf.f_ResG6[k]*cf.f_ResG7[k]^2-
                        cf.f_ResG3[k])*tau^2-6*(cf.f_ResG3[k]-1)*cf.f_ResG3[k]*
                        cf.f_ResG6[k]*cf.f_ResG7[k]*tau-cf.f_ResG3[k]^3+3*
                        cf.f_ResG3[k]^2-2*cf.f_ResG3[k])*exp(-cf.f_ResG6[k]*
                        (tau-cf.f_ResG7[k])^2-cf.f_ResG4[k]*(delta-
                        cf.f_ResG5[k])^2);
      end for;
    end if;
  end ttt_fRes_ttt;

  redeclare function extends ddd_fRes_ddd
    "Short form for delta*delta*delta*
  (dddalpha_r/(ddelta*ddelta*ddelta))_tau=const"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        ddd_fRes_ddd := ddd_fRes_ddd + cf.f_ResP1[k]*cf.f_ResP2[k]*
                        (cf.f_ResP2[k]-1)*(cf.f_ResP2[k]-2)*delta^cf.f_ResP2[k]*
                        tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        ddd_fRes_ddd := ddd_fRes_ddd - cf.f_ResB1[k]*delta^cf.f_ResB2[k]*tau^
                        cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k])*(cf.f_ResB4[k]*
                        delta^cf.f_ResB4[k]*(cf.f_ResB4[k]*(delta^cf.f_ResB4[k]*
                        (cf.f_ResB4[k]*(delta^cf.f_ResB4[k]-3)-3*cf.f_ResB2[k]+3)+
                        cf.f_ResB4[k]+3*cf.f_ResB2[k]-3)+3*cf.f_ResB2[k]^2-6*
                        cf.f_ResB2[k]+2)-(cf.f_ResB2[k]-2)*(cf.f_ResB2[k]-1)*
                        cf.f_ResB2[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        ddd_fRes_ddd := ddd_fRes_ddd - cf.f_ResG1[k]*tau^cf.f_ResG3[k]*delta^
                        cf.f_ResG2[k]*(8*cf.f_ResG4[k]^3*delta^6-24*cf.f_ResG4[k]^
                        3*cf.f_ResG5[k]*delta^5+12*cf.f_ResG4[k]^2*(2*
                        cf.f_ResG4[k]*cf.f_ResG5[k]^2-cf.f_ResG2[k]-1)*delta^4-4*
                        cf.f_ResG4[k]^2*cf.f_ResG5[k]*(2*cf.f_ResG4[k]*
                        cf.f_ResG5[k]^2-6*cf.f_ResG2[k]-3)*delta^3-6*
                        cf.f_ResG2[k]*cf.f_ResG4[k]*(2*cf.f_ResG4[k]*
                        cf.f_ResG5[k]^2-cf.f_ResG2[k])*delta^2-6*(cf.f_ResG2[k]-1)
                        *cf.f_ResG2[k]*cf.f_ResG4[k]*cf.f_ResG5[k]*delta-
                        cf.f_ResG2[k]^3+3*cf.f_ResG2[k]^2-2*cf.f_ResG2[k])*
                        exp(-cf.f_ResG4[k]*(delta-cf.f_ResG5[k])^2-cf.f_ResG6[k]*
                        (tau-cf.f_ResG7[k])^2);
      end for;
    end if;
  end ddd_fRes_ddd;

  redeclare function extends tdd_fRes_tdd
    "Short form for tau*delta*delta*(dddalpha_r/(dtau*ddelta*ddelta))"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        tdd_fRes_tdd := tdd_fRes_tdd + cf.f_ResP1[k]*cf.f_ResP2[k]*(
                        cf.f_ResP2[k]-1)*cf.f_ResP3[k]*delta^cf.f_ResP2[k]*tau^
                        cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        tdd_fRes_tdd := tdd_fRes_tdd + cf.f_ResB1[k]*cf.f_ResB3[k]*delta^
                        cf.f_ResB2[k]*tau^cf.f_ResB3[k]*exp(-delta^cf.f_ResB4[k])*
                        (cf.f_ResB4[k]*delta^cf.f_ResB4[k]*(cf.f_ResB4[k]*(delta^
                        cf.f_ResB4[k]-1)-2*cf.f_ResB2[k]+1)+cf.f_ResB2[k]*
                        (cf.f_ResB2[k]-1));
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        tdd_fRes_tdd := tdd_fRes_tdd + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                        cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta-cf.f_ResG5[k])^
                        2 - cf.f_ResG6[k]*(tau - cf.f_ResG7[k])^2)*
                        (cf.f_ResG3[k]-2*cf.f_ResG6[k]*tau*(tau-cf.f_ResG7[k]))*
                        ((cf.f_ResG2[k]-2*cf.f_ResG4[k]*delta*(delta-
                        cf.f_ResG5[k]))^2-cf.f_ResG2[k]-2*cf.f_ResG4[k]*delta^2);
      end for;
    end if;
  end tdd_fRes_tdd;

  redeclare function extends ttd_fRes_ttd
    "Short form for tau*tau*delta*(dddalpha_r/(dtau*dtau*ddelta))"
  protected
    EoS cf;

  algorithm
    if not cf.f_ResNp == 0 then
      for k in 1:cf.f_ResNp loop
        ttd_fRes_ttd := ttd_fRes_ttd + cf.f_ResP1[k]*cf.f_ResP2[k]*cf.f_ResP3[k]*
                        (cf.f_ResP3[k]-1)*delta^cf.f_ResP2[k]*tau^cf.f_ResP3[k];
      end for;
    end if;
    if not cf.f_ResNb == 0 then
      for k in 1:cf.f_ResNb loop
        ttd_fRes_ttd := ttd_fRes_ttd + cf.f_ResB1[k]*cf.f_ResB3[k]*(
                        cf.f_ResB3[k]-1)*delta^cf.f_ResB2[k]*tau^cf.f_ResB3[k]*
                        exp(-delta^cf.f_ResB4[k])*(cf.f_ResB2[k]-cf.f_ResB4[k]*
                        delta^cf.f_ResB4[k]);
      end for;
    end if;
    if not cf.f_ResNG == 0 then
      for k in 1:cf.f_ResNG loop
        ttd_fRes_ttd := ttd_fRes_ttd + cf.f_ResG1[k]*delta^cf.f_ResG2[k]*tau^
                        cf.f_ResG3[k]*exp(-cf.f_ResG4[k]*(delta-cf.f_ResG5[k])^
                        2 - cf.f_ResG6[k]*(tau-cf.f_ResG7[k])^2)*(cf.f_ResG2[k]-
                        2*cf.f_ResG4[k]*delta*(delta-cf.f_ResG5[k]))*((
                        cf.f_ResG3[k]-2*cf.f_ResG6[k]*tau*(tau-cf.f_ResG7[k]))^
                        2-cf.f_ResG3[k]-2*cf.f_ResG6[k]*tau^2);
      end for;
    end if;
  end ttd_fRes_ttd;
  /*Provide polynomial functions for saturation properties. These functions are
    fitted to external data (e.g. data extracted from RefProp or FluidProp).
    Currently, just one fitting approach is implemented. Therefore, the
    coefficients, which are obtained during the fitting procedure, are provided
     by records.
  */
  redeclare function extends saturationPressure
    "Saturation pressure of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real OM = (1 - T/fluidConstants[1].criticalTemperature);
    Real p_1 = 0;

  algorithm
    if T>fluidConstants[1].criticalTemperature then
     p := fluidConstants[1].criticalPressure;
    elseif T<fluidConstants[1].triplePointTemperature then
     p := fluidConstants[1].triplePointPressure;
    else
      for k in 1:cf.psat_Nt loop
        p_1 :=p_1 + cf.psat_N[k]*OM^cf.psat_E[k];
      end for;
      p := fluidConstants[1].criticalPressure *
           exp(fluidConstants[1].criticalTemperature/T * p_1);
    end if;
  end saturationPressure;

  redeclare function extends saturationTemperature
    "Saturation temperature of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real T_1 = 0;
    Real x = 0;

  algorithm
    x := (p - cf.Tsat_IO[1])/cf.Tsat_IO[2];
    for k in 1:cf.Tsat_Nt-1 loop
      T_1 := T_1 + cf.Tsat_N[k]*x^(cf.Tsat_Nt - k);
    end for;
    T_1 := T_1 + cf.Tsat_N[cf.Tsat_Nt];
    T := T_1*cf.Tsat_IO[4] + cf.Tsat_IO[3];
  end saturationTemperature;

  redeclare function extends bubbleDensity
    "Boiling curve specific density of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real dl_1 = 0;
    Real x = 0;

  algorithm
    x := (sat.Tsat - cf.dl_IO[1])/cf.dl_IO[2];
    for k in 1:cf.dl_Nt-1 loop
      dl_1 := dl_1 + cf.dl_N[k]*x^(cf.dl_Nt - k);
    end for;
    dl_1 := dl_1 + cf.dl_N[cf.dl_Nt];
    dl := dl_1*cf.dl_IO[4] + cf.dl_IO[3];
  end bubbleDensity;

  redeclare function extends dewDensity
    "Dew curve specific density of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real dv_1 = 0;
    Real x = 0;

  algorithm
    x := (sat.Tsat - cf.dv_IO[1])/cf.dv_IO[2];
    for k in 1:cf.dv_Nt-1 loop
      dv_1 := dv_1 + cf.dv_N[k]*x^(cf.dv_Nt - k);
    end for;
    dv_1 := dv_1 + cf.dv_N[cf.dv_Nt];
    dv := dv_1*cf.dv_IO[4] + cf.dv_IO[3];
  end dewDensity;

  redeclare function extends bubbleEnthalpy
    "Boiling curve specific enthalpy of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real hl_1 = 0;
    Real x = 0;

  algorithm
    x := (sat.psat - cf.hl_IO[1])/cf.hl_IO[2];
    for k in 1:cf.hl_Nt-1 loop
      hl_1 := hl_1 + cf.hl_N[k]*x^(cf.hl_Nt - k);
    end for;
    hl_1 := hl_1 + cf.hl_N[cf.hl_Nt];
    hl := hl_1*cf.hl_IO[4] + cf.hl_IO[3];
  end bubbleEnthalpy;

  redeclare function extends dewEnthalpy
    "Dew curve specific enthalpy of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real hv_1 = 0;
    Real x = 0;

  algorithm
    x := (sat.psat - cf.hv_IO[1])/cf.hv_IO[2];
    for k in 1:cf.hv_Nt-1 loop
      hv_1 := hv_1 + cf.hv_N[k]*x^(cf.hv_Nt - k);
    end for;
    hv_1 := hv_1 + cf.hv_N[cf.hv_Nt];
    hv := hv_1*cf.hv_IO[4] + cf.hv_IO[3];
  end dewEnthalpy;

  redeclare function extends bubbleEntropy
    "Boiling curve specific entropy of refrigerant (Ancillary equation)"
  protected
    BDSP cf;
    Real sl_1 = 0;
    Real x = 0;

  algorithm
    x := (sat.psat - cf.sl_IO[1])/cf.sl_IO[2];
    for k in 1:cf.sl_Nt-1 loop
      sl_1 := sl_1 + cf.sl_N[k]*x^(cf.sl_Nt - k);
    end for;
    sl_1 := sl_1 + cf.sl_N[cf.sl_Nt];
    sl := sl_1*cf.sl_IO[4] + cf.sl_IO[3];
  end bubbleEntropy;

  redeclare function extends dewEntropy
    "Dew curve specific entropy of propane (Ancillary equation)"
  protected
    BDSP cf;
    Real sv_1 = 0;
    Real x = 0;

  algorithm
    x := (sat.psat - cf.sv_IO[1])/cf.sv_IO[2];
    for k in 1:cf.sv_Nt-1 loop
      sv_1 := sv_1 + cf.sv_N[k]*x^(cf.sv_Nt - k);
    end for;
    sv_1 := sv_1 + cf.sv_N[cf.sv_Nt];
    sv := sv_1*cf.sv_IO[4] + cf.sv_IO[3];
  end dewEntropy;
  /*Provide functions to calculate thermodynamic properties depending on the
    independent variables. Moreover, these functions may depend on the
    Helmholtz EoS. Just change these functions if needed.
  */
  redeclare function temperature_ph
    "Calculates temperature as function of pressure and specific enthalpy"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEnthalpy h "Specific enthalpy";
    input FixedPhase phase=0
      "2 for two-phase, 1 for one-phase, 0 if not known";
    output Temperature T "Temperature";

  protected
    TSP cf;
    SmoothTransition st;

    SpecificEnthalpy dh = st.T_ph;
    SpecificEnthalpy h_dew = 0;
    SpecificEnthalpy h_bubble = 0;

    Real x1 = 0;
    Real y1 = 0;
    Real T1 = 0;
    Real x2 = 0;
    Real y2 = 0;
    Real T2 = 0;
    Integer count = 0;

  algorithm
    h_dew := dewEnthalpy(sat = setSat_p(p=p));
    h_bubble := bubbleEnthalpy(sat = setSat_p(p=p));

    if h<h_bubble-dh then
      x1 := (p-cf.T_phIO[1])/cf.T_phIO[2];
      y1 := (h-cf.T_phIO[3])/cf.T_phIO[4];
      T1 := cf.Tl_phD[1];
      for i in 1:cf.T_phNt[1] loop
        T1 := T1 + cf.Tl_phA[i]*x1^i;
      end for;
      for j in 1:cf.T_phNt[2] loop
        T1 := T1 + cf.Tl_phB[j]*y1^j;
      end for;
      if cf.T_phNt[1] >= cf.T_phNt[2] then
        for i in 1:cf.T_phNt[1]-1 loop
          for j in 1:min(i,cf.T_phNt[2]) loop
            count :=count + 1;
            T1 := T1 + cf.Tl_phC[count]*
                  x1^(cf.T_phNt[1] - i)*y1^j;
          end for;
        end for;
      else
        for j in 1:cf.T_phNt[2]-1 loop
          for i in 1:min(j,cf.T_phNt[1]) loop
            count :=count + 1;
            T1 := T1 + cf.Tl_phC[count]*
                  y1^(cf.T_phNt[2] - j)*x1^i;
          end for;
        end for;
      end if;
      T := T1*cf.T_phIO[6]+cf.T_phIO[5];
    elseif h>h_dew+dh then
       x2 := (p-cf.T_phIO[7])/cf.T_phIO[8];
       y2 := (h-cf.T_phIO[9])/cf.T_phIO[10];
       T2 := cf.Tv_phD[1];
       for i in 1:cf.T_phNt[4] loop
         T2:= T2 + cf.Tv_phA[i]*x2^i;
       end for;
       for j in 1:cf.T_phNt[5] loop
         T2:= T2 + cf.Tv_phB[j]*y2^j;
       end for;
       if cf.T_phNt[4] >= cf.T_phNt[5] then
         for i in 1:cf.T_phNt[4]-1 loop
           for j in 1:min(i, cf.T_phNt[5]) loop
             count :=count + 1;
             T2 := T2 + cf.Tv_phC[count]*
                   x2^(cf.T_phNt[4] - i)*y2^j;
           end for;
         end for;
       else
         for j in 1:cf.T_phNt[5]-1 loop
           for i in 1:min(j,cf.T_phNt[4]) loop
             count :=count + 1;
             T2 := T2 + cf.Tv_phC[count]*
                   y2^(cf.T_phNt[5] - j)*x2^i;
           end for;
         end for;
       end if;
       T := T2*cf.T_phIO[12]+cf.T_phIO[11];
    else
      if h<h_bubble then
        x1 := (p-cf.T_phIO[1])/cf.T_phIO[2];
        y1 := (h-cf.T_phIO[3])/cf.T_phIO[4];
        T1 := cf.Tl_phD[1];
        for i in 1:cf.T_phNt[1] loop
          T1 := T1 + cf.Tl_phA[i]*x1^i;
        end for;
        for j in 1:cf.T_phNt[2] loop
          T1 := T1 + cf.Tl_phB[j]*y1^j;
        end for;
        if cf.T_phNt[1] >= cf.T_phNt[2] then
          for i in 1:cf.T_phNt[1]-1 loop
            for j in 1:min(i, cf.T_phNt[2]) loop
              count :=count + 1;
              T1 := T1 + cf.Tl_phC[count]*
                    x1^(cf.T_phNt[1] - i)*y1^j;
            end for;
          end for;
        else
          for j in 1:cf.T_phNt[2]-1 loop
            for i in 1:min(j,cf.T_phNt[1]) loop
              count :=count + 1;
              T1 := T1 + cf.Tl_phC[count]*
                    y1^(cf.T_phNt[2] - j)*x1^i;
            end for;
          end for;
        end if;
        T1 := T1*cf.T_phIO[6]+cf.T_phIO[5];
        T := saturationTemperature(p)*(1 - (h_bubble - h)/dh) +
          T1*(h_bubble - h)/dh;
      elseif h>h_dew then
        x2 := (p-cf.T_phIO[7])/cf.T_phIO[8];
        y2 := (h-cf.T_phIO[9])/cf.T_phIO[10];
        T2 := cf.Tv_phD[1];
        for i in 1:cf.T_phNt[4] loop
          T2:= T2 + cf.Tv_phA[i]*x2^i;
        end for;
        for j in 1:cf.T_phNt[5] loop
          T2:= T2 + cf.Tv_phB[j]*y2^j;
        end for;
        if cf.T_phNt[4] >= cf.T_phNt[5] then
          for i in 1:cf.T_phNt[4]-1 loop
            for j in 1:min(i, cf.T_phNt[5]) loop
              count :=count + 1;
              T2 := T2 + cf.Tv_phC[count]*
                    x2^(cf.T_phNt[4] - i)*y2^j;
            end for;
          end for;
        else
          for j in 1:cf.T_phNt[5]-1 loop
            for i in 1:min(j,cf.T_phNt[4]) loop
              count :=count + 1;
              T2 := T2 + cf.Tv_phC[count]*
                    y2^(cf.T_phNt[5] - j)*x2^i;
            end for;
          end for;
        end if;
        T2 := T2*cf.T_phIO[12]+cf.T_phIO[11];
        T := saturationTemperature(p)*(1 - (h - h_dew)/dh) +
             T2*(h - h_dew)/dh;
      else
        T := saturationTemperature(p);
      end if;
    end if;
  end temperature_ph;

  redeclare function temperature_ps
    "Calculates temperature as function of pressure and specific entroy"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEntropy s "Specific entropy";
    input FixedPhase phase = 0
      "2 for two-phase, 1 for one-phase, 0 if not known";
    output Temperature T "Temperature";

  protected
    TSP cf;
    SmoothTransition st;

    SpecificEntropy ds = st.T_ps;
    SpecificEntropy s_dew = 0;
    SpecificEntropy s_bubble = 0;

    Real x1 = 0;
    Real y1 = 0;
    Real T1 = 0;
    Real x2 = 0;
    Real y2 = 0;
    Real T2 = 0;
    Integer count = 0;

  algorithm
    s_dew := dewEntropy(sat = setSat_p(p=p));
    s_bubble := bubbleEntropy(sat = setSat_p(p=p));

    if s<s_bubble-ds then
      x1 := (log(p)-cf.T_psIO[1])/cf.T_psIO[2];
      y1 := (s-cf.T_psIO[3])/cf.T_psIO[4];
      T1 := cf.Tl_psD[1];
      for i in 1:cf.T_psNt[1] loop
        T1:= T1 + cf.Tl_psA[i]*x1^i;
      end for;
      for j in 1:cf.T_psNt[2] loop
        T1:= T1 + cf.Tl_psB[j]*y1^j;
      end for;
      if cf.T_psNt[1] >= cf.T_psNt[2] then
        for i in 1:cf.T_psNt[1]-1 loop
          for j in 1:min(i,cf.T_psNt[2]) loop
            count :=count + 1;
            T1 := T1 + cf.Tl_psC[count]*
                  x1^(cf.T_psNt[1] - i)*y1^j;
          end for;
        end for;
      else
        for j in 1:cf.T_psNt[2]-1 loop
          for i in 1:min(j,cf.T_psNt[1]) loop
            count :=count + 1;
            T1 := T1 + cf.Tl_psC[count]*
                  y1^(cf.T_psNt[2] - j)*x1^i;
          end for;
        end for;
      end if;
      T := T1;
      T := T1*cf.T_psIO[6]+cf.T_psIO[5];
    elseif s>s_dew+ds then
        x2 := (log(p)-cf.T_psIO[7])/cf.T_psIO[8];
        y2 := (s-cf.T_psIO[9])/cf.T_psIO[10];
        T2 := cf.Tv_psD[1];
        for i in 1:cf.T_psNt[4] loop
          T2:= T2 + cf.Tv_psA[i]*x2^i;
        end for;
        for j in 1:cf.T_psNt[5] loop
          T2:= T2 + cf.Tv_psB[j]*y2^j;
        end for;
        if cf.T_psNt[4] >= cf.T_psNt[5] then
          for i in 1:cf.T_psNt[4]-1 loop
            for j in 1:min(i,cf.T_psNt[5]) loop
              count :=count + 1;
              T2 := T2 + cf.Tv_psC[count]*
                    x2^(cf.T_psNt[4] - i)*y2^j;
            end for;
          end for;
        else
          for j in 1:cf.T_psNt[5]-1 loop
            for i in 1:min(j,cf.T_psNt[4]) loop
              count :=count + 1;
              T2 := T2 + cf.Tv_psC[count]*
                    y2^(cf.T_psNt[5] - j)*x2^i;
            end for;
          end for;
        end if;
        T := T2*cf.T_psIO[12]+cf.T_psIO[11];
    else
      if s<s_bubble then
        x1 := (log(p)-cf.T_psIO[1])/cf.T_psIO[2];
        y1 := (s-cf.T_psIO[3])/cf.T_psIO[4];
        T1 := cf.Tl_psD[1];
        for i in 1:cf.T_psNt[1] loop
          T1:= T1 + cf.Tl_psA[i]*x1^i;
        end for;
        for j in 1:cf.T_psNt[2] loop
          T1:= T1 + cf.Tl_psB[j]*y1^j;
        end for;
        if cf.T_psNt[1] >= cf.T_psNt[2] then
          for i in 1:cf.T_psNt[1]-1 loop
            for j in 1:min(i,cf.T_psNt[2]) loop
              count :=count + 1;
              T1 := T1 + cf.Tl_psC[count]*
                    x1^(cf.T_psNt[1] - i)*y1^j;
            end for;
          end for;
        else
          for j in 1:cf.T_psNt[2]-1 loop
            for i in 1:min(j,cf.T_psNt[1]) loop
              count :=count + 1;
              T1 := T1 + cf.Tl_psC[count]*
                    y1^(cf.T_psNt[2] - j)*x1^i;
            end for;
          end for;
        end if;
        T1 := T1*cf.T_psIO[6]+cf.T_psIO[5];
        T := saturationTemperature(p)*(1 - (s_bubble - s)/ds) +
             T1*(s_bubble - s)/ds;
      elseif s>s_dew then
        x2 := (log(p)-cf.T_psIO[7])/cf.T_psIO[8];
        y2 := (s-cf.T_psIO[9])/cf.T_psIO[10];
        T2 := cf.Tv_psD[1];
        for i in 1:cf.T_psNt[4] loop
          T2:= T2 + cf.Tv_psA[i]*x2^i;
        end for;
        for j in 1:cf.T_psNt[5] loop
          T2:= T2 + cf.Tv_psB[j]*y2^j;
        end for;
        if cf.T_psNt[4] >= cf.T_psNt[5] then
          for i in 1:cf.T_psNt[4]-1 loop
            for j in 1:min(i,cf.T_psNt[5]) loop
              count :=count + 1;
              T2 := T2 + cf.Tv_psC[count]*
                    x2^(cf.T_psNt[4] - i)*y2^j;
            end for;
          end for;
        else
          for j in 1:cf.T_psNt[5]-1 loop
            for i in 1:min(j,cf.T_psNt[4]) loop
              count :=count + 1;
              T2 := T2 + cf.Tv_psC[count]*
                    y2^(cf.T_psNt[5] - j)*x2^i;
            end for;
          end for;
        end if;
        T2 := T2*cf.T_psIO[12]+cf.T_psIO[11];
        T := saturationTemperature(p)*(1 - (s - s_dew)/ds) +
             T2*(s - s_dew)/ ds;
      else
        T := saturationTemperature(p);
      end if;
    end if;
  end temperature_ps;

  redeclare function density_pT
    "Computes density as a function of pressure and temperature"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input Temperature T "Temperature";
    input FixedPhase phase = 0
      "2 for two-phase, 1 for one-phase, 0 if not known";
    output Density d "Density";

  protected
    TSP cf;
    SmoothTransition st;

    AbsolutePressure dp = st.d_pT;
    SaturationProperties sat = setSat_T(T=T);

    Real x1 = 0;
    Real y1 = 0;
    Real d1 = 0;
    Real x2 = 0;
    Real y2 = 0;
    Real d2 = 0;
    Integer count = 0;

  algorithm
    if p<sat.psat-dp then
      x1 := (p-cf.d_pTIO[7])/cf.d_pTIO[8];
      y1 := (T-cf.d_pTIO[9])/cf.d_pTIO[10];
      d1 := cf.dv_pTD[1];
      for i in 1:cf.d_pTNt[4] loop
        d1:= d1 + cf.dv_pTA[i]*x1^i;
      end for;
      for j in 1:cf.d_pTNt[5] loop
        d1:= d1 + cf.dv_pTB[j]*y1^j;
      end for;
      if cf.d_pTNt[4] >= cf.d_pTNt[5] then
        for i in 1:cf.d_pTNt[4]-1 loop
          for j in 1:min(i,cf.d_pTNt[5]) loop
            count :=count + 1;
            d1 := d1 + cf.dv_pTC[count]*
                  x1^(cf.d_pTNt[4] - i)*y1^j;
          end for;
        end for;
      else
        for j in 1:cf.d_pTNt[5]-1 loop
          for i in 1:min(j,cf.d_pTNt[4]) loop
            count :=count + 1;
            d1 := d1 + cf.dv_pTC[count]*
                  y1^(cf.d_pTNt[5] - j)*x1^i;
          end for;
        end for;
      end if;
      d := d1*cf.d_pTIO[12]+cf.d_pTIO[11];
    elseif p>sat.psat+dp then
      x2 := (p-cf.d_pTIO[1])/cf.d_pTIO[2];
      y2 := (T-cf.d_pTIO[3])/cf.d_pTIO[4];
      d2 := cf.dl_pTD[1];
      for i in 1:cf.d_pTNt[1] loop
        d2:= d2 + cf.dl_pTA[i]*x2^i;
      end for;
      for j in 1:cf.d_pTNt[2] loop
        d2:= d2 + cf.dl_pTB[j]*y2^j;
      end for;
      if cf.d_pTNt[1] >= cf.d_pTNt[2] then
        for i in 1:cf.d_pTNt[1]-1 loop
          for j in 1:min(i,cf.d_pTNt[2]) loop
            count :=count + 1;
            d2 := d2 + cf.dl_pTC[count]*
                  x2^(cf.d_pTNt[1] - i)*y2^j;
          end for;
        end for;
      else
        for j in 1:cf.d_pTNt[2]-1 loop
          for i in 1:min(j,cf.d_pTNt[1]) loop
            count :=count + 1;
            d2 := d2 + cf.dl_pTC[count]*
                  y2^(cf.d_pTNt[2] - j)*x2^i;
          end for;
        end for;
      end if;
      d := d2*cf.d_pTIO[6]+cf.d_pTIO[5];
    else
      if p<sat.psat then
        x1 := (p-cf.d_pTIO[7])/cf.d_pTIO[8];
        y1 := (T-cf.d_pTIO[9])/cf.d_pTIO[10];
        d1 := cf.dv_pTD[1];
        for i in 1:cf.d_pTNt[4] loop
          d1:= d1 + cf.dv_pTA[i]*x1^i;
        end for;
        for j in 1:cf.d_pTNt[5] loop
          d1:= d1 + cf.dv_pTB[j]*y1^j;
        end for;
        if cf.d_pTNt[4] >= cf.d_pTNt[5] then
          for i in 1:cf.d_pTNt[4]-1 loop
            for j in 1:min(i,cf.d_pTNt[5]) loop
              count :=count + 1;
              d1 := d1 + cf.dv_pTC[count]*
                    x1^(cf.d_pTNt[4] - i)*y1^j;
            end for;
          end for;
        else
          for j in 1:cf.d_pTNt[5]-1 loop
            for i in 1:min(j,cf.d_pTNt[4]) loop
              count :=count + 1;
              d1 := d1 + cf.dv_pTC[count]*
                    y1^(cf.d_pTNt[5] - j)*x1^i;
            end for;
          end for;
        end if;
        d1 := d1*cf.d_pTIO[12]+cf.d_pTIO[11];
        d := bubbleDensity(sat)*(1 -(sat.psat - p)/dp) + d1*(sat.psat - p)/dp;
      elseif p>=sat.psat then
        x2 := (p-cf.d_pTIO[1])/cf.d_pTIO[2];
        y2 := (T-cf.d_pTIO[3])/cf.d_pTIO[4];
        d2 := cf.dl_pTD[1];
        for i in 1:cf.d_pTNt[1] loop
          d2:= d2 + cf.dl_pTA[i]*x2^i;
        end for;
        for j in 1:cf.d_pTNt[2] loop
          d2:= d2 + cf.dl_pTB[j]*y2^j;
        end for;
        if cf.d_pTNt[1] >= cf.d_pTNt[2] then
          for i in 1:cf.d_pTNt[1]-1 loop
            for j in 1:min(i,cf.d_pTNt[2]) loop
              count :=count + 1;
              d2 := d2 + cf.dl_pTC[count]*
                    x2^(cf.d_pTNt[1] - i)*y2^j;
            end for;
          end for;
        else
          for j in 1:cf.d_pTNt[2]-1 loop
            for i in 1:min(j,cf.d_pTNt[1]) loop
              count :=count + 1;
              d2 := d2 + cf.dl_pTC[count]*
                    y2^(cf.d_pTNt[2] - j)*x2^i;
            end for;
          end for;
        end if;
        d2 := d2*cf.d_pTIO[6]+cf.d_pTIO[5];
        d := dewDensity(sat)*(1 -(p - sat.psat)/dp) + d2*(p - sat.psat)/dp;
      end if;
    end if;
  end density_pT;
end PartialHybridTwoPhaseMediumRecord;


within AixLib.Media.Refrigerants.Interfaces;
partial package TemplateHybridTwoPhaseMediumFormula
  "Template for media models using a hybrid approach without records"

  /*Provide basic definitions of the refrigerant. Therefore, fill constants
    or parameters and may add new constants or parameters if needed. Moreover,
    provide references within the information of the package.
  */
  constant Modelica.Media.Interfaces.PartialTwoPhaseMedium.FluidConstants[1]
    refrigerantConstants(
      each chemicalFormula = "CXHY",
      each structureFormula = "CXHY",
      each casRegistryNumber = "xx-xx-x",
      each iupacName = "name",
      each molarMass = 1,
      each criticalTemperature = 1,
      each criticalPressure = 1,
      each criticalMolarVolume = 1,
      each normalBoilingPoint = 1,
      each triplePointTemperature = 1,
      each meltingPoint = 1,
      each acentricFactor = 1,
      each triplePointPressure = 1,
      each dipoleMoment = 1,
      each hasCriticalData=true)
    "Thermodynamic constants for refrigerant";

  /*Provide basic information about the refrigerant. These basic information
    are the refrigerant name as well as the valid refrigerant limits in terms
    of specific enthalpy, density, absolute pressure and temperature.
  */
  extends
    AixLib.Media.Refrigerants.Interfaces.PartialHybridTwoPhaseMediumFormula(
    mediumName="Name",
    substanceNames={"Name"},
    singleState=false,
    SpecificEnthalpy(
      start=1.0e5,
      nominal=1.0e5,
      min=50e3,
      max=1000e3),
    Density(
      start=500,
      nominal=500,
      min=0.5,
      max=100),
    AbsolutePressure(
      start=1e5,
      nominal=5e5,
      min=0.5e5,
      max=30e5),
    Temperature(
      start=273.15,
      nominal=273.15,
      min=200.15,
      max=423.15),
    smoothModel=true,
    onePhase=false,
    ThermoStates=.Modelica.Media.Interfaces.Choices.IndependentVariables.phX,
    fluidConstants=refrigerantConstants);
    /*The vector substanceNames is mandatory, as the number of
      substances is determined based on its size. Here we assume
      a single-component medium.
      singleState is true if u and d do not depend on pressure, but only
      on a thermal variable (temperature or enthalpy). Otherwise, set it
      to false.
      For a single-substance medium, just set reducedX and fixedX to true,
      and there's no need to bother about medium compositions at all. Otherwise,
      set final reducedX = true if the medium model has nS-1 independent mass
      fraction, or reducedX = false if the medium model has nS independent
      mass fractions (nS = number of substances).
      If a mixture has a fixed composition set fixedX=true, otherwise false.
      The modifiers for reducedX and fixedX should normally be final
      since the other equations are based on these values.

      It is also possible to redeclare the min, max, and start attributes of
      Medium types, defined in the base class Interfaces.PartialMedium
      (the example of Temperature is shown here). Min and max attributes
      should be set in accordance to the limits of validity of the medium
      model, while the start attribute should be a reasonable default value
      for the initialization of nonlinear solver iterations.
    */

  /*Provide records thats contain the coefficients for the smooth transition
    between different regions.
  */
  redeclare record SmoothTransition
    "Record that contains ranges to calculate a smooth transition between
    different regions"
    SpecificEnthalpy T_ph = 2.5;
    SpecificEntropy T_ps = 2.5;
    AbsolutePressure d_pT = 2.5;
    SpecificEnthalpy d_ph = 2.5;
    Real d_ps(unit="J/(Pa.K.kg)") =  25/(30e5-0.5e5);
    Real h_ps(unit="J/(Pa.K.kg)") = 50/(30e5-0.5e5);
  end SmoothTransition;
  /*Provide Helmholtz equations of state (EoS) using an explicit formula.
  */
  redeclare function extends f_Idg
    "Dimensionless Helmholtz energy (Ideal gas contribution f_Idg)"
  algorithm

  end f_Idg;

  redeclare function extends f_Res
    "Dimensionless Helmholtz energy (Residual part alpha_r)"
  algorithm

  end f_Res;

  redeclare function extends t_fIdg_t
    "Short form for tau*(dalpha_0/dtau)_delta=const"
  algorithm

  end t_fIdg_t;

  redeclare function extends tt_fIdg_tt
    "Short form for tau*tau*(ddalpha_0/(dtau*dtau))_delta=const"
  algorithm

  end tt_fIdg_tt;

  redeclare function extends t_fRes_t
    "Short form for tau*(dalpha_r/dtau)_delta=const"
  algorithm

  end t_fRes_t;

  redeclare function extends tt_fRes_tt
    "Short form for tau*tau*(ddalpha_r/(dtau*dtau))_delta=const"
  algorithm

  end tt_fRes_tt;

  redeclare function extends d_fRes_d
    "Short form for delta*(dalpha_r/(ddelta))_tau=const"
  algorithm

  end d_fRes_d;

  redeclare function extends dd_fRes_dd
    "Short form for delta*delta(ddalpha_r/(ddelta*delta))_tau=const"
  algorithm

  end dd_fRes_dd;

  redeclare function extends td_fRes_td
    "Short form for tau*delta*(ddalpha_r/(dtau*ddelta))"
  algorithm

  end td_fRes_td;

  redeclare function extends ttt_fIdg_ttt
    "Short form for tau*tau*tau*(dddalpha_0/(dtau*dtau*dtau))_delta=const"
  algorithm

  end ttt_fIdg_ttt;

  redeclare function extends ttt_fRes_ttt
    "Short form for tau*tau*tau*(dddalpha_r/(dtau*dtau*dtau))_delta=const"
  algorithm

  end ttt_fRes_ttt;

  redeclare function extends ddd_fRes_ddd
    "Short form for delta*delta*delta*
    (dddalpha_r/(ddelta*ddelta*ddelta))_tau=const"
  algorithm

  end ddd_fRes_ddd;

  redeclare function extends tdd_fRes_tdd
    "Short form for tau*delta*delta*(dddalpha_r/(dtau*ddelta*ddelta))"
  algorithm

  end tdd_fRes_tdd;

  redeclare function extends ttd_fRes_ttd
    "Short form for tau*tau*delta*(dddalpha_r/(dtau*dtau*ddelta))"
  algorithm

  end ttd_fRes_ttd;
  /*Provide polynomial functions for saturation properties. These functions are
    fitted to external data (e.g. experimental data).
    Currently, just one fitting approach is implemented.
  */
  redeclare function extends saturationPressure
    "Saturation pressure of refrigerant (Ancillary equation)"
  protected
    Real OM = (1 - T/fluidConstants[1].criticalTemperature);

  algorithm
    if T>fluidConstants[1].criticalTemperature then
     p := fluidConstants[1].criticalPressure;
    elseif T<fluidConstants[1].triplePointTemperature then
     p := fluidConstants[1].triplePointPressure;
    else

    end if;
  end saturationPressure;

  redeclare function extends saturationTemperature
    "Saturation temperature of refrigerant (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end saturationTemperature;

  redeclare replaceable function extends bubbleDensity
    "Boiling curve specific density of refrigerant (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end bubbleDensity;

  redeclare function extends dewDensity
    "Dew curve specific density of refrigerant (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end dewDensity;

  redeclare function extends bubbleEnthalpy
    "Boiling curve specific enthalpy of refrigerant (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end bubbleEnthalpy;

  redeclare function extends dewEnthalpy
    "Dew curve specific enthalpy of refrigerant (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end dewEnthalpy;

  redeclare function extends bubbleEntropy
    "Boiling curve specific entropy of refrigerant (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end bubbleEntropy;

  redeclare function extends dewEntropy
    "Dew curve specific entropy of propane (Ancillary equation)"
  protected
    Real x = 0;

  algorithm
  end dewEntropy;
  /*Provide functions to calculate thermodynamic properties depending on the
    independent variables. Moreover, these functions may depend on the
    Helmholtz EoS.
  */
  redeclare function temperature_ph
    "Calculates temperature as function of pressure and specific enthalpy"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEnthalpy h "Specific enthalpy";
    input FixedPhase phase = 0
      "2 for two-phase, 1 for one-phase, 0 if not known";
    output Temperature T "Temperature";

  protected
    SmoothTransition st;
    SpecificEnthalpy dh = st.T_ph;
    SpecificEnthalpy h_dew = 0;
    SpecificEnthalpy h_bubble = 0;
    Real x1 = 0;
    Real y1 = 0;
    Real T1 = 0;
    Real x2 = 0;
    Real y2 = 0;
    Real T2 = 0;

  algorithm
  end temperature_ph;

  redeclare function temperature_ps
    "Calculates temperature as function of pressure and specific entroy"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEntropy s "Specific entropy";
    input FixedPhase phase = 0
      "2 for two-phase, 1 for one-phase, 0 if not known";
    output Temperature T "Temperature";

  protected
    SmoothTransition st;
    SpecificEntropy ds = st.T_ps;
    SpecificEntropy s_dew = 0;
    SpecificEntropy s_bubble = 0;
    Real x1 = 0;
    Real y1 = 0;
    Real T1 = 0;
    Real x2 = 0;
    Real y2 = 0;
    Real T2 = 0;

  algorithm
  end temperature_ps;

  redeclare function density_pT
    "Computes density as a function of pressure and temperature"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input Temperature T "Temperature";
    input FixedPhase phase = 0
      "2 for two-phase, 1 for one-phase, 0 if not known";
    output Density d "Density";

  protected
    SmoothTransition st;
    AbsolutePressure dp = st.d_pT;
    SaturationProperties sat = setSat_T(T=T);
    Real x1 = 0;
    Real y1 = 0;
    Real d1 = 0;
    Real x2 = 0;
    Real y2 = 0;
    Real d2 = 0;

  algorithm
  end density_pT;
  /*Provide functions to calculate further thermodynamic properties like the
    dynamic viscosity or thermal conductivity. Also add references.
  */
  redeclare function extends dynamicViscosity
    "Calculates dynamic viscosity of refrigerant"

  algorithm

  end dynamicViscosity;

  redeclare function extends thermalConductivity
    "Calculates thermal conductivity of refrigerant"

  algorithm

  end thermalConductivity;

  redeclare function extends surfaceTension
    "Surface tension in two phase region of refrigerant"

  algorithm

  end surfaceTension;
end TemplateHybridTwoPhaseMediumFormula;


within AixLib.Media.Refrigerants.Interfaces;
partial package TemplateHybridTwoPhaseMediumRecord
  "Template for media models using a hybrid approach with records"

  /*Provide basic definitions of the refrigerant. Therefore, fill constants
    or parameters and may add new constants or parameters if needed. Moreover,
    provide references within the information of the package.
  */
  constant Modelica.Media.Interfaces.PartialTwoPhaseMedium.FluidConstants[1]
    refrigerantConstants(
      each chemicalFormula = "CXHY",
      each structureFormula = "CXHY",
      each casRegistryNumber = "xx-xx-x",
      each iupacName = "name",
      each molarMass = 1,
      each criticalTemperature = 1,
      each criticalPressure = 1,
      each criticalMolarVolume = 1,
      each normalBoilingPoint = 1,
      each triplePointTemperature = 1,
      each meltingPoint = 1,
      each acentricFactor = 1,
      each triplePointPressure = 1,
      each dipoleMoment = 1,
      each hasCriticalData=true)
    "Thermodynamic constants for refrigerant";

  /*Provide basic information about the refrigerant. These basic information
    are the refrigerant name as well as the valid refrigerant limits in terms
    of specific enthalpy, density, absolute pressure and temperature.
  */
  extends
    AixLib.Media.Refrigerants.Interfaces.PartialHybridTwoPhaseMediumRecord(
    mediumName="Name",
    substanceNames={"Name"},
    singleState=false,
    SpecificEnthalpy(
      start=1.0e5,
      nominal=1.0e5,
      min=50e3,
      max=1000e3),
    Density(
      start=500,
      nominal=500,
      min=0.5,
      max=100),
    AbsolutePressure(
      start=1e5,
      nominal=5e5,
      min=0.5e5,
      max=30e5),
    Temperature(
      start=273.15,
      nominal=273.15,
      min=200.15,
      max=423.15),
    smoothModel=true,
    onePhase=false,
    ThermoStates=.Modelica.Media.Interfaces.Choices.IndependentVariables.phX,
    fluidConstants=refrigerantConstants);
    /*The vector substanceNames is mandatory, as the number of
      substances is determined based on its size. Here we assume
      a single-component medium.
      singleState is true if u and d do not depend on pressure, but only
      on a thermal variable (temperature or enthalpy). Otherwise, set it
      to false.
      For a single-substance medium, just set reducedX and fixedX to true,
      and there's no need to bother about medium compositions at all. Otherwise,
      set final reducedX = true if the medium model has nS-1 independent mass
      fraction, or reducedX = false if the medium model has nS independent
      mass fractions (nS = number of substances).
      If a mixture has a fixed composition set fixedX=true, otherwise false.
      The modifiers for reducedX and fixedX should normally be final
      since the other equations are based on these values.

      It is also possible to redeclare the min, max, and start attributes of
      Medium types, defined in the base class Interfaces.PartialMedium
      (the example of Temperature is shown here). Min and max attributes
      should be set in accordance to the limits of validity of the medium
      model, while the start attribute should be a reasonable default value
      for the initialization of nonlinear solver iterations.
    */

  /*Provide records thats contain the fitting coefficients for all fitted
    formula (e.g. Helmholtz equation of state).
  */
  redeclare record EoS
    "Record that contains fitting coefficients of the Helmholtz EoS"
    extends AixLib.DataBase.Media.Refrigerants.R290.EoS_IIR_P05_30_T263_343;
  end EoS;

  redeclare record BDSP "Record that contains fitting coefficients of the
    state properties at bubble and dew lines"
    extends AixLib.DataBase.Media.Refrigerants.R290.BDSP_IIR_P05_30_T263_343;
  end BDSP;

  redeclare record TSP "Record that contains fitting coefficients of the
    state properties calculated with two independent state properties"
    extends AixLib.DataBase.Media.Refrigerants.R290.TSP_IIR_P05_30_T263_343;
  end TSP;

  redeclare record SmoothTransition
    "Record that contains ranges to calculate a smooth transition between
    different regions"
    SpecificEnthalpy T_ph = 2.5;
    SpecificEntropy T_ps = 2.5;
    AbsolutePressure d_pT = 2.5;
    SpecificEnthalpy d_ph = 2.5;
    Real d_ps(unit="J/(Pa.K.kg)") =  25/(30e5-0.5e5);
    Real h_ps(unit="J/(Pa.K.kg)") = 50/(30e5-0.5e5);
  end SmoothTransition;
  /*Provide functions to calculate further thermodynamic properties like the
    dynamic viscosity or thermal conductivity. Also add references.
  */
  redeclare function extends dynamicViscosity
    "Calculates dynamic viscosity of refrigerant"

  algorithm
  end dynamicViscosity;

  redeclare function extends thermalConductivity
    "Calculates thermal conductivity of refrigerant"

  algorithm
  end thermalConductivity;

  redeclare function extends surfaceTension
    "Surface tension in two phase region of refrigerant"

  algorithm
  end surfaceTension;
end TemplateHybridTwoPhaseMediumRecord;


Types to be used in fluid models

within AixLib.Media.Refrigerants.Interfaces;
package Types "Types to be used in fluid models"
  extends Modelica.Media.Interfaces.Types;
end Types;


within AixLib.Media.Refrigerants;
package R134a "Package with models for refrigerant R134a"
  extends Modelica.Icons.VariantsPackage;
end R134a;