within Modelica.Fluid;
package Dissipation
  "Functions for convective heat transfer and pressure loss characteristics"
    extends Modelica.Icons.BasesPackage;
  import PI = Modelica.Constants.pi;
  import REC = Modelica.Fluid.Dissipation.Utilities.Records;
  import TYP = Modelica.Fluid.Dissipation.Utilities.Types;

  package UsersGuide "User's guide"
    extends Modelica.Icons.Information;
    class GettingStarted "Getting Started"
      extends Modelica.Icons.Information;
end straightPipe

Here the compressible case for the unknown mass flow rate (M_FLOW) is calculated by the
known pressure difference (dp) out of the interfaces of the thermohydraulic framework and
the input records (IN_con,IN_var) provide data like geometry and fluid properties for
example.

Step 5: Assign record variables

In the last step the variables of the input records for the function have to be assigned.
The assignment of the record variables can either be done directly in the record on the
diagram layer or in the equation layer.
The assignment of the input record in the equation layer results into the following
model:

model straightPipe
 ...
//compressible fluid flow
  //input record

Fluid.Dissipation.Examples.Applications.PressureLoss.BaseClasses.StraightPipe.Overall.Pres
sureLossInput_con
    IN_con(
    d_hyd=d_hyd,
    L=L,
    roughness=roughness,
    K=K);

Fluid.Dissipation.Examples.Applications.PressureLoss.BaseClasses.StraightPipe.Overall.Pres
sureLossInput_var
    IN_var(
    eta=eta,
    rho=rho);
 ...
end straight Pipe;

