## FCSys.Characteristics.BaseClasses.CharacteristicEOS

Base thermodynamic package with only the p-v-T relations

### Information

This package may be used with the assumption of ideal gas or of constant specific volume, although it is more general than that.

Notes regarding the constants:

- bv: The powers of p/T increase by row. The powers of T increase by column. If `n_v[1] == -1`, then the rows of bv correspond to 1, B*T, C*T2, D*T3, …, where 1, B*, C*, and D* are the first, second, third, and fourth coefficients in the volume-explicit virial equation of state [Dymond2002, pp. 1–2]. Currently, virial equations of state are supported up to the fourth coefficient (D*). If additional terms are required, review and modify the definition of bp.
- The defaults for bv and nv represent ideal gas.

Extends from Modelica.Icons.MaterialPropertiesPackage (Icon for package containing property classes).

### Package Content

Name | Description
--- | ---
p0=U.bar | Reference pressure (po)
n_v={-1,0} | Powers of p/T and T for 1st row and column of bv (nv)
b_v=[1] | Coefficients for specific volume as a polynomial in p/T and T (bv)
isCompressible=anyTrue({anyTrue({abs(b_v[i, j]) > Modelica.Constants.small and n_v[1] + i - 1 <> 0 for i in 1:size(b_v, 1)}) for j in 1:size(b_v, 2)}) | `true`, if density depends on pressure
hasThermalExpansion=anyTrue({anyTrue({abs(b_v[i, j]) > Modelica.Constants.small and n_v[2] + j - n_v[1] - i <> 0 for i in 1:size(b_v, 1)}) for j in 1:size(b_v, 2)}) | `true`, if density depends on temperature
n_p={n_v[1] - size(b_v, 1) + 1,n_v[2] + 1} | Powers of v and T for 1st row and column of bp
b_p=if size(b_v, 1) == 1 then b_v .^ (-n_p[1]) else {(if n_v[1] + i == 0 or n_v[1] + i == 1 or size(b_v, 1) == 1 then b_v[i, :] else (if n_v[1] + i == 2 and n_v[1] <= 0 then b_v[i, :] + b_v[i - 1, :] .^ 2 else (if n_v[1] + i == 3 and n_v[1] <= 0 then b_v[i, :] + b_v[i - 2, :] .* (b_v[i - 2, :] .^ 2 + 3*b_v[i - 1, :]) else zeros(size(b_v, 2))))) for i in size(b_v, 1):-1:1} | Coefficients of p as a polynomial in v and T
dp_Tv | Derivative of pressure as defined by pT v()
dv_Tp | Derivative of specific volume as defined by vT p()
p_Tv | Pressure as a function of temperature and specific volume (pT v())
v_Tp | Specific volume as a function of temperature and pressure (vT p())
beta | Isothermal compressibility as a function of temperature and pressure (β)

### Types and constants

    constant Q.PressureAbsolute p0=U.bar
      "Reference pressure (po)";

    constant Integer n_v[2]={-1,0}
      "Powers of p/T and T for 1st row and column of bv (nv)";

    constant Real b_v[:, :]=[1]
      "Coefficients for specific volume as a polynomial in p/T and T (bv)";

    final constant Boolean isCompressible=anyTrue({anyTrue({abs(b_v[i, j]) >
        Modelica.Constants.small and n_v[1] + i - 1 <> 0 for i in 1:size(b_v, 1)})
        for j in 1:size(b_v, 2)})
      "true, if density depends on pressure";

    final constant Boolean hasThermalExpansion=anyTrue({anyTrue({abs(b_v[i, j]) >
        Modelica.Constants.small and n_v[2] + j - n_v[1] - i <> 0 for i in 1:size(
        b_v, 1)}) for j in 1:size(b_v, 2)})
      "true, if density depends on temperature";

    final constant Integer n_p[2]={n_v[1] - size(b_v, 1) + 1,n_v[2] + 1}
      "Powers of v and T for 1st row and column of bp";

    final constant Real b_p[size(b_v, 1), size(b_v, 2)]=if size(b_v, 1) == 1 then
        b_v .^ (-n_p[1]) else {(if n_v[1] + i == 0 or n_v[1] + i == 1 or size(b_v, 1)
         == 1 then b_v[i, :] else (if n_v[1] + i == 2 and n_v[1] <= 0 then b_v[i, :]
         + b_v[i - 1, :] .^ 2 else (if n_v[1] + i == 3 and n_v[1] <= 0 then b_v[i,
        :] + b_v[i - 2, :] .* (b_v[i - 2, :] .^ 2 + 3*b_v[i - 1, :]) else zeros(
        size(b_v, 2))))) for i in size(b_v, 1):-1:1}
      "Coefficients of p as a polynomial in v and T";