If the implementation of a HTPL correlation is done in an existing application model, the
unknown variables out of Step 1 (M_FLOW and dp for compressible or DP and m_flow for
incompressible case) have to be adjusted to the model variables (typically the interface
variables). The implementation of HTPL correlation into Modelica.Fluid can be
found for  flow
models of several devices.

 "));
    end GettingStarted;

    class ReleaseNotes "Release notes"
      extends Modelica.Icons.ReleaseNotes;
    end ReleaseNotes;

  class Contact "Contact"
    extends Modelica.Icons.Contact;
  end Contact;
  end UsersGuide;

  package HeatTransfer "Package for calculation of heat transfer"
  extends Modelica.Icons.VariantsPackage;
    package Channel
    extends Modelica.Icons.VariantsPackage;

      function kc_evenGapLaminar
        "Mean heat transfer coefficient of even gap | laminar flow regime | considering boundary layer development | heat transfer at ONE or BOTH sides | identical and constant wall temperatures"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Gb 6-10

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapLaminar_IN_con
          IN_con "Input record for function kc_evenGapLaminar"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapLaminar_IN_var
          IN_var "Input record for function kc_evenGapLaminar"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.kc_evenGap;

        Real MIN=Modelica.Constants.eps;

        Real laminar=2200 "Maximum Reynolds number of laminar flow regime";

        SI.Area A_cross=IN_con.s*IN_con.h "Cross sectional area of gap";
        SI.Diameter d_hyd=2*IN_con.s "Hydraulic diameter";

        Real prandtlMax=if IN_con.target == TYP.UndevOne then 10 else if IN_con.target
             == TYP.UndevBoth then 1000 else 0 "Maximum Prandtl number";
        Real prandtlMin=if IN_con.target == TYP.UndevOne or IN_con.target == TYP.UndevBoth then
                  0.1 else 0 "Minimum Prandtl number";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity in gap";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := max(1, abs(IN_var.rho*velocity*d_hyd/max(MIN, IN_var.eta)));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapLaminar_KC(IN_con,
          IN_var);
        Nu := kc*d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > laminar then 1 else 0;
        fstatus[2] := if IN_con.target == TYP.UndevOne or IN_con.target == TYP.UndevBoth then
                if Pr > prandtlMax or Pr < prandtlMin then 1 else 0 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_evenGapLaminar;

      function kc_evenGapLaminar_KC
        "Mean heat transfer coefficient of even gap | laminar flow regime | considering boundary layer development | heat transfer at ONE or BOTH sides | identical and constant wall temperatures"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Gb 6-10

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapLaminar_IN_con
          IN_con "Input record for function kc_evenGapLaminar_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapLaminar_IN_var
          IN_var "Input record for function kc_evenGapLaminar_KC"
        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_evenGapLaminar_KC";

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.kc_evenGap;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=max(MIN, IN_con.s*IN_con.h)
          "Cross sectional area of gap";
        SI.Diameter d_hyd=2*IN_con.s "Hydraulic diameter";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity in gap";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*d_hyd/max(MIN, IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        //variables for mean Nusselt number
        //SOURCE: p.Gb 7, eq. 36/37
        SI.NusseltNumber Nu_1=if IN_con.target == TYP.DevOne or IN_con.target == TYP.UndevOne then
                  4.861 else if IN_con.target == TYP.DevBoth or IN_con.target == TYP.UndevBoth then
                  7.541 else 0 "First Nusselt number";
        //SOURCE: p.Gb 7, eq. 38
        SI.NusseltNumber Nu_2=1.841*(Re*Pr*d_hyd/(max(IN_con.L, MIN)))^(1/3)
          "Second Nusselt number";
        //SOURCE: p.Gb 7, eq. 42
        SI.NusseltNumber Nu_3=if IN_con.target == TYP.UndevOne or IN_con.target ==
            TYP.UndevBoth then (2/(1 + 22*Pr))^(1/6)*(Re*Pr*d_hyd/(max(IN_con.L, MIN)))
            ^(0.5) else 0 "Third mean Nusselt number";
        SI.NusseltNumber Nu=((Nu_1)^3 + (Nu_2)^3 + (Nu_3)^3)^(1/3);

        //Documentation
      algorithm
        kc := Nu*((IN_var.lambda/max(MIN, d_hyd)));
      end kc_evenGapLaminar_KC;

      record kc_evenGapLaminar_IN_con
        "Input record for function kc_evenGapLaminar and kc_evenGapLaminar_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_con;
      end kc_evenGapLaminar_IN_con;

      record kc_evenGapLaminar_IN_var
        "Input record for function kc_evenGapLaminar and kc_evenGapLaminar_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_var;
      end kc_evenGapLaminar_IN_var;

      function kc_evenGapOverall
        "Mean heat transfer coefficient of even gap | overall flow regime | considering boundary layer development | heat transfer at ONE or BOTH sides | identical and constant wall temperatures | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Gb 6-10

        import MIN = Modelica.Constants.eps;
        // import SMOOTH = Modelica.Fluid.Dissipation.Utilities.Functions.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_con
          IN_con "Input record for function kc_evenGapOverall"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_var
          IN_var "Input record for function kc_evenGapOverall"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.kc_evenGap;

        Real MIN=Modelica.Constants.eps;

        Real laminar=2200 "Maximum Reynolds number for laminar regime";
        Real turbulent=1e4 "Minimum Reynolds number for turbulent regime";

        SI.Area A_cross=IN_con.s*IN_con.h "Cross sectional area of gap";
        SI.Diameter d_hyd=2*IN_con.s "Hydraulic diameter";

        Real prandtlMax=if IN_con.target == TYP.UndevOne then 10 else if IN_con.target
             == TYP.UndevBoth then 1000 else 0 "Maximum Prandtl number";
        Real prandtlMin=if IN_con.target == TYP.UndevOne or IN_con.target == TYP.UndevBoth then
                  0.1 else 0 "Minimum Prandtl number";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity in gap";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := max(1e-3, abs(IN_var.rho*velocity*d_hyd/max(MIN, IN_var.eta)));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_KC(IN_con, IN_var);
        Nu := kc*d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if IN_con.target == TYP.UndevOne or IN_con.target == TYP.UndevBoth then
                if Pr > prandtlMax or Pr < prandtlMin then 1 else 0 else 0;
        fstatus[2] := if d_hyd/IN_con.L > 1.0 then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_evenGapOverall;

      function kc_evenGapOverall_KC
        "Mean heat transfer coefficient of even gap | overall flow regime | considering boundary layer development | heat transfer at ONE or BOTH sides | identical and constant wall temperatures | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Gb 6-10

        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_con
          IN_con "Input record for function kc_evenGapOverall_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_var
          IN_var "Input record for function kc_evenGapOverall_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_evenGapOverall_KC";

      protected
        Real MIN=Modelica.Constants.eps;

        Real laminar=2200 "Maximum Reynolds number for laminar regime";
        Real turbulent=1e4 "Minimum Reynolds number for turbulent regime";

        SI.Area A_cross=max(MIN, IN_con.s*IN_con.h)
          "Cross sectional area of gap";
        SI.Diameter d_hyd=2*IN_con.s "Hydraulic diameter";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity in gap";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*d_hyd/max(MIN, IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        kc_evenGapTurbulent_IN_con IN_con_turb(h=IN_con.h,s=IN_con.s,L=IN_con.L);
      algorithm
        kc := SMOOTH(
                laminar,
                turbulent,
                Re)*Dissipation.HeatTransfer.Channel.kc_evenGapLaminar_KC(
          IN_con, IN_var) + SMOOTH(
                turbulent,
                laminar,
                Re)*Dissipation.HeatTransfer.Channel.kc_evenGapTurbulent_KC(IN_con_turb,
          IN_var);
      end kc_evenGapOverall_KC;

      record kc_evenGapOverall_IN_con
        "Input record for function kc_evenGapOverall and kc_evenGapOverall_KC"

              //even gap variables
              extends
          Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.EvenGap;
      end kc_evenGapOverall_IN_con;

      record kc_evenGapOverall_IN_var
        "Input record for function kc_evenGapOverall and kc_evenGapOverall_KC"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;

        //input variable (mass flow rate)
        SI.MassFlowRate m_flow
      end kc_evenGapOverall_IN_var;

      function kc_evenGapTurbulent
        "Mean heat transfer coefficient of even gap | turbulent flow regime | developed fluid flow | heat transfer at BOTH sides | identical and constant wall temperatures"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Gb 7

        import MIN = Modelica.Constants.eps;

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapTurbulent_IN_con
          IN_con "Input record for function kc_evenGapTurbulent"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapTurbulent_IN_var
          IN_var "Input record for function kc_evenGapTurbulent"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        Real prandtlMax=100 "Maximum Prandtl number";
        Real prandtlMin=0.6 "Minimum Prandtl number";
        Real turbulentMax=1e6
          "Maximum Reynolds number for turbulent flow regime";
        Real turbulentMin=3e4
          "Minimum Reynolds number for turbulent flow regime";

        SI.Area A_cross=max(MIN, IN_con.s*IN_con.h)
          "Cross sectional area of gap";
        SI.Diameter d_hyd=2*IN_con.s "Hydraulic diameter";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity in gap";

        //failure status
        Real fstatus[3] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := max(1, abs(IN_var.rho*velocity*d_hyd/max(MIN, IN_var.eta)));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapTurbulent_KC(IN_con,
          IN_var);
        Nu := kc*d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > turbulentMax or Re < turbulentMin then 1 else 0;
        fstatus[2] := if Pr > prandtlMax or Pr < prandtlMin then 1 else 0;
        fstatus[3] := if d_hyd/max(MIN, IN_con.L) > 1.0 then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_evenGapTurbulent;

      function kc_evenGapTurbulent_KC
        "Mean heat transfer coefficient of even gap | turbulent flow regime | developed fluid flow | heat transfer at BOTH sides | identical and constant wall temperatures"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Gb 7

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapTurbulent_IN_con
          IN_con "Input record for function kc_evenGapTurbulent_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapTurbulent_IN_var
          IN_var "Input record for function kc_evenGapTurbulent_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_evenGapTurbulent_KC";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=max(MIN, IN_con.s*IN_con.h)
          "Cross sectional area of gap";
        SI.Diameter d_hyd=2*IN_con.s "Hydraulic diameter";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity in gap";
        SI.ReynoldsNumber Re=max(MIN,(IN_var.rho*velocity*d_hyd/max(MIN, IN_var.eta)));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        //SOURCE: p.Ga 5, eq. 27
        Real zeta=1/max(MIN, 1.8*Modelica.Math.log10(abs(Re)) - 1.5)^2
          "Pressure loss coefficient";

        //SOURCE: p.Gb 5, eq. 26
        //assumption according to Gb 7, sec. 2.4
        SI.NusseltNumber Nu=abs((zeta/8)*Re*Pr/(1 + 12.7*(zeta/8)^0.5*(Pr^(2/3) - 1))
            *(1 + (d_hyd/max(MIN, IN_con.L))^(2/3)));

        //Documentation
      algorithm
        kc := Nu*(IN_var.lambda/max(MIN, d_hyd));
      end kc_evenGapTurbulent_KC;

      record kc_evenGapTurbulent_IN_con
        "Input record for function kc_evenGapTurbulent and kc_evenGapTurbulent_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_con(
            final target=Modelica.Fluid.Dissipation.Utilities.Types.kc_evenGap.DevBoth);
      end kc_evenGapTurbulent_IN_con;

      record kc_evenGapTurbulent_IN_var
        "Input record for function kc_evenGapTurbulent and kc_evenGapTurbulent_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.Channel.kc_evenGapOverall_IN_var;
      end kc_evenGapTurbulent_IN_var;
    end Channel;

    package General
    extends Modelica.Icons.VariantsPackage;
      function kc_approxForcedConvection
        "Mean convective heat transfer coefficient for forced convection | approximation | turbulent regime | hydrodynamically developed fluid flow"
        extends Modelica.Icons.Function;
        //SOURCE: A Bejan and A.D. Kraus. Heat Transfer handbook.John Wiley & Sons, 2nd edition, 2003. (p.424 ff)
        //Notation of equations according to SOURCE

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.General.kc_approxForcedConvection_IN_con
          IN_con "Input record for function kc_approxForcedConvection"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.General.kc_approxForcedConvection_IN_var
          IN_var "Input record for function kc_approxForcedConvection"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.kc_general;

        Real MIN=Modelica.Constants.eps;

        Real prandtlMax[3]={120,16700,500} "Maximum Prandtl number";
        Real prandtlMin[3]={0.7,0.7,1.5} "Minimum Prandtl number";
        Real reynoldsMax[3]={1.24e5,1e6,1e6} "Maximum Reynolds number";
        Real reynoldsMin[3]={2500,1e4,3e3} "Minimum Reynolds number";

        SI.Diameter d_hyd=max(MIN, 4*IN_con.A_cross/max(MIN, IN_con.perimeter))
          "Hydraulic diameter";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

      algorithm
        Pr := Modelica.Fluid.Dissipation.Utilities.Functions.General.PrandtlNumber(
                IN_var.cp,
                IN_var.eta,
                IN_var.lambda);
        Re := max(1, Modelica.Fluid.Dissipation.Utilities.Functions.General.ReynoldsNumber(
                IN_con.A_cross,
                IN_con.perimeter,
                IN_var.rho,
                IN_var.eta,
                abs(IN_var.m_flow))) "Reynolds number";
        kc := Modelica.Fluid.Dissipation.HeatTransfer.General.kc_approxForcedConvection_KC(
          IN_con, IN_var);
        Nu := kc*d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if IN_con.target == TYP.Rough then if Pr > prandtlMax[1] or Pr
           < prandtlMin[1] then 1 else 0 else if IN_con.target == TYP.Middle then if
          Pr > prandtlMax[2] or Pr < prandtlMin[2] then 1 else 0 else if IN_con.target
           == TYP.Finest then if Pr > prandtlMax[3] or Pr < prandtlMin[3] then 1 else
                0 else 0;
        fstatus[2] := if IN_con.target == TYP.Rough then if Re > reynoldsMax[1] or Re
           < reynoldsMin[1] then 1 else 0 else if IN_con.target == TYP.Middle then
          if Re > reynoldsMax[2] or Re < reynoldsMin[2] then 1 else 0 else if IN_con.target
           == TYP.Finest then if Re > reynoldsMax[3] or Re < reynoldsMin[3] then 1 else
                0 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_approxForcedConvection;

      function kc_approxForcedConvection_KC
        "Mean convective heat transfer coefficient for forced convection | approximation | turbulent regime | hydrodynamically developed fluid flow"
        extends Modelica.Icons.Function;
        //SOURCE: A Bejan and A.D. Kraus. Heat Transfer handbook.John Wiley & Sons, 2nd edition, 2003. (p.424 ff)
        //Notation of equations according to SOURCE

        //type =
        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.General.kc_approxForcedConvection_IN_con
          IN_con "Input record for function kc_approxForcedConvection_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.General.kc_approxForcedConvection_IN_var
          IN_var "Input record for function kc_approxForcedConvection_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_approxForcedConvection_KC";

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.kc_general;

        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, 4*IN_con.A_cross/max(MIN, IN_con.perimeter))
          "Hydraulic diameter";

        SI.PrandtlNumber Pr=max(MIN, abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda)))
          "Prandtl number";
        SI.ReynoldsNumber Re=(4*abs(IN_var.m_flow)/max(MIN, IN_con.perimeter*
            IN_var.eta)) "Reynolds number";

      algorithm
        kc := IN_var.lambda/d_hyd*(if IN_con.target == TYP.Rough then 0.023*Re^(4/5)*
          Pr^IN_con.exp_Pr else if IN_con.target == TYP.Middle then 0.023*Re^(4/5)*Pr
          ^(1/3)*(IN_var.eta/IN_var.eta_wall)^0.14 else if IN_con.target == TYP.Finest and Pr
           <= 1.5 then 0.0214*max(1, abs(Re^0.8 - 100))*Pr^0.4 else if IN_con.target
           == TYP.Finest then 0.012*max(1, abs(Re^0.87 - 280))*Pr^0.4 else 0);

        //Documentation
      end kc_approxForcedConvection_KC;

      record kc_approxForcedConvection_IN_con
        "Input record for function kc_approxForcedConvection and kc_approxForcedConvection_KC"
        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.General;
        parameter Real exp_Pr=0.4
      "Exponent for Prandtl number w.r.t. Dittus/Boelter | 0.4 for heating | 0.3 for cooling"
      end kc_approxForcedConvection_IN_con;

      record kc_approxForcedConvection_IN_var
        "Input record for function kc_approxForcedConvection and kc_approxForcedConvection_KC"
        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;
        SI.DynamicViscosity eta_wall
          "Dynamic viscosity of fluid at wall temperature"

        //input variable (mass flow rate)
        SI.MassFlowRate m_flow
      end kc_approxForcedConvection_IN_var;
    end General;

    package HeatExchanger
    extends Modelica.Icons.VariantsPackage;
      function kc_flatTube
        extends Modelica.Icons.Function;
        //SOURCE: A.M. Jacobi, Y. Park, D. Tafti, X. Zhang. AN ASSESSMENT OF THE STATE OF THE ART, AND POTENTIAL DESIGN IMPROVEMENTS, FOR FLAT-TUBE HEAT EXCHANGERS IN AIR CONDITIONING AND REFRIGERATION APPLICATIONS - PHASE I

        //icon

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_flatTube_IN_con
          IN_con "Input record for function kc_flatTube"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_flatTube_IN_var
          IN_var "Input record for function kc_flatTube"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP =
            Modelica.Fluid.Dissipation.Utilities.Types.HTXGeometry_flatTubes;

        SI.Length h=if IN_con.geometry == TYP.RectangularFin then IN_con.D_h*(1 +
            IN_con.alpha)/(2*IN_con.alpha) else 0 "Free flow height";
        SI.Length s=if IN_con.geometry == TYP.RectangularFin then h*IN_con.alpha else
                  0 "Lateral fin spacing (free flow width)";
        SI.Length t=if IN_con.geometry == TYP.RectangularFin then s*IN_con.gamma else
                  0 "Fin thickness";
        SI.Length l=if IN_con.geometry == TYP.RectangularFin then t/IN_con.delta else
                  0 "Fin length";
        SI.Area A_c=if IN_con.geometry == TYP.LouverFin then IN_con.A_fr*((IN_con.F_l
             - IN_con.delta_f)*(IN_con.F_p - IN_con.delta_f)/((IN_con.F_l + IN_con.D_m)
            *IN_con.F_p)) else if IN_con.geometry == TYP.RectangularFin then IN_con.A_fr
            *(h*s/((h + t + IN_con.D_m)*(s + t))) else 0
          "Minimum flow cross-sectional area";
      algorithm
        kc := Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_flatTube_KC(IN_con,
          IN_var);
        Pr := abs(IN_var.eta*IN_var.cp/IN_var.lambda);

        if IN_con.geometry == TYP.LouverFin then
          Re := abs(IN_var.m_flow)*IN_con.L_p/(IN_var.eta*A_c);
          Nu := max(1e-3, kc*IN_con.L_p/IN_var.lambda);
        elseif IN_con.geometry == TYP.RectangularFin then
          Re := abs(IN_var.m_flow)*IN_con.D_h/(IN_var.eta*A_c);
          Nu := max(1e-3, kc*IN_con.D_h/IN_var.lambda);
        else
          assert(IN_con.geometry == TYP.LouverFin or IN_con.geometry == TYP.RectangularFin,
            "Unknown choice of geometry is selected");
        end if;

        failureStatus := if IN_con.geometry == TYP.LouverFin then if Re < 100 or Re
           > 3000 then 1 else 0 else if IN_con.geometry == TYP.RectangularFin then
          if Re < 300 or Re > 5000 then 1 else 0 else 0;
      end kc_flatTube;

      function kc_flatTube_KC
        extends Modelica.Icons.Function;
        //SOURCE: A.M. Jacobi, Y. Park, D. Tafti, X. Zhang. AN ASSESSMENT OF THE STATE OF THE ART, AND POTENTIAL DESIGN IMPROVEMENTS, FOR FLAT-TUBE HEAT EXCHANGERS IN AIR CONDITIONING AND REFRIGERATION APPLICATIONS - PHASE I

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_flatTube_IN_con
          IN_con "Input record for function kc_flatTube_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_flatTube_IN_var
          IN_var "Input record for function kc_flatTube_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_flatTubePlateFin_KC";

      protected
        type TYP =
            Modelica.Fluid.Dissipation.Utilities.Types.HTXGeometry_flatTubes;

        Real MIN=Modelica.Constants.eps;
        Real Phi=IN_con.Phi*180/PI "Louver angle";

        SI.PrandtlNumber Pr=IN_var.eta*IN_var.cp/IN_var.lambda "Prandtl number";
        Real j "Colburn j factor";

        SI.Length h=if IN_con.geometry == TYP.RectangularFin then IN_con.D_h*(1 +
            IN_con.alpha)/(2*IN_con.alpha) else 0 "Free flow height";
        SI.Length s=if IN_con.geometry == TYP.RectangularFin then h*IN_con.alpha else
                  0 "Lateral fin spacing (free flow width)";
        SI.Length t=if IN_con.geometry == TYP.RectangularFin then s*IN_con.gamma else
                  0 "Fin thickness";
        SI.Length l=if IN_con.geometry == TYP.RectangularFin then t/IN_con.delta else
                  0 "Fin length";
        SI.Area A_c=if IN_con.geometry == TYP.LouverFin then IN_con.A_fr*((IN_con.F_l
             - IN_con.delta_f)*(IN_con.F_p - IN_con.delta_f)/((IN_con.F_l + IN_con.D_m)
            *IN_con.F_p)) else if IN_con.geometry == TYP.RectangularFin then IN_con.A_fr
            *(h*s/((h + t + IN_con.D_m)*(s + t))) else 0
          "Minimum flow cross-sectional area";
        SI.ReynoldsNumber Re_Dh=max(MIN, (abs(IN_var.m_flow)*IN_con.D_h/(IN_var.eta*
            A_c))) "Reynolds number based on hydraulic diameter";
        SI.ReynoldsNumber Re_Lp=max(MIN, (abs(IN_var.m_flow)*IN_con.L_p/(IN_var.eta*
            A_c))) "Reynolds number based on louver pitch";

      algorithm
        if IN_con.geometry == TYP.LouverFin then
          j := Re_Lp^(-0.49)*(Phi/90)^0.27*(IN_con.F_p/IN_con.L_p)^(-0.14)*(IN_con.F_l
            /IN_con.L_p)^(-0.29)*(IN_con.T_d/IN_con.L_p)^(-0.23)*(IN_con.L_l/IN_con.L_p)
            ^0.68*(IN_con.T_p/IN_con.L_p)^(-0.28)*(IN_con.delta_f/IN_con.L_p)^(-0.05);
          kc := j*(Re_Lp*Pr^(1/3)*IN_var.lambda/IN_con.L_p);

        elseif IN_con.geometry == TYP.RectangularFin then
          j := 0.6522*Re_Dh^(-0.5403)*(s/h)^(-0.1541)*(t/l)^0.1499*(t/s)^(-0.0678)*(1
             + 5.269e-5*Re_Dh^1.340*(s/h)^0.504*(t/l)^0.456*(t/s)^(-1.055))^0.1;
          kc := j*(Re_Dh*Pr^(1/3)*IN_var.lambda/IN_con.D_h);

        else
          assert(IN_con.geometry == TYP.LouverFin or IN_con.geometry == TYP.RectangularFin,
            "Unknown choice of geometry is selected");
        end if;
      end kc_flatTube_KC;

      record kc_flatTube_IN_con
        "Input record for function kc_flatTube and kc_flatTube_KC"
        extends Modelica.Icons.Record;

        Modelica.Fluid.Dissipation.Utilities.Types.HTXGeometry_flatTubes
          geometry = Dissipation.Utilities.Types.HTXGeometry_flatTubes.LouverFin
          "Choice of fin geometry"

        SI.Area A_fr=0 "Frontal area"
        SI.Length D_h=0 "Hydraulic diameter"
        SI.Length D_m=0 "Major tube diameter for flat tube"
        SI.Length F_l=0 "Fin length"
        SI.Length F_p=0 "Fin pitch, fin spacing + fin thickness"
        SI.Length L_l=0 "Louver length"
        SI.Length L_p=0 "Louver pitch"
        SI.Length T_d=0 "Tube depth"
        SI.Length T_p=0 "Tube pitch"

        Real alpha=0 "Lateral fin spacing (s) / free flow height (h)"
        Real gamma=0 "Fin thickness (t) / lateral fin spacing (s)"
        Real delta=0 "Fin thickness (t) / Fin length (l)"
        SI.Length delta_f=0 "Fin thickness"
        SI.Angle Phi=0 "Louver angle"

      end kc_flatTube_IN_con;

      record kc_flatTube_IN_var
        "Input record for function kc_flatTube and kc_flatTube_KC"
        extends Modelica.Icons.Record;

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;

        //input variable (mass flow rate)
        SI.MassFlowRate m_flow

      end kc_flatTube_IN_var;

      function kc_roundTube
        extends Modelica.Icons.Function;
        //SOURCE: A.M. Jacobi, Y. Park, D. Tafti, X. Zhang. AN ASSESSMENT OF THE STATE OF THE ART, AND POTENTIAL DESIGN IMPROVEMENTS, FOR FLAT-TUBE HEAT EXCHANGERS IN AIR CONDITIONING AND REFRIGERATION APPLICATIONS - PHASE I

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_roundTube_IN_con
          IN_con "Input record for function kc_roundTube"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_roundTube_IN_var
          IN_var "Input record for function kc_roundTube"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP =
            Modelica.Fluid.Dissipation.Utilities.Types.HTXGeometry_roundTubes;

        SI.Area A_c=IN_con.A_fr*((IN_con.F_p*IN_con.P_t - IN_con.F_p*IN_con.D_c - (
            IN_con.P_t - IN_con.D_c)*IN_con.delta_f)/(IN_con.F_p*IN_con.P_t))
          "Minimum flow cross-sectional area";
        SI.Area A_tot=if IN_con.geometry == TYP.LouverFin then IN_con.A_fr*((IN_con.N
            *PI*IN_con.D_c*(IN_con.F_p - IN_con.delta_f) + 2*(IN_con.P_t*IN_con.L -
            IN_con.N*PI*IN_con.D_c^2/4))/(IN_con.P_t*IN_con.F_p)) else 0
          "Total heat transfer area";
        SI.Length D_h=if IN_con.geometry == TYP.LouverFin then 4*A_c*IN_con.L/A_tot else
                  0 "Hydraulic diameter";

        /*SI.Length D_h=
    if IN_con.geometry==2 then
      4*A_c/(IN_con.A_fr*(2*(IN_con.P_t-IN_con.D_c+IN_con.F_p)/(IN_con.F_p*(IN_con.P_t-IN_con.D_c)))) else
      0 "Hydraulic diameter";*/

      algorithm
        kc := Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_roundTube_KC(IN_con,
          IN_var);
        Pr := abs(IN_var.eta*IN_var.cp/IN_var.lambda);

        if IN_con.geometry == TYP.PlainFin or IN_con.geometry == TYP.LouverFin or
            IN_con.geometry == TYP.SlitFin or IN_con.geometry == TYP.WavyFin then
          Re := abs(IN_var.m_flow)*IN_con.D_c/(IN_var.eta*A_c);
          Nu := max(1e-3, kc*IN_con.D_c/IN_var.lambda);
        else
          assert(IN_con.geometry == TYP.PlainFin or IN_con.geometry == TYP.LouverFin or
            IN_con.geometry == TYP.SlitFin or IN_con.geometry == TYP.WavyFin,
            "Unknown choice of geometry is selected");
        end if;

        failureStatus := if IN_con.geometry == TYP.PlainFin then if Re < 300 or Re >
          8000 then 1 else 0 else if IN_con.geometry == TYP.LouverFin then if Re <
          300 or Re > 7000 then 1 else 0 else if IN_con.geometry == TYP.SlitFin then
          if Re < 400 or Re > 7000 then 1 else 0 else if IN_con.geometry == TYP.WavyFin then
                if Re < 350 or Re > 7000 then 1 else 0 else 0;
      end kc_roundTube;

      function kc_roundTube_KC
        extends Modelica.Icons.Function;
        //SOURCE: A.M. Jacobi, Y. Park, D. Tafti, X. Zhang. AN ASSESSMENT OF THE STATE OF THE ART, AND POTENTIAL DESIGN IMPROVEMENTS, FOR FLAT-TUBE HEAT EXCHANGERS IN AIR CONDITIONING AND REFRIGERATION APPLICATIONS - PHASE I

        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_roundTube_IN_con
          IN_con "Input record for function kc_roundTube_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HeatExchanger.kc_roundTube_IN_var
          IN_var "Input record for function kc_roundTube_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_roundTube_KC";

      protected
        type TYP =
            Modelica.Fluid.Dissipation.Utilities.Types.HTXGeometry_roundTubes;

        Real MIN=Modelica.Constants.eps;

        SI.ReynoldsNumber Re_i "Reynolds number at transition to linearized calculation for wavy fins";

        SI.PrandtlNumber Pr=IN_var.eta*IN_var.cp/IN_var.lambda "Prandtl number";
        Real j "Colburn j factor";

        SI.Area A_c=IN_con.A_fr*((IN_con.F_p*IN_con.P_t - IN_con.F_p*IN_con.D_c - (
            IN_con.P_t - IN_con.D_c)*IN_con.delta_f)/(IN_con.F_p*IN_con.P_t))
          "Minimum flow cross-sectional area";
        SI.Area A_tot=if IN_con.geometry == TYP.LouverFin then IN_con.A_fr*((IN_con.N
            *PI*IN_con.D_c*(IN_con.F_p - IN_con.delta_f) + 2*(IN_con.P_t*IN_con.L -
            IN_con.N*PI*IN_con.D_c^2/4))/(IN_con.P_t*IN_con.F_p)) else 0
          "Total heat transfer area";
        SI.ReynoldsNumber Re_Dc=max(MIN, (abs(IN_var.m_flow)*IN_con.D_c/(IN_var.eta*
            A_c))) "Reynolds number based on fin collar diameter";
        SI.Length D_h=if IN_con.geometry == TYP.LouverFin then 4*A_c*IN_con.L/A_tot else
                  0 "Hydraulic diameter";

        /*SI.Length D_h=
    if IN_con.geometry==2 then
      4*A_c/(IN_con.A_fr*(2*(IN_con.P_t-IN_con.D_c+IN_con.F_p-IN_con.delta_f)/(IN_con.F_p*IN_con.P_t))) else
      0 "Hydraulic diameter";*/

        Real J1=0 "Exponent for computation of Colburn j factor";
        Real J2=0 "Exponent for computation of Colburn j factor";
        Real J3=0 "Exponent for computation of Colburn j factor";
        Real J4=0 "Exponent for computation of Colburn j factor";
        Real J5=0 "Exponent for computation of Colburn j factor";
        Real J6=0 "Exponent for computation of Colburn j factor";
        Real J7=0 "Exponent for computation of Colburn j factor";
        Real J8=0 "Exponent for computation of Colburn j factor";

      algorithm
        if IN_con.geometry == TYP.PlainFin then
          j := 0.991*(2.24*Re_Dc^(-0.092)*(IN_con.N/4)^(-0.031))^(0.607*(4 - IN_con.N))
            *(0.14*Re_Dc^(-0.328)*(IN_con.P_t/IN_con.P_l)^(-0.502)*(IN_con.F_p/IN_con.D_c)
            ^(0.0312))*(2.55*(IN_con.P_l/IN_con.D_c)^(-1.28));
          kc := j*(Re_Dc*Pr^(1/3)*IN_var.lambda/IN_con.D_c);

        elseif IN_con.geometry == TYP.LouverFin then
          if Re_Dc < 900 then
            J1 := -0.991 - 0.1055*(IN_con.P_l/IN_con.P_t)^3.1*log(IN_con.L_h/IN_con.L_p);
            J2 := -0.7344 + 2.1059*IN_con.N^0.55/(log(Re_Dc) - 3.2);
            J3 := 0.08485*(IN_con.P_l/IN_con.P_t)^(-4.4)*IN_con.N^(-0.68);
            J4 := -0.1741*log(IN_con.N);
            j := 14.3117*Re_Dc^J1*(IN_con.F_p/IN_con.D_c)^J2*(IN_con.L_h/IN_con.L_p)^
              J3*(IN_con.F_p/IN_con.P_l)^J4*(IN_con.P_l/IN_con.P_t)^(-1.724);
          elseif Re_Dc > 1100 then
            J5 := -0.6027 + 0.02593*(IN_con.P_l/D_h)^0.52*IN_con.N^(-0.5)*log(IN_con.L_h
              /IN_con.L_p);
            J6 := -0.4776 + 0.40774*IN_con.N^0.7/(log(Re_Dc) - 4.4);
            J7 := -0.58655*(IN_con.F_p/D_h)^2.3*(IN_con.P_l/IN_con.P_t)^(-1.6)*IN_con.N
              ^(-0.65);
            J8 := 0.0814*(log(Re_Dc) - 3);
            j := 1.1373*Re_Dc^J5*(IN_con.F_p/IN_con.P_l)^J6*(IN_con.L_h/IN_con.L_p)^
              J7*(IN_con.P_l/IN_con.P_t)^J8*IN_con.N^0.3545;
          else
            J1 := -0.991 - 0.1055*(IN_con.P_l/IN_con.P_t)^3.1*log(IN_con.L_h/IN_con.L_p);
            J2 := -0.7344 + 2.1059*IN_con.N^0.55/(log(Re_Dc) - 3.2);
            J3 := 0.08485*(IN_con.P_l/IN_con.P_t)^(-4.4)*IN_con.N^(-0.68);
            J4 := -0.1741*log(IN_con.N);
            J5 := -0.6027 + 0.02593*(IN_con.P_l/D_h)^0.52*IN_con.N^(-0.5)*log(IN_con.L_h
              /IN_con.L_p);
            J6 := -0.4776 + 0.40774*IN_con.N^0.7/(log(Re_Dc) - 4.4);
            J7 := -0.58655*(IN_con.F_p/D_h)^2.3*(IN_con.P_l/IN_con.P_t)^(-1.6)*IN_con.N
              ^(-0.65);
            J8 := 0.0814*(log(Re_Dc) - 3);
            j := SMOOTH(
              900,
              1100,
              Re_Dc)*(14.3117*Re_Dc^J1*(IN_con.F_p/IN_con.D_c)^J2*(IN_con.L_h/IN_con.L_p)
              ^J3*(IN_con.F_p/IN_con.P_l)^J4*(IN_con.P_l/IN_con.P_t)^(-1.724)) +
              SMOOTH(
              1100,
              900,
              Re_Dc)*(1.1373*Re_Dc^J5*(IN_con.F_p/IN_con.P_l)^J6*(IN_con.L_h/IN_con.L_p)
              ^J7*(IN_con.P_l/IN_con.P_t)^J8*IN_con.N^0.3545);
          end if;
          kc := SMOOTH(
            100,
            0,
            Re_Dc)*j*(Re_Dc*Pr^(1/3)*IN_var.lambda/IN_con.D_c);

        elseif IN_con.geometry == TYP.SlitFin then
          J1 := -0.674 + 0.1316*IN_con.N/log(Re_Dc) - 0.3769*IN_con.F_p/IN_con.D_c -
            1.8857*IN_con.N/Re_Dc;
          J2 := -0.0178 + 0.996*IN_con.N/log(Re_Dc) + 26.7*IN_con.N/Re_Dc;
          J3 := 1.865 + 1244.03*IN_con.F_p/(Re_Dc*IN_con.D_c) - 14.37/log(Re_Dc);
          j := 1.6409*Re_Dc^J1*(IN_con.S_p/IN_con.S_h)^1.16*(IN_con.P_t/IN_con.P_l)^
            1.37*(IN_con.F_p/IN_con.D_c)^J2*IN_con.N^J3;
          kc := j*(Re_Dc*Pr^(1/3)*IN_var.lambda/IN_con.D_c);

        elseif IN_con.geometry == TYP.WavyFin then
          Re_i := 2*exp(2.921)^(1/(A_c/IN_con.A_fr)); // 2 * turning point of the not linearized kc calculation
          if Re_Dc > Re_i then
            // original calculation
            j := 1.201/((Modelica.Math.log(Re_Dc^(A_c/IN_con.A_fr)))^2.921);
          else
            // linearized calculation to avoid increasing of kc for low Reynolds numbers and division by zero for Re = 1
            j := (Re_Dc-Re_i)*(-1.201*2.921*(A_c/IN_con.A_fr)/((Modelica.Math.log(Re_i^(A_c/IN_con.A_fr)))^3.921*Re_i)) + 1.201/((Modelica.Math.log(Re_i^(A_c/IN_con.A_fr)))^2.921);
          end if;
          kc := j*(Re_Dc*Pr^(1/3)*IN_var.lambda/IN_con.D_c);

        else
          assert(IN_con.geometry == TYP.PlainFin or IN_con.geometry == TYP.LouverFin or
            IN_con.geometry == TYP.SlitFin or IN_con.geometry == TYP.WavyFin,
            "Unknown choice of geometry is selected");
        end if;
      end kc_roundTube_KC;

      record kc_roundTube_IN_con
        "Input record for function kc_roundTube and kc_roundTube_KC"
        extends Modelica.Icons.Record;

        Modelica.Fluid.Dissipation.Utilities.Types.HTXGeometry_roundTubes
          geometry = Dissipation.Utilities.Types.HTXGeometry_roundTubes.PlainFin
          "Choice of fin geometry"

        SI.Area A_fr=0 "Frontal area"
        SI.Length D_c=0 "Fin collar diameter"
        SI.Length F_p=0 "Fin pitch, fin spacing + fin thickness"
        SI.Length L=0 "Heat exchanger length"
        SI.Length L_h=0 "Louver height"
        SI.Length L_p=0 "Louver pitch"
        Integer N=0 "Number of tube rows"
        SI.Length P_d=0 "Pattern depth of wavy fin, wave height"
        SI.Length P_l=0 "Longitudinal tube pitch"
        SI.Length P_t=0 "Transverse tube pitch"
        SI.Length S_h=0 "Slit height"
        SI.Length S_p=0 "Slit pitch"
        SI.Length X_f=0 "Half wave length of wavy fin"

        SI.Length delta_f=0 "Fin thickness"

      end kc_roundTube_IN_con;

      record kc_roundTube_IN_var
        "Input record for function kc_roundTube and kc_roundTube_KC"
        extends Modelica.Icons.Record;

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;

        //input variable (mass flow rate)
        SI.MassFlowRate m_flow

      end kc_roundTube_IN_var;
    end HeatExchanger;

    package HelicalPipe
    extends Modelica.Icons.VariantsPackage;
      function kc_laminar
        "Mean heat transfer coefficient of helical pipe | laminar flow regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, section Gc1 - Gc2
        //Notation of equations according to SOURCE

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_laminar_IN_con
          IN_con "Input record for function kc_laminar"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_laminar_IN_var
          IN_var "Input record for function kc_laminar"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=IN_con.d_hyd "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        SI.Diameter d_s=IN_con.L/(IN_con.n_nt*PI) "Mean coil diameter";
        SI.Diameter d_w=sqrt(max(MIN, (d_s^2 - (IN_con.h/PI)^2)))
          "Mean helical pipe diameter";
        SI.Diameter d_coil=max(d_w, d_w*(1 + (IN_con.h/(PI*d_w))^2))
          "Mean curvature diameter of helical pipe";
        SI.ReynoldsNumber Re_crit=2300*(1 + 8.6*(IN_con.d_hyd/d_coil)^0.45)
          "Critical Reynolds number";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";

        //failure status
        Real fstatus[1] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := abs(IN_var.rho*velocity*IN_con.d_hyd/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_laminar_KC(IN_con, IN_var);
        Nu := kc*IN_con.d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > Re_crit then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_laminar;

      function kc_laminar_KC
        "Mean heat transfer coefficient of helical pipe | hydrodynamically developed laminar flow regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, section Gc1 - Gc2
        //Notation of equations according to SOURCE

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_laminar_IN_con
          IN_con "Input record for function kc_laminar_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_laminar_IN_var
          IN_var "Input record for function kc_laminar_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_laminar_KC";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=IN_con.d_hyd "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        SI.Diameter d_s=IN_con.L/(IN_con.n_nt*PI) "Mean coil diameter";
        SI.Diameter d_w=sqrt(max(MIN, (d_s^2 - (IN_con.h/PI)^2)))
          "Mean helical pipe diameter";
        SI.Diameter d_coil=max(d_w, d_w*(1 + (IN_con.h/(PI*d_w))^2))
          "Mean curvature diameter of helical pipe";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*IN_con.d_hyd/max(MIN, IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        Real m=0.5 + 0.2903*(IN_con.d_hyd/d_coil)^0.194
          "Exponent for actual Reynolds number";

        //Documentation
      algorithm
        kc := (IN_var.lambda/IN_con.d_hyd)*(3.66 + 0.08*(1 + 0.8*(IN_con.d_hyd/d_coil)
          ^0.9)*Re^(m)*Pr^(1/3));
      end kc_laminar_KC;

      record kc_laminar_IN_con
        "Input record for function kc_laminar and kc_laminar_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_con;
      end kc_laminar_IN_con;

      record kc_laminar_IN_var
        "Input record for function kc_laminar and kc_laminar_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_var;
      end kc_laminar_IN_var;

      function kc_overall
        "Mean heat transfer coefficient of helical pipe | overall flow regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, section Gc1 - Gc2
        //Notation of equations according to SOURCE

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_con
          IN_con "Input record for function kc_overall"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_var
          IN_var "Input record for function kc_overall"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := (IN_var.rho*velocity*IN_con.d_hyd/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_KC(IN_con, IN_var);
        Nu := kc*IN_con.d_hyd/max(MIN, IN_var.lambda);

        failureStatus := 0;
      end kc_overall;

      function kc_overall_KC
        "Mean heat transfer coefficient of helical pipe | overall flow regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, section Gc1 - Gc2
        //Notation of equations according to SOURCE

        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_con
          IN_con "Input record for function kc_overall_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_var
          IN_var "Input record for function kc_overall_KC"
        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_overall_KC";

      protected
        Real MIN=Modelica.Constants.eps;
        Real laminar=2e3 "Maximum Reynolds number for laminar regime";
        Real turbulent=2.2e4 "Minimum Reynolds number for turbulent regime";

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";
        SI.Diameter d_s=max(1e-6, IN_con.L/(IN_con.n_nt*PI))
          "Mean coil diameter";
        SI.Diameter d_w=sqrt(max(MIN, abs(d_s^2 - (IN_con.h/PI)^2)))
          "Mean helical pipe diameter";
        SI.Diameter d_coil=d_w*(1 + (IN_con.h/(PI*d_w))^2)
          "Mean curvature diameter of helical pipe";
        SI.ReynoldsNumber Re_crit=min(4e3, 2300*(1 + 8.6*(IN_con.d_hyd/d_coil)^0.45))
          "Critical Reynolds number";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*IN_con.d_hyd/max(MIN,
            IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        //Documentation
      algorithm
        kc := SMOOTH(
                Re_crit,
                turbulent,
                Re)*Dissipation.HeatTransfer.HelicalPipe.kc_laminar_KC(IN_con,
          IN_var) + SMOOTH(
                turbulent,
                Re_crit,
                Re)*Dissipation.HeatTransfer.HelicalPipe.kc_turbulent_KC(IN_con,
          IN_var);
      end kc_overall_KC;

      record kc_overall_IN_con
        "Input record for function kc_overall and kc_overall_KC"

        //helical pipe variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.HelicalPipe;
      end kc_overall_IN_con;

      record kc_overall_IN_var
        "Input record for function kc_overall and kc_overall_KC"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;

        //input variable (mass flow rate)
        SI.MassFlowRate m_flow
      end kc_overall_IN_var;

      function kc_turbulent
        "Mean heat transfer coefficient of helical pipe | hydrodynamically developed turbulent flow regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, section Gc1 - Gc2
        //Notation of equations according to SOURCE

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_turbulent_IN_con
          IN_con "Input record for function kc_turbulent"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_turbulent_IN_var
          IN_var "Input record for function kc_turbulent"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        Real turbulent=2.2e4 "Minimum Reynolds number for turbulent regime";

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";

        //failure status
        Real fstatus[1] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/IN_var.lambda);
        Re := abs(IN_var.rho*velocity*IN_con.d_hyd/IN_var.eta);
        kc := Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_turbulent_KC(IN_con, IN_var);
        Nu := kc*IN_con.d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re < turbulent then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_turbulent;

      function kc_turbulent_KC
        "Mean heat transfer coefficient of helical pipe | hydrodynamically developed turbulent flow regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, section Gc1 - Gc2
        //Notation of equations according to SOURCE

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_turbulent_IN_con
          IN_con "Input record for function kc_turbulent_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_turbulent_IN_var
          IN_var "Input record for function kc_turbulent_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_turbulent_KC";

      protected
        Real MIN=Modelica.Constants.eps;
        Real turbulent=2.2e4 "Minimum Reynolds number for turbulent regime";

        SI.Diameter d_hyd=IN_con.d_hyd "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        SI.Diameter d_s=IN_con.L/(IN_con.n_nt*PI) "Mean coil diameter";
        SI.Diameter d_w=sqrt(max(MIN, (d_s^2 - (IN_con.h/PI)^2)))
          "Mean helical pipe diameter";
        SI.Diameter d_coil=max(d_w, d_w*(1 + (IN_con.h/(PI*d_w))^2))
          "Mean curvature diameter of helical pipe";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*IN_con.d_hyd/max(MIN,
            IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        Real zeta_TOT=0.3164*max(turbulent, Re)^(-0.25) + 0.03*sqrt(IN_con.d_hyd/
            d_coil) "Pressure loss coefficient";

        //Documentation
      algorithm
        kc := (IN_var.lambda/IN_con.d_hyd)*(zeta_TOT/8)*Re*Pr/(1 + 12.7*sqrt(zeta_TOT
          /8)*(Pr^(2/3) - 1));
      end kc_turbulent_KC;

      record kc_turbulent_IN_con
        "Input record for function kc_turbulent and kc_turbulent_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_con;
      end kc_turbulent_IN_con;

      record kc_turbulent_IN_var
        "Input record for function kc_turbulent and kc_turbulent_KC"

        extends
          Modelica.Fluid.Dissipation.HeatTransfer.HelicalPipe.kc_overall_IN_var;
      end kc_turbulent_IN_var;
    end HelicalPipe;

    package Plate
    extends Modelica.Icons.VariantsPackage;

      function kc_laminar
        "Mean heat transfer coefficient of plate | laminar regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, Aufl. 9, Springer-Verlag, 2002, Section Gd 1
        //Notation of equations according to SOURCE

        //input records
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_laminar_IN_con
          IN_con "Input record for function kc_laminar"
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_laminar_IN_var
          IN_var "Input record for function kc_laminar"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        Real laminar=1e5 "Maximum Reynolds number of laminar flow regime";
        Real prandtlMax=2000 "Maximum Prandtl number";
        Real prandtlMin=0.6 "Minimum Prandtl number";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda);
        Re := abs(IN_var.rho*IN_var.velocity*IN_con.L/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_laminar_KC(IN_con, IN_var);
        Nu := kc*IN_con.L/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > laminar then 1 else 0;
        fstatus[2] := if Pr > prandtlMax or Pr < prandtlMin then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_laminar;

      function kc_laminar_KC
        "Mean heat transfer coefficient of plate | laminar regime"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, Aufl. 9, Springer-Verlag, 2002, Section Gd 1
        //Notation of equations according to SOURCE

        //input records
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_laminar_IN_con
          IN_con "Input record for function kc_laminar_KC"
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_laminar_IN_var
          IN_var "Input record for function kc_laminar_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_laminar_KC";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Length L=max(MIN, IN_con.L);

        SI.SpecificHeatCapacityAtConstantPressure cp=IN_var.cp;
        SI.DynamicViscosity eta=max(MIN, IN_var.eta);
        SI.ThermalConductivity lambda=max(MIN, IN_var.lambda);
        SI.Density rho=IN_var.rho;

        SI.Velocity velocity=abs(IN_var.velocity) "Mean velocity";
        SI.ReynoldsNumber Re=(rho*velocity*L/eta);
        SI.PrandtlNumber Pr=eta*cp/lambda;

        //Documentation
      algorithm
        kc := (lambda/L)*(0.664*abs(Re)^0.5*Pr^(1/3));
      end kc_laminar_KC;

      record kc_laminar_IN_con
        "Input record for function kc_laminar and kc_laminar_KC"
        extends Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_con;
      end kc_laminar_IN_con;

      record kc_laminar_IN_var
        "Input record for function kc_laminar and kc_laminar_KC"
        extends Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_var;
      end kc_laminar_IN_var;

      function kc_overall
        "Mean heat transfer coefficient of even plate | overall regime | constant wall temperature"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, Aufl. 9, Springer-Verlag, 2002, Section Gd 1
        //Notation of equations according to SOURCE

        //input records
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_con
          IN_con "Input record for function kc_overall"
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_var
          IN_var "Input record for function kc_overall"
        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        Real prandtlMax=2000 "Maximum Prandtl number";
        Real prandtlMin=0.6 "Minimum Prandtl number";
        Real reynoldsMax=1e7 "Maximum Reynolds number";
        Real reynoldsMin=1e1 "Minimum Reynolds number";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda);
        Re := abs(IN_var.rho*IN_var.velocity*IN_con.L/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_KC(IN_con, IN_var);
        Nu := kc*IN_con.L/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > reynoldsMax or Re < reynoldsMin then 1 else 0;
        fstatus[2] := if Pr > prandtlMax or Pr < prandtlMin then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_overall;

      function kc_overall_KC
        "Mean heat transfer coefficient of even plate | overall regime | constant wall temperature"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, Aufl. 9, Springer-Verlag, 2002, Section Gd 1
        //Notation of equations according to SOURCE

        //input records
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_con
          IN_con "Input record for function kc_overall_KC"
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_var
          IN_var "Input record for function kc_overall_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_overall_KC";

      protected
        SI.CoefficientOfHeatTransfer kc_lam=
            Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_laminar_KC(     IN_con, IN_var);
        SI.CoefficientOfHeatTransfer kc_turb=
            Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_turbulent_KC(     IN_con, IN_var);

        //Documentation
      algorithm
        kc := sqrt((kc_lam)^2 + (kc_turb)^2);
      end kc_overall_KC;

      record kc_overall_IN_con
        "Input record for function kc_overall and function kc_overall_KC"
        //plate variables
        extends Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.Plate;
      end kc_overall_IN_con;

      record kc_overall_IN_var
        "Input record for function kc_overall and function kc_overall_KC"
        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;

        //input variable (fluid flow velocity)
        SI.Velocity velocity
      end kc_overall_IN_var;

      function kc_turbulent
        "Mean heat transfer coefficient of even plate | turbulent regime | constant wall temperature"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, Aufl. 9, Springer-Verlag, 2002, Section Gd 1
        //Notation of equations according to SOURCE

        //input records
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_turbulent_IN_con
          IN_con "Input record for function kc_turbulent"
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_turbulent_IN_var
          IN_var "Input record for function kc_turbulent"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        Real prandtlMax=2000 "Maximum Prandtl number";
        Real prandtlMin=0.6 "Minimum Prandtl number";
        Real reynoldsMax=1e7 "Maximum Reynolds number";
        Real reynoldsMin=5e5 "Minimum Reynolds number";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := abs(IN_var.rho*IN_var.velocity*IN_con.L/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_turbulent_KC(IN_con, IN_var);
        Nu := kc*IN_con.L/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > reynoldsMax or Re < reynoldsMin then 1 else 0;
        fstatus[2] := if Pr > prandtlMax or Pr < prandtlMin then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_turbulent;

      function kc_turbulent_KC
        "Mean heat transfer coefficient of even plate | turbulent regime | constant wall temperature"
        extends Modelica.Icons.Function;
        //SOURCE: VDI-Waermeatlas, Aufl. 9, Springer-Verlag, 2002, Section Gd 1
        //Notation of equations according to SOURCE

        //input records
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_turbulent_IN_con
          IN_con "Input record for function kc_turbulent_KC"
        input Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_turbulent_IN_var
          IN_var "Input record for function kc_turbulent_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_turbulent_KC";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Length L=max(MIN, IN_con.L);

        SI.SpecificHeatCapacityAtConstantPressure cp=IN_var.cp;
        SI.DynamicViscosity eta=IN_var.eta;
        SI.ThermalConductivity lambda=max(MIN, IN_var.lambda);
        SI.Density rho=IN_var.rho;

        SI.Velocity velocity=abs(IN_var.velocity) "Mean velocity";
        SI.ReynoldsNumber Re=abs(rho*velocity*L/eta);
        SI.PrandtlNumber Pr=abs(eta*cp/lambda);

        //Documentation
      algorithm
        kc := abs((lambda/L))*(0.037*Re^0.8*Pr)/(1 + 2.443/(max(Re^0.1, 1e-6))*(Pr^(2
          /3) - 1));
      end kc_turbulent_KC;

      record kc_turbulent_IN_con
        "Input record for function kc_turbulent and kc_turbulent_KC"
        extends Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_con;
      end kc_turbulent_IN_con;

      record kc_turbulent_IN_var
        "Input record for function kc_turbulent and kc_turbulent_KC"
        extends Modelica.Fluid.Dissipation.HeatTransfer.Plate.kc_overall_IN_var;
      end kc_turbulent_IN_var;
    end Plate;

    package StraightPipe
    extends Modelica.Icons.VariantsPackage;

      function kc_laminar
        "Mean heat transfer coefficient of straight pipe | uniform wall temperature or uniform heat flux | hydrodynamically developed or undeveloped laminar flow regime"
        extends Modelica.Icons.Function;
        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_laminar_IN_con
          IN_con "Input record for function kc_laminar"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_laminar_IN_var
          IN_var "Input record for function kc_laminar"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        Real MIN=Modelica.Constants.eps;

        Real laminar=2e3 "Maximum Reynolds number of laminar flow regime";
        Real prandtlMax=1000 "Maximum Prandtl number";
        Real prandtlMin=0.6 "Minimum Prandtl number";

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";

        //failure status
        Real fstatus[2] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := (IN_var.rho*velocity*IN_con.d_hyd/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_laminar_KC(IN_con, IN_var);
        Nu := kc*IN_con.d_hyd/max(MIN, IN_var.lambda);

        //failure status
        fstatus[1] := if Re > laminar then 1 else 0;
        fstatus[2] := if Pr > prandtlMax or Pr < prandtlMin then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_laminar;

      function kc_laminar_KC
        "Mean heat transfer coefficient of straight pipe | uniform wall temperature or uniform heat flux | hydrodynamically developed or undeveloped laminar flow regime"
        extends Modelica.Icons.Function;
        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_laminar_IN_con
          IN_con "Input record for function kc_laminar_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_laminar_IN_var
          IN_var "Input record for function kc_laminar_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_laminar_KC";

      protected
        type TYP =
            Modelica.Fluid.Dissipation.Utilities.Types.HeatTransferBoundary;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";

        Real Nu0=if IN_con.target == TYP.UWTuDFF or IN_con.target == TYP.UWTuUFF then
                  0.7 else if IN_con.target == TYP.UHFuDFF or IN_con.target == TYP.UHFuUFF then
                  0.6 else 0 "Help variable for mean Nusselt number";
        Real Nu1=if IN_con.target == TYP.UWTuDFF or IN_con.target == TYP.UWTuUFF then
                  3.66 else if IN_con.target == TYP.UHFuDFF or IN_con.target == TYP.UHFuUFF then
                  4.364 else 0 "Help variable for mean Nusselt number";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*IN_con.d_hyd/max(MIN,
            IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        SI.NusseltNumber Nu2=if IN_con.target == TYP.UWTuDFF or IN_con.target == TYP.UWTuUFF then
                  1.615*(Re*Pr*IN_con.d_hyd/IN_con.L)^(1/3) else if IN_con.target ==
            TYP.UHFuDFF or IN_con.target == TYP.UHFuUFF then 1.953*(Re*Pr*IN_con.d_hyd
            /IN_con.L)^(1/3) else 0 "Help variable for mean Nusselt number";
        SI.NusseltNumber Nu3=if IN_con.target == TYP.UWTuUFF then (2/(1 + 22*Pr))^(1/
            6)*(Re*Pr*IN_con.d_hyd/IN_con.L)^0.5 else if IN_con.target == TYP.UHFuUFF then
                  0.924*(Pr^(1/3))*(Re*IN_con.d_hyd/IN_con.L)^(1/2) else 0
          "Help variable for mean Nusselt number";

        SI.NusseltNumber Nu=(Nu1^3 + Nu0^3 + (Nu2 - Nu0)^3 + Nu3^3)^(1/3)
          "Mean Nusselt number";

        //Documentation
      algorithm
        kc := Nu*IN_var.lambda/max(MIN, IN_con.d_hyd);
      end kc_laminar_KC;

      record kc_laminar_IN_con
        "Input record for function kc_laminar and kc_laminar_KC"
        extends Utilities.Records.HeatTransfer.StraightPipe;

          //choices
        Modelica.Fluid.Dissipation.Utilities.Types.HeatTransferBoundary target=Dissipation.Utilities.Types.HeatTransferBoundary.UWTuDFF
          "Choice of heat transfer boundary condition"
      end kc_laminar_IN_con;

      record kc_laminar_IN_var
        "Input record for function kc_laminar and kc_laminar_KC"
        extends
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_IN_var;
      end kc_laminar_IN_var;

      function kc_overall
        "Mean heat transfer coefficient of straight pipe | uniform wall temperature or uniform heat flux | hydrodynamically developed or undeveloped overall flow regime| pressure loss dependence"
        extends Modelica.Icons.Function;
        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_IN_con
          IN_con "Input record for function kc_overall"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_IN_var
          IN_var "Input record for function kc_overall"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";

        //failure status
        Real fstatus[3] "Check of expected boundary conditions";

      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := (IN_var.rho*velocity*IN_con.d_hyd/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_KC(IN_con, IN_var);
        Nu := kc*IN_con.d_hyd/max(MIN, IN_var.lambda);

        //failure status
        if IN_con.roughness == TYP.Neglected then
          if Re < 2e4 or Re > 1e6 then
            fstatus[1] := 1;
          else
            fstatus[1] := 0;
          end if;
        elseif IN_con.roughness == TYP.Considered then
          if Re < 1e4 or Re > 1e6 then
            fstatus[1] := 1;
          else
            fstatus[1] := 0;
          end if;
        else
          assert(IN_con.roughness == TYP.Neglected or IN_con.roughness == TYP.Considered,
            "Unknown choice of roughness is selected");
        end if;
        fstatus[2] := if Pr < 0.6 or Pr > 1e3 then 1 else 0;
        fstatus[3] := if IN_con.d_hyd/max(MIN, IN_con.L) > 1 then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_overall;

      function kc_overall_KC
        "Mean heat transfer coefficient of straight pipe | uniform wall temperature or uniform heat flux | hydrodynamically developed or undeveloped overall flow regime| pressure loss dependence"
        extends Modelica.Icons.Function;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_IN_con
          IN_con "Input record for function kc_overall_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_IN_var
          IN_var "Input record for function kc_overall_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_overall_KC";

      protected
        Real MIN=Modelica.Constants.eps;
        Real laminar=2200 "Maximum Reynolds number for laminar regime";
        Real turbulent=1e4 "Minimum Reynolds number for turbulent regime";

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";
        SI.ReynoldsNumber Re=(IN_var.rho*velocity*IN_con.d_hyd/max(MIN,
            IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));

        kc_turbulent_IN_con IN_con_turb(d_hyd=IN_con.d_hyd, L= IN_con.L, roughness = IN_con.roughness, K=IN_con.K);
        kc_laminar_IN_con IN_con_lam(d_hyd=IN_con.d_hyd, L= IN_con.L, target=IN_con.target);

      algorithm
        kc := SMOOTH(
                laminar,
                turbulent,
                Re)*Dissipation.HeatTransfer.StraightPipe.kc_laminar_KC(IN_con_lam,
          IN_var) + SMOOTH(
                turbulent,
                laminar,
                Re)*Dissipation.HeatTransfer.StraightPipe.kc_turbulent_KC(IN_con_turb,
          IN_var);
      end kc_overall_KC;

      record kc_overall_IN_con
        "Input record for function kc_overall and kc_overall_KC"

          //choices
        Modelica.Fluid.Dissipation.Utilities.Types.HeatTransferBoundary target=Dissipation.Utilities.Types.HeatTransferBoundary.UWTuDFF
          "Choice of heat transfer boundary condition"

        extends kc_turbulent_IN_con;
      end kc_overall_IN_con;

      record kc_overall_IN_var
        "Input record for function kc_overall and kc_overall_KC"
        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.FluidProperties;

        //input variable (mass flow rate)
        SI.MassFlowRate m_flow
      end kc_overall_IN_var;

      function kc_turbulent
        "Mean heat transfer coefficient of straight pipe | hydrodynamically developed turbulent flow regime | pressure loss dependence"
        extends Modelica.Icons.Function;
        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_turbulent_IN_con
          IN_con "Input record for function kc_turbulent"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_turbulent_IN_var
          IN_var "Input record for function kc_turbulent"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Convective heat transfer coefficient"
        output SI.PrandtlNumber Pr "Prandtl number"
        output SI.ReynoldsNumber Re "Reynolds number"
        output SI.NusseltNumber Nu "Nusselt number"
        output Real failureStatus
          "0== boundary conditions fulfilled | 1== failure >> check if still meaningful results"

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/(IN_var.rho*A_cross)
          "Mean velocity";

        //failure status
        Real fstatus[3] "Check of expected boundary conditions";

        //Documentation
      algorithm
        Pr := abs(IN_var.eta*IN_var.cp/max(MIN, IN_var.lambda));
        Re := (IN_var.rho*velocity*IN_con.d_hyd/max(MIN, IN_var.eta));
        kc := Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_turbulent_KC(IN_con, IN_var);
        Nu := kc*IN_con.d_hyd/max(MIN, IN_var.lambda);

        //failure status
        if IN_con.roughness == TYP.Neglected then
          if Re < 2e4 or Re > 1e6 then
            fstatus[1] := 1;
          else
            fstatus[1] := 0;
          end if;
        elseif IN_con.roughness == TYP.Considered then
          if Re < 1e4 or Re > 1e6 then
            fstatus[1] := 1;
          else
            fstatus[1] := 0;
          end if;
        else
          assert(IN_con.roughness == TYP.Neglected or IN_con.roughness == TYP.Considered,
            "Unknown choice of roughness is selected");
        end if;
        fstatus[2] := if Pr <= 0.6 or Pr >= 1e3 then 1 else 0;
        fstatus[3] := if IN_con.d_hyd/max(MIN, IN_con.L) > 1 then 1 else 0;

        failureStatus := 0;
        for i in 1:size(fstatus, 1) loop
          if fstatus[i] == 1 then
            failureStatus := 1;
          end if;
        end for;
      end kc_turbulent;

      function kc_turbulent_KC
        "Mean heat transfer coefficient of straight pipe | hydrodynamically developed turbulent flow regime | pressure loss dependence"
        extends Modelica.Icons.Function;
        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_turbulent_IN_con
          IN_con "Input record for function kc_turbulent_KC"
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_turbulent_IN_var
          IN_var "Input record for function kc_turbulent_KC"

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Output for function kc_turbulent_KC";

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";

        SI.Velocity velocity=abs(IN_var.m_flow)/(IN_var.rho*A_cross)
          "Mean velocity";
        SI.ReynoldsNumber Re=max(MIN,(IN_var.rho*velocity*IN_con.d_hyd/IN_var.eta));
        SI.PrandtlNumber Pr=abs(IN_var.eta*IN_var.cp/IN_var.lambda);

        Real zeta=abs(1/max(MIN, 1.8*Modelica.Math.log10(abs(Re)) - 1.5)^2)
          "Pressure loss coefficient";

        //Documentation
      algorithm
        kc := if IN_con.roughness == TYP.Neglected then abs(IN_var.lambda/IN_con.d_hyd)
          *0.023*Re^0.8*Pr^(1/3) else if IN_con.roughness == TYP.Considered then abs(
          IN_var.lambda/IN_con.d_hyd)*(abs(zeta)/8)*abs(Re)*abs(Pr)/(1 + 12.7*(abs(
          zeta)/8)^0.5*(abs(Pr)^(2/3) - 1))*(1 + (IN_con.d_hyd/IN_con.L)^(2/3)) else
          0;
      end kc_turbulent_KC;

      record kc_turbulent_IN_con
        "Input record for function kc_turbulent and kc_turbulent_KC"
        extends Utilities.Records.HeatTransfer.StraightPipe;

        Modelica.Fluid.Dissipation.Utilities.Types.Roughness roughness=Dissipation.Utilities.Types.Roughness.Considered
          "Choice of considering surface roughness"

        SI.Length K=0 "Roughness (average height of surface asperities)"
      end kc_turbulent_IN_con;

      record kc_turbulent_IN_var
        "Input record for function kc_turbulent and kc_turbulent_KC"
        extends
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_overall_IN_var;
      end kc_turbulent_IN_var;

      function kc_twoPhaseOverall_KC
        "Local two phase heat transfer coefficient of straight pipe | horizontal or vertical boiling | horizontal condensation"
        extends Modelica.Icons.Function;
        //SOURCE_1: Bejan,A.: HEAT TRANSFER HANDBOOK, Wiley, 2003.
        //SOURCE_2: Gungor, K.E. and R.H.S. Winterton: A general correlation for flow boiling in tubes and annuli, Int.J. Heat Mass Transfer, Vol.29, p.351-358, 1986.

        //input records
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_twoPhaseOverall_KC_IN_con
          IN_con
        input
          Modelica.Fluid.Dissipation.HeatTransfer.StraightPipe.kc_twoPhaseOverall_KC_IN_var
          IN_var

        //output variables
        output SI.CoefficientOfHeatTransfer kc
          "Local two phase heat transfer coefficient";

      protected
        Real MIN=Modelica.Constants.eps;

        //Documentation
      algorithm
        kc := if IN_con.target == Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget.BoilHor then
          Modelica.Fluid.Dissipation.Utilities.Functions.HeatTransfer.TwoPhase.kc_twoPhase_boilingHorizontal_KC(
          IN_con, IN_var) else if IN_con.target == Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget.BoilVer then
          Modelica.Fluid.Dissipation.Utilities.Functions.HeatTransfer.TwoPhase.kc_twoPhase_boilingVertical_KC(
          IN_con, IN_var) else if IN_con.target == Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget.CondHor then
          Modelica.Fluid.Dissipation.Utilities.Functions.HeatTransfer.TwoPhase.kc_twoPhase_condensationHorizontal_KC(
          IN_con, IN_var) else MIN;
      end kc_twoPhaseOverall_KC;

      record kc_twoPhaseOverall_KC_IN_con
        "Input record for function kc_twoPhaseOverall_KC"
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_con;
      end kc_twoPhaseOverall_KC_IN_con;

      record kc_twoPhaseOverall_KC_IN_var
        "Input record for function kc_twoPhaseOverall_KC"
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_var;
      end kc_twoPhaseOverall_KC_IN_var;
    end StraightPipe;
  end HeatTransfer;

  package PressureLoss "Package for calculation of pressure loss"
  extends Modelica.Icons.VariantsPackage;

    package Bend "Package for pressure loss calculation of bends"
    extends Modelica.Icons.VariantsPackage;

      function dp_curvedOverall_DP
        "Pressure loss of curved bend | calculate pressure loss | overall flow regime | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 2nd edition, 1984.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Lac 6 (Verification)
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Bend;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_curvedOverall_IN_con
          IN_con "Input record for function dp_curvedOverall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_curvedOverall_IN_var
          IN_var "Input record for function dp_curvedOverall_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_curvedOverall_DP";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        Real frac_RD=max(MIN, IN_con.R_0/d_hyd) "Relative curvature radius";
        Real k=max(MIN, abs(IN_con.K)/d_hyd) "Relative roughness";
        Real delta=IN_con.delta*180/PI "Angle of turning";
        SI.Length L=IN_con.delta*IN_con.R_0 "Length of flow path";

        //SOURCE_1: p.336, sec.15: definition of flow regime boundaries
        SI.ReynoldsNumber Re_min=1 "Minimum Reynolds number";
        SI.ReynoldsNumber Re_lam_max=6.5e3
          "Maximum Reynolds number for laminar regime (6.5e3)";
        SI.ReynoldsNumber Re_turb_min=4e4
          "Minimum Reynolds number for turbulent regime (4e4)";
        SI.ReynoldsNumber Re_turb_max=3e5
          "Maximum Reynolds number for turbulent regime (3e5)";
        SI.ReynoldsNumber Re_turb_const=1e6
          "Reynolds number for independence on pressure loss coefficient (1e6)";

        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(1e2, 754*Modelica.Math.exp(
            if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //SOURCE_1: p.357, diag. 6-1: coefficients for local resistance coefficient [zeta_LOC]:
        //IN_con.R_0/IN_con.d_hyd <= 3
        Real A1=if delta <= 70 then 0.9*sin(delta*PI/180) else if delta >= 100 then
            0.7 + 0.35*delta/90 else 1.0
          "Coefficient considering effect for angle of turning on zeta_LOC";
        Real A2=if frac_RD > 2.0 then 6e2 else if frac_RD <= 2.0 and frac_RD > 0.55 then
                  (if frac_RD > 1.0 then 1e3 else if frac_RD <= 1.0 and frac_RD > 0.7 then
                  3e3 else 6e3) else 4e3
          "Coefficient considering laminar regime on zeta_LOC";
        Real B1=if frac_RD >= 1.0 then 0.21*(frac_RD)^(-0.5) else 0.21*(frac_RD)^(-2.5)
          "Coefficient considering relative curvature radius (R_0/d_hyd) on zeta_LOC";
        Real C1=1.0
          "Considering relative elongation of cross sectional area on zeta_LOC (here: circular cross sectional area)";
        TYP.LocalResistanceCoefficient zeta_LOC_sharp_turb=max(MIN, A1*B1*C1)
          "Local resistance coefficient for turbulent regime (Re > Re_turb_max)";

        SI.ReynoldsNumber Re=max(Re_min, 4*abs(m_flow)/(PI*IN_con.d_hyd*IN_var.eta))
          "Reynolds number";

        //mass flow rate boundaries for w.r.t. flow regimes
        SI.MassFlowRate m_flow_smooth=Re_min*PI*IN_con.d_hyd*IN_var.eta/4;

        //SOURCE_1: p.357, diag. 6-1, sec. 2 / p.336, sec. 15 (turbulent regime + hydraulically rough):
        //IN_con.R_0/IN_con.d_hyd < 3
        Real C_Re=if frac_RD > 0.7 then 11.5/Re^0.19 else if frac_RD <= 0.7 and
            frac_RD >= 0.55 then 5.45/Re^0.131 else 1 + 4400/Re
          "Correction factor for hydraulically rough turbulent regime (Re_turb_min < Re < Re_turb_max)";

        //SOURCE_1: p.357, diag. 6-1
        //IN_con.R_0/IN_con.d_hyd < 3
        TYP.LocalResistanceCoefficient zeta_LOC_sharp=if Re < Re_lam_leave then A2/Re
             + zeta_LOC_sharp_turb else if Re < Re_turb_min then SMOOTH(
            Re_lam_leave,
            Re_turb_min,
            Re)*(A2/max(Re_lam_leave, Re) + zeta_LOC_sharp_turb) + SMOOTH(
            Re_turb_min,
            Re_lam_leave,
            Re)*(C_Re*zeta_LOC_sharp_turb) else if Re < Re_turb_max then SMOOTH(
            Re_turb_min,
            Re_turb_max,
            Re)*(C_Re*zeta_LOC_sharp_turb) + SMOOTH(
            Re_turb_max,
            Re_turb_min,
            Re)*zeta_LOC_sharp_turb else zeta_LOC_sharp_turb
          "Local resistance coefficient for R_0/d_hyd < 3";

        TYP.LocalResistanceCoefficient zeta_LOC=zeta_LOC_sharp
          "Local resistance coefficient";

        //SOURCE_2: p.191, eq. 8.4: considering surface roughness
        //restriction of lambda_FRI at maximum Reynolds number Re=1e6 (SOURCE_2: p.207, sec. 9.2.4)
        TYP.DarcyFrictionFactor lambda_FRI_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/min(1e6, max(Re_lam_leave, Re))^0.9))^2
          "Darcy friction factor considering surface roughness";

        //SOURCE_2: p.207, sec. 9.2.4: correction factors CF w.r.t.surface roughness
        Real CF_fri=1+SMOOTH(
            Re_lam_max,
            Re_lam_leave,
            Re)*min(1.4, (lambda_FRI_rough*L/d_hyd/zeta_LOC)) + SMOOTH(
            Re_lam_leave,
            Re_lam_max,
            Re) "Correction factor for surface roughness";

        TYP.PressureLossCoefficient zeta_TOT=max(1, CF_fri)*zeta_LOC
          "Pressure loss coefficient";

        //Documentation

      algorithm
        DP := zeta_TOT*(IN_var.rho/2)*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
          m_flow,
          m_flow_smooth,
          2)/max(MIN, (IN_var.rho*A_cross)^2);
      end dp_curvedOverall_DP;

      function dp_curvedOverall_MFLOW
        "Pressure loss of curved bend | calculate mass flow rate | overall flow regime | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 2nd edition, 1984.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Lac 6 (Verification)
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Bend;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_curvedOverall_IN_con
          IN_con "Input record for function dp_curvedOverall_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_curvedOverall_IN_var
          IN_var "Input record for function dp_curvedOverall_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_curvedOverall_MFLOW";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        Real frac_RD=max(MIN, IN_con.R_0/d_hyd) "Relative curvature radius";
        Real k=max(MIN, abs(IN_con.K)/d_hyd) "Relative roughness";
        Real delta=IN_con.delta*180/PI "Angle of turning";
        SI.Length L=IN_con.delta*IN_con.R_0 "Length of flow path";

        //SOURCE_1: p.336, sec.15: definition of flow regime boundaries
        SI.ReynoldsNumber Re_min=1 "Minimum Reynolds number";
        SI.ReynoldsNumber Re_lam_max=6.5e3
          "Maximum Reynolds number for laminar regime (6.5e3)";
        SI.ReynoldsNumber Re_turb_min=4e4
          "Minimum Reynolds number for turbulent regime (4e4)";
        SI.ReynoldsNumber Re_turb_max=3e5
          "Maximum Reynolds number for turbulent regime (3e5)";
        SI.ReynoldsNumber Re_turb_const=1e6
          "Reynolds number for independence on pressure loss coefficient (1e6)";

        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(1e2, 754*Modelica.Math.exp(
            if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //SOURCE_1: p.357, diag. 6-1: coefficients for local resistance coefficient [zeta_LOC]:
        //IN_con.R_0/IN_con.d_hyd <= 3
        Real A1=if delta <= 70 then 0.9*sin(delta/180*PI) else if delta >= 100 then
            0.7 + 0.35*delta/90 else 1.0
          "Coefficient considering effect for angle of turning on zeta_LOC";
        Real A2=if frac_RD > 2.0 then 6e2 else if frac_RD <= 2.0 and frac_RD > 0.55 then
                  (if frac_RD > 1.0 then 1e3 else if frac_RD <= 1.0 and frac_RD > 0.7 then
                  3e3 else 6e3) else 4e3
          "Coefficient considering laminar regime on zeta_LOC";
        Real B1=if frac_RD >= 1.0 then 0.21*(frac_RD)^(-0.5) else 0.21*(frac_RD)^(-2.5)
          "Coefficient considering relative curvature radius (R_0/d_hyd) on zeta_LOC";
        Real C1=1.0
          "Considering relative elongation of cross sectional area on zeta_LOC (here: circular cross sectional area)";
        TYP.LocalResistanceCoefficient zeta_LOC_sharp_turb=max(MIN, A1*B1*C1)
          "Local resistance coefficient for turbulent regime (Re > Re_turb_max)";

        //SOURCE_1: p.357, diag. 6-1: pressure loss boundaries for w.r.t. flow regimes
        //IN_con.R_0/d_hyd <=3
        SI.AbsolutePressure dp_lam_max=(zeta_LOC_sharp_turb + A2/Re_lam_leave)*IN_var.rho
            /2*(Re_lam_leave*IN_var.eta/(IN_var.rho*d_hyd))^2
          "Maximum pressure loss for laminar regime";
        SI.AbsolutePressure dp_turb_min=zeta_LOC_sharp_turb*(if frac_RD > 0.7 then
            11.5/Re_turb_min^0.19 else if frac_RD <= 0.7 and frac_RD >= 0.55 then
            5.45/Re_turb_min^0.131 else 1 + 4400/Re_turb_min)*IN_var.rho/2*(
            Re_turb_min*IN_var.eta/(IN_var.rho*d_hyd))^2
          "Minimum pressure loss for turbulent regime";
        SI.AbsolutePressure dp_turb_max=zeta_LOC_sharp_turb*(if frac_RD > 0.7 then
            11.5/Re_turb_max^0.19 else if frac_RD <= 0.7 and frac_RD >= 0.55 then
            5.45/Re_turb_max^0.131 else 1 + 4400/Re_turb_max)*IN_var.rho/2*(
            Re_turb_max*IN_var.eta/(IN_var.rho*d_hyd))^2
          "Maximum pressure loss for turbulent regime";
        SI.AbsolutePressure dp_turb_const=zeta_LOC_sharp_turb*IN_var.rho/2*(
            Re_turb_const*IN_var.eta/(IN_var.rho*d_hyd))^2
          "Pressure loss for independence of Reynolds number on pressure loss coefficient";

        //SOURCE_1: p.357, diag. 6-1: mean velocities for assumed flow regime
        //IN_con.R_0/d_hyd <=3
        SI.Velocity v_lam=if 1e7*sqrt(abs(zeta_LOC_sharp_turb*abs(dp)*IN_var.rho*
            d_hyd^2)) < abs(A2*IN_var.eta) then 2*abs(dp)*d_hyd/A2/IN_var.eta else (-
            A2/2*IN_var.eta + 0.5*sqrt(max(MIN, (A2*IN_var.eta)^2 + 8*
            zeta_LOC_sharp_turb*abs(dp)*IN_var.rho*d_hyd^2)))/zeta_LOC_sharp_turb/
            IN_var.rho/d_hyd
          "Mean velocity in laminar regime (Re < Re_lam_leave)";
        SI.Velocity v_tra=if 1e7*sqrt(abs(zeta_LOC_sharp_turb*abs(dp_lam_max)*IN_var.rho
            *d_hyd^2)) < abs(A2*IN_var.eta) then 2*abs(dp_lam_max)*d_hyd/A2/IN_var.eta
             else (-A2/2*IN_var.eta + 0.5*sqrt(max(MIN, (A2*IN_var.eta)^2 + 8*
            zeta_LOC_sharp_turb*abs(dp_lam_max)*IN_var.rho*d_hyd^2)))/
            zeta_LOC_sharp_turb/IN_var.rho/d_hyd
          "Mean velocity in transition regime (Re_lam_leave < Re_turb_min)";
        SI.Velocity v_turb=if frac_RD > 0.7 then (max(MIN, abs(dp))/(IN_var.rho/2*
            11.5*zeta_LOC_sharp_turb)*(IN_var.rho*IN_con.d_hyd/max(MIN, IN_var.eta))^
            0.19)^(1/(2 - 0.19)) else if frac_RD > 0.55 and frac_RD < 0.7 then (max(
            MIN, abs(dp))/(IN_var.rho/2*5.45*zeta_LOC_sharp_turb)*(IN_var.rho*IN_con.d_hyd
            /max(MIN, IN_var.eta))^0.131)^(1/(2 - 0.131)) else -2200/(IN_var.rho*
            IN_con.d_hyd/IN_var.eta) + ((-2200/(IN_var.rho*IN_con.d_hyd/max(MIN,
            IN_var.eta)))^2 + 2*abs(max(MIN, dp))/max(MIN, IN_var.rho))^0.5
          "Mean velocity in turbulent regime with dependence on pressure loss coefficient (Re_turb_min < Re < Re_turb_max)";
        SI.Velocity v_turb_const=sqrt(max(MIN, 2*abs(dp)/(IN_var.rho*
            zeta_LOC_sharp_turb)))
          "Mean velocity in turbulent regime with independence on pressure loss coefficient (Re > Re_turb_max)";

        //mean velocity under smooth conditions w.r.t. flow regime
        SI.Velocity v_smooth=if dp < dp_lam_max then v_lam else if dp < dp_turb_min then
                  SMOOTH(
            dp_lam_max,
            dp_turb_min,
            dp)*v_lam + SMOOTH(
            dp_turb_min,
            dp_lam_max,
            dp)*v_turb else if dp < dp_turb_max then v_turb else SMOOTH(
            dp_turb_max,
            dp_turb_const,
            dp)*v_turb + SMOOTH(
            dp_turb_const,
            dp_turb_max,
            dp)*v_turb_const
          "Mean velocity under smooth conditions for R_0/d_hyd < 3";

        SI.ReynoldsNumber Re_smooth=max(Re_min, IN_var.rho*v_smooth*d_hyd/IN_var.eta)
          "Reynolds number under smooth conditions";

        //SOURCE_2: p.191, eq. 8.4: considering surface roughness
        //restriction of lambda_FRI at maximum Reynolds number Re=1e6 (SOURCE_2: p.207, sec. 9.2.4)
        TYP.DarcyFrictionFactor lambda_FRI_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/min(1e6, max(Re_lam_leave, Re_smooth))^0.9))^2
          "Darcy friction factor considering surface roughness";
        TYP.DarcyFrictionFactor lambda_FRI_smooth=0.25/(Modelica.Math.log10(5.74/max(
            Re_lam_leave, Re_smooth)^0.9))^2
          "Darcy friction factor neglecting surface roughness";

        //SOURCE_2: p.207, sec. 9.2.4: correction factors CF w.r.t.surface roughness
        Real CF_3=1+SMOOTH(
            6e3,
            1e3,
            Re_smooth)*min(1.4, (lambda_FRI_rough*L/d_hyd/zeta_LOC_sharp_turb)) + SMOOTH(
            1e3,
            6e3,
            Re_smooth) "Correction factor for surface roughness";

        SI.Velocity velocity=v_smooth/max(1, CF_3)^(0.5)
          "Corrected velocity considering surface roughness";

        //Documentation

      algorithm
        M_FLOW := sign(dp)*IN_var.rho*A_cross*abs(velocity);
      end dp_curvedOverall_MFLOW;

      record dp_curvedOverall_IN_con
        "Input record for function dp_curvedOverall_DP and dp_curvedOverall_MFLOW"

        //bend variables
        extends Modelica.Fluid.Dissipation.Utilities.Records.PressureLoss.Bend;
      end dp_curvedOverall_IN_con;

      record dp_curvedOverall_IN_var
        "Input record for function dp_curvedOverall_DP and dp_curvedOverall_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;
      end dp_curvedOverall_IN_var;

      function dp_edgedOverall_DP
        "Pressure loss of edged bend | calculate pressure loss | overall flow regime | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 2nd edition, 1984.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Lac 6 (Verification)
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Bend;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_edgedOverall_IN_con
          IN_con "Input record for function dp_edgedOverall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_edgedOverall_IN_var
          IN_var "Input record for function dp_edgedOverall_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_edgedOverall_DP";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=PI*d_hyd^2/4 "Circular cross sectional area";
        Real k=max(MIN, abs(IN_con.K)/IN_con.d_hyd) "Relative roughness";
        Real delta=IN_con.delta*180/PI "Angle of turning";

        //definition of flow regime boundaries
        //SOURCE_2: p.207, sec. 9.2.4
        //SOURCE_3: p.Lac 6, fig. 16
        SI.ReynoldsNumber Re_min=1 "Minimum Reynolds number";
        SI.ReynoldsNumber Re_lam_min=5e2
          "Start of transition regime for roughness contribution";
        SI.ReynoldsNumber Re_lam_max=1e4
          "End of transition regime for roughness contribution";
        SI.ReynoldsNumber Re_turb_min=1e5
          "Minimum Reynolds number for Reynolds-dependent transition regime";
        SI.ReynoldsNumber Re_turb_max=2e5
          "Maximum Reynolds number for Reynolds-dependent transition regime (k_Re=1)";
        SI.ReynoldsNumber Re_turb_const=1e6
          "Reynolds number for independence on pressure loss coefficient (1e6)";

        //SOURCE_1: p. 81, sec. 2-2-21: start of transition regime
        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //SOURCE_1: p.366, diag. 6-7
        Real A=0.95 + 33.5/max(MIN, delta)
          "Coefficient considering effect of angle of turning on zeta_LOC";
        Real C1=1
          "Considering relative elongation of cross sectional area on zeta_LOC (here: circular cross sectional area)";

        //SOURCE_1: p.366, diag. 6-7
        TYP.LocalResistanceCoefficient zeta_LOC=max(MIN, 0.95*sin(PI/180*delta/2)^2
             + 2.05*sin(PI/180*delta/2)^4) "Local resistance coefficient";

        //SOURCE_1: p.365: Correction w.r.t. effect of Reynolds number in laminar regime
        Real B=24.8
          "Coefficient considering effect of Reynolds number on zeta_TOT";
        Real exp=0.263
          "Exponent for Reynolds number correction in laminar regime";

        Real v_min=Re_min*IN_var.eta/(IN_var.rho*d_hyd)
          "Minimum mean velocity for linear interpolation";

        SI.Velocity velocity=m_flow/(IN_var.rho*A_cross) "Mean velocity";
        SI.ReynoldsNumber Re=max(Re_min, IN_var.rho*abs(velocity)*d_hyd/IN_var.eta)
          "Reynolds number";

        //SOURCE_2: p.191, eq. 8.4: considering surface roughness
        TYP.DarcyFrictionFactor lambda_FRI_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/max(Re_lam_min, Re)^0.9))
            ^2 "Darcy friction factor considering surface roughness";
        TYP.DarcyFrictionFactor lambda_FRI_smooth=0.25/(Modelica.Math.log10(5.74/max(Re_lam_min, Re)^0.9))^2
          "Darcy friction factor neglecting surface roughness";

        //SOURCE_3: Lac 6, Figure 18
        Real CF_fri= SMOOTH(Re_lam_leave, Re_lam_min, Re)*max(1, min(1.4, (lambda_FRI_rough/
            lambda_FRI_smooth))) + SMOOTH(Re_lam_min, Re_lam_leave, Re)
          "Correction factor for surface roughness";

        //SOURCE_2: p.208, diag. 9.3: Correction w.r.t. effect of Reynolds number
        Real CF_Re=SMOOTH(
            Re_turb_min,
            Re_turb_max,
            Re)*B/Re^exp + SMOOTH(
            Re_turb_max,
            Re_turb_min,
            Re) "Correction factor for Reynolds number";

        TYP.PressureLossCoefficient zeta_TOT=A*C1*zeta_LOC*CF_Re*CF_fri
          "Pressure loss coefficient";

      algorithm
        DP := zeta_TOT*(IN_var.rho/2)*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                velocity,
                v_min,
                2);
      end dp_edgedOverall_DP;

      function dp_edgedOverall_MFLOW
        "Pressure loss of edged bend | calculate mass flow rate | overall flow regime | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 2nd edition, 1984.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002, Section Lac 6 (Verification)
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Bend;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_edgedOverall_IN_con
          IN_con "Input record for function dp_edgedOverall_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Bend.dp_edgedOverall_IN_var
          IN_var "Input record for function dp_edgedOverall_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_edgedOverall_MFLOW";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=IN_con.d_hyd "Hydraulic diameter";
        SI.Area A_cross=PI*d_hyd^2/4 "Circular cross sectional area";
        Real k=max(MIN, abs(IN_con.K)/IN_con.d_hyd) "Relative roughness";
        Real delta=IN_con.delta*180/PI "Angle of turning";

        //definition of flow regime boundaries
        //SOURCE_2: p.207, sec. 9.2.4
        //SOURCE_3: p.Lac 6, fig. 16
        SI.ReynoldsNumber Re_min=1 "Minimum Reynolds number";
        SI.ReynoldsNumber Re_lam_min=500
          "Start of transition regime for roughness contribution";
        SI.ReynoldsNumber Re_lam_max=1e4
          "End of transition regime for roughness contribution";
        SI.ReynoldsNumber Re_turb_min=1e5
          "Minimum Reynolds number for Reynolds-dependent transition regime";
        SI.ReynoldsNumber Re_turb_max=2e5
          "Maximum Reynolds number for Reynolds-dependent transition regime (k_Re=1)";
        SI.ReynoldsNumber Re_turb_const=1e6
          "Reynolds number for independence on pressure loss coefficient (1e6)";

        //SOURCE_1: p. 81, sec. 2-2-21: start of transition regime
        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //SOURCE_1: p.366, diag. 6-7
        Real A=0.95 + 33.5/max(MIN, delta)
          "Coefficient considering effect of angle of turning on zeta_LOC";
        Real C1=1
          "Considering relative elongation of cross sectional area on zeta_LOC (here: circular cross sectional area)";

        //SOURCE_1: p.366, diag. 6-7
        TYP.LocalResistanceCoefficient zeta_LOC=max(MIN, 0.95*sin(PI/180*delta/2)^2
             + 2.05*sin(PI/180*delta/2)^4) "Local resistance coefficient";

        //SOURCE_1: p.365: Correction w.r.t. effect of Reynolds number
        Real B=24.8
          "Coefficient considering effect of Reynolds number on zeta_TOT";
        Real exp=0.263 "Exponent for Reynolds number correction";
        Real pow=(2 - exp) "Pressure loss = f(mass flow rate^pow)";
      //   Real k_Re = B/(max(MIN, velocity)*IN_con.d_hyd*IN_var.rho)^exp*IN_var.eta^exp;

        SI.Velocity v_min = Re_min*IN_var.eta/(IN_var.rho*d_hyd)
          "Minimum mean velocity for regularization";

        SI.Pressure dp_min=A*C1*zeta_LOC*(B/2)*(d_hyd/IN_var.eta)^(-exp)*IN_var.rho^(1 - exp)
            *v_min^(pow)
          "Linear smoothing of mass flow rate for decreasing pressure loss";

        SI.Velocity v_lam_min = Re_lam_min*IN_var.eta/(IN_var.rho*d_hyd)
          "Mean velocity for starting of transition to roughness regime";
        SI.Velocity v_lam_leave = Re_lam_leave*IN_var.eta/(IN_var.rho*d_hyd)
          "Mean velocity for end of transition to roughness regime";

        SI.Pressure dp_lam_min=A*C1*zeta_LOC*(B/2)*(d_hyd/IN_var.eta)^(-exp)*IN_var.rho^(1 - exp)
            *v_lam_min^(pow)
          "Pressure loss for starting of transition to roughness regime";

        TYP.DarcyFrictionFactor lambda_lam_leave_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/Re_lam_leave^0.9))^2
          "Darcy friction factor considering surface roughness at Re_lem_leave";
        TYP.DarcyFrictionFactor lambda_lam_leave_smooth=0.25/(Modelica.Math.log10(5.74/Re_lam_leave^0.9))^2
          "Darcy friction factor neglecting surface roughness at Re_lam_leave";

        SI.Pressure dp_lam_leave=A*C1*zeta_LOC*(B/2)*max(1, min(1.4, (lambda_lam_leave_rough/
            lambda_lam_leave_smooth)))*(d_hyd/IN_var.eta)^(-exp)*IN_var.rho^(1 - exp)
            *v_lam_leave^(pow)
          "Pressure loss at end of transition to surface roughness regime";

        TYP.DarcyFrictionFactor lambda_turb_min_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/Re_turb_min^0.9))^2
          "Darcy friction factor considering surface roughness at starting transition to constant turbulent regime";
        TYP.DarcyFrictionFactor lambda_turb_min_smooth=0.25/(Modelica.Math.log10(5.74/Re_turb_min^0.9))^2
          "Darcy friction factor neglecting surface roughness at starting transition to constant turbulent regime";

        TYP.DarcyFrictionFactor lambda_turb_max_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/Re_turb_max^0.9))^2
          "Darcy friction factor considering surface roughness at starting transition to constant turbulent regime";
        TYP.DarcyFrictionFactor lambda_turb_max_smooth=0.25/(Modelica.Math.log10(5.74/Re_turb_max^0.9))^2
          "Darcy friction factor neglecting surface roughness at starting transition to constant turbulent regime";

        SI.Velocity v_turb_min = Re_turb_min*IN_var.eta/(IN_var.rho*d_hyd)
          "Mean velocity for starting of transition to constant turbulent regime";

        SI.Velocity v_turb_max = Re_turb_max*IN_var.eta/(IN_var.rho*d_hyd)
          "Mean velocity for end of transition to constant turbulent regime";

        SI.Pressure dp_turb_min=A*C1*zeta_LOC*(B/2)*max(1, min(1.4, (lambda_turb_min_rough/
            lambda_turb_min_smooth)))*(d_hyd/IN_var.eta)^(-exp)*IN_var.rho^(1 - exp)
            *v_turb_min^(pow)
          "Pressure loss at starting of transition to constant turbulent regime";

        SI.Pressure dp_turb_max=A*C1*zeta_LOC*max(1, min(1.4, (lambda_turb_max_rough/
            lambda_turb_max_smooth)))*IN_var.rho/2*v_turb_max^2
          "Pressure loss at end of transition to constant turbulent regime";

        SI.Velocity v_turb=(A*C1*zeta_LOC*IN_var.rho/2)^(-0.5)*
            Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
            abs(dp),
            dp_min,
            0.5) "Mean velocity under turbulent conditions";

        SI.Velocity v_lam=(2*(d_hyd/IN_var.eta)^exp/(A*C1*zeta_LOC*B*(IN_var.rho)^(1 - exp)))^(1/pow)*
            Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
            abs(dp),
            dp_min,
            1/pow) "Mean velocity under laminar conditions";

        //mean velocity under smooth conditions w.r.t. flow regime
        SI.Velocity v_smooth=if abs(dp) > dp_turb_max then v_turb
            else if abs(dp) < dp_turb_min then v_lam
            else SMOOTH(
            dp_turb_max,
            dp_turb_min,
            abs(dp))*v_turb + SMOOTH(
            dp_turb_min,
            dp_turb_max,
            abs(dp))*v_lam "Mean velocity under smooth conditions";

        SI.ReynoldsNumber Re_smooth=max(Re_min, IN_var.rho*v_smooth*d_hyd/IN_var.eta)
          "Reynolds number under smooth conditions";

        //SOURCE_2: p.191, eq. 8.4: considering surface roughness
        TYP.DarcyFrictionFactor lambda_FRI_rough=0.25/(Modelica.Math.log10(k/(3.7*
            IN_con.d_hyd) + 5.74/max(Re_lam_min, Re_smooth)^0.9))
            ^2 "Darcy friction factor considering surface roughness";
        TYP.DarcyFrictionFactor lambda_FRI_smooth=0.25/(Modelica.Math.log10(5.74/max(Re_lam_min, Re_smooth)^0.9))^2
          "Darcy friction factor neglecting surface roughness";

        //SOURCE_3: Lac 6, Figure 18
        Real CF_fri= SMOOTH(dp_lam_leave, dp_lam_min, abs(dp))*max(1, min(1.4, (lambda_FRI_rough/
            lambda_FRI_smooth))) + SMOOTH(dp_lam_min, dp_lam_leave, abs(dp))
          "Correction factor for surface roughness";

        SI.Velocity velocity=v_smooth/max(1, CF_fri)^(0.5)
          "Corrected velocity considering surface roughness";

      algorithm
          M_FLOW := sign(dp)*IN_var.rho*A_cross*velocity;
      end dp_edgedOverall_MFLOW;

      record dp_edgedOverall_IN_con
        "Input record for function dp_edgedOverall_DP and dp_edgedOverall_MFLOW"

        //edged bend variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.PressureLoss.EdgedBend;
      end dp_edgedOverall_IN_con;

      record dp_edgedOverall_IN_var
        "Input record for function dp_edgedOverall_DP and dp_edgedOverall_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;
      end dp_edgedOverall_IN_var;
    end Bend;

    package Channel "Package for pressure loss calculation of channels"
    extends Modelica.Icons.VariantsPackage;

      function dp_internalFlowOverall_DP
        "Pressure loss of internal flow | calculate pressure loss | overall flow regime | surface roughness | several geometries"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 1978.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Channel;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Channel.dp_internalFlowOverall_IN_con
          IN_con "Input record for function dp_internalFlowOverall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Channel.dp_internalFlowOverall_IN_var
          IN_var "Input record for function dp_internalFlowOverall_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_internalFlowOverall_DP";

      protected
        type TYP =
            Modelica.Fluid.Dissipation.Utilities.Types.GeometryOfInternalFlow;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=max(MIN, if IN_con.geometry == TYP.Annular then (PI/4)*((
            IN_con.D_ann)^2 - (IN_con.d_ann)^2) else if IN_con.geometry == TYP.Circular then
                  PI/4*(IN_con.d_cir)^2 else if IN_con.geometry == TYP.Elliptical then
                  PI*IN_con.a_ell*IN_con.b_ell else if IN_con.geometry == TYP.Rectangular then
                  IN_con.a_rec*IN_con.b_rec else if IN_con.geometry == TYP.Isosceles then
                  0.5*(IN_con.a_tri*IN_con.h_tri) else 0)
          "Cross sectional area";
        SI.Length perimeter=max(MIN, if IN_con.geometry == TYP.Annular then PI*(
            IN_con.D_ann + IN_con.d_ann) else if IN_con.geometry == TYP.Circular then
                  PI*IN_con.d_cir else if IN_con.geometry == TYP.Elliptical then PI*(
            IN_con.a_ell + IN_con.b_ell) else if IN_con.geometry == TYP.Rectangular then
                  2*(IN_con.a_rec + IN_con.b_rec) else if IN_con.geometry == TYP.Isosceles then
                  IN_con.a_tri + 2*sqrt((IN_con.h_tri)^2 + (IN_con.a_tri/2)^2) else 0)
          "Perimeter";
        SI.Diameter d_hyd=4*A_cross/perimeter "Hydraulic diameter";
        Real beta=IN_con.beta*180/PI "Top angle";

        //SOURCE_2: p.138, sec 8.5
        Real Dd_ann=min(max(MIN, IN_con.d_ann), IN_con.D_ann)/max(MIN, max(IN_con.d_ann,
            IN_con.D_ann))
          "Ratio of small to large diameter of annular geometry";
        Real CF_ann=98.7378*Dd_ann^0.0589
          "Correction factor for annular geometry";
        Real ab_rec=min(IN_con.a_rec, IN_con.b_rec)/max(MIN, max(IN_con.a_rec, IN_con.b_rec))
          "Aspect ratio of rectangular geometry";
        Real CF_rec=-59.85*(ab_rec)^3 + 148.67*(ab_rec)^2 - 128.1*(ab_rec) + 96.1
          "Correction factor for rectangular geometry";
        Real ab_ell=min(IN_con.a_ell, IN_con.b_ell)/max(MIN, max(IN_con.a_ell, IN_con.b_ell))
          "Ratio of small to large length of annular geometry";
        Real CF_ell=-169.2211*(ab_ell)^4 + 260.9028*(ab_ell)^3 - 113.7890*(ab_ell)^2
             + 9.2588*(ab_ell)^1 + 78.7124
          "Correction factor for elliptical geometry";
        Real CF_tri=-0.0013*(min(90, beta))^2 + 0.1577*(min(90, beta)) + 48.5575
          "Correction factor for triangular geometry";
        Real CF_lam=if IN_con.geometry == TYP.Annular then CF_ann else if IN_con.geometry
             == TYP.Circular then 64 else if IN_con.geometry == TYP.Elliptical then
            CF_ell else if IN_con.geometry == TYP.Rectangular then CF_rec else if
            IN_con.geometry == TYP.Isosceles then CF_tri else 0
          "Correction factor for laminar flow";

        //SOURCE_1: p.81, fig. 2-3, sec 21-22: definition of flow regime boundaries
        Real k=max(MIN, abs(IN_con.K)/d_hyd) "Relative roughness";
        SI.ReynoldsNumber Re_lam_min=1e3
          "Minimum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_max=2090*(1/max(0.007, k))^0.0635
          "Maximum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //Adapted mass flow rate for function dp_turbulent of a straight pipe
        SI.MassFlowRate m_flow_turb=m_flow*(PI/4*d_hyd^2)/A_cross
          "Mass flow rate for turbulent calculation";
        SI.Velocity velocity=m_flow/(IN_var.rho*A_cross)
          "Velocity of internal flow";
        SI.ReynoldsNumber Re=IN_var.rho*abs(velocity)*d_hyd/IN_var.eta;

      protected
        Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_con
          IN_2_con(
          final roughness=IN_con.roughness,
          final d_hyd=d_hyd,
          final K=IN_con.K,
          final L=IN_con.L) "Input record for turbulent regime"
        Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var
          IN_2_var(                                                                     final eta=
                IN_var.eta, final rho=IN_var.rho)
          "Input record for turbulent regime"

        //Documentation

      algorithm
        DP := SMOOTH(
                Re_lam_min,
                Re_lam_max,
                Re)*(CF_lam/2)*IN_con.L/d_hyd^2*velocity*IN_var.eta + SMOOTH(
                Re_lam_max,
                Re_lam_min,
                Re)*Dissipation.PressureLoss.StraightPipe.dp_turbulent_DP(
                IN_2_con,
                IN_2_var,
                m_flow_turb);
      end dp_internalFlowOverall_DP;

      function dp_internalFlowOverall_MFLOW
        "Pressure loss of internal flow | calculate mass flow rate | overall flow regime | surface roughness | several geometries"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.Channel;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Channel.dp_internalFlowOverall_IN_con
          IN_con "Input record for function dp_internalFlowOverall_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Channel.dp_internalFlowOverall_IN_var
          IN_var "Input record for function dp_internalFlowOverall_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW "Output of function dp_overall_MFLOW";

      protected
        type TYP1 =
            Modelica.Fluid.Dissipation.Utilities.Types.GeometryOfInternalFlow;
        type TYP2 = Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=max(MIN, if IN_con.geometry == TYP1.Annular then (PI/4)*((
            IN_con.D_ann)^2 - (IN_con.d_ann)^2) else if IN_con.geometry == TYP1.Circular then
                  PI/4*(IN_con.d_cir)^2 else if IN_con.geometry == TYP1.Elliptical then
                  PI*IN_con.a_ell*IN_con.b_ell else if IN_con.geometry == TYP1.Rectangular then
                  IN_con.a_rec*IN_con.b_rec else if IN_con.geometry == TYP1.Isosceles then
                  0.5*(IN_con.a_tri*IN_con.h_tri) else 0)
          "Cross sectional area";
        SI.Length perimeter=max(MIN, if IN_con.geometry == TYP1.Annular then PI*(
            IN_con.D_ann + IN_con.d_ann) else if IN_con.geometry == TYP1.Circular then
                  PI*IN_con.d_cir else if IN_con.geometry == TYP1.Elliptical then PI*
            (IN_con.a_ell + IN_con.b_ell) else if IN_con.geometry == TYP1.Rectangular then
                  2*(IN_con.a_rec + IN_con.b_rec) else if IN_con.geometry == TYP1.Isosceles then
                  IN_con.a_tri + 2*sqrt((IN_con.h_tri)^2 + (IN_con.a_tri/2)^2) else 0)
          "Perimeter";
        SI.Diameter d_hyd=4*A_cross/perimeter "Hydraulic diameter";
        Real beta=IN_con.beta*180/PI "Top angle";

        //SOURCE_2: p.138, sec 8.5
        Real Dd_ann=min(max(MIN, IN_con.d_ann), IN_con.D_ann)/max(MIN, max(IN_con.d_ann,
            IN_con.D_ann))
          "Ratio of small to large diameter of annular geometry";
        Real CF_ann=98.7378*Dd_ann^0.0589
          "Correction factor for annular geometry";
        Real ab_rec=min(IN_con.a_rec, IN_con.b_rec)/max(MIN, max(IN_con.a_rec, IN_con.b_rec))
          "Aspect ratio of rectangular geometry";
        Real CF_rec=-59.85*(ab_rec)^3 + 148.67*(ab_rec)^2 - 128.1*(ab_rec) + 96.1
          "Correction factor for rectangular geometry";
        Real ab_ell=min(IN_con.a_ell, IN_con.b_ell)/max(MIN, max(IN_con.a_ell, IN_con.b_ell))
          "Ratio of small to large length of annular geometry";
        Real CF_ell=-169.2211*(ab_ell)^4 + 260.9028*(ab_ell)^3 - 113.7890*(ab_ell)^2
             + 9.2588*(ab_ell)^1 + 78.7124
          "Correction factor for elliptical geometry";
        Real CF_tri=-0.0013*(min(90, beta))^2 + 0.1577*(min(90, beta)) + 48.5575
          "Correction factor for triangular geometry";
        Real CF_lam=if IN_con.geometry == TYP1.Annular then CF_ann else if IN_con.geometry
             == TYP1.Circular then 64 else if IN_con.geometry == TYP1.Elliptical then
                  CF_ell else if IN_con.geometry == TYP1.Rectangular then CF_rec else
                  if IN_con.geometry == TYP1.Isosceles then CF_tri else 0
          "Correction factor for laminar flow";

        //SOURCE_1: p.81, fig. 2-3, sec 21-22: definition of flow regime boundaries
        Real k=max(MIN, abs(IN_con.K)/d_hyd) "Relative roughness";
        SI.ReynoldsNumber Re_lam_min=1e3
          "Minimum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_max=2090*(1/max(0.007, k))^0.0635
          "Maximum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_turb_min=4e3
          "Minimum Reynolds number for turbulent regime";

        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //determining Darcy friction factor out of pressure loss calculation for straight pipe:
        //dp = lambda_FRI*L/d_hyd*(rho/2)*velocity^2 and assuming lambda_FRI == lambda_FRI_calc/Re^2
        TYP.DarcyFrictionFactor lambda_FRI_calc=2*abs(dp)*d_hyd^3*IN_var.rho/(IN_con.L
            *IN_var.eta^2) "Adapted Darcy friction factor";

        //SOURCE_3: p.Lab 1, eq. 5: determine Re assuming laminar regime
        SI.ReynoldsNumber Re_lam=lambda_FRI_calc/CF_lam
          "Reynolds number assuming laminar regime";

        //SOURCE_3: p.Lab 2, eq. 10: determine Re assuming turbulent regime (Colebrook-White)
        SI.ReynoldsNumber Re_turb=if IN_con.roughness == TYP2.Neglected then (max(MIN,
            lambda_FRI_calc)/0.3164)^(1/1.75) else -2*sqrt(max(lambda_FRI_calc, MIN))
            *Modelica.Math.log10(2.51/sqrt(max(lambda_FRI_calc, MIN)) + k/3.7)
          "Reynolds number assuming turbulent regime";

        //determine actual flow regime
        SI.ReynoldsNumber Re_check=if Re_lam < Re_lam_leave then Re_lam else Re_turb;
        //determine Re for transition regime
        SI.ReynoldsNumber Re_trans=if Re_lam >= Re_lam_leave then
            Modelica.Fluid.Dissipation.Utilities.Functions.General.CubicInterpolation_Re(
            Re_check,
            Re_lam_leave,
            Re_turb_min,
            k,
            lambda_FRI_calc) else 0;
        //determine actual Re
        SI.ReynoldsNumber Re=if Re_lam < Re_lam_leave then Re_lam else if Re_turb >
            Re_turb_min then Re_turb else Re_trans;

        Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_con
          IN_2_con(
          final roughness=IN_con.roughness,
          final d_hyd=d_hyd,
          final K=IN_con.K,
          final L=IN_con.L) "Input record for turbulent regime"
        Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var
          IN_2_var(                                                                     final eta=
                IN_var.eta, final rho=IN_var.rho)
          "Input record for turbulent regime"

        //Documentation

      algorithm
        M_FLOW := SMOOTH(
                Re_lam_min,
                Re_turb,
                Re)*IN_var.rho*A_cross*(dp*(2/CF_lam)*(d_hyd^2/IN_con.L)*(1/
          IN_var.eta)) + SMOOTH(
                Re_turb,
                Re_lam_min,
                Re)*(A_cross/((PI/4)*d_hyd^2))*
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_turbulent_MFLOW(
                IN_2_con,
                IN_2_var,
                dp);
      end dp_internalFlowOverall_MFLOW;

      record dp_internalFlowOverall_IN_con
        "Input record for function dp_internalFlowOverall_DP and dp_internalFlowOverall_MFLOW"

        //channel variables
        Modelica.Fluid.Dissipation.Utilities.Types.Roughness roughness=Dissipation.Utilities.Types.Roughness.Considered
          "Choice of considering surface roughness"
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.PressureLoss.Geometry;
      end dp_internalFlowOverall_IN_con;

      record dp_internalFlowOverall_IN_var
        "Input record for function dp_internalFlowOverall_DP and dp_internalFlowOverall_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;
      end dp_internalFlowOverall_IN_var;
    end Channel;

    package General "Package for generic pressure loss calculations"
    extends Modelica.Icons.VariantsPackage;

      function dp_idealGas_DP
        "Generic pressure loss | calculate pressure loss | ideal gas | mean density"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;
        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_idealGas_IN_con
          IN_con "Input record for function dp_idealGas_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_idealGas_IN_var
          IN_var "Input record for function dp_idealGas_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_idealGas_DP";

      protected
        Real Km_internal=IN_con.Km "Coefficient for pressure loss";

        SI.Density rho_internal=IN_var.p_m/(IN_con.R_s*IN_var.T_m)
          "Mean density";
        SI.VolumeFlowRate V_flow=m_flow/rho_internal "Volume flow rate [m3/s]";
        SI.VolumeFlowRate V_flow_min=(IN_con.R_s/Km_internal)^(1/IN_con.exp)*
            rho_internal^(1/IN_con.exp - 1)*IN_con.dp_smooth^(1/IN_con.exp)
          "Start of approximation for decreasing volume flow rate";

        //Documentation

      algorithm
        DP := (Km_internal/IN_con.R_s)*(rho_internal)^(IN_con.exp - 1)*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                V_flow,
                V_flow_min,
                IN_con.exp);
      end dp_idealGas_DP;

      function dp_idealGas_MFLOW
        "Generic pressure loss | calculate mass flow rate | ideal gas | mean density"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;
        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_idealGas_IN_con
          IN_con "Input record for function dp_idealGas_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_idealGas_IN_var
          IN_var "Input record for function dp_idealGas_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW "Output for function dp_idealGas_MFLOW";

      protected
        Real Km_internal=IN_con.Km "Coefficient for pressure loss";

        SI.Density rho_internal=IN_var.p_m/(IN_con.R_s*IN_var.T_m)
          "Mean density";

        //Documentation

      algorithm
        M_FLOW := (IN_con.R_s/Km_internal)^(1/IN_con.exp)*(rho_internal)^(1/
          IN_con.exp)*Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                IN_con.dp_smooth,
                1/IN_con.exp);
      end dp_idealGas_MFLOW;

      record dp_idealGas_IN_con
        "Input record for function dp_idealGas_DP and dp_idealGas_MFLOW"

        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.IdealGas_con;

        //linearisation
        SI.Pressure dp_smooth(min=Modelica.Constants.eps) = 1
          "Start linearisation for smaller pressure loss"

      end dp_idealGas_IN_con;

      record dp_idealGas_IN_var
        "Input record for function dp_idealGas_DP and dp_idealGas_MFLOW"

        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.IdealGas_var;

      end dp_idealGas_IN_var;

      function dp_nominalDensityViscosity_DP
        "Generic pressure loss | calculate mass flow rate | nominal operation point | pressure loss law (exponent) | density and dynamic viscosity dependence"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalDensityViscosity_IN_con
          IN_con "Input record for function dp_nominalDensityViscosity_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalDensityViscosity_IN_var
          IN_var "Input record for function dp_nominalDensityViscosity_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP
          "Output for function dp_nominalDensityViscosity_DP";

      protected
        SI.MassFlowRate m_flow_smooth=(max(1, 0.01*IN_con.dp_nom)*IN_var.rho/IN_con.rho_nom
            *(1/IN_var.eta*IN_con.eta_nom)^(IN_con.exp_eta)*(1/IN_con.m_flow_nom))^(1
            /IN_con.exp) "Start of approximation for decreasing mass flow rate";

        //Documentation

      algorithm
        DP := if IN_con.exp > 1.0 or IN_con.exp < 1.0 then
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                m_flow,
                m_flow_smooth,
                IN_con.exp)*(IN_var.eta/IN_con.eta_nom)^IN_con.exp_eta*IN_con.rho_nom
          /IN_var.rho*IN_con.dp_nom*(1/IN_con.m_flow_nom)^(IN_con.exp) else
          m_flow/IN_con.m_flow_nom*(IN_var.eta/IN_con.eta_nom)^IN_con.exp_eta*
          IN_con.rho_nom/IN_var.rho*IN_con.dp_nom;
      end dp_nominalDensityViscosity_DP;

      function dp_nominalDensityViscosity_MFLOW
        "Generic pressure loss | calculate M_FLOW (compressible) | nominal operation point | pressure loss law (exponent) | density and dynamic viscosity dependence"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalDensityViscosity_IN_con
          IN_con "Input record for function dp_nominalDensityViscosity_MFLOW"

        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalDensityViscosity_IN_var
          IN_var "Input record for function dp_nominalDensityViscosity_MFLOW"

        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_nominalDensityViscosity_MFLOW";

        //Documentation

      algorithm
        M_FLOW := if IN_con.exp > 1.0 or IN_con.exp < 1.0 then
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                0.01*IN_con.dp_nom,
                1/IN_con.exp)*(IN_con.eta_nom/IN_var.eta)^(IN_con.exp_eta/
          IN_con.exp)*(1/IN_con.dp_nom*IN_var.rho/IN_con.rho_nom)^(1/IN_con.exp)
          *IN_con.m_flow_nom else dp/IN_con.dp_nom*(IN_con.eta_nom/IN_var.eta)^
          (IN_con.exp_eta)*IN_var.rho/IN_con.rho_nom*IN_con.m_flow_nom;
      end dp_nominalDensityViscosity_MFLOW;

      record dp_nominalDensityViscosity_IN_con
        "Output record for function dp_nominalDensityViscosity_DP and dp_nominalDensityViscosity_MFLOW"

        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.NominalDensityViscosity;
      end dp_nominalDensityViscosity_IN_con;

      record dp_nominalDensityViscosity_IN_var
        "Output record for function dp_nominalDensityViscosity_DP and dp_nominalDensityViscosity_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;
      end dp_nominalDensityViscosity_IN_var;

      function dp_nominalPressureLossLawDensity_DP
        "Generic pressure loss | calculate pressure loss | nominal operation point | pressure loss law (coefficient and exponent) | density dependence"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalPressureLossLawDensity_IN_con
          IN_con
          "Input record for function dp_nominalPressureLossLawDensity_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalPressureLossLawDensity_IN_var
          IN_var
          "Input record for function dp_nominalPressureLossLawDensity_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP
          "Output for function dp_nominalPressureLossLawDensity_yesAJac_DP";

      protected
        Real exp_density=if IN_con.target ==Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate then
                  1 - IN_con.exp else 1
          "Exponent of density fraction (rho/rho_nom)";
        SI.MassFlowRate m_flow_nom=if IN_con.target ==Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate then
                  IN_con.m_flow_nom else IN_var.rho*IN_con.V_flow_nom
          "Nominal mean flow velocity at operation point";

        SI.MassFlowRate m_flow_linear=(0.01*(IN_con.zeta_TOT_nom/IN_var.zeta_TOT)*(
            IN_con.rho_nom/IN_var.rho)^(exp_density)*(IN_con.A_cross/IN_con.A_cross_nom)
            ^(IN_con.exp)*IN_con.m_flow_nom)^(1/IN_con.exp)
          "Start of approximation for decreasing mass flow rate";

        //Documentation

      algorithm
        DP := if IN_con.exp > 1.0 or IN_con.exp < 1.0 then
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                m_flow,
                m_flow_linear,
                IN_con.exp)*IN_con.dp_nom*(IN_var.zeta_TOT/IN_con.zeta_TOT_nom)
          *(IN_var.rho/IN_con.rho_nom)^(exp_density)*(IN_con.A_cross_nom/IN_con.A_cross)
          ^(IN_con.exp)*(1/IN_con.m_flow_nom)^(IN_con.exp) else IN_con.dp_nom*(
          IN_var.zeta_TOT/IN_con.zeta_TOT_nom)*(IN_var.rho/IN_con.rho_nom)^(
          exp_density)*(IN_con.A_cross_nom/IN_con.A_cross)^(1)*(m_flow/IN_con.m_flow_nom)
          ^(1);
      end dp_nominalPressureLossLawDensity_DP;

      function dp_nominalPressureLossLawDensity_MFLOW
        "Generic pressure loss | calculate mass flow rate | nominal operation point | pressure loss law (coefficient and exponent) | density dependence"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalPressureLossLawDensity_IN_con
          IN_con
          "Input record for function dp_nominalPressureLossLawDensity_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_nominalPressureLossLawDensity_IN_var
          IN_var
          "Input record for function dp_nominalPressureLossLawDensity_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_nominalPressurelosslawDensity_MFLOW";

      protected
        Real exp_density=if IN_con.target ==Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate then
                  1 - IN_con.exp else 1
          "Exponent of density fraction (rho/rho_nom)";
        SI.MassFlowRate m_flow_nom=if IN_con.target ==Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate then
                  IN_con.m_flow_nom else IN_var.rho*IN_con.V_flow_nom
          "Nominal mean flow velocity at operation point";

        //Documentation

      algorithm
        M_FLOW := if IN_con.exp > 1.0 or IN_con.exp < 1.0 then
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                0.01*IN_con.dp_nom,
                1/IN_con.exp)*IN_con.m_flow_nom*(IN_con.A_cross/IN_con.A_cross_nom)
          *(IN_con.rho_nom/IN_var.rho)^(exp_density/IN_con.exp)*((1/IN_con.dp_nom)
          *(IN_con.zeta_TOT_nom/IN_var.zeta_TOT))^(1/IN_con.exp) else IN_con.m_flow_nom
          *(IN_con.A_cross/IN_con.A_cross_nom)*(IN_con.rho_nom/IN_var.rho)^(
          exp_density/1)*((dp/IN_con.dp_nom)*(IN_con.zeta_TOT_nom/IN_var.zeta_TOT))
          ^(1/1);
      end dp_nominalPressureLossLawDensity_MFLOW;

      record dp_nominalPressureLossLawDensity_IN_con
        "Input record for function dp_nominalPressureLossLawDensity_DP and dp_nominalPressureLossLawDensity_MFLOW"

        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.NominalPressureLossLawDensity_con;
      end dp_nominalPressureLossLawDensity_IN_con;

      record dp_nominalPressureLossLawDensity_IN_var
        "Input record for function dp_nominalPressureLossLawDensity_DP and dp_nominalPressureLossLawDensity_MFLOW"

        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.NominalPressureLossLawDensity_var;

        //fluid property variables
        SI.Density rho "Density of fluid"
      end dp_nominalPressureLossLawDensity_IN_var;

      function dp_pressureLossCoefficient_DP
        "Generic pressure loss | calculate pressure loss | pressure loss coefficient (zeta_TOT)"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_pressureLossCoefficient_IN_con
          IN_con "Input record for dp_pressureLossCoefficient_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_pressureLossCoefficient_IN_var
          IN_var "Input record for dp_pressureLossCoefficient_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP
          "Output for function dp_pressureLossCoefficient_DP";

        //Documentation

      algorithm
        DP := 0.5*IN_var.zeta_TOT*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                m_flow,
                sqrt(IN_con.dp_smooth/(0.5*IN_var.zeta_TOT*IN_var.rho))*IN_var.rho
            *IN_con.A_cross,
                2)/(IN_var.rho*(IN_con.A_cross)^2);
      end dp_pressureLossCoefficient_DP;

      function dp_pressureLossCoefficient_MFLOW
        "Generic pressure loss | calculate mass flow rate | pressure loss coefficient (zeta_TOT)"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_pressureLossCoefficient_IN_con
          IN_con "Input record for function dp_pressureLossCoefficient_MFLOW"

        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_pressureLossCoefficient_IN_var
          IN_var "Input record for function dp_pressureLossCoefficient_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_pressureLossCoefficientt_MFLOW";

        //Documentation

      algorithm
        M_FLOW := IN_var.rho*IN_con.A_cross*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                IN_con.dp_smooth,
                0.5)/sqrt(0.5*IN_var.zeta_TOT*IN_var.rho);
      end dp_pressureLossCoefficient_MFLOW;

      record dp_pressureLossCoefficient_IN_con
        "Input record for function dp_pressureLossCoefficient_DP and dp_pressureLossCoefficient_MFLOW"
        extends Modelica.Icons.Record;

        //generic variables
        SI.Area A_cross=Modelica.Constants.pi*0.1^2/4 "Cross sectional area"

        //linearisation
        SI.Pressure dp_smooth=1
          "Start linearisation for decreasing pressure loss"
      end dp_pressureLossCoefficient_IN_con;

      record dp_pressureLossCoefficient_IN_var
        "Input record for function dp_pressureLossCoefficient_DP and dp_pressureLossCoefficient_MFLOW"
        extends Modelica.Icons.Record;

        //generic variables
        TYP.PressureLossCoefficient zeta_TOT=0.02*1/0.1
          "Pressure loss coefficient"

        //fluid property variables
        SI.Density rho "Density of fluid"
      end dp_pressureLossCoefficient_IN_var;

      function dp_volumeFlowRate_DP
        "Generic pressure loss | calculate pressure loss | quadratic function (dp=a*V_flow^2 + b*V_flow)"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_volumeFlowRate_IN_con
          IN_con "Input record for function dp_volumeFlowRate_DP"

        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_volumeFlowRate_IN_var
          IN_var "Input record for function dp_volumeFlowRate_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_volumeFlowRate_DP";

      protected
        Real a=abs(IN_con.a);
        Real b=abs(IN_con.b);

        SI.VolumeFlowRate V_flow=m_flow/max(Modelica.Constants.eps, IN_var.rho)
          "Volume flow rate";
        SI.Pressure dp_min=max(Modelica.Constants.eps, abs(IN_con.dp_min))
          "Start of approximation for decreasing pressure loss";
        SI.VolumeFlowRate V_flow_smooth=if a > 0 and b <= 0 then sqrt(dp_min/a) else 0
          "Start of approximation for decreasing volume flow rate";

        //Documentation

      algorithm
        assert(a+b>0, "Please provide non-zero factors for either a or b of function dp=a*V_flow^2 + b*V_flow");

        // Please note the function is reqularized for zero flow with the parameter b if b>0.

        DP := a*(if a>0 and b<=0 then Dissipation.Utilities.Functions.General.SmoothPower(
                V_flow,
                V_flow_smooth,
                2) elseif a>0 and b>0 then V_flow*abs(V_flow) else 0) + b*V_flow;
      end dp_volumeFlowRate_DP;

      function dp_volumeFlowRate_MFLOW
        "Generic pressure loss | calculate mass flow rate | quadratic function (dp=a*V_flow^2 + b*V_flow)"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.General;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_volumeFlowRate_IN_con
          IN_con "Input record for function dp_volumeFlowRate_MFLOW"

        input
          Modelica.Fluid.Dissipation.PressureLoss.General.dp_volumeFlowRate_IN_var
          IN_var "Input record for function dp_volumeFlowRate_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_volumeFlowRate_MFLOW";

      protected
        Real a=abs(IN_con.a);
        Real b=abs(IN_con.b);

        SI.Pressure dp_min=max(Modelica.Constants.eps, abs(IN_con.dp_min))
          "Start of approximation for decreasing pressure loss";

        //Documentation

      algorithm
        assert(a+b>0, "Please provide non-zero factors for either a or b of function dp=a*V_flow^2 + b*V_flow");

        // Please note the function is reqularized for zero flow with the parameter b if b>0.

        M_FLOW := IN_var.rho*(if a>0 and b<=0 then
                Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                (1/a)*dp,
                (1/a)*dp_min,
                0.5)
                elseif a>0 and b>0 then
                sign(dp)*(-b/(2*a) + sqrt((b/(2*a))^2 + (1/a)*abs(dp)))
                else b*dp);
      end dp_volumeFlowRate_MFLOW;

      record dp_volumeFlowRate_IN_con
        "Input record for function dp_volumeFlowRate_DP and dp_volumeFlowRate_MFLOW"

        //generic variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.QuadraticVFLOW;

        SI.Pressure dp_min=0.1
          "Start of approximation for decreasing pressure loss (only used for b=0)";

      end dp_volumeFlowRate_IN_con;

      record dp_volumeFlowRate_IN_var
        "Input record for function dp_volumeFlowRate_DP and dp_volumeFlowRate_MFLOW"
        extends Modelica.Icons.Record;

        SI.Density rho "Density of fluid"

      end dp_volumeFlowRate_IN_var;
    end General;

    package Orifice "Package for pressure loss calculation of orifices"
    extends Modelica.Icons.VariantsPackage;

      function dp_suddenChange_DP
        "Pressure loss of orifice with sudden change in cross sectional area | calculate pressure loss | turbulent flow regime | smooth surface | arbitrary cross sectional area | without baffles | sharp edge"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Orifice;

        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_suddenChange_IN_con
          IN_con "Input record for function dp_suddenChange_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_suddenChange_IN_var
          IN_var "Input record for function dp_suddenChange_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_suddenChange_DP";

      protected
        Real MIN=Modelica.Constants.eps;
        SI.ReynoldsNumber Re_min=1
          "Minimum Reynolds number for linear smoothing";
        //restriction of local resistance coefficient zeta_LOC >> numerical improvement
        TYP.LocalResistanceCoefficient zeta_LOC_min=1e-3
          "Minimal local resistance coefficient";

        SI.Area A_1=max(MIN, min(IN_con.A_1, IN_con.A_2))
          "Small cross sectional area of orifice";
        SI.Area A_2=max(MIN, max(IN_con.A_1, IN_con.A_2))
          "Large cross sectional area of orifice";
        SI.Length C_1=max(MIN, min(IN_con.C_1, IN_con.C_2))
          "Perimeter of small cross sectional area of orifice";
        SI.Length C_2=max(MIN, max(IN_con.C_1, IN_con.C_2))
          "Perimeter of large cross sectional area of orifice";
        SI.Diameter d_hyd=4*A_1/C_1
          "Hydraulic diameter of small cross sectional area of orifice";

        //sudden expansion  :  SOURCE_1, section 4, diagram 4-1, page 208
        //assumption of Re >= 3.3e3 for sudden expansion
        TYP.LocalResistanceCoefficient zeta_LOC_exp=max(zeta_LOC_min, (1 - A_1/A_2)^2);

        //sudden contraction:  SOURCE_1, section 4, diagram 4-9, page 216 / 217
        //assumption of Re >= 1.0e4 for sudden contraction
        TYP.LocalResistanceCoefficient zeta_LOC_con=max(zeta_LOC_min, 0.5*(1 - A_1/
            A_2)^0.75);

        SI.Velocity velocity_1=m_flow/(IN_var.rho*A_1)
          "Mean velocity in smaller cross sectional area";

        //determine Reynolds number for small cross sectional area of orifice
        SI.ReynoldsNumber Re=IN_var.rho*d_hyd*velocity_1/IN_var.eta;

        //actual local resistance coefficient
        TYP.LocalResistanceCoefficient zeta_LOC=zeta_LOC_exp*SMOOTH(
            Re_min,
            0,
            Re) + zeta_LOC_con*SMOOTH(
            -Re_min,
            0,
            Re) + zeta_LOC_min*SMOOTH(
            0,
            Re_min,
            abs(Re));

        //Documentation

      algorithm
        DP := zeta_LOC*IN_var.rho/2*(IN_var.eta/IN_var.rho/d_hyd)^2*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                Re,
                Re_min,
                2);
      end dp_suddenChange_DP;

      function dp_suddenChange_MFLOW
        "Pressure loss of orifice with sudden change in cross sectional area | calculate mass flow rate | turbulent flow regime | smooth surface | arbitrary cross sectional area | without baffles | sharp edge"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Orifice;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_suddenChange_IN_con
          IN_con "Input record for function dp_suddenChange_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_suddenChange_IN_var
          IN_var "Input record for function dp_suddenChange_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_suddenChange_MFLOW";

      protected
        Real MIN=Modelica.Constants.eps;
        SI.Pressure dp_min=1 "Pressure loss for linear smoothing";
        //restriction of local resistance coefficient zeta_LOC >> numerical improvement
        TYP.LocalResistanceCoefficient zeta_LOC_min=1e-3
          "Minimal local resistance coefficient";

        SI.Area A_1=max(MIN, min(IN_con.A_1, IN_con.A_2))
          "Small cross sectional area of orifice";
        SI.Area A_2=max(MIN, max(IN_con.A_1, IN_con.A_2))
          "Large cross sectional area of orifice";

        //sudden expansion  :  SOURCE_1, section 4, diagram 4-1, page 208
        //assumption of Re >= 3.3e3 for sudden expansion
        TYP.LocalResistanceCoefficient zeta_LOC_exp=max(zeta_LOC_min, (1 - A_1/A_2)^2);

        //sudden contraction:  SOURCE_1, section 4, diagram 4-9, page 216 / 217
        //assumption of Re >= 1.0e4 for sudden contraction
        TYP.LocalResistanceCoefficient zeta_LOC_con=max(zeta_LOC_min, 0.5*(1 - A_1/
            A_2)^0.75);

        //actual local resistance coefficient
        TYP.LocalResistanceCoefficient zeta_LOC=max(zeta_LOC_min, zeta_LOC_exp*SMOOTH(
            dp_min,
            0,
            dp) + zeta_LOC_con*SMOOTH(
            -dp_min,
            0,
            dp)) + zeta_LOC_min*SMOOTH(
            0,
            dp_min,
            abs(dp));

        //Documentation

      algorithm
        M_FLOW := IN_var.rho*A_1*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                dp_min,
                0.5)*(max(MIN, 2/(IN_var.rho*zeta_LOC)))^0.5;
      end dp_suddenChange_MFLOW;

      record dp_suddenChange_IN_con
        "Input record for function dp_suddenChange_DP and dp_suddenChange_MFLOW"

        //orifice variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.PressureLoss.SuddenChange;
      end dp_suddenChange_IN_con;

      record dp_suddenChange_IN_var
        "Input record for function dp_suddenChange_DP and dp_suddenChange_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;
      end dp_suddenChange_IN_var;

      function dp_thickEdgedOverall_DP
        "Pressure loss of thick and sharp edged orifice | calculate pressure loss | overall flow regime | constant influence of friction  | arbitrary cross sectional area"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Orifice;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_thickEdgedOverall_IN_con
          IN_con "Input record for function dp_thickEdgedOverall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_thickEdgedOverall_IN_var
          IN_var "Input record for function dp_thickEdgedOverall_DP"

        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_thickEdgedOverall_DP";

      protected
        Real MIN=Modelica.Constants.eps;

        TYP.DarcyFrictionFactor lambda_FRI=0.02
          "Assumption for Darcy friction factor in vena contraction according to SOURCE_1";
        SI.ReynoldsNumber Re_min=1;
        SI.ReynoldsNumber Re_lim=1e3
          "Limitation for laminar regime if dp is target";

        SI.Area A_0=IN_con.A_0 "Cross sectional area of vena contraction";
        SI.Area A_1=IN_con.A_1
          "Cross sectional area of large cross sectional area";
        SI.Diameter d_hyd_0=max(MIN, 4*A_0/IN_con.C_0)
          "Hydraulic diameter of vena contraction";
        SI.Diameter d_hyd_1=max(MIN, 4*A_1/IN_con.C_1)
          "Hydraulic diameter of large cross sectional area";
        SI.Length l=IN_con.L "Length of vena contraction";
        Real l_bar=IN_con.L/d_hyd_0;

        //SOURCE_1, section 4, diagram 4-15, page 222:
        Real phi=0.25 + 0.535*min(l_bar, 2.4)^8/(0.05 + min(l_bar, 2.4)^8);
        Real tau=(max(2.4 - l_bar, 0))*10^(-phi);

        TYP.PressureLossCoefficient zeta_TOT_1=max(MIN, (0.5*(1 - A_0/A_1)^0.75 + tau
            *(1 - A_0/A_1)^1.375 + (1 - A_0/A_1)^2 + lambda_FRI*l/d_hyd_0)*(A_1/A_0)^
            2)
          "Pressure loss coefficient w.r.t. to flow velocity in large cross sectional area";
        SI.Velocity v_0=m_flow/(IN_var.rho*A_0)
          "Mean velocity in vena contraction";
        SI.ReynoldsNumber Re=IN_var.rho*v_0*d_hyd_0/max(MIN, IN_var.eta)
          "Reynolds number in vena contraction";

        //Documentation

      algorithm
        DP := zeta_TOT_1*IN_var.rho/2*(IN_var.eta/IN_var.rho/d_hyd_1)^2*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                Re,
                Re_min,
                2)*(d_hyd_1/d_hyd_0*A_0/A_1)^2;
      end dp_thickEdgedOverall_DP;

      function dp_thickEdgedOverall_MFLOW
        "Pressure loss of thick and sharp edged orifice | calculate mass flow rate | overall flow regime | constant influence of friction  | arbitrary cross sectional area"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //Notation of equations according to SOURCES

        import FD = Modelica.Fluid.Dissipation.PressureLoss.Orifice;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_thickEdgedOverall_IN_con
          IN_con "Input record for function dp_thickEdgedOverall_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Orifice.dp_thickEdgedOverall_IN_var
          IN_var "Input record for function dp_thickEdgedOverall_MFLOW"

        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW
          "Output for function dp_thickEdgedOverall_MFLOW";

      protected
        Real MIN=Modelica.Constants.eps;
        TYP.DarcyFrictionFactor lambda_FRI=0.02
          "Assumption for Darcy friction factor in vena contraction according to SOURCE_1";
        SI.ReynoldsNumber Re_lim=1e3
          "Limitation for laminar regime if dp is target";

        SI.Area A_0=IN_con.A_0 "Cross sectional area of vena contraction";
        SI.Area A_1=IN_con.A_1 "Large cross sectional area";
        SI.Diameter d_hyd_0=max(MIN, 4*A_0/IN_con.C_0)
          "Hydraulic diameter of vena contraction";
        SI.Diameter d_hyd_1=max(MIN, 4*A_1/IN_con.C_1)
          "Hydraulic diameter of large cross sectional area";
        SI.Length l=IN_con.L "Length of vena contraction";
        Real l_bar=IN_con.L/d_hyd_0;

        //SOURCE_1, section 4, diagram 4-15, page 222:
        Real phi=0.25 + 0.535*min(l_bar, 2.4)^8/(0.05 + min(l_bar, 2.4)^8);
        Real tau=(max(2.4 - l_bar, 0))*10^(-phi);

        TYP.PressureLossCoefficient zeta_TOT_1=max(MIN, (0.5*(1 - A_0/A_1)^0.75 + tau
            *(1 - A_0/A_1)^1.375 + (1 - A_0/A_1)^2 + lambda_FRI*l/d_hyd_0)*(A_1/A_0)^
            2)
          "Pressure loss coefficient w.r.t. to flow velocity in large cross sectional area";

        //Documentation

      algorithm
        M_FLOW := IN_var.rho*A_1*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                IN_con.dp_smooth,
                0.5)/(0.5*IN_var.rho*zeta_TOT_1)^0.5;
      end dp_thickEdgedOverall_MFLOW;

      record dp_thickEdgedOverall_IN_con
        "Input record for function dp_thickEdgedOverall_DP and dp_thickEdgedOverall_MFLOW"

        //orifice variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.PressureLoss.Orifice;

        //linearisation
        SI.Pressure dp_smooth(min=Modelica.Constants.eps) = 1
          "Start linearisation for decreasing pressure loss"
      end dp_thickEdgedOverall_IN_con;

      record dp_thickEdgedOverall_IN_var
        "Input record for function dp_thickEdgedOverall_DP and dp_thickEdgedOverall_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;
      end dp_thickEdgedOverall_IN_var;
    end Orifice;

    package StraightPipe
      "Package for pressure loss calculation of straight pipes"
    extends Modelica.Icons.VariantsPackage;

      function dp_laminar_DP
        "Pressure loss of straight pipe | calculate pressure loss| laminar flow regime (Hagen-Poiseuille)"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.

        import FD = Modelica.Fluid.Dissipation.PressureLoss.StraightPipe;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_laminar_IN_con
          IN_con "Input record for function dp_laminar_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_laminar_IN_var
          IN_var "Input record for function dp_laminar_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_laminar_DP";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=IN_con.d_hyd "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";

        SI.Velocity velocity=m_flow/max(MIN, IN_var.rho*A_cross)
          "Mean velocity";

        //Documentation

      algorithm
        DP := 32*IN_var.eta*velocity*IN_con.L/d_hyd^2;
      end dp_laminar_DP;

      function dp_laminar_MFLOW
        "Pressure loss of straight pipe | calculate mass flow rate | laminar flow regime (Hagen-Poiseuille)"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.

        import FD = Modelica.Fluid.Dissipation.PressureLoss.StraightPipe;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_laminar_IN_con
          IN_con "Input record for function dp_laminar_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_laminar_IN_var
          IN_var "Input record for function dp_laminar_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW "Output for function dp_laminar_MFLOW";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";

        //Documentation

      algorithm
        M_FLOW := IN_var.rho*A_cross*(dp*d_hyd^2/(32*IN_var.eta*IN_con.L));
      end dp_laminar_MFLOW;

      record dp_laminar_IN_con
        "Input record for function dp_laminar_DP and dp_laminar_MFLOW"
        extends Utilities.Records.PressureLoss.StraightPipe;

      end dp_laminar_IN_con;

      record dp_laminar_IN_var
        "Input record for function dp_laminar_DP and dp_laminar_MFLOW"

        extends
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var;

      end dp_laminar_IN_var;

      function dp_overall_DP
        "Pressure loss of straight pipe | calculate pressure loss | overall flow regime | surface roughness"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.StraightPipe;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_con
          IN_con "Input record for function dp_overall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var
          IN_var "Input record for function dp_overall_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_overall_DP";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        Real k=max(MIN, abs(IN_con.K)/IN_con.d_hyd) "Relative roughness";
        SI.Length perimeter=PI*IN_con.d_hyd "Perimeter";

        //SOURCE_1: p.81, fig. 2-3, sec 21-22: definition of flow regime boundaries
        SI.ReynoldsNumber Re_lam_min=1e3
          "Minimum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_max=2090*(1/max(0.007, k))^0.0635
          "Maximum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        SI.ReynoldsNumber Re=
            Modelica.Fluid.Dissipation.Utilities.Functions.General.ReynoldsNumber(
            A_cross,
            perimeter,
            IN_var.rho,
            IN_var.eta,
            m_flow);

        dp_laminar_IN_con IN_con_lam(d_hyd=IN_con.d_hyd, L= IN_con.L);
      algorithm
        DP := SMOOTH(
                Re_lam_min,
                Re_lam_max,
                Re)*Dissipation.PressureLoss.StraightPipe.dp_laminar_DP(
                IN_con_lam,
                IN_var,
                m_flow) + SMOOTH(
                Re_lam_max,
                Re_lam_min,
                Re)*Dissipation.PressureLoss.StraightPipe.dp_turbulent_DP(
                IN_con,
                IN_var,
                m_flow);
      end dp_overall_DP;

      function dp_overall_MFLOW
        "Pressure loss of straight pipe | calculate mass flow rate | overall flow regime | surface roughness"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.StraightPipe;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;
        import Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_con
          IN_con "Input record for function dp_overall_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var
          IN_var "Input record for function dp_overall_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW "Output of function dp_overall_MFLOW";

      protected
        Real MIN=Modelica.Constants.eps;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=max(MIN, PI*IN_con.d_hyd^2/4)
          "Circular cross sectional area";
        Real k=max(MIN, abs(IN_con.K)/IN_con.d_hyd) "Relative roughness";

        //SOURCE_1: p.81, fig. 2-3, sec 21-22: definition of flow regime boundaries
        SI.ReynoldsNumber Re_lam_min=1e3
          "Minimum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_max=2090*(1/max(0.007, k))^0.0635
          "Maximum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_turb_min=4e3
          "Minimum Reynolds number for turbulent regime";

        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //determining Darcy friction factor out of pressure loss calculation for straight pipe:
        //dp = lambda_FRI*L/d_hyd*(rho/2)*velocity^2 and assuming lambda_FRI == lambda_FRI_calc/Re^2
        TYP.DarcyFrictionFactor lambda_FRI_calc=2*abs(dp)*d_hyd^3*IN_var.rho/(IN_con.L
            *IN_var.eta^2) "Adapted Darcy friction factor";

        //SOURCE_3: p.Lab 1, eq. 5: determine Re assuming laminar regime (Blasius)
        SI.ReynoldsNumber Re_lam=lambda_FRI_calc/64
          "Reynolds number assuming laminar regime";

        //SOURCE_3: p.Lab 2, eq. 10: determine Re assuming turbulent regime (Colebrook-White)
        SI.ReynoldsNumber Re_turb=if IN_con.roughness == Roughness.Neglected then (max(MIN,
            lambda_FRI_calc)/0.3164)^(1/1.75) else -2*sqrt(max(lambda_FRI_calc, MIN))
            *Modelica.Math.log10(2.51/sqrt(max(lambda_FRI_calc, MIN)) + k/3.7)
          "Reynolds number assuming turbulent regime";

        //determine actual flow regime
        SI.ReynoldsNumber Re_check=if Re_lam < Re_lam_leave then Re_lam else Re_turb;
        //determine Re for transition regime
        SI.ReynoldsNumber Re_trans=if Re_lam >= Re_lam_leave then
            Modelica.Fluid.Dissipation.Utilities.Functions.General.CubicInterpolation_Re(
            Re_check,
            Re_lam_leave,
            Re_turb_min,
            k,
            lambda_FRI_calc) else 0;
        //determine actual Re
        SI.ReynoldsNumber Re=if Re_lam < Re_lam_leave then Re_lam else if Re_turb >
            Re_turb_min then Re_turb else Re_trans;

        dp_laminar_IN_con IN_con_lam(d_hyd=IN_con.d_hyd, L= IN_con.L);

      algorithm
        M_FLOW := SMOOTH(
                Re_lam_min,
                Re_turb,
                Re)*Dissipation.PressureLoss.StraightPipe.dp_laminar_MFLOW(
                IN_con_lam,
                IN_var,
                dp) + SMOOTH(
                Re_turb,
                Re_lam_min,
                Re)*Dissipation.PressureLoss.StraightPipe.dp_turbulent_MFLOW(
                IN_con,
                IN_var,
                dp);
      end dp_overall_MFLOW;

      record dp_overall_IN_con
        "Input record for function dp_overall_DP and dp_overall_MFLOW"

        //straight pipe variables
        extends dp_turbulent_IN_con;

      end dp_overall_IN_con;

      record dp_overall_IN_var
        "Input record for function dp_overall_DP and dp_overall_MFLOW"

        //fluid property variables
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.PressureLoss;

      end dp_overall_IN_var;

      function dp_turbulent_DP
        "Pressure loss of straight pipe | calculate pressure loss | turbulent flow regime | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 2nd edition, 1984.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002.
        import FD = Modelica.Fluid.Dissipation.PressureLoss.StraightPipe;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_turbulent_IN_con
          IN_con "Input record for function dp_turbulent_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_turbulent_IN_var
          IN_var "Input record for function dp_turbulent_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Output for function dp_turbulent_DP";

      protected
        type TYP1 = Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        Real MIN=Modelica.Constants.eps;

        SI.ReynoldsNumber Re_min=1;
        SI.Velocity v_min=Re_min*IN_var.eta/(IN_var.rho*IN_con.d_hyd);

        SI.Diameter d_hyd=IN_con.d_hyd "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        Real k=max(MIN, abs(IN_con.K)/IN_con.d_hyd) "Relative roughness";

        //SOURCE_1: p.81, fig. 2-3, sec 21-22: definition of flow regime boundaries
        SI.ReynoldsNumber Re_lam_min=1e3
          "Minimum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_max=2090*(1/max(0.007, k))^0.0635
          "Maximum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_turb_min=4e3
          "Minimum Reynolds number for turbulent regime";

        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        SI.Velocity velocity=m_flow/(IN_var.rho*A_cross) "Mean velocity";
        SI.ReynoldsNumber Re=max(Re_min, IN_var.rho*abs(velocity)*d_hyd/IN_var.eta);

        //SOURCE_2: p.191, eq. 8.4: determining Darcy friction factor
        //assuming lambda_FRI == lambda_FRI_calc/Re^2
        TYP.DarcyFrictionFactor lambda_FRI_smooth=0.3164*Re^(1.75)
          "Darcy friction factor neglecting surface roughness (Blasius)";
        //here with lambda_FRI_rough == lambda_FRI*Re^2
        TYP.DarcyFrictionFactor lambda_FRI_rough=0.25*(max(Re, Re_lam_leave)/
            Modelica.Math.log10(k/3.7 + 5.74/max(Re, Re_lam_leave)^0.9))^2
          "Darcy friction factor considering surface roughness";
        TYP.DarcyFrictionFactor lambda_FRI=if IN_con.roughness == TYP1.Neglected then
                  lambda_FRI_smooth else lambda_FRI_rough
          "Darcy friction factor";
        TYP.DarcyFrictionFactor lambda_FRI_calc=if Re < Re_lam_leave then 64/Re else
            if Re > Re_turb_min then lambda_FRI/Re^2 else
            Modelica.Fluid.Dissipation.Utilities.Functions.General.CubicInterpolation_lambda(
            Re,
            Re_lam_leave,
            Re_turb_min,
            k)/Re^2 "Darcy friction factor";

        TYP.PressureLossCoefficient zeta_TOT=lambda_FRI_calc*IN_con.L/d_hyd
          "Pressure loss coefficient";

        //Documentation

      algorithm
        DP := zeta_TOT*(IN_var.rho/2)*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                velocity,
                v_min,
                2);
      end dp_turbulent_DP;

      function dp_turbulent_MFLOW
        "Pressure loss of straight pipe | calculate mass flow rate | turbulent flow regime | surface roughness"
        extends Modelica.Icons.Function;
        //SOURCE_1: Idelchik, I.E.: HANDBOOK OF HYDRAULIC RESISTANCE, 3rd edition, 2006.
        //SOURCE_2: Miller, D.S.: INTERNAL FLOW SYSTEMS, 2nd edition, 1984.
        //SOURCE_3: VDI-Waermeatlas, 9th edition, Springer-Verlag, 2002.

        import FD = Modelica.Fluid.Dissipation.PressureLoss.StraightPipe;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_turbulent_IN_con
          IN_con "Input record for function dp_turbulent_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_turbulent_IN_var
          IN_var "Input record for function dp_turbulent_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW "Mass flow rate";

      protected
        type TYP1 = Modelica.Fluid.Dissipation.Utilities.Types.Roughness;

        Real MIN=Modelica.Constants.eps;
        SI.ReynoldsNumber Re_min=1;

        SI.Diameter d_hyd=max(MIN, IN_con.d_hyd) "Hydraulic diameter";
        SI.Area A_cross=PI*IN_con.d_hyd^2/4 "Circular cross sectional area";
        Real k=max(MIN, abs(IN_con.K)/IN_con.d_hyd) "Relative roughness";

        //SOURCE_1: p.81, fig. 2-3, sec 21-22: definition of flow regime boundaries
        SI.ReynoldsNumber Re_lam_min=1e3
          "Minimum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_lam_max=2090*(1/max(0.007, k))^0.0635
          "Maximum Reynolds number for laminar regime";
        SI.ReynoldsNumber Re_turb_min=4e3
          "Minimum Reynolds number for turbulent regime";

        SI.ReynoldsNumber Re_lam_leave=min(Re_lam_max, max(Re_lam_min, 754*
            Modelica.Math.exp(if k <= 0.007 then 0.0065/0.007 else 0.0065/k)))
          "Start of transition regime for increasing Reynolds number (leaving laminar regime)";

        //determining Darcy friction factor out of pressure loss calculation for straight pipe:
        //dp = lambda_FRI*L/d_hyd*(rho/2)*velocity^2 and assuming lambda_FRI == lambda_FRI_calc/Re^2
        TYP.DarcyFrictionFactor lambda_FRI_calc=2*abs(dp)*d_hyd^3*IN_var.rho/(IN_con.L
            *IN_var.eta^2) "Adapted Darcy friction factor";

        //SOURCE_3: p.Lab 1, eq. 5: determine Re assuming laminar regime (Hagen-Poiseuille)
        SI.ReynoldsNumber Re_lam=lambda_FRI_calc/64
          "Reynolds number assuming laminar regime";

        //SOURCE_3: p.Lab 2, eq. 10: determine Re assuming turbulent regime (Colebrook-White)
        SI.ReynoldsNumber Re_turb=if IN_con.roughness == TYP1.Neglected then (max(MIN,
            lambda_FRI_calc)/0.3164)^(1/1.75) else -2*sqrt(max(lambda_FRI_calc, MIN))
            *Modelica.Math.log10(2.51/sqrt(max(lambda_FRI_calc, MIN)) + k/3.7)
          "Reynolds number assuming turbulent regime";

        //determine actual flow regime
        SI.ReynoldsNumber Re_check=if Re_lam < Re_lam_leave then Re_lam else Re_turb;
        //determine Re for transition regime
        SI.ReynoldsNumber Re_trans=if Re_lam >= Re_lam_leave then
            Modelica.Fluid.Dissipation.Utilities.Functions.General.CubicInterpolation_Re(
            Re_check,
            Re_lam_leave,
            Re_turb_min,
            k,
            lambda_FRI_calc) else 0;
        //determine actual Re
        SI.ReynoldsNumber Re=if Re_lam < Re_lam_leave then Re_lam else if Re_turb >
            Re_turb_min then Re_turb else Re_trans;

        //determine velocity
        SI.Velocity velocity=(if dp >= 0 then Re else -Re)*IN_var.eta/(IN_var.rho*
            d_hyd) "Mean velocity";

        //Documentation

      algorithm
        M_FLOW := IN_var.rho*A_cross*velocity;
      end dp_turbulent_MFLOW;

      record dp_turbulent_IN_con
        "Input record for function dp_turbulent_DP and dp_turbulent_MFLOW"

        Modelica.Fluid.Dissipation.Utilities.Types.Roughness roughness=Dissipation.Utilities.Types.Roughness.Neglected
          "Choice of considering surface roughness"

        extends Utilities.Records.PressureLoss.StraightPipe;

          SI.Length K=0 "Roughness (average height of surface asperities)"
      end dp_turbulent_IN_con;

      record dp_turbulent_IN_var
        "Input record for function dp_turbulent_DP and dp_turbulent_MFLOW"

        extends
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var;
      end dp_turbulent_IN_var;

      function dp_twoPhaseOverall_DP
        "Pressure loss of straight pipe for two phase flow | calculate (frictional, momentum, geodetic) pressure loss"
        extends Modelica.Icons.Function;
        //SOURCE_1: Friedel,L.:IMPROVED FRICTION PRESSURE DROP CORRELATIONS FOR HORIZONTAL AND VERTICAL TWO PHASE PIPE FLOW, 3R International, Vol. 18, Issue 7, pp. 485-491, 1979
        //SOURCE_2: Chisholm,D.:PRESSURE GRADIENTS DUE TO FRICTION DURING THE FLOW OF EVAPORATING TWO-PHASE MIXTURES IN SMOOTH TUBES AND CHANNELS, Int. J. Heat Mass Transfer, Vol. 16, pp. 347-358, Pergamon Press 1973
        //SOURCE_3: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.
        //SOURCE 4: J.M. Jensen and H. Tummescheit. Moving boundary models for dynamic simulations of two-phase flows. In Proceedings of the 2nd International Modelica Conference, pp. 235-244, Oberpfaffenhofen, Germany, 2002. The Modelica Association.
        //SOURCE_5: Thome, J.R., Engineering Data Book 3, Swiss Federal Institute of Technology Lausanne (EPFL), 2009.

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_twoPhaseOverall_IN_con
          IN_con "Input record for function dp_twoPhaseOverall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_twoPhaseOverall_IN_var
          IN_var "Input record for function dp_twoPhaseOverall_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Two phase pressure loss";

      protected
        type TYP = Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseFrictionalPressureLoss;

        Real MIN=Modelica.Constants.eps;

        SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
        SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
          "Hydraulic diameter";

        Real mdot_A=abs(m_flow)/A_cross "Mass flux";
        Real xflowEnd=min(1, max(0, abs(IN_var.x_flow_end)))
          "Mass flow rate quality at end of length";
        Real xflowSta=min(1, max(0, abs(IN_var.x_flow_sta)))
          "Mass flow rate quality at start of length";
        Real x_flow=(xflowEnd + xflowSta)/2
          "Mean mass flow rate quality over length";

        //SOURCE_5: p.17-1 to 17-5, sec. 17.1 to 17.2: Considering cross sectional void fraction [epsilon=A_g/(A_g+A_l)]
        Real epsilon=
          Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.VoidFraction(
            IN_con.voidFractionApproach,
            true,
            IN_var.rho_g,
            IN_var.rho_l,
            x_flow) "Void fraction";

        //SOURCE_1: Considering frictional pressure loss w.r.t. to correlation of Friedel
        //SOURCE_2: Considering frictional pressure loss w.r.t. to correlation of Chisholm
        SI.Pressure DP_fric=if IN_con.frictionalPressureLoss == TYP.Friedel then
          Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.dp_twoPhaseFriedel_DP(
            Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con(A_cross=IN_con.A_cross, perimeter=IN_con.perimeter, length=IN_con.length),
            Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var(rho_g=IN_var.rho_g, rho_l=IN_var.rho_l, eta_g=IN_var.eta_g, eta_l=IN_var.eta_l, sigma=IN_var.sigma, x_flow=IN_var.x_flow),
            m_flow) else if IN_con.frictionalPressureLoss == TYP.Chisholm then
          Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.dp_twoPhaseChisholm_DP(
            Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con(A_cross=IN_con.A_cross, perimeter=IN_con.perimeter, length=IN_con.length),
            Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var(rho_g=IN_var.rho_g, rho_l=IN_var.rho_l, eta_g=IN_var.eta_g, eta_l=IN_var.eta_l, sigma=IN_var.sigma, x_flow=IN_var.x_flow),
            m_flow) else 0 "Frictional pressure loss";

        //SOURCE_3: p.Lba 4, eq. 22: Considering momentum pressure loss assuming heterogeneous approach for two phase flow
        //Evaporation >> positive momentum pressure loss (assumed vice versa at condensation)
        SI.Pressure DP_mom=if IN_con.momentumPressureLoss then
          Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.dp_twoPhaseMomentum_DP(
            IN_con.voidFractionApproach,
            IN_con.massFlowRateCorrection,
            IN_con.A_cross,
            IN_con.perimeter,
            IN_var.rho_g,
            IN_var.rho_l,
            IN_var.x_flow_end,
            IN_var.x_flow_sta,
            abs(m_flow)) else 0 "Momentum pressure loss";

        //SOURCE_3: p.Lbb 1, eq. 4: Considering geodetic pressure loss assuming constant void fraction for flow length
        SI.Pressure DP_geo=if IN_con.geodeticPressureLoss then
          Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.dp_twoPhaseGeodetic_DP(
            IN_con.voidFractionApproach,
            true,
            IN_con.length,
            IN_con.phi,
            IN_var.rho_g,
            IN_var.rho_l,
            IN_var.x_flow) else 0 "Geodetic pressure loss";

        //Documentation
      algorithm
        DP := DP_fric + DP_mom + DP_geo;
      end dp_twoPhaseOverall_DP;

      record dp_twoPhaseOverall_IN_con
        "Input record for function dp_twoPhaseOverall_DP"

        //choices
        Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseFrictionalPressureLoss
          frictionalPressureLoss=Dissipation.Utilities.Types.TwoPhaseFrictionalPressureLoss.Friedel
          "Choice of frictional pressure loss approach"
        Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach
          voidFractionApproach = Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous
          "Choice of void fraction approach"

        Boolean momentumPressureLoss=false "Considering momentum pressure loss"
        Boolean massFlowRateCorrection=false
          "Consider heterogeneous mass flow rate correction"
        Boolean geodeticPressureLoss=false "Considering geodetic pressure loss"

        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con;
        SI.Angle phi=0 "Tilt angle to horizontal"

      end dp_twoPhaseOverall_IN_con;

      record dp_twoPhaseOverall_IN_var
        "Input record for function dp_twoPhaseOverall_DP"

        Real x_flow_end=0 "Mass flow rate quality at end of length"
        Real x_flow_sta=0 "Mass flow rate quality at start of length"
        extends
          Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var(final
            x_flow=(x_flow_end + x_flow_sta)/2);

      end dp_twoPhaseOverall_IN_var;
    end StraightPipe;

    package Valve "Package for pressure loss calculation of valves"
    extends Modelica.Icons.VariantsPackage;

      function dp_severalGeometryOverall_DP
        "Pressure loss of valve | calculate pressure loss | several geometries | overall flow regime"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.Valve;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;
        import TYP = Modelica.Fluid.Dissipation.Utilities.Types;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Valve.dp_severalGeometryOverall_IN_con
          IN_con "Input record for function dp_severalGeometryOverall_DP"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Valve.dp_severalGeometryOverall_IN_var
          IN_var "Input record for function dp_severalGeometryOverall_DP"
        input SI.MassFlowRate m_flow "Mass flow rate"

        //output variables
        output SI.Pressure DP "Pressure loss";

      protected
        type TYP1 =
            Modelica.Fluid.Dissipation.Utilities.Types.ValveCoefficient;
        type TYP2 = Modelica.Fluid.Dissipation.Utilities.Types.ValveGeometry;

        Real MIN=Modelica.Constants.eps;

        SI.Area Av=if IN_con.valveCoefficient == TYP1.AV then IN_con.Av else if
            IN_con.valveCoefficient == TYP1.KV then IN_con.Kv*27.7e-6 else if IN_con.valveCoefficient
             == TYP1.CV then IN_con.Cv*24e-6 else if IN_con.valveCoefficient == TYP1.OP then
                  IN_con.m_flow_nominal/max(MIN, IN_con.opening_nominal*sqrt(IN_con.rho_nominal
            *IN_con.dp_nominal)) else MIN
          "Av (metric) flow coefficient [Av]=m^2";

        TYP.PressureLossCoefficient zeta_bal=SMOOTH(
            0.05,
            0,
            IN_var.opening)*10^(-3.8397*IN_var.opening + 2.9449) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Ball valves";
        TYP.PressureLossCoefficient zeta_dia=SMOOTH(
            0.05,
            0,
            IN_var.opening)*10^(2.2596*exp(-1.8816*IN_var.opening)) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Diaphragm valves";
        TYP.PressureLossCoefficient zeta_but=SMOOTH(
            0.05,
            0,
            IN_var.opening)*619.81*exp(-7.3211*IN_var.opening) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Butterfly valves";
        TYP.PressureLossCoefficient zeta_gat=SMOOTH(
            0.05,
            0,
            IN_var.opening)*51.45*exp(-6.046*IN_var.opening) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Gate valves";
        TYP.PressureLossCoefficient zeta_slu=SMOOTH(
            0.05,
            0,
            IN_var.opening)*248.89*exp(-7.8265*IN_var.opening) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Sluice valves";

        TYP.PressureLossCoefficient zeta_TOT=if IN_con.geometry == TYP2.Ball then
            zeta_bal else if IN_con.geometry == TYP2.Diaphragm then zeta_dia else if
            IN_con.geometry == TYP2.Butterfly then zeta_but else if IN_con.geometry
             == TYP2.Gate then zeta_gat else if IN_con.geometry == TYP2.Sluice then
            zeta_slu else 0 "Pressure loss coefficient of chosen valve";

        Real valveCharacteristic=sqrt(2/min(IN_con.zeta_TOT_max, max(MIN, max(IN_con.zeta_TOT_min,
            abs(zeta_TOT)))))
          "Valve characteristic considering opening of chosen valve";

        SI.MassFlowRate m_flow_small=valveCharacteristic*Av*sqrt(IN_var.rho)*sqrt(IN_con.dp_small)
            "Mass flow rate at linearisation";

        //Documentation

      algorithm
        DP := 1/((valveCharacteristic*Av)^2*IN_var.rho)*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                m_flow,
                m_flow_small,
                2);
      end dp_severalGeometryOverall_DP;

      function dp_severalGeometryOverall_MFLOW
        "Pressure loss of valve | calculate mass flow rate | several geometries | overall flow regime"
        extends Modelica.Icons.Function;
        import FD = Modelica.Fluid.Dissipation.PressureLoss.Valve;
        import SMOOTH =
          Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;
        import TYP = Modelica.Fluid.Dissipation.Utilities.Types;

        //input records
        input
          Modelica.Fluid.Dissipation.PressureLoss.Valve.dp_severalGeometryOverall_IN_con
          IN_con "Input record for function dp_severalGeometryOverall_MFLOW"
        input
          Modelica.Fluid.Dissipation.PressureLoss.Valve.dp_severalGeometryOverall_IN_var
          IN_var "Input record for function dp_severalGeometryOverall_MFLOW"
        input SI.Pressure dp "Pressure loss"

        //output variables
        output SI.MassFlowRate M_FLOW "Mass flow rate";

      protected
        type TYP1 =
            Modelica.Fluid.Dissipation.Utilities.Types.ValveCoefficient;
        type TYP2 = Modelica.Fluid.Dissipation.Utilities.Types.ValveGeometry;

        Real MIN=Modelica.Constants.eps;

        SI.Area Av=if IN_con.valveCoefficient == TYP1.AV then IN_con.Av else if
            IN_con.valveCoefficient == TYP1.KV then IN_con.Kv*27.7e-6 else if IN_con.valveCoefficient
             == TYP1.CV then IN_con.Cv*24e-6 else if IN_con.valveCoefficient == TYP1.OP then
                  IN_con.m_flow_nominal/max(MIN, IN_con.opening_nominal*sqrt(IN_con.rho_nominal
            *IN_con.dp_nominal)) else MIN
          "Av (metric) flow coefficient [Av]=m^2";

        TYP.PressureLossCoefficient zeta_bal=SMOOTH(
            0.05,
            0,
            IN_var.opening)*10^(-3.8397*IN_var.opening + 2.9449) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Ball valves";
        TYP.PressureLossCoefficient zeta_dia=SMOOTH(
            0.05,
            0,
            IN_var.opening)*10^(2.2596*exp(-1.8816*IN_var.opening)) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Diaphragm valves";
        TYP.PressureLossCoefficient zeta_but=SMOOTH(
            0.05,
            0,
            IN_var.opening)*619.81*exp(-7.3211*IN_var.opening) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Butterfly valves";
        TYP.PressureLossCoefficient zeta_gat=SMOOTH(
            0.05,
            0,
            IN_var.opening)*51.45*exp(-6.046*IN_var.opening) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Gate valves";
        TYP.PressureLossCoefficient zeta_slu=SMOOTH(
            0.05,
            0,
            IN_var.opening)*248.89*exp(-7.8265*IN_var.opening) + SMOOTH(
            0,
            0.05,
            IN_var.opening)*IN_con.zeta_TOT_max "Sluice valves";

        TYP.PressureLossCoefficient zeta_TOT=if IN_con.geometry == TYP2.Ball then
            zeta_bal else if IN_con.geometry == TYP2.Diaphragm then zeta_dia else if
            IN_con.geometry == TYP2.Butterfly then zeta_but else if IN_con.geometry
             == TYP2.Gate then zeta_gat else if IN_con.geometry == TYP2.Sluice then
            zeta_slu else 0 "Pressure loss coefficient of chosen valve";

        Real valveCharacteristic=sqrt(2/min(IN_con.zeta_TOT_max, max(MIN, max(IN_con.zeta_TOT_min,
            abs(zeta_TOT)))))
          "Valve characteristic considering opening of chosen valve";

        //Documentation

      algorithm
        M_FLOW := valveCharacteristic*Av*sqrt(IN_var.rho)*
          Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower(
                dp,
                IN_con.dp_small,
                0.5);
      end dp_severalGeometryOverall_MFLOW;

      record dp_severalGeometryOverall_IN_con
        "Input record for function dp_severalGeometryOverall_DP and dp_severalGeometryOverall_MFLOW"

        extends Modelica.Icons.Record;

        Modelica.Fluid.Dissipation.Utilities.Types.ValveGeometry geometry=Dissipation.Utilities.Types.ValveGeometry.Ball
          "Choice of geometry for valve"
        Modelica.Fluid.Dissipation.Utilities.Types.ValveCoefficient
          valveCoefficient=
            Modelica.Fluid.Dissipation.Utilities.Types.ValveCoefficient.AV
          "Choice of valve coefficient"

        //valve variables
        Real Av=PI*0.1^2/4 "Av (metric) flow coefficient [Av]=m^2"
        Real Kv=Av/27.7e-6 "Kv (metric) flow coefficient [Kv]=m^3/h"
        Real Cv=Av/24.6e-6 "Cv (US) flow coefficient [Cv]=USG/min"
        SI.Pressure dp_nominal=1e3 "Nominal pressure loss"
        SI.MassFlowRate m_flow_nominal=opening_nominal*Av*sqrt(rho_nominal*dp_nominal)
            "Nominal mass flow rate"
        SI.Density rho_nominal=1000 "Nominal inlet density"
        Real opening_nominal=0.5 "Nominal opening"
        Real zeta_TOT_min=1e-3
          "Minimal pressure loss coefficient at full opening"
        Real zeta_TOT_max=1e8
          "Maximum pressure loss coefficient at closed opening"

        //numerical aspects
        SI.Pressure dp_small=0.01*dp_nominal
          "Linearisation for a pressure loss smaller then dp_small"
      end dp_severalGeometryOverall_IN_con;

      record dp_severalGeometryOverall_IN_var
        "Input record for function dp_severalGeometryOverall_DP and dp_severalGeometryOverall_MFLOW"

        extends Modelica.Icons.Record;

        //valve variables
        Real opening=1 "Opening of valve | 0==closed and 1== fully opened"

        //fluid property variables
        SI.DynamicViscosity eta "Dynamic viscosity of fluid"
        SI.Density rho "Density of fluid"
      end dp_severalGeometryOverall_IN_var;
    end Valve;
  end PressureLoss;

  package Utilities "Package for utilities (should not be used directly)"
  extends Modelica.Icons.UtilitiesPackage;
    package SharedDocumentation "Shared Documentation"
      extends Modelica.Icons.Information;

      package HeatTransfer
        extends Modelica.Icons.Information;

        package Channel
        extends Modelica.Icons.Information;

        class kc_evenGapLaminar
          extends Modelica.Icons.Information;
        end kc_evenGapLaminar;

        class kc_evenGapOverall
          extends Modelica.Icons.Information;
        end kc_evenGapOverall;

        class kc_evenGapTurbulent
          extends Modelica.Icons.Information;
        end kc_evenGapTurbulent;

        end Channel;

        package General
        extends Modelica.Icons.Information;

        class kc_approxForcedConvection
          extends Modelica.Icons.Information;
        end kc_approxForcedConvection;
        end General;

        package HeatExchanger
        extends Modelica.Icons.Information;

        class kc_flatTube
          extends Modelica.Icons.Information;
        end kc_flatTube;

        class kc_roundTube
          extends Modelica.Icons.Information;
        end kc_roundTube;

        end HeatExchanger;

        package HelicalPipe
        extends Modelica.Icons.Information;

        class kc_laminar
          extends Modelica.Icons.Information;
        end kc_laminar;

        class kc_overall
          extends Modelica.Icons.Information;
        end kc_overall;

        class kc_turbulent
          extends Modelica.Icons.Information;
        end kc_turbulent;

        end HelicalPipe;

        package Plate
        extends Modelica.Icons.Information;

        class kc_laminar
          extends Modelica.Icons.Information;
        end kc_laminar;

        class kc_overall
          extends Modelica.Icons.Information;
        end kc_overall;

        class kc_turbulent
          extends Modelica.Icons.Information;
        end kc_turbulent;
        end Plate;

        package StraightPipe
        extends Modelica.Icons.Information;

        class kc_laminar
          extends Modelica.Icons.Information;
        end kc_laminar;

        class kc_overall
          extends Modelica.Icons.Information;
        end kc_overall;

        class kc_turbulent
          extends Modelica.Icons.Information;
        end kc_turbulent;

        class kc_twoPhaseOverall
          extends Modelica.Icons.Information;
        end kc_twoPhaseOverall;

        end StraightPipe;

      end HeatTransfer;

    package PressureLoss
      extends Modelica.Icons.Information;

    package Bend
      extends Modelica.Icons.Information;

    class dp_curvedOverall
     extends Modelica.Icons.Information;
    end dp_curvedOverall;

    class dp_edgedOverall
     extends Modelica.Icons.Information;
    end dp_edgedOverall;
    end Bend;

    package Channel
      extends Modelica.Icons.Information;

    class dp_internalFlowOverall
     extends Modelica.Icons.Information;
    end dp_internalFlowOverall;
    end Channel;

    package General
      extends Modelica.Icons.Information;

    class dp_idealGas
     extends Modelica.Icons.Information;
    end dp_idealGas;

    class dp_nominalDensityViscosity
     extends Modelica.Icons.Information;
    end dp_nominalDensityViscosity;

    class dp_nominalPressureLossLawDensity
     extends Modelica.Icons.Information;

where the exponent for the fraction of densities is determined w.r.t. the chosen nominal mass flow rate or nominal volume flow rate to:

exp_density = if NominalMassFlowRate == Modelica.Fluid.Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate then 1-exp else 1

with

 NominalMassFlowRate    	 as reference for pressure loss law (mass flow rate of volume flow rate),

 exp                    	 as exponent of pressure loss calculation [-],

 exp_density            	 as exponent for density [-].

To avoid numerical difficulties this pressure loss function is linear smoothed for small pressure losses, with

dp ≤ 0.01*dp_nom

Note that the input and output arguments for functions throughout this library always use mass flow rates. Here you can choose NominalMassFlowRate == Modelica.Fluid.Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate for using a nominal mass flow rate or NominalMassFlowRate == Modelica.Fluid.Dissipation.Utilities.Types.MassOrVolumeFlowRate.VolumeFlowRate for using a nominal volume flow rate. The output argument will always be a mass flow rate for further use as flow model in a thermo-hydraulic framework.

Note that the pressure loss coefficients (zeta_TOT,zeta_TOT_nom) refer to its mean flow velocities (v,v_nom) in the pressure loss law to obtain its corresponding pressure loss.

Verification

Compressible case [Mass flow rate = f(dp)]:

The generic mass flow rate M_FLOW in dependence of the pressure loss dp is shown for a turbulent pressure loss regime (exp == 2) in the figure below.