## FCSys.Characteristics.BaseClasses.CharacteristicEOS.dp_Tv

Derivative of pressure as defined by pT v()

### Information

Extends from Modelica.Icons.Function (Icon for functions).

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TemperatureAbsolute | T | 298.15*U.K | Temperature [L2.M/(N.T2)]
VolumeSpecificAbsolute | v | 298.15*U.K/p0 | Specific volume [L3/N]
Temperature | dT | 0 | Derivative of temperature [L2.M/(N.T2)]
VolumeSpecific | dv | 0 | Derivative of specific volume [L3/N]

### Outputs

Type | Name | Description
--- | --- | ---
Pressure | dp | Derivative of pressure [M/(L.T2)]

### Modelica definition

    function dp_Tv
      "Derivative of pressure as defined by pT v()"
      import FCSys.Utilities.Polynomial;
      extends Modelica.Icons.Function;

      input Q.TemperatureAbsolute T=298.15*U.K "Temperature";
      input Q.VolumeSpecificAbsolute v=298.15*U.K/p0 "Specific volume";
      input Q.Temperature dT=0 "Derivative of temperature";
      input Q.VolumeSpecific dv=0 "Derivative of specific volume";
      output Q.Pressure dp "Derivative of pressure";
    algorithm
      dp := if isCompressible then Polynomial.f(
        v,
        {Polynomial.f(
          T,
          b_p[i, :] .* {(n_p[1] + i - 1)*T*dv + (n_p[2] + j - 1)*v*dT for j in 1:
            size(b_p, 2)},
          n_p[2] - 1) for i in 1:size(b_p, 1)},
        n_p[1] - 1) else 0;

    end dp_Tv;

## FCSys.Characteristics.BaseClasses.CharacteristicEOS.dv_Tp

Derivative of specific volume as defined by vT p()

### Information

Extends from Modelica.Icons.Function (Icon for functions).

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TemperatureAbsolute | T | 298.15*U.K | Temperature [L2.M/(N.T2)]
PressureAbsolute | p | p0 | Pressure [M/(L.T2)]
Temperature | dT | 0 | Derivative of temperature [L2.M/(N.T2)]
Pressure | dp | 0 | Derivative of pressure [M/(L.T2)]

### Outputs

Type | Name | Description
--- | --- | ---
VolumeSpecific | dv | Derivative of specific volume [L3/N]

### Modelica definition

    function dv_Tp
      "Derivative of specific volume as defined by vT p()"
      import FCSys.Utilities.Polynomial;
      extends Modelica.Icons.Function;
      input Q.TemperatureAbsolute T=298.15*U.K "Temperature";
      input Q.PressureAbsolute p=p0 "Pressure";
      input Q.Temperature dT=0 "Derivative of temperature";
      input Q.Pressure dp=0 "Derivative of pressure";
      output Q.VolumeSpecific dv "Derivative of specific volume";
    algorithm
      dv := Polynomial.f(
        p,
        {Polynomial.f(
          T,
          b_v[i, :] .* {(n_v[1] + i - 1)*T*dp + (n_v[2] - n_v[1] + j - i)*p*dT for
            j in 1:size(b_v, 2)},
          n_v[2] - n_v[1] - i) for i in 1:size(b_v, 1)},
        n_v[1] - 1);

    end dv_Tp;