Note that the verification for dp_nominalPressureLossLawDensity is also valid for this inverse calculation due to using the same functions.

References

Elmqvist, H., M.Otter and S.E. Cellier:

Inline integration: A new mixed
    symbolic / numeric approach for solving differential-algebraic equation systems..
    In Proceedings of European Simulation MultiConference, Prague, 1995.

Wischhusen, S.:

Dynamische Simulation zur wirtschaftlichen Bewertung von komplexen Energiesystemen..
    PhD thesis, Technische Universität Hamburg-Harburg, 2005.

"));
    end dp_nominalPressureLossLawDensity;

    class dp_pressureLossCoefficient
     extends Modelica.Icons.Information;
    end dp_pressureLossCoefficient;

    class dp_volumeFlowRate
     extends Modelica.Icons.Information;
    end dp_volumeFlowRate;
    end General;

    package Orifice
      extends Modelica.Icons.Information;

    class dp_suddenChange
     extends Modelica.Icons.Information;
    end dp_suddenChange;

    class dp_thickEdgedOverall
     extends Modelica.Icons.Information;
    end dp_thickEdgedOverall;
    end Orifice;

    package StraightPipe
      extends Modelica.Icons.Information;

    class dp_laminar
     extends Modelica.Icons.Information;
    end dp_laminar;

    class dp_overall
     extends Modelica.Icons.Information;
    end dp_overall;

    class dp_turbulent
     extends Modelica.Icons.Information;
    end dp_turbulent;

    class dp_twoPhaseOverall
     extends Modelica.Icons.Information;
    end dp_twoPhaseOverall;
    end StraightPipe;

    package Valve
      extends Modelica.Icons.Information;

    class dp_severalGeometryOverall
     extends Modelica.Icons.Information;
    end dp_severalGeometryOverall;
    end Valve;
    end PressureLoss;
    end SharedDocumentation;

    package Functions "Package for utility functions"
      extends Modelica.Icons.FunctionsPackage;

      package PressureLoss "Package for utility pressure loss functions"
        extends Modelica.Icons.FunctionsPackage;

        package TwoPhase
          "Package with utility functions to compute two phase pressure loss characteristics"
          extends Modelica.Icons.FunctionsPackage;

          function dp_twoPhaseChisholm_DP
            "Frictional pressure loss of straight pipe for two phase flow according to Chisholm correlation | calculate pressure loss | overall flow regime"
            extends Modelica.Icons.Function;
            //SOURCE_1: Chisholm,D.:PRESSURE GRADIENTS DUE TO FRICTION DURING THE FLOW OF EVAPORATING TWO-PHASE MIXTURES IN SMOOTH TUBES AND CHANNELS, Int. J. Heat Mass Transfer, Vol. 16, pp. 347-358, Pergamon Press 1973

            //records
            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var
              IN_var
            input SI.MassFlowRate m_flow "Mass flow rate"

            output SI.Pressure DP "Output for function dp_twoPhaseChisholm_DP";

          protected
            Real MIN=Modelica.Constants.eps;

            Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_con
              IN_con_1ph(
              final roughness=Dissipation.Utilities.Types.Roughness.Neglected,
              final d_hyd=4*abs(IN_con.A_cross)/max(MIN, abs(IN_con.perimeter)),
              final K=0,
              final L=abs(IN_con.length));

            Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_IN_var
              IN_var_1ph(
                final eta=IN_var.eta_l, final rho=IN_var.rho_l);

          algorithm
            DP := Modelica.Fluid.Dissipation.PressureLoss.StraightPipe.dp_overall_DP(
                        IN_con_1ph,
                        IN_var_1ph,
                        m_flow)*(
              Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.TwoPhaseMultiplierChisholm(
                        IN_con,
                        IN_var,
                        m_flow));
          end dp_twoPhaseChisholm_DP;

          function dp_twoPhaseFriedel_DP
            "Frictional pressure loss of straight pipe for two phase flow according to Friedel correlation | calculate pressure loss| overall flow regime"
            extends Modelica.Icons.Function;
            //SOURCE_1: Friedel,L.:IMPROVED FRICTION PRESSURE DROP CORRELATIONS FOR HORIZONTAL AND VERTICAL TWO PHASE PIPE FLOW, 3R International, Vol. 18, Issue 7, pp. 485-491, 1979
            //SOURCE_2: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.

            import SMOOTH =
              Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;
            import SMOOTH2 =
              Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower;

            //records
            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var
              IN_var
            input SI.MassFlowRate m_flow "Mass flow rate"

            output SI.Pressure DP "Output for function dp_twoPhaseFriedel_DP";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
              "Hydraulic diameter";

            Real mdot_A=abs(m_flow)/A_cross "Mass flux";
            SI.ReynoldsNumber Re_liq=max(1, mdot_A*d_hyd/max(MIN, IN_var.eta_l))
              "Reynolds number assuming (total) mass flux flowing as liquid";
            SI.ReynoldsNumber Re_lam_leave=1055
              "Maximum Reynolds number for laminar regime (1055)";
            SI.ReynoldsNumber Re_turb=1100
              "Minimum Reynolds number for turbulent regime (1100)";
            SI.ReynoldsNumber Re_smooth=m_flow/A_cross*d_hyd/max(MIN, abs(IN_var.eta_l))
              "Reynolds number for smoothing";
            TYP.DarcyFrictionFactor lambda_FRI_lam=64/Re_liq
              "Darcy friction factor for laminar regime";
            TYP.DarcyFrictionFactor lambda_FRI_turb=(0.86859*Modelica.Math.log(max(1, (
                Re_liq/max(MIN, (1.964*Modelica.Math.log(Re_liq) - 3.8215))))))^(-2)
              "Darcy friction factor for turbulent regime";
            TYP.DarcyFrictionFactor lambda_FRI=lambda_FRI_lam*SMOOTH(
                Re_lam_leave,
                Re_turb,
                Re_liq) + lambda_FRI_turb*SMOOTH(
                Re_turb,
                Re_lam_leave,
                Re_liq);
            TYP.PressureLossCoefficient zeta_FRI=lambda_FRI*IN_con.length/d_hyd
              "Pressure loss coefficient";
            SI.Pressure DP_liq=zeta_FRI*mdot_A^2/(2*max(MIN, IN_var.rho_l))
              "Frictional pressure loss assuming (total) mass flux flowing as liquid";

          algorithm
            DP := SMOOTH2(
                        Re_smooth,
                        1,
                        0)*DP_liq*(
              Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.TwoPhaseMultiplierFriedel(
                        IN_con,
                        IN_var,
                        m_flow));
          end dp_twoPhaseFriedel_DP;

          function dp_twoPhaseGeodetic_DP
            "Geodetic pressure loss of straight pipe for two phase flow | calculate pressure loss"
            extends Modelica.Icons.Function;
            //SOURCE_1: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.

            import PI = Modelica.Constants.pi;

            input
              Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach
              voidFractionApproach=Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous
              "Choice of void fraction approach";

            input Boolean crossSectionalAveraged=true
              "= true, if cross sectional averaged void fraction, otherwise volumetric"

            //geometry
            input SI.Length length=1 "Length in fluid flow direction"
            input SI.Angle phi=0 "Tilt angle to horizontal"

            //fluid properties
            input SI.Density rho_g(min=Modelica.Constants.eps)
              "Density of gaseous phase"
            input SI.Density rho_l(min=Modelica.Constants.eps)
              "Density of liquid phase"
            input Real x_flow(
              min=0,
              max=1) = 0 "Mass flow rate quality"

            output SI.Pressure DP_geo "Geodetic pressure loss";

          protected
            Real xflow=min(1, max(0, abs(x_flow))) "Mass flow rate quality";
            Real eps=
                Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.VoidFraction(
                voidFractionApproach,
                crossSectionalAveraged,
                rho_g,
                rho_l,
                xflow) "Void fraction";

          algorithm
            //SOURCE_1: p.Lbb 1, eq. 4: Considering geodetic pressure loss assuming constant void fraction for flow length
            DP_geo := (eps*rho_g + (1 - eps)*rho_l)*9.81*length*sin(phi);
          end dp_twoPhaseGeodetic_DP;

          function dp_twoPhaseMomentum_DP
            "Momentum pressure loss of straight pipe for two phase flow | calculate pressure loss"
            extends Modelica.Icons.Function;
            //SOURCE_1: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.
            //SOURCE_2: Thome, J.R., Engineering Data Book 3, Swiss Federal Institute of Technology Lausanne (EPFL), 2009.
            //SOURCE 3: J.M. Jensen and H. Tummescheit. Moving boundary models for dynamic simulations of two-phase flows. In Proceedings of the 2nd International Modelica Conference, pp. 235-244, Oberpfaffenhofen, Germany, 2002. The Modelica Association.

            import PI = Modelica.Constants.pi;
            import MIN = Modelica.Constants.eps;
            import SMOOTH =
              Modelica.Fluid.Dissipation.Utilities.Functions.General.SmoothPower;

            //choices
            input
              Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach
              voidFractionApproach=
                Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous
              "Choice of void fraction approach"

            //SOURCE_3: p.52, eq. 4.6: heterogeneous effects on momentum pressure loss considered through corrected mass flow rate
            input Boolean massFlowRateCorrection=false
              "Consider heterogeneous mass flow rate correction"

            //geometry
            input SI.Area A_cross(min=Modelica.Constants.eps) = PI*0.1^2/4
              "Cross sectional area"
            input SI.Length perimeter(min=Modelica.Constants.eps) = PI*0.1
              "Perimeter"

            //fluid properties
            input SI.Density rho_g(min=Modelica.Constants.eps) "Density of gas"
            input SI.Density rho_l(min=Modelica.Constants.eps)
              "Density of liquid"
            input Real x_flow_end(
              min=0,
              max=1) = 0 "Mass flow rate quality at end of length"
            input Real x_flow_sta(
              min=0,
              max=1) = 0 "Mass flow rate quality at start of length"

            input SI.MassFlowRate m_flow "Mass flow rate"

            output SI.Pressure DP_mom "Momentum pressure loss";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area Across=max(MIN, A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, perimeter))
              "Hydraulic diameter";

            Real mdot_A=abs(m_flow)/Across "Mass flux";
            Real xflowEnd=min(1, max(0, abs(x_flow_end)))
              "Mass flow rate quality at end of length";
            Real xflowSta=min(1, max(0, abs(x_flow_sta)))
              "Mass flow rate quality at start of length";
            Real xflowMean=(xflowEnd + xflowSta)/2
              "Mean mass flow rate quality over length";

            Real delta_xflow=xflowEnd - xflowSta
              "Difference of mass flow rate quality between end and start of length (pos >> evaporation, neg >> condensation";

            //SOURCE_2: Considering void fraction approaches
            Real eps_end=
                Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.VoidFraction(
                voidFractionApproach,
                true,
                rho_g,
                rho_l,
                xflowEnd) "Void fraction at end of length";
            Real eps_sta=
                Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.VoidFraction(
                voidFractionApproach,
                true,
                rho_g,
                rho_l,
                xflowSta) "Void fraction at start of length";

            //SOURCE_2: p.17-6, eq. 17.3.3: Considering mean two phase density at end and start of length
            SI.Density rho_end=
                Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.TwoPhaseDensity(
                voidFractionApproach,
                massFlowRateCorrection,
                rho_g,
                rho_l,
                eps_end,
                xflowEnd) "Mean two phase density at end of length";
            SI.Density rho_sta=
                Modelica.Fluid.Dissipation.Utilities.Functions.PressureLoss.TwoPhase.TwoPhaseDensity(
                voidFractionApproach,
                massFlowRateCorrection,
                rho_g,
                rho_l,
                eps_sta,
                xflowSta) "Mean two phase density at start of length";

            SI.Velocity meanVelEnd=abs(m_flow)/max(MIN, rho_end*A_cross)
              "Mean velocity of two phase flow at end of length";
            SI.Velocity meanVelSta=abs(m_flow)/max(MIN, rho_sta*A_cross)
              "Mean velocity of two phase flow at start of length";

            //SOURCE 3: p.15, eq. 2.26: Considering velocity difference for heterogeneous approach using slip ratio
            Real SR=Dissipation.Utilities.Functions.PressureLoss.TwoPhase.SlipRatio(
                voidFractionApproach,
                rho_g,
                rho_l,
                xflowMean) "Slip ratio for velocity void fraction approach";
            SI.Velocity deltaVelEnd=meanVelEnd*(SR - 1)/(xflowEnd*(SR - 1) + 1)
              "Velocity difference of two phases at end of length";
            SI.Velocity deltaVelSta=meanVelSta*(SR - 1)/(xflowSta*(SR - 1) + 1)
              "Velocity difference of two phases at start of length";

            //SOURCE 3: p.52, eq. 4.6: Considering of corrected mass flow rate for heterogeneous approach
            SI.MassFlowRate mdotCorEnd=xflowEnd*(1 - xflowEnd)*rho_end*deltaVelEnd*Across
              "Correction mass flow rate at end of length";
            SI.MassFlowRate mdotCorSta=xflowSta*(1 - xflowSta)*rho_sta*deltaVelSta*Across
              "Correction mass flow rate at start of length";

            //SOURCE 3: p.53, eq. 4.13: Calculation of heterogeneous approach with correction of mass flow rate for considering velocity difference between fluid phases
            SI.Pressure dp_mom_cor=SMOOTH(
                delta_xflow,
                0.05,
                0)*abs(mdot_A*meanVelEnd + mdotCorEnd*deltaVelEnd/Across) - abs(mdot_A*
                meanVelSta + mdotCorEnd*deltaVelSta/Across)
              "Momentum pressure loss using mass flow rate correction";

          algorithm
            //SOURCE_1: p.Lba 4, eq. 22: Considering momentum pressure loss assuming heterogeneous approach for two phase flow
            //Momentum pressure loss occurs for a changing mass flow rate quality due to condensation or evaporation
            //At evaporation the liquid phase with a slow velocity has to be accelerated to the higher velocity of the gas
            //The difference in static pressure at the outlet and the inlet causes a positive momentum pressure loss at evaporation (assumed vice versa for condensation)
            DP_mom := if massFlowRateCorrection then dp_mom_cor else mdot_A^2*SMOOTH(
              delta_xflow,
              0.05,
              0)*abs(1/max(MIN, rho_end) - 1/max(MIN, rho_sta));
          end dp_twoPhaseMomentum_DP;

          function TwoPhaseMultiplierFriedel
            "Calculation of two phase multiplier according to Friedel | constant mass flow rate quality | horizontal flow | vertical upflow and downflow"
            extends Modelica.Icons.Function;
            //SOURCE_1: Friedel,L.:IMPROVED FRICTION PRESSURE DROP CORRELATIONS FOR HORIZONTAL AND VERTICAL TWO PHASE PIPE FLOW, 3R International, Vol. 18, Issue 7, pp. 485-491, 1979
            //SOURCE_2: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.

            import Modelica.Math.log;
            import SMOOTH =
              Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var
              IN_var(
                final sigma=0)
            input SI.MassFlowRate m_flow "Mass flow rate"

            output Real phi "Two phase multiplier w.r.t. Friedel";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
              "Hydraulic diameter";

            //SOURCE_2: p.Lba 4, sec. 3.3: Correlation based on constant mass flow rate quality (x_flow) for increment (dx)
            //Pressure loss for total length (e.g., L=n*dx) can be achieved by discretization
            Real mdot_A=abs(m_flow)/A_cross "Mass flux";
            Real x_flow=max(0, min(1, abs(IN_var.x_flow)))
              "Mass flow rate quality";

            //SOURCE_1: p.490 (Appendix): Characteristic numbers based on total mass flow rate flowing as liquid
            SI.FroudeNumber Fr_l=max(MIN, mdot_A^2/max(MIN, 9.81*IN_var.rho_l^2*d_hyd))
              "Froude number based on liquid flow";
            SI.ReynoldsNumber Re_g=max(1, mdot_A*d_hyd/max(MIN, IN_var.eta_g))
              "Reynolds number based on gas flow";
            SI.ReynoldsNumber Re_l=max(1, mdot_A*d_hyd/max(MIN, IN_var.eta_l))
              "Reynolds number based on liquid flow";
            SI.WeberNumber We_l=max(MIN, mdot_A^2*d_hyd/max(MIN, IN_var.sigma*IN_var.rho_l))
              "Weber number based on liquid flow";

            //SOURCE_1: p.490 (Appendix): Smoothing for sudden change from assumed laminar to assumed turbulent regime (numerical improvement at Re=1055)
            SI.ReynoldsNumber Re_lam_max=1025
              "Maximum Reynolds number assuming laminar regime";
            SI.ReynoldsNumber Re_turb_min=1075
              "Minimum Reynolds number assuming turbulent regime";

            //SOURCE_2: p.Lbb 2, eq. 9-10: Considering influence of Reynolds number on Darcy friction factor for smooth straight pipes
            //Correlation based on neglect of surface roughness
            //Correlation based on assumption that total mass flow rate is flowing as gas
            TYP.DarcyFrictionFactor lambda_lam_g=64/Re_g
              "Darcy friction factor of gas for assumed laminar regime";
            TYP.DarcyFrictionFactor lambda_turb_g=1/max(MIN, 0.86859*log(max(1, Re_g/max(
                MIN, 1.964*log(Re_g) - 3.8215))))^(2)
              "Darcy friction factor of gas for assumed turbulent regime";
            TYP.DarcyFrictionFactor lambda_g=lambda_lam_g*SMOOTH(
                Re_lam_max,
                Re_turb_min,
                Re_g) + lambda_turb_g*SMOOTH(
                Re_turb_min,
                Re_lam_max,
                Re_g) "Darcy friction factor of gas for overall regime";
            //Correlation based on assumption that total mass flow rate is flowing as liquid
            TYP.DarcyFrictionFactor lambda_lam_l=64/Re_l
              "Darcy friction factor of liquid for assumed laminar regime";
            TYP.DarcyFrictionFactor lambda_turb_l=1/max(MIN, 0.86859*log(max(1, Re_l/max(
                MIN, 1.964*log(Re_l) - 3.8215))))^(2)
              "Darcy friction factor of liquid for assumed turbulent regime";
            TYP.DarcyFrictionFactor lambda_l=lambda_lam_l*SMOOTH(
                Re_lam_max,
                Re_turb_min,
                Re_l) + lambda_turb_l*SMOOTH(
                Re_turb_min,
                Re_lam_max,
                Re_l) "Darcy friction factor of liquid for overall regime";

            Real A=(1 - x_flow)^2 + x_flow^2*(IN_var.rho_l/max(MIN, IN_var.rho_g))*(
                lambda_g/max(MIN, lambda_l)) "Summand for two phase multiplier";

            //SOURCE_1: p.490 (Appendix): Two phase multiplier for vertical downflow for future usage
            Real phi_vdo=A + 38.5*x_flow^0.76*(1 - x_flow)^0.314*(IN_var.rho_l/max(MIN,
                IN_var.rho_g))^0.86*(IN_var.eta_g/max(MIN, IN_var.eta_l))^0.73*(1 -
                IN_var.eta_g/max(MIN, IN_var.eta_l))^6.84*(1/Fr_l^(0.0001))*(1/We_l^(
                0.087));

            //SOURCE_1: p.490 (Appendix): Two phase multiplier for horizontal and vertical upflow (failure in SOURCE_2)
            Real phi_vup=A + 3.43*x_flow^0.685*(1 - x_flow)^0.24*(IN_var.rho_l/max(MIN,
                IN_var.rho_g))^0.8*(IN_var.eta_g/max(MIN, IN_var.eta_l))^0.22*(1 - IN_var.eta_g
                /max(MIN, IN_var.eta_l))^0.89*(1/Fr_l^(0.048))*(1/We_l^(0.0334));

          algorithm
            phi := phi_vup;
          end TwoPhaseMultiplierFriedel;

          function TwoPhaseMultiplierChisholm
            "Calculation of two phase multiplier according to Chisholm | constant mass flow rate quality"
            extends Modelica.Icons.Function;
            //SOURCE_1: Chisholm,D.:PRESSURE GRADIENTS DUE TO FRICTION DURING THE FLOW OF EVAPORATING TWO-PHASE MIXTURES IN SMOOTH TUBES AND CHANNELS, Int. J. Heat Mass Transfer, Vol. 16, pp. 347-358, Pergamon Press 1973
            //SOURCE_2: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.

            import SMOOTH =
              Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.General.TwoPhaseFlow_var
              IN_var
            input SI.MassFlowRate m_flow "Mass flow rate"

            output Real phi "Two phase multiplier w.r.t. Chisholm";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
              "Hydraulic diameter";

            Real mdot_A=abs(m_flow)/A_cross "Mass flux";
            Real x_flow=max(0, min(1, abs(IN_var.x_flow)))
              "Mass flow rate quality";

            //SOURCE_1: p.357, Appendix 1: Considering Darcy friction factor (lambda_FRI) of smooth pipes for overall flow regime
            Real n_exp=0.2 "Exponent for Reynolds number (lambda_FRI= A/Re^n)";

            //SOURCE_1: p.349, eq. 21: Considering effect of physical properties (failure in SOURCE_2)
            Real gamma=max(1, abs(IN_var.rho_l/max(MIN, IN_var.rho_g))^0.5*(IN_var.eta_g/
                max(MIN, IN_var.eta_l))^(n_exp/2));

            //SOURCE: p. 353, tab. 2: Considering effect of mass flux on two phase multiplier
            Real B_gamma_1=SMOOTH(
                450,
                550,
                mdot_A)*4.8 + SMOOTH(
                550,
                450,
                mdot_A)*2400/max(MIN, mdot_A) - SMOOTH(
                1950,
                1850,
                mdot_A)*2400/max(MIN, mdot_A) + SMOOTH(
                1950,
                1850,
                mdot_A)*55/max(MIN, mdot_A^0.5)
              "Coefficient B for gamma <= 9.5";
            Real B_gamma_2=SMOOTH(
                550,
                650,
                mdot_A)*520/max(1, max(9.5, gamma)*mdot_A^0.5) + SMOOTH(
                650,
                550,
                mdot_A)*21/max(9.5, gamma)
              "Coefficient B for 9.5 <= gamma <= 28";
            Real B_gamma=SMOOTH(
                9.0,
                10,
                gamma)*B_gamma_1 + SMOOTH(
                10,
                9.0,
                gamma)*B_gamma_2 - SMOOTH(
                28.5,
                27.7,
                gamma)*B_gamma_2 + SMOOTH(
                28.5,
                27.5,
                gamma)*15000/max(MIN, gamma^2*mdot_A^0.5)
              "Coefficient B for gamma";

            //SOURCE_1: p. 350, eq. 24/26: Considering two phase multiplier w.r.t. Chisholm
          algorithm
            phi := 1 + (gamma^2 - 1)*(B_gamma*x_flow^((2 - n_exp)/2)*(1 - x_flow)^((2 -
              n_exp)/2) + x_flow^(2 - n_exp));
          end TwoPhaseMultiplierChisholm;

          function TwoPhaseDensity
            "Calculation of mean density for two phase flow"
            extends Modelica.Icons.Function;
            //SOURCE_1: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.
            input
              Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach
              voidFractionApproach=
                Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous
              "Choice of void fraction approach"

            //SOURCE_3: p.52, eq. 4.6: heterogeneous effects on momentum pressure loss considered through corrected mass flow rate
            input Boolean massFlowRateCorrection=false
              "Consider heterogeneous mass flow rate correction"

            input SI.Density rho_g(min=Modelica.Constants.eps)
              "Density of gaseous phase"
            input SI.Density rho_l(min=Modelica.Constants.eps)
              "Density of liquid phase"
            input Real epsilon_A(min=0,max=1)
              "Void fraction (cross sectional averaged)"
            // It should be enable=not (voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous)
            // But then there is no value for epsilon_A
            input Real x_flow(min=0,max=1) "Mass flow rate quality"

            output SI.Density rho_2ph "Mean density of two phase flow";
          protected
            Real MIN=Modelica.Constants.eps;

            Real epsilonA=min(1, max(0, abs(epsilon_A)))
              "Void fraction (cross sectional averaged)";
            Real xflow=min(1, max(0, abs(x_flow))) "Mass flow rate quality";

            //SOURCE_1: p.Lba 3, eq. 17: Mean two phase density assuming homogeneous approach
            SI.Density rho_hom=1/max(MIN, x_flow/max(MIN, rho_g) + (1 - x_flow)/max(MIN,
                rho_l));
            //SOURCE_1: p.Lbb 7, tab. 2: Mean two phase density assuming momentum flux approach
            SI.Density rho_mom=1/max(MIN, (x_flow)^2/max(MIN, rho_g*epsilonA) + (1 -
                x_flow)^2/max(MIN, rho_l*(1 - epsilonA)));
            //SOURCE_1: p.Lbb 7, tab. 2: Mean two phase density assuming kinetic energy flow approach from Zivi (corrected formula!)
            SI.Density rho_kin=1/max(MIN, rho_hom*(x_flow^3/max(MIN, rho_g^2*epsilonA^2)
                 + (1 - x_flow)^3/max(MIN, rho_l^2*(1 - epsilonA)^2)));

          algorithm
            rho_2ph := if not massFlowRateCorrection then rho_hom else if
              voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous then
                    rho_hom else if voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Momentum then
                    rho_mom else if voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Energy then
                    rho_kin else MIN;
          end TwoPhaseDensity;

          function VoidFraction
            "Calculation of (cross sectional) void fraction for two phase flow"
            extends Modelica.Icons.Function;
            //SOURCE_1: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.
            //SOURCE_2: Thome, J.R., Engineering Data Book 3, Swiss Federal Institute of Technology Lausanne (EPFL), 2009.

            input
              Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach
              voidFractionApproach=Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous
              "Choice of void fraction approach"

            input Boolean crossSectionalAveraged=true
              "= true, if cross sectional averaged void fraction, otherwise volumetric"

            input SI.Density rho_g(min=Modelica.Constants.eps)
              "Density of gaseous phase"
            input SI.Density rho_l(min=Modelica.Constants.eps)
              "Density of liquid phase"
            input Real x_flow(
              min=0,
              max=1) = 0 "Mass flow rate quality"

            output Real epsilon "Void fraction";
            output Real slipRatio "Slip ratio";

          protected
            Real MIN=Modelica.Constants.eps;

            Real xflow=min(1, max(0, abs(x_flow))) "Mass flow rate quality";

            Real SR=Dissipation.Utilities.Functions.PressureLoss.TwoPhase.SlipRatio(
                voidFractionApproach,
                rho_g,
                rho_l,
                xflow) "Slip ratio for void fraction approach";

            //SOURCE_2: p.17-5, eq. 17.2.5: (Heterogeneous) cross sectional void fraction [epsilon_A=A_g/(A_g+A_l)]
            Real epsilon_A=rho_l*x_flow/max(MIN, rho_l*x_flow + rho_g*(1 - x_flow)*SR);

          algorithm
            epsilon := if crossSectionalAveraged then epsilon_A else epsilon_A/((1/max(
              MIN, SR))*(1 - epsilon_A) + epsilon_A);
            slipRatio := SR;
          end VoidFraction;

          function SlipRatio "Calculation of (analytical/empirical) slip ratio"
            extends Modelica.Icons.Function;
            //SOURCE_1: VDI-Waermeatlas, 10th edition, Springer-Verlag, 2006.
            //SOURCE_2: Thome, J.R., Engineering Data Book 3, Swiss Federal Institute of Technology Lausanne (EPFL), 2009.
            //SOURCE 3: J.M. Jensen and H. Tummescheit. Moving boundary models for dynamic simulations of two-phase flows. In Proceedings of the 2nd International Modelica Conference, pp. 235-244, Oberpfaffenhofen, Germany, 2002. The Modelica Association.

            input
              Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach
              voidFractionApproach=Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous
              "Choice of void fraction approach"

            input SI.Density rho_g(min=Modelica.Constants.eps)
              "Density of gaseous phase"
            input SI.Density rho_l(min=Modelica.Constants.eps)
              "Density of liquid phase"
            input Real x_flow=0 "Mass flow rate quality"

            output Real SR "Slip ratio";

          protected
            Real MIN=Modelica.Constants.eps;

            //SOURCE_1: p.Lba 3, sec. 3.2
            Real SR_hom=1 "Slip ratio w.r.t. homogeneous approach";
            //SOURCE_2: p.17-6, eq. 17.3.4
            Real SR_mom=abs(rho_l/max(MIN, rho_g))^0.5
              "Slip ratio w.r.t. momentum flux approach (heterogeneous)";
            //SOURCE_2: p.17-7, eq. 17.3.13
            Real SR_kin=abs(rho_l/max(MIN, rho_g))^(1/3)
              "Slip ratio w.r.t. kinetic energy flow approach from Zivi (heterogeneous)";
            //SOURCE_2: p.17-10, eq. 17.4.3
            Real SR_chi=(1 - x_flow*(1 - abs(rho_l)/max(MIN, abs(rho_g))))^0.5
              "Empirical slip ratio w.r.t. momentum flux approach from Chisholm (heterogeneous)";

          algorithm
            SR := if voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Homogeneous then
                    SR_hom else if voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Momentum then
                    SR_mom else if voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Energy then
                    SR_kin else if voidFractionApproach == Modelica.Fluid.Dissipation.Utilities.Types.VoidFractionApproach.Chisholm then
                    SR_chi else 1;
          end SlipRatio;
        end TwoPhase;
      end PressureLoss;

      package HeatTransfer "Package for utility heat transfer functions"
        extends Modelica.Icons.FunctionsPackage;

        package TwoPhase
          "Package with utility functions to compute two phase heat transfer characteristics"
          extends Modelica.Icons.FunctionsPackage;

          function kc_twoPhase_condensationHorizontal_KC
            "Local two phase heat transfer coefficient of straight pipe | horizontal condensation"
            extends Modelica.Icons.Function;
            //SOURCE_1: M.M. Shah. A general correlation for heat transfer during film condensation inside pipes.Int. J. Heat Mass Transfer, Vol.22, p.547-556, 1979.

            //records
            input
              Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_var
              IN_var

            output SI.CoefficientOfHeatTransfer kc
              "Local two phase heat transfer coefficient";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
              "Hydraulic diameter";

            Real x_flow=max(0, min(1, abs(IN_var.x_flow)))
              "Mass flow rate quality";
            Real p_red=max(MIN, abs(IN_var.pressure)/max(MIN, abs(IN_con.p_crit)))
              "Reduced pressure";

            SI.Velocity velocity=abs(IN_var.m_flow)/max(MIN, IN_var.rho_l*A_cross)
              "Mean velocity";
            SI.ReynoldsNumber Re_l=(IN_var.rho_l*velocity*d_hyd/max(MIN, IN_var.eta_l))
              "Reynolds number assuming (total) mass flux flowing as liquid";
            SI.PrandtlNumber Pr_l=abs(IN_var.eta_l*IN_var.cp_l/max(MIN, IN_var.lambda_l))
              "Prandtl number assuming (total) mass flux flowing as liquid";

            //SOURCE_1: p.548, eq. 8: Considering two phase multiplier for condensation w.r.t. Shah
            SI.CoefficientOfHeatTransfer kc_1ph=0.023*Re_l^0.8*Pr_l^0.4*IN_var.lambda_l
                /d_hyd;

          algorithm
            kc := kc_1ph*((1 - x_flow)^0.8 + 3.8*x_flow^0.76*(1 - x_flow)^0.04/p_red^
              0.38);
          end kc_twoPhase_condensationHorizontal_KC;

          function kc_twoPhase_boilingVertical_KC
            "Local two phase heat transfer coefficient of straight pipe | vertical boiling"
            extends Modelica.Icons.Function;
            //SOURCE_1: Bejan,A.: HEAT TRANSFER HANDBOOK, Wiley, 2003.
            //SOURCE_2: Gungor, K.E. and R.H.S. Winterton: A general correlation for flow boiling in tubes and annuli, Int.J. Heat Mass Transfer, Vol.29, p.351-358, 1986.

            //records
            input
              Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_var
              IN_var

            output SI.CoefficientOfHeatTransfer kc
              "Local two phase heat transfer coefficient";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
              "Hydraulic diameter";

            Real mdot_A=abs(IN_var.m_flow)/A_cross "Mass flux";
            Real x_flow=max(0, min(1, abs(IN_var.x_flow)))
              "Mass flow rate quality";
            Real p_red=max(MIN, abs(IN_var.pressure)/max(MIN, abs(IN_con.p_crit)))
              "Reduced pressure";

            //SOURCE_1: p.674, sec. 9.8.3: Considering nucleate and convective boiling w.r.t. equation of Gungor-Winterton
            SI.MassFlowRate mdot_l=abs(IN_var.m_flow)*(1 - x_flow)
              "Mass flow rate of liquid only";
            SI.Velocity velocity_l=mdot_l/max(MIN, IN_var.rho_l*A_cross)
              "Mean velocity assuming liquid mass flow rate flows alone";
            SI.ReynoldsNumber Re_l=(IN_var.rho_l*velocity_l*d_hyd/max(MIN, IN_var.eta_l))
              "Reynolds number assuming liquid mass flow rate flows alone";
            SI.PrandtlNumber Pr_l=abs(IN_var.eta_l*IN_var.cp_l/max(MIN, IN_var.lambda_l))
              "Prandtl number assuming liquid mass flow rate flows alone";

            //SOURCE_1: p.674, eq. 9.98: Considering effect of heat flux on nucleate boiling with Boiling number
            //Boiling number (Bo) is defined as ratio of actual heat flux to maximum heat flux necessary for complete evaporation of liquid
            Real Bo=abs(IN_var.qdot_A)/(max(MIN, mdot_A*IN_var.dh_lg))
              "Boiling number";
            //SOURCE_1: p.673, eq. 9.94: Considering of Martinelli parameter w.r.t. equation of Chen
            Real X_tt=abs(((1 - x_flow)/max(MIN, x_flow))^0.9*(IN_var.rho_g/max(MIN,
                IN_var.rho_l))^0.5*(IN_var.eta_l/max(MIN, IN_var.eta_g))^0.1)
              "Martinelli parameter";

            //SOURCE_1: p.675, eq. 9.105: Considering of convection enhancement factor w.r.t. equation of Gungor-Winterton
            Real E_fc=1 + 24000*Bo^1.16 + 1.37*(1/max(MIN, X_tt))^0.86
              "Enhancement factor for forced convection";
            //SOURCE_1: p.675, eq. 9.105: Considering of boiling suppression factor w.r.t. equation of Gungor-Winterton
            Real S_nb=1/max(MIN, 1 + 1.15e-6*E_fc^2*Re_l^1.17)
              "Suppression factor for nucleate boiling";

            //SOURCE_1: p.672, eq. 9.91: Considering effect of forced convective boiling ew.r.t. equation of Dittus-Boelter
            SI.CoefficientOfHeatTransfer kc_fc=0.023*Re_l^0.8*Pr_l^0.4*(IN_var.lambda_l
                /d_hyd)
              "Convective heat transfer coefficient assuming liquid mass flow rate only";
            //SOURCE_1: p.675, eq. 9.107: Considering effect of nucleate boiling w.r.t. equation of Cooper
            SI.CoefficientOfHeatTransfer kc_nb=55*p_red^0.12*(1/max(MIN,
                Modelica.Math.log10(1/p_red))^0.55)*(1/max(MIN, IN_con.MM)^0.5)*IN_var.qdot_A
                ^0.67 "Nucleate boiling heat transfer coefficient";

            //SOURCE_2: p.354, sec. final equations: Calculation of two phase heat transfer coefficient for vertical pipes w.r.t. equation of Gungor-Winterton
          algorithm
            kc := E_fc*kc_fc + S_nb*kc_nb;
          end kc_twoPhase_boilingVertical_KC;

          function kc_twoPhase_boilingHorizontal_KC
            "Local two phase heat transfer coefficient of straight pipe | horizontal boiling"
            extends Modelica.Icons.Function;
            //SOURCE_1: Bejan,A.: HEAT TRANSFER HANDBOOK, Wiley, 2003.
            //SOURCE_2: Gungor, K.E. and R.H.S. Winterton: A general correlation for flow boiling in tubes and annuli, Int.J. Heat Mass Transfer, Vol.29, p.351-358, 1986.

            import SMOOTH =
              Modelica.Fluid.Dissipation.Utilities.Functions.General.Stepsmoother;

            //records
            input
              Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_con
              IN_con
            input
              Modelica.Fluid.Dissipation.Utilities.Records.HeatTransfer.TwoPhaseFlowHT_IN_var
              IN_var

            output SI.CoefficientOfHeatTransfer kc
              "Local two phase heat transfer coefficient";

          protected
            Real MIN=Modelica.Constants.eps;

            SI.Area A_cross=max(MIN, IN_con.A_cross) "Cross sectional area";
            SI.Diameter d_hyd=max(MIN, 4*A_cross/max(MIN, IN_con.perimeter))
              "Hydraulic diameter";

            Real mdot_A=abs(IN_var.m_flow)/A_cross "Mass flux";
            Real x_flow=max(0, min(1, abs(IN_var.x_flow)))
              "Mass flow rate quality";
            Real p_red=max(MIN, abs(IN_var.pressure)/max(MIN, abs(IN_con.p_crit)))
              "Reduced pressure";

            //SOURCE_1: p.674, sec. 9.8.3: Considering nucleate and convective boiling w.r.t. equation of Gungor-Winterton
            SI.MassFlowRate mdot_l=abs(IN_var.m_flow)*(1 - x_flow)
              "Mass flow rate of liquid only";
            SI.Velocity velocity_l=mdot_l/max(MIN, IN_var.rho_l*A_cross)
              "Mean velocity assuming liquid mass flow rate flows alone";
            SI.ReynoldsNumber Re_l=(IN_var.rho_l*velocity_l*d_hyd/max(MIN, IN_var.eta_l))
              "Reynolds number assuming liquid mass flow rate flows alone";
            SI.PrandtlNumber Pr_l=abs(IN_var.eta_l*IN_var.cp_l/max(MIN, IN_var.lambda_l))
              "Prandtl number assuming liquid mass flow rate flows alone";
            //SOURCE_1: p.352, sec. Nomenclature: Considering effect of stratification w.r.t. Froude number
            SI.FroudeNumber Fr_l=abs(mdot_A^2/max(MIN, IN_var.rho_l^2*9.81*d_hyd))
              "Froude number assuming (total) mass flux flowing as liquid";

            //SOURCE_1: p.674, eq. 9.98: Considering effect of heat flux on nucleate boiling with Boiling number
            //Boiling number (Bo) is defined as ratio of actual heat flux to maximum heat flux necessary for complete evaporation of liquid
            Real Bo=abs(IN_var.qdot_A)/(max(MIN, mdot_A*IN_var.dh_lg))
              "Boiling number";
            //SOURCE_1: p.673, eq. 9.94: Considering of Martinelli parameter w.r.t. equation of Chen
            Real X_tt=abs(((1 - x_flow)/max(MIN, x_flow))^0.9*(IN_var.rho_g/max(MIN,
                IN_var.rho_l))^0.5*(IN_var.eta_l/max(MIN, IN_var.eta_g))^0.1)
              "Martinelli parameter";

            //SOURCE_1: p.675, eq. 9.105: Considering of convection enhancement factor w.r.t. equation of Gungor-Winterton
            Real E_fc=1 + 24000*Bo^1.16 + 1.37*(1/max(MIN, X_tt))^0.86
              "Enhancement factor for forced convection";
            //SOURCE_1: p.675, eq. 9.105: Considering of boiling suppression factor w.r.t. equation of Gungor-Winterton
            Real S_nb=1/max(MIN, 1 + 1.15e-6*E_fc^2*Re_l^1.17)
              "Suppression factor for nucleate boiling";
            //SOURCE_1: p.680, eq. 9.123: Considering correction of convection enhancement factor for horizontal pipes
            Real E_fc_hor=SMOOTH(
                  0.049,
                  0.051,
                  Fr_l)*Fr_l^max(0, abs(0.1 - 2*Fr_l)) + SMOOTH(
                  0.051,
                  0.049,
                  Fr_l)
              "Correction of enhancement factor for forced convection in horizontal pipes";
            //SOURCE_1: p.680, eq. 9.124: Considering correction of boiling suppression factor for horizontal pipes
            Real S_nb_hor=SMOOTH(
                  0.049,
                  0.051,
                  Fr_l)*Fr_l^0.5 + SMOOTH(
                  0.051,
                  0.049,
                  Fr_l)
              "Correction of suppression factor for nucleate boiling in horizontal pipes";

            //SOURCE_1: p.672, eq. 9.91: Considering effect of forced convective boiling ew.r.t. equation of Dittus-Boelter
            SI.CoefficientOfHeatTransfer kc_fc=0.023*Re_l^0.8*Pr_l^0.4*(IN_var.lambda_l
                /d_hyd)
              "Convective heat transfer coefficient assuming liquid mass flow rate only";
            //SOURCE_1: p.675, eq. 9.107: Considering effect of nucleate boiling w.r.t. equation of Cooper
            SI.CoefficientOfHeatTransfer kc_nb=55*p_red^0.12*(1/max(MIN,
                Modelica.Math.log10(1/p_red))^0.55)*(1/max(MIN, IN_con.MM^0.5))*abs(
                IN_var.qdot_A)^0.67
              "Nucleate boiling heat transfer coefficient";

            //SOURCE_2: p.354, sec. final equations: Calculation of two phase heat transfer coefficient for horizontal pipes w.r.t. equation of Gungor-Winterton
          algorithm
            kc := E_fc*E_fc_hor*kc_fc + S_nb*S_nb_hor*kc_nb;
          end kc_twoPhase_boilingHorizontal_KC;

        end TwoPhase;
      end HeatTransfer;

      package General "Package with utility functions"
        extends Modelica.Icons.FunctionsPackage;

        function CubicInterpolation_Re
          "Cubic Hermite spline interpolation of the Reynolds number in transition regime of the Moody diagram (inverse formulation)"
          extends Modelica.Icons.Function;
          import Modelica.Math;
          input Real Re_turbulent "Unused input";
          input SI.ReynoldsNumber Re1 "Boundary Reynolds number for laminar regime";
          input SI.ReynoldsNumber Re2 "Boundary Reynolds number for turbulent regime";
          input Real Delta "Relative roughness";
          input Real lambda2 "Modified friction coefficient (= independent variable)";
          output SI.ReynoldsNumber Re "Interpolated Reynolds number in transition region";
        protected
          // Point x1=lg(lambda2(Re1)) with derivative yd1=1 at y1=lg(Re1)
          Real x1=Math.log10(64*Re1) "Lower abscissa value";
          Real y1=Math.log10(Re1) "Lower ordinate value";
          Real yd1=1 "Left boundary slope";

          // Point x2=lg(lambda2(Re2)) with derivative yd2 at y2≈lg(Re2)
          Real aux1=(0.5/Math.log(10))*5.74*0.9;
          Real aux2=Delta/3.7 + 5.74/Re2^0.9;
          Real aux3=Math.log10(aux2);
          Real L2=0.25*(Re2/aux3)^2;
          Real aux4=2.51/sqrt(L2) + 0.27*Delta;
          Real aux5=-2*sqrt(L2)*Math.log10(aux4);
          Real x2=Math.log10(L2) "Upper abscissa value";
          Real y2=Math.log10(aux5) "Upper ordinate value";
          Real yd2=0.5 + (2.51/Math.log(10))/(aux5*aux4) "Right boundary slope";

          // Constants: Cubic polynomial between x1=lg(lambda2(Re1)) and x2=lg(lambda2(Re2))
          Real diff_x=x2 - x1 "Interval length";
          Real m=(y2 - y1)/diff_x;
          Real c2=(3*m - 2*yd1 - yd2)/diff_x;
          Real c3=(yd1 + yd2 - 2*m)/(diff_x*diff_x);
          Real lambda2_1=64*Re1;
          Real dx=Math.log10(lambda2/lambda2_1);

        algorithm
          // Prefer optimized interpolation formula for Re to avoid cubicHermite function call
          // Re := 10^Modelica.Fluid.Utilities.cubicHermite(Math.log10(lambda2), x1, x2, y1, y2, yd1, yd2);
          Re := Re1*(lambda2/lambda2_1)^(yd1 + dx*(c2 + dx*c3));

Description

Function CubicInterpolation_Re(..) approximates the Reynolds number
Re in the transition regime between laminar and turbulent flow
of the Moody diagram by an inverse formulation of a cubic Hermite spline interpolation. See
Modelica.Fluid.UsersGuide.ComponentDefinition.WallFriction (especially Region 2)
for a detailed explanation.

", revisions="
2018-11-20 Stefan Wischhusen: Renamed function from CubicInterpolation_DP to CubicInterpolation_Re.
"));
        end CubicInterpolation_Re;

        function CubicInterpolation_lambda
          "Cubic Hermite spline interpolation of the modified friction coefficient in transition regime of the Moody diagram (direct formulation)"
          extends Modelica.Icons.Function;
          import Modelica.Math;
          input SI.ReynoldsNumber Re "Reynolds number (= independent variable)";
          input SI.ReynoldsNumber Re1 "Boundary Reynolds number for laminar regime";
          input SI.ReynoldsNumber Re2 "Boundary Reynolds number for turbulent regime";
          input Real Delta "Relative roughness";
          output Real lambda2 "Interpolated modified friction coefficient in transition regime";
        protected
          // Point x1=lg(Re1) with derivative yd1=1 at y1=lg(lambda2(Re1))
          Real x1=Math.log10(Re1) "Lower abscissa value";
          Real y1=Math.log10(64*Re1) "Lower ordinate value";
          Real yd1=1 "Left boundary slope";

          // Point x2=lg(Re2) with derivative yd2 at y2=lg(lambda2(Re2))
          Real aux1=(0.5/Math.log(10))*5.74*0.9;
          Real aux2=Delta/3.7 + 5.74/Re2^0.9;
          Real aux3=Math.log10(aux2);
          Real L2=0.25*(Re2/aux3)^2;
          Real aux4=2.51/sqrt(L2) + 0.27*Delta;
          Real aux5=-2*sqrt(L2)*Math.log10(aux4);
          Real x2=Math.log10(Re2) "Upper abscissa value";
          Real y2=Math.log10(L2) "Upper ordinate value";
          Real yd2=2 + 4*aux1/(aux2*aux3*(Re2)^0.9) "Right boundary slope";

          // Constants: Cubic polynomial between x1=lg(Re1) and x2=lg(Re2)
          Real diff_x=x2 - x1 "Interval length";
          Real m=(y2 - y1)/diff_x;
          Real c2=(3*m - 2*yd1 - yd2)/diff_x;
          Real c3=(yd1 + yd2 - 2*m)/(diff_x*diff_x);
          Real dx=Math.log10(Re/Re1);

        algorithm
          // Prefer optimized interpolation formula for lambda2 to avoid cubicHermite function call
          // lambda2 := 10^Modelica.Fluid.Utilities.cubicHermite(Math.log10(Re), x1, x2, y1, y2, yd1, yd2);
          lambda2 := 64*Re1*(Re/Re1)^(yd1 + dx*(c2 + dx*c3));