## FCSys.Characteristics.BaseClasses.CharacteristicEOS.p_Tv

Pressure as a function of temperature and specific volume (pT v())

### Information

If the species is incompressible then p(T, v) is undefined, and the function will return a value of zero.

The derivative of this function is dp_Tv().

Extends from Modelica.Icons.Function (Icon for functions).

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TemperatureAbsolute | T | 298.15*U.K | Temperature [L2.M/(N.T2)]
VolumeSpecificAbsolute | v | 298.15*U.K/p0 | Specific volume [L3/N]

### Outputs

Type | Name | Description
--- | --- | ---
PressureAbsolute | p | Pressure [M/(L.T2)]

### Modelica definition

    function p_Tv
      "Pressure as a function of temperature and specific volume (pT v())"
      annotation(derivative=dp_Tv);
      import FCSys.Utilities.Polynomial;
      extends Modelica.Icons.Function;
      input Q.TemperatureAbsolute T=298.15*U.K "Temperature";
      input Q.VolumeSpecificAbsolute v=298.15*U.K/p0 "Specific volume";
      output Q.PressureAbsolute p "Pressure";
    algorithm
      // assert(isCompressible,
      //  "The pressure is undefined since the material is incompressible.",
      //  AssertionLevel.warning);
      // Note:  This isn't used because it creates an error instead of a warning
      // in Dymola 2014
      p := if isCompressible then Polynomial.f(
        v,
        {Polynomial.f(
          T,
          b_p[i, :],
          n_p[2]) for i in 1:size(b_p, 1)},
        n_p[1]) else p0;
    end p_Tv;

## FCSys.Characteristics.BaseClasses.CharacteristicEOS.v_Tp

Specific volume as a function of temperature and pressure (vT p())

### Information

The derivative of this function is dv_Tp().

Extends from Modelica.Icons.Function (Icon for functions).

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TemperatureAbsolute | T | 298.15*U.K | Temperature [L2.M/(N.T2)]
PressureAbsolute | p | p0 | Pressure [M/(L.T2)]

### Outputs

Type | Name | Description
--- | --- | ---
VolumeSpecificAbsolute | v | Specific volume [L3/N]

### Modelica definition

    function v_Tp
      "Specific volume as a function of temperature and pressure (vT p())"
      annotation(derivative=dv_Tp);
      import FCSys.Utilities.Polynomial;
      extends Modelica.Icons.Function;
      input Q.TemperatureAbsolute T=298.15*U.K "Temperature";
      input Q.PressureAbsolute p=p0 "Pressure";
      output Q.VolumeSpecificAbsolute v "Specific volume";
    algorithm
      v := Polynomial.f(
        p,
        {Polynomial.f(
          T,
          b_v[i, :],
          n_v[2] - n_v[1] - i + 1) for i in 1:size(b_v, 1)},
        n_v[1]);
    end v_Tp;

## FCSys.Characteristics.BaseClasses.CharacteristicEOS.beta

Isothermal compressibility as a function of temperature and pressure (β)

### Information

For an ideal gas, this function is independent of temperature (although temperature remains as a valid input).

Extends from Modelica.Icons.Function (Icon for functions).

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TemperatureAbsolute | T | 298.15*U.K | Temperature [L2.M/(N.T2)]
PressureAbsolute | p | p0 | Pressure [M/(L.T2)]

### Outputs

Type | Name | Description
--- | --- | ---
PressureReciprocal | beta | Isothermal compressibility [L.T2/M]

### Modelica definition

    function beta
      "Isothermal compressibility as a function of temperature and pressure (β)"
      extends Modelica.Icons.Function;

      input Q.TemperatureAbsolute T=298.15*U.K "Temperature";
      input Q.PressureAbsolute p=p0 "Pressure";

      output Q.PressureReciprocal beta "Isothermal compressibility";

    algorithm
      beta := -dv_Tp(
        T=T,
        p=p,
        dT=0,
        dp=1)/v_Tp(T, p);
    end beta;