Description

Function CubicInterpolation_lambda(..) approximates the modified friction coefficient
lambda2=lambda*Re^2 in the transition regime between laminar and turbulent flow
of the Moody diagram by a (direct) cubic Hermite spline interpolation.
See
Modelica.Fluid.UsersGuide.ComponentDefinition.WallFriction (especially Region 2)
for a detailed explanation.

", revisions="
2018-11-20 Stefan Wischhusen: Renamed function from CubicInterpolation_MFLOW to CubicInterpolation_lambda.
"));
        end CubicInterpolation_lambda;

        function LambertW
          "Closed approximation of Lambert's w function for solving f(x) = x exp(x) for x"
          extends Modelica.Icons.Function;
          input Real y "Input f(x)";
          output Real x "Output W(y)";
        protected
          Real xl;

        algorithm
          if (y <= 500.0) then
            xl := Modelica.Math.log(y + 1.0);
            x := 0.665*(1 + 0.0195*xl)*xl + 0.04;
          else
            xl := 0;
            x := Modelica.Math.log(y - 4.0) - (1.0 - 1.0/Modelica.Math.log(y))*
              Modelica.Math.log(Modelica.Math.log(y));
          end if;

          assert(y > -1/Modelica.Math.exp(1),
            "Lambert-w-function is only valid for inputs y > -1/Modelica.Math.exp(1)!");
        end LambertW;

        function LambertWIter
          "Iterative form of Lambert's w function for solving f(x) = x exp(x) for x"
          extends Modelica.Icons.Function;
          input Real y "Input f(x)";
          output Real x "Output W(y)";
          output Integer iter;
        protected
          Real w;
          Real prec=1e-12;
          Real c1;
          Real c2;
          Real dw;
          Real w1;
          /*Real wTimesExpW;
  Real wPlusOneTimesExpW;*/
          Real dev;
          Integer i;

        algorithm
          w := if y > 0.1 then Modelica.Fluid.Dissipation.Utilities.Functions.General.LambertW(
            y) else sqrt(5.43656*max(y, -1/Modelica.Math.exp(1)) + 2) - 1;
          dev := 1;
          i := 0;
          while prec < dev and i < 100 loop
            /*wTimesExpW := w*Modelica.Math.exp(w);
                wPlusOneTimesExpW := (w+1)*Modelica.Math.exp(w);
                w := w-(wTimesExpW-y)/(wPlusOneTimesExpW-(w+2)*(wTimesExpW-y)/(2*w+2));
                dev := abs((y-wTimesExpW)/wPlusOneTimesExpW);
                i := i+1;*/

            c1 := Modelica.Math.exp(w);
            c2 := w*c1 - y;
            w1 := if w <> 1 then w + 1 else w;
            dw := c2/(c1*w1 - ((w + 2)*c2/(2*w1)));
            w := w - dw;
            //dev := abs(dw)/(2+abs(w));
            dev := abs((y - w*c1)/(w + 1)*c1);
            i := i + 1;
          end while;
          x := w;
          iter := i;
        end LambertWIter;

        function PrandtlNumber "Calculation of Prandtl number"
          extends Modelica.Icons.Function;
          import MIN = Modelica.Constants.eps;

          //fluid properties
          input SI.SpecificHeatCapacityAtConstantPressure cp
            "Specific heat capacity of fluid at constant pressure";
          input SI.DynamicViscosity eta "Dynamic viscosity of fluid";
          input SI.ThermalConductivity lambda "Thermal conductivity of fluid";

          output SI.PrandtlNumber Pr "Prandtl number";

        algorithm
          Pr := eta*cp/max(MIN, lambda);
        end PrandtlNumber;

        function ReynoldsNumber "Calculation of Reynolds number"
          extends Modelica.Icons.Function;
          import MIN = Modelica.Constants.eps;

          //geometry
          input SI.Area A_cross "Cross sectional area";
          input SI.Length perimeter "Wetted perimeter";

          //fluid properties
          input SI.Density rho "Density of fluid";
          input SI.DynamicViscosity eta "Dynamic viscosity of fluid";

          input SI.MassFlowRate m_flow "Mass flow rate";

          output SI.ReynoldsNumber Re "Reynolds number";
          output SI.Velocity velocity "Mean velocity";

        protected
          SI.Diameter d_hyd=4*A_cross/max(MIN, perimeter) "Hydraulic diameter";

        algorithm
          Re := 4*abs(m_flow)/max(MIN, (perimeter*eta));
          velocity := m_flow/max(MIN, (rho*A_cross));
        end ReynoldsNumber;

        function SmoothPower
          "Limiting the derivative of function y = if x>=0 then x^pow else -(-x)^pow"
          extends Modelica.Icons.Function;
          input Real x "Input variable";
          input Real deltax "Range for interpolation";
          input Real pow "Exponent for x";
          output Real y "Output variable";
        protected
          Real adeltax=abs(deltax);
          Real C3=(pow - 1)/2*adeltax^(pow - 3);
          Real C1=(3 - pow)/2*adeltax^(pow - 1);

        algorithm
          y := if x >= adeltax then x^pow else if x <= -adeltax then -(-x)^pow else (C1
             + C3*x*x)*x;
        end SmoothPower;

        function SmoothPower_der "The derivative of function SmoothPower"
          extends Modelica.Icons.Function;
          input Real x "Input variable";
          input Real deltax "Range of interpolation";
          input Real pow "Exponent for x";
          input Real dx "Derivative of x";
          output Real dy "Derivative of SmoothPower";
        protected
          Real C3;
          Real C1;
          Real adeltax;

        algorithm
          adeltax := abs(deltax);
          if x >= adeltax then
            dy := dx*pow*x^(pow - 1);
          elseif x <= -adeltax then
            dy := dx*pow*(-x)^(pow - 1);
          else
            C3 := (pow - 1)/2*adeltax^(pow - 3);
            C1 := (3 - pow)/2*adeltax^(pow - 1);
            dy := (C1 + 3*C3*x*x)*dx;
          end if;
        end SmoothPower_der;

        function Stepsmoother "Continuous interpolation for x"

          extends Modelica.Icons.Function;
          input Real func "Input value for that result = 100%";
          input Real nofunc "Input value for that result = 0%";
          input Real x "Input variable for continuous interpolation";
          output Real result "Output value";

        protected
          Real m=Modelica.Constants.pi/(func - nofunc);
          Real b=-Modelica.Constants.pi/2 - m*nofunc;

        algorithm
          result := if x >= func and func > nofunc or x
             <= func and nofunc > func then 1 else if x
             <= nofunc and func > nofunc or x >= nofunc and nofunc > func then 0 else (1+Modelica.Math.tanh(Modelica.Math.tan(m*x + b)))/2;
        end Stepsmoother;

        function Stepsmoother_der "Derivative of function Stepsmoother"

          extends Modelica.Icons.Function;
          input Real func "Input for that result = 100%";
          input Real nofunc "Input for that result = 0%";
          input Real x "Input for interpolation";
          input Real dfunc "Derivative of func";
          input Real dnofunc "Derivative of nofunc";
          input Real dx "Derivative of x";
          output Real dresult;

        protected
          Real m=Modelica.Constants.pi/(func - nofunc);
          Real b=-Modelica.Constants.pi/2 - m*nofunc;

        algorithm
        dresult := if x >= func and func > nofunc or x <= func and nofunc > func or x <= nofunc and func > nofunc or x >= nofunc
             and nofunc > func then 0 else (1 - Modelica.Math.tanh(Modelica.Math.tan(m*x + b))^2)*
             (1 + Modelica.Math.tan(m*x + b)^2)*(-m^2/Modelica.Constants.pi*(dfunc - dnofunc)*x
              + m*dx + m^2/Modelica.Constants.pi*(dfunc - dnofunc)*nofunc - m*dnofunc)/2;
        end Stepsmoother_der;
      end General;
    end Functions;

    package Icons "Icons for Fluid.Dissipation and Fluid.Fittings libraries"
      extends Modelica.Icons.IconsPackage;

      package HeatTransfer "Icons for heat transfer calculation"
      extends Modelica.Icons.IconsPackage;

        partial model Gap1_d "Geometry figure for gap"

        end Gap1_d;

        partial model HelicalPipe1_d "Geometry figure for helical pipe"
        end HelicalPipe1_d;

        partial model Plate1_d "Geometry figure 1 for plate"
        end Plate1_d;

        partial model Plate2_d "Geometry figure 2 for plate"
        end Plate2_d;

        partial model Channel_i "Icon for heat transfer in a channel"
        end Channel_i;

        partial model General_i "Icon for general heat transfer component"
        end General_i;

        partial model HeatExchanger_i
          "Icon for heat transfer of a heat exchanger"
        end HeatExchanger_i;

        partial model HelicalPipe_i "Icon for heat transfer in a helical pipe"
        end HelicalPipe_i;

        partial model Plate_i "Icon for heat transfer of a plate"
        end Plate_i;

        partial model StraightPipe_i
          "Icon for heat transfer of a straight pipe"

        end StraightPipe_i;
      end HeatTransfer;

      package PressureLoss "Icons for pressure loss calculation"
        extends Modelica.Icons.IconsPackage;

        partial model BendEdged_d "Geometry figure of edged bend"

        end BendEdged_d;

        partial model Channel_d "Geometry figure for channel"

        end Channel_d;

        partial model OrificeSuddenChangeSection_d
          "Geometry figure for orifice with sudden change of cross sectional area"

        end OrificeSuddenChangeSection_d;

        partial model OrificeThickEdged_d
          "Geometry figure for orifice with thick edged vena contraction"
        end OrificeThickEdged_d;

        partial model StraightPipe_d "Geometry figure for straight pipe"

        end StraightPipe_d;

        partial model Valve_d "Icon for valve"

        end Valve_d;

        model FlowModel "Icon for flow model in Modelica.Fluid applications"
        end FlowModel;

        partial model Bend_i "Icon for bend"
        end Bend_i;

        partial model Channel_i "Icon for channel"
        end Channel_i;

        partial model General_i "Icon for general pressure drop"
        end General_i;

        partial model HeatExchanger_i
        end HeatExchanger_i;

        partial model Orifice_i "Icon for orifice"
        end Orifice_i;

        partial model StraightPipe_i "Icon for straight pipe"
        end StraightPipe_i;

        partial model Valve_i "Icon for valve"
        end Valve_i;
      end PressureLoss;

    end Icons;

    package Records "Package for base records"
    extends Modelica.Icons.RecordsPackage;
      package General
        extends Modelica.Icons.RecordsPackage;
        record PressureLoss
          "Base record for fluid properties for pressure loss"
          extends Modelica.Icons.Record;

          SI.DynamicViscosity eta "Dynamic viscosity of fluid"
          SI.Density rho "Density of fluid"
        end PressureLoss;

        record FluidProperties "Base record for fluid properties"
          extends Modelica.Icons.Record;

          SI.SpecificHeatCapacityAtConstantPressure cp
            "Specific heat capacity of fluid at constant pressure"

          SI.DynamicViscosity eta "Dynamic viscosity of fluid"

          SI.ThermalConductivity lambda "Thermal conductivity of fluid"

          SI.Density rho "Density of fluid"
        end FluidProperties;

        record IdealGas_con
          "Base record for generic pressure loss function | ideal gas | mean density"
          extends Modelica.Icons.Record;

          Real exp=2 "Exponent of pressure loss law"
          SI.SpecificHeatCapacity R_s "Specific gas constant of ideal gas"
          Real Km=6824.86
            "Coefficient for pressure loss law [(Pa)^2/{(kg/s)^exp*K}]"

        end IdealGas_con;

        record IdealGas_var
          "Base record for generic pressure loss function | ideal gas | mean density"
          extends Modelica.Icons.Record;

          SI.Density rho_m "Mean density of ideal gas"
          SI.Temperature T_m "Mean temperature of ideal gas"
          SI.Pressure p_m "Mean pressure of ideal gas"

        end IdealGas_var;

        record NominalDensityViscosity
          "Base record for generic pressure loss function"

          extends Modelica.Icons.Record;

          SI.Pressure dp_nom=2
            "Nominal pressure loss (at nominal values of mass flow rate and density)"
          Real exp=2 "Exponent of pressure loss law"
          SI.MassFlowRate m_flow_nom=1
            "Nominal mass flow rate (at nominal values of pressure loss and density)"
          SI.Density rho_nom
            "Nominal density (at nominal values of mass flow rate and pressure loss)"
          Real exp_eta=1 "Exponent for dynamic viscosity dependence"
          SI.DynamicViscosity eta_nom
            "Dynamic viscosity at nominal pressure loss"

        end NominalDensityViscosity;

        record NominalPressureLossLawDensity_con
          "Base record for generic pressure loss function"

          extends Modelica.Icons.Record;

          //NominalMassFlowRate
          Modelica.Fluid.Dissipation.Utilities.Types.MassOrVolumeFlowRate
            target =                                                             Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate
            "MassFlowRate == use nominal mass flow rate | VolumeFlowRate == use nominal volume flow rate"

          SI.Area A_cross=A_cross_nom "Cross sectional area"
          SI.Area A_cross_nom=Modelica.Constants.pi*0.1^2/4
            "Nominal cross sectional area"

          SI.Pressure dp_nom=2
            "Nominal pressure loss (at nominal values of mass flow rate and density)"
          SI.MassFlowRate m_flow_nom=1
            "Nominal mass flow rate (at nominal values of pressure loss and density)"
          Real exp=2 "Exponent of pressure loss law"

          SI.VolumeFlowRate V_flow_nom=m_flow_nom/rho_nom
            "Nominal volume flow rate (at nominal values of pressure loss and density)"
          SI.Density rho_nom
            "Nominal density (at nominal values of mass flow rate and pressure loss)"

          Types.PressureLossCoefficient zeta_TOT_nom=0.02*1/0.1
            "Nominal pressure loss coefficient (for nominal values)"

        end NominalPressureLossLawDensity_con;

        record NominalPressureLossLawDensity_var
          "Base record for generic pressure loss function"

          extends Modelica.Icons.Record;

          TYP.PressureLossCoefficient zeta_TOT=0.2 "Pressure loss coefficient"

        end NominalPressureLossLawDensity_var;

        record QuadraticVFLOW
          "Base record for generic pressure loss function | quadratic function (dp=a*Vdot^2 + b*Vdot)"

          extends Modelica.Icons.Record;

          Real a(unit="(Pa.s2)/m6") = 15 "Coefficient for quadratic term"
          Real b(unit="(Pa.s)/m3") = 0 "Coefficient for linear term"

        end QuadraticVFLOW;

        record TwoPhaseFlow_con "Base record for two phase Flow"
          extends Modelica.Icons.Record;

          SI.Area A_cross=PI*0.1^2/4 "Cross sectional area"
          SI.Length perimeter=PI*0.1 "Wetted perimeter"
          SI.Length length=1 "Length in fluid flow direction"

        end TwoPhaseFlow_con;

        record TwoPhaseFlow_var "Base record for two phase flow"
          extends Modelica.Icons.Record;

          SI.Density rho_g "Density of gas"
          SI.Density rho_l "Density of liquid"
          SI.DynamicViscosity eta_g "Dynamic viscosity of gas"
          SI.DynamicViscosity eta_l "Dynamic viscosity of liquid"
          SI.SurfaceTension sigma "Surface tension"

          //input variables
          Real x_flow=0 "Mean mass flow rate quality over length"
        end TwoPhaseFlow_var;

        record IdealGas
          "Base record for generic pressure loss function | ideal gas | mean density"
          extends Modelica.Icons.Record;

          parameter Real exp(min=Modelica.Constants.eps) = 2
            "Exponent of pressure loss law"
          parameter SI.SpecificHeatCapacity R_s(min=1)
            "Specific gas constant of ideal gas"

          Real Km(min=Modelica.Constants.eps) = R_s*(2e3)/((10)^exp/rho_m)
            "Coefficient for pressure loss law [(Pa)^2/{(kg/s)^exp*K}]"
          SI.Density rho_m=p_m/(R_s*T_m) "Mean density of ideal gas"
          SI.Temperature T_m "Mean temperature of ideal gas"
          SI.Pressure p_m "Mean pressure of ideal gas"

        end IdealGas;

        record NominalPressureLossLawDensity
          "Base record for generic pressure loss function"

          extends Modelica.Icons.Record;

          //NominalMassFlowRate
          Modelica.Fluid.Dissipation.Utilities.Types.MassOrVolumeFlowRate
            target =                                                             Dissipation.Utilities.Types.MassOrVolumeFlowRate.MassFlowRate
            "MassFlowRate == use nominal mass flow rate | VolumeFlowRate == use nominal volume flow rate"

          parameter SI.Area A_cross=A_cross_nom "Cross sectional area"
          parameter SI.Area A_cross_nom=Modelica.Constants.pi*0.1^2/4
            "Nominal cross sectional area"

          parameter SI.Pressure dp_nom(min=Modelica.Constants.eps) = 2
            "Nominal pressure loss (at nominal values of mass flow rate and density)"
          parameter SI.MassFlowRate m_flow_nom(min=Modelica.Constants.eps) = 1
            "Nominal mass flow rate (at nominal values of pressure loss and density)"
          parameter Real exp(min=Modelica.Constants.eps) = 2
            "Exponent of pressure loss law"

          SI.VolumeFlowRate V_flow_nom(min=Modelica.Constants.eps) = m_flow_nom/rho_nom
            "Nominal volume flow rate (at nominal values of pressure loss and density)"
          SI.Density rho_nom(min=Modelica.Constants.eps)
            "Nominal density (at nominal values of mass flow rate and pressure loss)"

          Types.PressureLossCoefficient zeta_TOT=zeta_TOT_nom
            "Pressure loss coefficient"
          parameter Types.PressureLossCoefficient zeta_TOT_nom=0.02*1/0.1
            "Nominal pressure loss coefficient (for nominal values)"

        end NominalPressureLossLawDensity;

        record TwoPhaseFlow "Base record for two phase Flow"
          extends Modelica.Icons.Record;

          SI.Density rho_l "Density of liquid"
          SI.Density rho_g "Density of gas"
          SI.DynamicViscosity eta_l "Dynamic viscosity of liquid"
          SI.DynamicViscosity eta_g "Dynamic viscosity of gas"
          SI.MassFraction x=0.5 "Vapour fraction"
          SI.SurfaceTension sigma "Surface Tension"
          Real n=0.25 "Exponent in Blasius equation (0.2-0.25)"
        end TwoPhaseFlow;
      end General;

      package HeatTransfer
        extends Modelica.Icons.RecordsPackage;
        record EvenGap "Input for even gap"
          extends Modelica.Icons.Record;

          //choices
          Modelica.Fluid.Dissipation.Utilities.Types.kc_evenGap target=Dissipation.Utilities.Types.kc_evenGap.DevBoth
            "Target variable of calculation"

          SI.Length h=0.1 "Height of cross sectional area"
          SI.Length s=0.05
            "Distance between parallel plates in cross sectional area"
          SI.Length L=1 "Overflowed length of gap"
        end EvenGap;

        record General "Input for generic correlation"
          extends Modelica.Icons.Record;

          //choices
          Modelica.Fluid.Dissipation.Utilities.Types.kc_general target=Dissipation.Utilities.Types.kc_general.Finest
            "Target correlation"

          //geometry
          SI.Area A_cross=Modelica.Constants.pi*0.1^2/4 "Cross sectional area"
          SI.Length perimeter=Modelica.Constants.pi*0.1 "Wetted perimeter"
        end General;

        record HelicalPipe "Input for helical pipe"
          extends Modelica.Icons.Record;

          Real n_nt=1 "Total number of turns"
          SI.Diameter d_hyd=0.1 "Hydraulic diameter"
          SI.Length h=0.01 "Distance between turns"
          SI.Length L=1 "Total length of helical pipe"

        end HelicalPipe;

        record Plate "Input for plate"
          extends Modelica.Icons.Record;

          SI.Length L=1 "Length of plate"

        end Plate;

        record StraightPipe "Input for straight pipe"
          extends Modelica.Icons.Record;

          SI.Diameter d_hyd=0.1 "Hydraulic diameter"
          SI.Length L=1 "Length"
        end StraightPipe;

        record TwoPhaseFlowHT_IN_con
          "Base record for two phase heat transfer coefficient"
          extends Modelica.Icons.Record;

          //choices
          Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget
            target=
              Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget.BoilHor
            "Choice of (horizontal/vertical) boiling or (horizontal) condensation in pipe"

          SI.Area A_cross=Modelica.Constants.pi*0.1^2/4 "Cross sectional area"
          SI.Length perimeter=Modelica.Constants.pi*0.1 "Wetted perimeter"

          Modelica.Fluid.Dissipation.Utilities.Types.MolarMass_gpmol MM=18.02
            "Molar mass of fluid"
          SI.Pressure p_crit "Critical pressure of fluid"
        end TwoPhaseFlowHT_IN_con;

        record TwoPhaseFlowHT_IN_var
          "Base record for two phase heat transfer coefficient"
          extends Modelica.Icons.Record;

          //choices
          Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget
            target=
              Modelica.Fluid.Dissipation.Utilities.Types.TwoPhaseHeatTransferTarget.BoilHor
            "Choice of (horizontal/vertical) boiling or (horizontal) condensation in pipe"

          //fluid properties
          SI.SpecificHeatCapacityAtConstantPressure cp_l
            "Specific heat capacity of liquid"
          SI.ThermalConductivity lambda_l "Thermal conductivity of liquid"
          SI.Density rho_g "Density of gas"
          SI.Density rho_l "Density of liquid"
          SI.DynamicViscosity eta_g "Dynamic viscosity of gas"
          SI.DynamicViscosity eta_l "Dynamic viscosity of liquid"

          SI.Pressure pressure "Mean pressure of fluid"
          SI.SpecificEnthalpy dh_lg "Evaporation enthalpy of fluid"

          //input variables
          SI.MassFlowRate m_flow "Mass flow rate"
          SI.HeatFlux qdot_A=0 "Heat flux at boiling"

          Real x_flow=0 "Mass flow rate quality"
        end TwoPhaseFlowHT_IN_var;
      end HeatTransfer;

      package PressureLoss
        extends Modelica.Icons.RecordsPackage;

        record Bend "Input for bend"
          extends EdgedBend;
          SI.Radius R_0=0.5*d_hyd "Curvature radius"

        end Bend;

        record Geometry "Input for several geometries of internal flow"
          extends Modelica.Icons.Record;

          Modelica.Fluid.Dissipation.Utilities.Types.GeometryOfInternalFlow
            geometry=
              Modelica.Fluid.Dissipation.Utilities.Types.GeometryOfInternalFlow.Circular
            "Choice of geometry for internal flow"

          SI.Length K=0 "Roughness (average height of surface asperities)"
          SI.Length L=1 "Length"

          //geometry variables
          //annular(1)
          SI.Diameter d_ann=d_cir "Small diameter"
          SI.Diameter D_ann=2*d_ann "Large diameter"
          //circular(2)
          SI.Diameter d_cir=0.1 "Internal diameter"
          //elliptical(3)
          SI.Length a_ell=(3/4)*d_cir "Half length of long base line"
          SI.Length b_ell=0.5*a_ell "Half length of short base line"
          //rectangular(4)
          SI.Length a_rec=d_cir "Horizontal length"
          SI.Length b_rec=a_rec "Vertical length"
          //triangular(5)
          SI.Length a_tri=d_cir*(1 + sqrt(2)) "Length of base line"
          SI.Length h_tri=0.5*a_tri
            "Height to top angle perpendicular to base line"
          SI.Angle beta=90*PI/180 "Top angle"
        end Geometry;

        record Orifice "Input for orifice"

          extends Modelica.Icons.Record;

          SI.Area A_0=0.1*A_1 "Cross sectional area of vena contraction"
          SI.Length C_0=0.1*C_1 "Perimeter of vena contraction"
          SI.Area A_1=PI*0.01^2/4 "Large cross sectional area of orifice"
          SI.Length C_1=PI*0.01 "Large perimeter of orifice"
          SI.Length L=1e-3 "Length of vena contraction"
        end Orifice;

        record PressureLossInput "Input for pressure loss calculation"
          extends Modelica.Icons.Record;

          //target variables
          Modelica.Fluid.Dissipation.Utilities.Types.PressureLossTarget target=Dissipation.Utilities.Types.PressureLossTarget.PressureLoss
            "Target variable of calculation"

          SI.Pressure dp=0 "Pressure loss"
          SI.MassFlowRate m_flow=0 "Mass flow rate"

        end PressureLossInput;

        record StraightPipe "Input for straight pipe"

          extends Modelica.Icons.Record;

          SI.Diameter d_hyd=0.1 "Hydraulic diameter"
          SI.Length L=1 "Length"
        end StraightPipe;

        record Tjunction "Input for T-junction"
          extends Modelica.Icons.Record;

          //T-junction variables
          Boolean united_converging_cross_section=true
            "= true, if A_cross_total = 2*A_cross_branch, otherwise A_cross_total > 2*A_cross_branch"
          Boolean velocity_reference_branches=true
            "= true, if pressure loss coefficients w.r.t. velocity in each passage, otherwise w.r.t. velocity in total passage"

          Integer alpha=90 "Angle of branching"

          SI.Diameter d_hyd[3]=ones(3)*0.1
            "Hydraulic diameter of passages [side,straight,total]"

          //restrictions
          SI.MassFlowRate m_flow_min=1e-3
            "Restriction for smoothing at reverse fluid flow"
          SI.Velocity v_max=2e2 "Restriction for maximum fluid flow velocity"
          Real zeta_TOT_max=1e3
            "Restriction for maximum value of pressure loss coefficient"
        end Tjunction;

        record Diffuser "Input for diffuser"
          extends Modelica.Icons.Record;

          SI.Angle alpha=PI*45/180 "Diffuser diverging angle"

          SI.Area A_1=PI*0.01^2/4
            "Small constant cross sectional area before diffuser section"
          SI.Area A_2=2*A_1
            "Large constant cross sectional area after diffuser section"
          SI.Length C_1=PI*0.01 "Small perimeter before diffuser section"
          SI.Length C_2=2*C_1 "Large perimeter after diffuser section"
          SI.Length L_1=0.1 "Length of straight pipe before diffuser section"
          SI.Length L_2=L_1 "Length of straight pipe after diffuser section"
          SI.Length L_d=L_1
            "Length of diffuser section (parallel to bulk fluid flow)"

          //numerical aspects
          SI.Pressure dp_small=1
            "Linearisation for a pressure loss smaller then dp_small"
          Real zeta_TOT_min=1e-3
            "Minimal pressure loss coefficient for infinite Reynolds number"
          Real zeta_TOT_max=1e8
            "Maximum pressure loss coefficient for Reynolds number approaching zero"
        end Diffuser;

        record EdgedBend "Input for bend"
          extends Modelica.Icons.Record;

          SI.Diameter d_hyd(min=Modelica.Constants.eps) = 0.1
            "Hydraulic diameter"
          SI.Angle delta=90*PI/180 "Angle of turning"
          SI.Length K=0
            "Roughness (absolute average height of surface asperities)"

        end EdgedBend;

        record SuddenChange "Input for sudden change of diameter"

          extends Modelica.Icons.Record;

          SI.Area A_1=PI*0.01^2/4 "Small cross sectional area of orifice"
          SI.Area A_2=A_1 "Large cross sectional area of orifice"
          SI.Length C_1=PI*0.01 "Small perimeter of orifice"
          SI.Length C_2=C_1 "Large perimeter of orifice"
        end SuddenChange;
      end PressureLoss;
    end Records;

    package Types "Package for types"
    extends Modelica.Icons.TypesPackage;
      type DarcyFrictionFactor = Modelica.Icons.TypeReal (
          final quantity=
              "Darcy friction factor | lambda_fri = zeta_fri / (length/diameter)",
          final unit="1",
          min=0,
          max=1111);
      type FrictionalResistanceCoefficient = Modelica.Icons.TypeReal (
          final quantity="Frictional resistance coefficient | zeta_fri",
          final unit="1",
          min=0,
          max=1111);
      type LocalResistanceCoefficient = Modelica.Icons.TypeReal (
          final quantity="Local resistance coefficient | zeta_loc",
          final unit="1",
          min=0,
          max=1111);
      type PressureLossCoefficient = Modelica.Icons.TypeReal (
          final quantity="Pressure loss coefficient | zeta_tot = zeta_loc + zeta_fri",
          final unit="1",
          min=0,
          max=1111);
      type TwoPhaseFrictionalPressureLoss = enumeration(
          Friedel "Friedel correlation for frictional pressure loss",
          Chisholm "Chisholm correlation for frictional pressure loss");
      type Roughness = enumeration(
          Neglected "Neglect surface roughness",
          Considered "Consider surface roughness");
      type TwoPhaseHeatTransferTarget = enumeration(
          BoilHor "Boiling horizontal",
          BoilVer "Boiling vertical",
          CondHor "Condensation horizontal");
      type PressureLossTarget = enumeration(
          PressureLoss "Calculate pressure loss from mass flow rate",
          MassFlowRate "Calculate mass flow rate from pressure loss");
      type GeometryOfInternalFlow = enumeration(
          Annular "Annular geometry",
          Circular "Circular geometry",
          Elliptical "Elliptical geometry",
          Rectangular "Rectangular geometry",
          Isosceles "Isosceles triangular geometry");
      type kc_evenGap = enumeration(
          DevOne
            "Hydrodynamically DEVELOPED laminar flow regime AND heat transfer at ONE side",
          DevBoth
            "Hydrodynamically DEVELOPED laminar flow regime AND heat transfer at BOTH sides",
          UndevOne
            "Hydrodynamic and thermal START of laminar flow regime AND heat transfer at ONE side",
          UndevBoth
            "Hydrodynamic and thermal START of laminar flow regime AND heat transfer at BOTH side");

      type kc_general = enumeration(
          Rough "Roughest approximation w.r.t. Dittus/Boelter (1930)",
          Middle "Middle approximation w.r.t. Sieder/Tate (1936)",
          Finest "Finest approximation w.r.t. Gnielinski (1976)");
      type HeatTransferBoundary = enumeration(
          UWTuDFF "Uniform wall temperature in developed fluid flow (UWT+DFF)",
          UHFuDFF "Uniform heat flux in developed fluid flow (UHF+DFF)",
          UWTuUFF
            "Uniform wall temperature in undeveloped fluid flow (UWT+UFF)",
          UHFuUFF "Uniform heat flux in undeveloped fluid flow (UHF+UFF)");

      type MassOrVolumeFlowRate = enumeration(
          MassFlowRate "Mass flow rate",
          VolumeFlowRate "Volume flow rate");
      type VoidFractionApproach = enumeration(
          Homogeneous "Homogeneous approach",
          Momentum "Analytical momentum flux approach (heterogeneous)",
          Energy "Kinetic energy flow approach w.r.t. Zivi (heterogeneous)",
          Chisholm
            "Empirical momentum flux approach w.r.t. Chisholm (heterogeneous)");

      type OrificeGeometry = enumeration(
          SharpEdged "Sharp edged shape of orifice inlet",
          ThickEdged "Thick edged shape of orifice inlet",
          TiltedEdged "Tilted edged shape of orifice inlet",
          RoundedEdged "Rounded edged shape of orifice inlet");
      type ValveGeometry = enumeration(
          Ball "Ball valve",
          Diaphragm "Diaphragm valve",
          Butterfly "Butterfly valve",
          Gate "Gate valve",
          Sluice "Sluice valve");
      type ValveCoefficient = enumeration(
          AV "Av (metric) flow coefficient",
          KV "Kv (metric) flow coefficient",
          CV "Cv (US) flow coefficient",
          OP "Av defined by operating point");
      type FluidFlowRegime = enumeration(
          Laminar "Laminar fluid flow regime",
          Overall "Overall fluid flow regime",
          Turbulent "Turbulent fluid flow regime");
      type HTXGeometry_flatTubes = enumeration(
          LouverFin "Louver fin",
          RectangularFin "Rectangular offset strip fin");
      type HTXGeometry_roundTubes = enumeration(
          PlainFin "Plain fin",
          LouverFin "Louver fin",
          SlitFin "Slit fin",
          WavyFin "Wavy fin (Herringbone wavy fin)");

      type MolarMass_gpmol = Real (final quantity="Molar mass", final unit="g/mol");
    end Types;
  end Utilities;

end Dissipation;