Utilities (chemicals.utils)

This module contains miscellaneous functions which may be useful. This includes definitions of some chemical properties, and conversions between others.

For reporting bugs, adding feature requests, or submitting pull requests, please use the GitHub issue tracker.

chemicals.utils.API_to_SG(API: float) float[source]

Calculates specific gravity of a liquid given its API, as shown in [1].

SG at 60F=141.5API gravity+131.5\text{SG at}~60^\circ\text{F} = \frac{141.5}{\text{API gravity} +131.5}
Parameters:
APIfloat

API of the fluid [-]

Returns:
SGfloat

Specific gravity of the fluid at 60 degrees Farenheight [-]

Notes

Defined only at 60 degrees Fahrenheit.

References

[1]

API Technical Data Book: General Properties & Characterization. American Petroleum Institute, 7E, 2005.

Examples

>>> API_to_SG(60.62)
0.7365188423901728
chemicals.utils.API_to_rho(API, rho_ref=999.0170824078306)[source]

Calculates mass density of a liquid given its API, as shown in [1].

ρ 60F=141.5ρrefAPI+131.5\rho~60^\circ\text{F} = \frac{141.5\rho_{ref}}{\text{API} + 131.5}
Parameters:
APIfloat

API of the fluid [-]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
rhofloat

Mass density the fluid at 60 degrees Farenheight [kg/m^3]

Notes

Defined only at 60 degrees Fahrenheit.

References

[1]

API Technical Data Book: General Properties & Characterization. American Petroleum Institute, 7E, 2005.

Examples

>>> API_to_rho(rho_to_API(820))
820.0
chemicals.utils.Baume_heavy_to_SG(Baume)[source]

Calculates specific gravity of a liquid heavier than water given its degrees Baumé, as shown in [1].

SG at 60F=145145Degrees Baumeˊ\text{SG at}~60^\circ\text{F} = \frac{145}{145 - \text{Degrees Baumé}}
Parameters:
Baumefloat

Degrees Baumé of the fluid [-]

Returns:
SGfloat

Specific gravity of the fluid at 60 degrees Fahrenheit [-]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids heavier than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> Baume_heavy_to_SG(23.75)
1.19
chemicals.utils.Baume_heavy_to_rho(Baume, rho_ref=999.0170824078306)[source]

Calculates mass density of a liquid heavier than water given its degrees Baumé, as shown in [1].

ρ 60F=145ρref145Degrees Baumeˊ\rho~60^\circ\text{F} = \frac{145\rho_{ref}}{145 - \text{Degrees Baumé}}
Parameters:
Baumefloat

Degrees Baumé of the fluid [-]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
rhofloat

Mass density the fluid at 60 degrees Fahrenheit [kg/m^3]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids heavier than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> Baume_heavy_to_rho(23.75)
1194.70
chemicals.utils.Baume_light_to_SG(Baume)[source]

Calculates specific gravity of a liquid lighter than water given its degrees Baumé, as shown in [1].

SG at 60F=140130+Degrees Baumeˊ\text{SG at}~60^\circ\text{F} = \frac{140}{130 + \text{Degrees Baumé}}
Parameters:
Baumefloat

Degrees Baumé of the fluid [-]

Returns:
SGfloat

Specific gravity of the fluid at 60 degrees Fahrenheit [-]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids lighter than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> Baume_light_to_SG(40.7317)
0.82
chemicals.utils.Baume_light_to_rho(Baume, rho_ref=999.0170824078306)[source]

Calculates mass density of a liquid lighter than water given its degrees Baumé, as shown in [1].

ρ 60F=140ρref130+Degrees Baumeˊ\rho~60^\circ\text{F} = \frac{140\rho_{ref}}{130 + \text{Degrees Baumé}}
Parameters:
Baumefloat

Degrees Baumé of the fluid [-]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
rhofloat

Mass density the fluid at 60 degrees Fahrenheit [kg/m^3]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids lighter than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> Baume_light_to_rho(40.7317)
819.194
chemicals.utils.Cp_minus_Cv(T: int, dP_dT: float, dP_dV: float) float[source]

Calculate the difference between a real gas’s constant-pressure heat capacity and constant-volume heat capacity, as given in [1], [2], and [3]. The required derivatives should be calculated with an equation of state.

CpCv=T(PT)V2/(PV)TC_p - C_v = -T\left(\frac{\partial P}{\partial T}\right)_V^2/ \left(\frac{\partial P}{\partial V}\right)_T
Parameters:
Tfloat

Temperature of fluid [K]

dP_dTfloat

Derivative of P with respect to T, [Pa/K]

dP_dVfloat

Derivative of P with respect to V, [Pa*mol/m^3]

Returns:
Cp_minus_Cvfloat

Cp - Cv for a real gas, [J/mol/K]

Notes

Equivalent expressions are:

CpCv=T(VT)P2/(VP)TC_p - C_v= -T\left(\frac{\partial V}{\partial T}\right)_P^2/\left( \frac{\partial V}{\partial P}\right)_T
CpCv=T(PT)(VT)C_p - C_v = T\left(\frac{\partial P}{\partial T}\right) \left(\frac{\partial V}{\partial T}\right)

Note that these are not second derivatives, only first derivatives, some of which are squared.

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

[2]

Walas, Stanley M. Phase Equilibria in Chemical Engineering. Butterworth-Heinemann, 1985.

[3]

Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: Wiley-VCH, 2012.

Examples

Calculated for hexane from the PR EOS at 299 K and 1 MPa (liquid):

>>> Cp_minus_Cv(299, 582232.475794113, -3665180614672.253)
27.654681381642394
chemicals.utils.Joule_Thomson(T: int, V: float, Cp: float, dV_dT: float | None = None, beta: float | None = None) float[source]

Calculate a real fluid’s Joule Thomson coefficient. The required derivative should be calculated with an equation of state, and Cp is the real fluid versions. This can either be calculated with dV_dT directly, or with beta if it is already known.

μJT=(TP)H=1Cp[T(VT)PV]=VCp(βT1)\mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right)
Parameters:
Tfloat

Temperature of fluid, [K]

Vfloat

Molar volume of fluid, [m^3/mol]

Cpfloat

Real fluid heat capacity at constant pressure, [J/mol/K]

dV_dTfloat, optional

Derivative of V with respect to T, [m^3/mol/K]

betafloat, optional

Isobaric coefficient of a thermal expansion, [1/K]

Returns:
mu_JTfloat

Joule-Thomson coefficient [K/Pa]

References

[1]

Walas, Stanley M. Phase Equilibria in Chemical Engineering. Butterworth-Heinemann, 1985.

[2]

Pratt, R. M. “Thermodynamic Properties Involving Derivatives: Using the Peng-Robinson Equation of State.” Chemical Engineering Education 35, no. 2 (March 1, 2001): 112-115.

Examples

Example from [2]:

>>> Joule_Thomson(T=390, V=0.00229754, Cp=153.235, dV_dT=1.226396e-05)
1.621956080529905e-05
chemicals.utils.Parachor(MW: float, rhol: float, rhog: float, sigma: float) float[source]

Calculate Parachor for a pure species, using its density in the liquid and gas phases, surface tension, and molecular weight.

P=σ0.25MWρLρVP = \frac{\sigma^{0.25} MW}{\rho_L - \rho_V}
Parameters:
MWfloat

Molecular weight, [g/mol]

rholfloat

Liquid density [kg/m^3]

rhogfloat

Gas density [kg/m^3]

sigmafloat

Surface tension, [N/m]

Returns:
Pfloat

Parachor, [N^0.25*m^2.75/mol]

Notes

To convert the output of this function to units of [mN^0.25*m^2.75/kmol], multiply by 5623.4132519.

Values in group contribution tables for Parachor are often listed as dimensionless, in which they are multiplied by 5623413 and the appropriate units to make them dimensionless.

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

[2]

Green, Don, and Robert Perry. Perry’s Chemical Engineers’ Handbook, 8E. McGraw-Hill Professional, 2007.

[3]

Danner, Ronald P, and Design Institute for Physical Property Data. Manual for Predicting Chemical Process Design Data. New York, N.Y, 1982.

Examples

Calculating Parachor from a known surface tension for methyl isobutyl ketone at 293.15 K

>>> Parachor(100.15888, 800.8088185536124, 4.97865317223119, 0.02672166960656005)
5.088443542210164e-05

Converting to the dimensionless form:

>>> 5623413*5.088443542210164e-05
286.14419565030687

Compared to 274.9 according to a group contribution method described in [3].

chemicals.utils.Qls_to_ms(Qls, MWs, Vmls)[source]

Converts a list of standard liquid volume flow rates to mass flow rates. Requires molecular weights and standard liquid molar volumes for all species.

mi=QliMWi1000Vmlim_i = \frac{{Ql}_i {MW}_i}{1000 {Vml}_i}
Parameters:
Qlsiterable

Standard liquid volume flow rates [m^3/s]

MWsiterable

Molecular weights [g/mol]

Vmlsiterable

Molar volumes in the liquid phase [m^3/mol]

Returns:
msiterable

Mass flow rates [kg/s]

Notes

Does not check that inputs are of the same length.

Examples

>>> Qls_to_ms([1.666666666e-02, 1.11111111e-01], [24, 45], [1e-4, 2e-4])
[4.0, 25.0]
chemicals.utils.Qls_to_ns(Qls, Vmls)[source]

Converts a list of standard liquid volume flow rates to mole flow rates. Requires standard liquid molar volumes for all species.

ni=QliVmlin_i = \frac{{Ql}_i}{{Vml}_i}
Parameters:
Qlsiterable

Standard liquid volume flow rates [m^3/s]

Vmlsiterable

Standard liquid molar volumes of each component [m^3/mol]

Returns:
nsiterable

Mole flow rates [mol/s]

Notes

Does not check that inputs are of the same length.

Examples

>>> Qls_to_ns([2e-4, 6e-4], [1e-4, 2e-4])
[2.0, 3.0]
chemicals.utils.SG(rho: int, rho_ref: float = 999.0170824078306) float[source]

Calculates the specific gravity of a substance with respect to another substance; by default, this is water at 15.555 °C (60 °F). For gases, normally the reference density is 1.2 kg/m^3, that of dry air. However, in general specific gravity should always be specified with respect to the temperature and pressure of its reference fluid. This can vary widely.

SG=ρρrefSG = \frac{\rho}{\rho_{ref}}
Parameters:
rhofloat

Density of the substance, [kg/m^3]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
SGfloat

Specific gravity of the substance with respect to the reference density, [-]

Notes

Another common reference point is water at 4°C (rho_ref=999.9748691393087). Specific gravity is often used by consumers instead of density. The reference for solids is normally the same as for liquids - water.

Examples

>>> SG(860)
0.8608461408159591
chemicals.utils.SG_to_API(SG: float) float[source]

Calculates API of a liquid given its specific gravity, as shown in [1].

API gravity=141.5SG131.5\text{API gravity} = \frac{141.5}{\text{SG}} - 131.5
Parameters:
SGfloat

Specific gravity of the fluid at 60 degrees Farenheight [-]

Returns:
APIfloat

API of the fluid [-]

Notes

Defined only at 60 degrees Fahrenheit.

References

[1]

API Technical Data Book: General Properties & Characterization. American Petroleum Institute, 7E, 2005.

Examples

>>> SG_to_API(0.7365)
60.62491513917175
chemicals.utils.SG_to_Baume_heavy(SG)[source]

Calculates degrees Baumé of a liquid heavier than water given its specific gravity, as shown in [1].

Degrees Baumeˊ=145145SG\text{Degrees Baumé} = 145 - \frac{145}{\text{SG}}
Parameters:
SGfloat

Specific gravity of the fluid at 60 degrees Fahrenheit [-]

Returns:
Baumefloat

Degrees Baumé of the fluid [-]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids heavier than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> SG_to_Baume_heavy(1.2012)
24.28
chemicals.utils.SG_to_Baume_light(SG)[source]

Calculates degrees Baumé of a liquid lighter than water given its specific gravity, as shown in [1].

Degrees Baumeˊ=140SG130\text{Degrees Baumé} = \frac{140}{\text{SG}} - 130
Parameters:
SGfloat

Specific gravity of the fluid at 60 degrees Fahrenheit [-]

Returns:
Baumefloat

Degrees Baumé of the fluid [-]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids lighter than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> SG_to_Baume_light(0.8209)
40.544
chemicals.utils.Vfs_to_zs(Vfs: list[float], Vms: list[float]) list[float][source]

Converts a list of mass fractions to mole fractions. Requires molecular weights for all species.

zi=VfiVm,iiVfiVm,iz_i = \frac{\frac{\text{Vf}_i}{V_{m,i}}}{\sum_i \frac{\text{Vf}_i}{V_{m,i}}}
Parameters:
Vfsiterable

Molar volume fractions [-]

Vmsiterable

Molar volumes of species [m^3/mol]

Returns:
zslist

Mole fractions [-]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

Molar volumes are specified in terms of pure components only. Function works with any phase.

Examples

Acetone and benzene example

>>> Vfs_to_zs([0.596, 0.404], [8.0234e-05, 9.543e-05])
[0.6369779395901142, 0.3630220604098858]
chemicals.utils.Vm_to_rho(Vm: float, MW: float) float[source]

Calculate the density of a chemical, given its molar volume and molecular weight.

ρ=MW1000VM\rho = \frac{MW}{1000\cdot VM}
Parameters:
Vmfloat

Molar volume, [m^3/mol]

MWfloat

Molecular weight, [g/mol]

Returns:
rhofloat

Density, [kg/m^3]

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

>>> Vm_to_rho(0.000132, 86.18)
652.8787878787879
chemicals.utils.Watson_K(Tb: int, SG: float) float[source]

Calculates the Watson or UOP K Characterization factor of a liquid of a liquid given its specific gravity, and its average boiling point as shown in [1].

KW=Tb1/3SG at 60FK_W = \frac{T_b^{1/3}}{\text{SG at}~60^\circ\text{F}}
Parameters:
Tbfloat

Average normal boiling point, [K]

SGfloat

Specific gravity of the fluid at 60 degrees Farenheight [-]

Returns:
K_Wfloat

Watson characterization factor

Notes

There are different ways to compute the average boiling point, so two different definitions are often used - K_UOP using volume average boiling point (VABP) using distillation points of 10%, 30%, 50%, 70%, and 90%; and K_Watson using mean average boiling point (MeABP).

References

[1] (1,2)

API Technical Data Book: General Properties & Characterization. American Petroleum Institute, 7E, 2005.

Examples

>>> Watson_K(400, .8)
11.20351186639291

Sample problem in Comments on Procedure 2B5.1 of [1]; a fluids has a MEAB of 580 F and a SG of 34.5.

>>> from fluids.core import F2K
>>> Watson_K(F2K(580), API_to_SG(34.5))
11.884570347084471
chemicals.utils.Z(T: int, P: float, V: float) float[source]

Calculates the compressibility factor of a gas, given its temperature, pressure, and molar volume.

Z=PVRTZ = \frac{PV}{RT}
Parameters:
Tfloat

Temperature, [K]

Pfloat

Pressure [Pa]

Vfloat

Molar volume, [m^3/mol]

Returns:
Zfloat

Compressibility factor, [-]

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

>>> Z(600, P=1E6, V=0.00463)
0.9281016730797026
chemicals.utils.d2ns_to_dn2_partials(d2ns: list[list[float]], dns: list[float]) list[list[float]][source]
Convert second-order mole number derivatives of a quantity

to the following second-order partial derivative:

2nFnjni=2Fninj+Fni+Fnj\frac{\partial^2 n F}{\partial n_j \partial n_i} = \frac{\partial^2 F}{\partial n_i \partial n_j} + \frac{\partial F}{\partial n_i} + \frac{\partial F}{\partial n_j}

Requires the second order mole number derivatives and the first order mole number derivatives of the mixture only.

Parameters:
d2nslist[float]

Second order derivatives of a quantity with respect to mole number (summing to 1), [prop/mol^2]

dnslist[float]

Derivatives of a quantity with respect to mole number (summing to 1), [prop/mol]

Returns:
second_partial_propertieslist[list[float]]

Derivatives of a quantity with respect to mole number (summing to 1), [prop]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

This was originally implemented to allow for the calculation of first mole number derivatices of log fugacity coefficients; the two arguments are the second and first mole number derivatives of the overall mixture log fugacity coefficient.

Derived with the following SymPy code.

>>> from sympy import *
>>> n1, n2 = symbols('n1, n2')
>>> f, g, h = symbols('f, g, h', cls=Function)
>>> diff(h(n1, n2)*f(n1,  n2), n1, n2)
f(n1, n2)*Derivative(h(n1, n2), n1, n2) + h(n1, n2)*Derivative(f(n1, n2), n1, n2) + Derivative(f(n1, n2), n1)*Derivative(h(n1, n2), n2) + Derivative(f(n1, n2), n2)*Derivative(h(n1, n2), n1)

Examples

>>> d2ns = [[0.152, 0.08, 0.547], [0.08, 0.674, 0.729], [0.547, 0.729, 0.131]]
>>> d2ns_to_dn2_partials(d2ns, [20.0, .124, 900.52])
[[40.152, 20.203999999999997, 921.067], [20.204, 0.922, 901.3729999999999], [921.067, 901.373, 1801.1709999999998]]
chemicals.utils.d2xs_to_d2xsn1(d2xs: list[list[float]]) list[list[float]][source]

Convert the second mole fraction derivatives of a quantity (calculated so they do not sum to 1) to derivatives such that they do sum to 1 Requires the second derivatives of the mixture only. The size of the returned array is one less than the input in both dimensions

(2Fxixj)xiN=1=(2Fxixj2FxixN2FxjxN+2FxNxN)xiN1\left(\frac{\partial^2 F}{\partial x_i \partial x_j }\right)_{\sum_{x_i}^N =1} = \left(\frac{\partial^2 F}{\partial x_i\partial x_j} -\frac{\partial^2 F}{\partial x_i\partial x_N} -\frac{\partial^2 F}{\partial x_j\partial x_N} +\frac{\partial^2 F}{\partial x_N\partial x_N} \right)_{\sum_{x_i}^N \ne 1}
Parameters:
d2xslist[float]

Second of a quantity with respect to mole fraction (not summing to 1), [prop]

Returns:
d2xsm1list[float]

Second derivatives of a quantity with respect to mole fraction (summing to 1 by altering the last component’s composition), [prop]

Examples

>>> d2xs_to_d2xsn1([[-2890.4327598108, -6687.0990540960065, -1549.375443699441], [-6687.099054095983, -2811.2832904869883, -1228.6223853777503], [-1549.3754436994498, -1228.6223853777562, -3667.388098758508]])
[[-3459.069971170426, -7576.489323777324], [-7576.489323777299, -4021.4266184899957]]
chemicals.utils.d2xs_to_dxdn_partials(d2xs, xs)[source]

Convert second-order mole fraction derivatives of a quantity (calculated so they do not sum to 1) to the following second-order partial derivative:

2nFxjni=2Fxixjkxk2Fxkxj\frac{\partial^2 n F}{\partial x_j \partial n_i} = \frac{\partial^2 F}{\partial x_i x_j} - \sum_k x_k \frac{\partial^2 F}{\partial x_k \partial x_j}

Requires the second derivatives and the mole fractions of the mixture only.

Parameters:
d2xslist[float]
Second derivatives of a quantity with respect to mole fraction (not

summing to 1), [prop]

xslist[float]

Mole fractions of the species, [-]

Returns:
partial_propertieslist[float]

Derivatives of a quantity with respect to mole number (summing to 1), [prop]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

Examples

>>> d2xs = [[0.152, 0.08, 0.547], [0.08, 0.674, 0.729], [0.547, 0.729, 0.131]]
>>> d2xs_to_dxdn_partials(d2xs, [0.7, 0.2, 0.1])
[[-0.02510000000000001, -0.18369999999999997, 0.005199999999999982], [-0.0971, 0.41030000000000005, 0.18719999999999992], [0.3699, 0.4653, -0.41080000000000005]]
chemicals.utils.dns_to_dn_partials(dns, F, partial_properties=None)[source]

Convert the mole number derivatives of a quantity (calculated so they do sum to 1) to partial molar quantites.

(nFni)nki=Fi+n(Fni)nki\left(\frac{\partial n F}{\partial n_i}\right)_{n_{k \ne i}} = F_i + n \left(\frac{\partial F}{\partial n_i}\right)_{n_{k\ne i}}

In the formula, the n is 1.

Parameters:
dnslist[float]

Derivatives of a quantity with respect to mole number (summing to 1), [prop/mol]

Ffloat

Property evaluated at constant composition, [prop]

partial_propertieslist[float], optional

Optional output array for derivatives of a quantity with respect to mole number (summing to 1), [prop]

Returns:
partial_propertieslist[float]

Derivatives of a quantity with respect to mole number (summing to 1), [prop]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

This applies to a specific phase only, not to a mixture of multiple phases.

This is especially useful for fugacity calculations.

Examples

>>> dns_to_dn_partials([0.001459, -0.002939, -0.004334], -0.0016567)
[-0.0001977000000000001, -0.0045957, -0.0059907]
chemicals.utils.dxs_to_dn_partials(dxs, xs, F, partial_properties=None)[source]

Convert the mole fraction derivatives of a quantity (calculated so they do not sum to 1) to partial molar quantites. Requires the derivatives and the mole fractions of the mixture.

(nFni)=(Fxi)+Fjxj(Fxj)\left(\frac{\partial n F}{\partial n_i}\right) = \left(\frac{\partial F}{\partial x_i}\right)+ F - \sum_j x_j \left(\frac{\partial F}{\partial x_j}\right)
Parameters:
dxslist[float]

Derivatives of a quantity with respect to mole fraction (not summing to 1), [prop]

xslist[float]

Mole fractions of the species, [-]

Ffloat

Property evaluated at constant composition, [prop]

partial_propertieslist[float], optional

Array for Derivatives of a quantity with respect to mole number (summing to 1), [prop]

Returns:
partial_propertieslist[float]

Derivatives of a quantity with respect to mole number (summing to 1), [prop]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

This applies to a specific phase only, not to a mixture of multiple phases.

Examples

>>> dxs_to_dn_partials([-0.0026404, -0.00719, -0.00859], [0.7, 0.2, 0.1],
... -0.0016567)
[-0.00015182, -0.0047014199999999996, -0.00610142]
chemicals.utils.dxs_to_dns(dxs, xs, dns=None)[source]

Convert the mole fraction derivatives of a quantity (calculated so they do not sum to 1) to mole number derivatives (where the mole fractions do sum to one). Requires the derivatives and the mole fractions of the mixture.

(Mni)nki=[(Mxi)xkijxj(Mxj)xkj]\left(\frac{\partial M}{\partial n_i}\right)_{n_{k\ne i}} = \left[ \left(\frac{\partial M}{\partial x_i}\right)_{x_{k\ne i}} - \sum_j x_j \left(\frac{\partial M}{\partial x_j} \right)_{x_{k\ne j}} \right]
Parameters:
dxslist[float]

Derivatives of a quantity with respect to mole fraction (not summing to 1), [prop]

xslist[float]

Mole fractions of the species, [-]

dnslist[float], optional

Return array, [prop/mol]

Returns:
dnslist[float]

Derivatives of a quantity with respect to mole number (summing to 1), [prop/mol]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

This applies to a specific phase only, not to a mixture of multiple phases.

Examples

>>> dxs_to_dns([-0.0028, -0.00719, -0.00859], [0.7, 0.2, 0.1])
[0.0014570000000000004, -0.002933, -0.004333]
chemicals.utils.dxs_to_dxsn1(dxs: list[float]) list[float][source]

Convert the mole fraction derivatives of a quantity (calculated so they do not sum to 1) to derivatives such that they do sum to 1 by changing the composition of the last component in the negative of the component which is changed. Requires the derivatives of the mixture only. The size of the returned array is one less than the input.

(Fxi)xiN=1=(FxiFxN)xiN1\left(\frac{\partial F}{\partial x_i}\right)_{\sum_{x_i}^N =1} = \left(\frac{\partial F}{\partial x_i} - \frac{\partial F}{\partial x_N}\right)_{\sum_{x_i}^N \ne 1}
Parameters:
dxslist[float]

Derivatives of a quantity with respect to mole fraction (not summing to 1), [prop]

Returns:
dxsm1list[float]

Derivatives of a quantity with respect to mole fraction (summing to 1 by altering the last component’s composition), [prop]

Examples

>>> dxs_to_dxsn1([-2651.3181821109024, -2085.574403592012, -2295.0860830203587])
[-356.23209909054367, 209.51167942834672]
chemicals.utils.isentropic_exponent(Cp: float, Cv: float) float[source]

Calculate the isentropic coefficient of an ideal gas, given its constant- pressure and constant-volume heat capacity.

k=CpCvk = \frac{C_p}{C_v}
Parameters:
Cpfloat

Ideal gas heat capacity at constant pressure, [J/mol/K]

Cvfloat

Ideal gas heat capacity at constant volume, [J/mol/K]

Returns:
kfloat

Isentropic exponent, [-]

Notes

For real gases, there are more complexities and formulas. Each of the formulas reverts to this formula in the case of an ideal gas.

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

>>> isentropic_exponent(33.6, 25.27)
1.329639889196676
chemicals.utils.isentropic_exponent_PT(Cp, P, dV_dT_P)[source]

Calculate the isentropic coefficient of real fluid using the definition of P(1k)Tk=constP^{(1-k)}T^k = \text{const}.

k=11PCp(VT)Pk = \frac{1}{1 - \frac{P}{C_p}\left(\frac{\partial V}{\partial T}\right)_P}
Parameters:
Cpfloat

Real heat capacity at constant pressure, [J/mol/K]

Pfloat

Pressure [Pa]

dV_dT_Pfloat

Derivative of V with respect to T (at constant pressure), [m^3/(mol*K)]

Returns:
k_PTfloat

Isentropic exponent of a real fluid, [-]

References

[1]

Pini, Matteo. “NiceProp: An Interactive Python-Based Educational Tool for Non-Ideal Compressible Fluid Dynamics.” SoftwareX 17 (2022): 100897.

[2]

Kouremenos, D. A., and K. A. Antonopoulos. “Isentropic Exponents of Real Gases and Application for the Air at Temperatures from 150 K to 450 K.” Acta Mechanica 65, no. 1 (January 1, 1987): 81-99. https://doi.org/10.1007/BF01176874.

Examples

Isentropic exponent of air according to Lemmon (2000) at 1000 bar and 300 K:

>>> isentropic_exponent_PT(Cp=38.36583283578205, P=100000000.0, dV_dT_P=9.407705210161724e-08)
1.32487270350443
chemicals.utils.isentropic_exponent_PV(Cp, Cv, Vm, P, dP_dV_T)[source]

Calculate the isentropic coefficient of real fluid using the definition of PVk=constPV^k = \text{const}.

k=VPCpCv(PV)Tk = -\frac{V}{P}\frac{C_p}{C_v}\left(\frac{\partial P}{\partial V}\right)_T
Parameters:
Cpfloat

Real heat capacity at constant pressure, [J/mol/K]

Cvfloat

Real heat capacity at constant volume, [J/mol/K]

Vmfloat

Molar volume, [m^3/mol]

Pfloat

Pressure [Pa]

dP_dV_Tfloat

Derivative of P with respect to V (at constant temperature), [Pa*mol/m^3]

Returns:
k_PVfloat

Isentropic exponent of a real fluid, [-]

References

[1]

Pini, Matteo. “NiceProp: An Interactive Python-Based Educational Tool for Non-Ideal Compressible Fluid Dynamics.” SoftwareX 17 (2022): 100897.

[2]

Kouremenos, D. A., and K. A. Antonopoulos. “Isentropic Exponents of Real Gases and Application for the Air at Temperatures from 150 K to 450 K.” Acta Mechanica 65, no. 1 (January 1, 1987): 81-99. https://doi.org/10.1007/BF01176874.

Examples

Isentropic exponent of air according to Lemmon (2000) at 1000 bar and 300 K:

>>> isentropic_exponent_PV(Cp=38.36583283578205, Cv=23.98081290153672, Vm=4.730885141495376e-05, P=100000000.0, dP_dV_T=-5417785576072.434)
4.100576762582646
chemicals.utils.isentropic_exponent_TV(Cv, Vm, dP_dT_V)[source]

Calculate the isentropic coefficient of real fluid using the definition of TVk1=constTV^{k-1} = \text{const}.

k=1+VCv(PT)Vk = 1 + \frac{V}{C_v} \left(\frac{\partial P}{\partial T}\right)_V
Parameters:
Cvfloat

Real heat capacity at constant volume, [J/mol/K]

Vmfloat

Molar volume, [m^3/mol]

dP_dT_Vfloat

Derivative of P with respect to T (at constant volume), [Pa/K]

Returns:
k_TVfloat

Isentropic exponent of a real fluid, [-]

References

[1]

Pini, Matteo. “NiceProp: An Interactive Python-Based Educational Tool for Non-Ideal Compressible Fluid Dynamics.” SoftwareX 17 (2022): 100897.

[2]

Kouremenos, D. A., and K. A. Antonopoulos. “Isentropic Exponents of Real Gases and Application for the Air at Temperatures from 150 K to 450 K.” Acta Mechanica 65, no. 1 (January 1, 1987): 81-99. https://doi.org/10.1007/BF01176874.

Examples

Isentropic exponent of air according to Lemmon (2000) at 1000 bar and 300 K:

>>> isentropic_exponent_TV(Cv=23.98081290153672, Vm=4.730885141495376e-05, dP_dT_V=509689.2959155567)
2.005504495083
chemicals.utils.isobaric_expansion(V: float, dV_dT: float) float[source]

Calculate the isobaric coefficient of a thermal expansion, given its molar volume at a certain T and P, and its derivative of molar volume with respect to T.

β=1V(VT)P\beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P
Parameters:
Vfloat

Molar volume at T and P, [m^3/mol]

dV_dTfloat

Derivative of molar volume with respect to T, [m^3/mol/K]

Returns:
betafloat

Isobaric coefficient of a thermal expansion, [1/K]

Notes

For an ideal gas, this expression simplified to:

β=1T\beta = \frac{1}{T}

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

Calculated for hexane from the PR EOS at 299 K and 1 MPa (liquid):

>>> isobaric_expansion(0.000130229900873546, 1.58875261849113e-7)
0.0012199599384121608
chemicals.utils.isothermal_compressibility(V: float, dV_dP: float) float[source]

Calculate the isothermal coefficient of compressibility, given its molar volume at a certain T and P, and its derivative of molar volume with respect to P.

κ=1V(VP)T\kappa = -\frac{1}{V}\left(\frac{\partial V}{\partial P} \right)_T
Parameters:
Vfloat

Molar volume at T and P, [m^3/mol]

dV_dPfloat

Derivative of molar volume with respect to P, [m^3/mol/Pa]

Returns:
kappafloat

Isothermal coefficient of compressibility, [1/Pa]

Notes

For an ideal gas, this expression simplified to:

κ=1P\kappa = \frac{1}{P}

The isothermal bulk modulus is the inverse of this quantity:

K=V(PV)TK = -V\left(\frac{\partial P}{\partial V} \right)_T

The ideal gas isothermal bulk modulus is simply the gas’s pressure.

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

Calculated for hexane from the PR EOS at 299 K and 1 MPa (liquid):

>>> isothermal_compressibility(0.000130229900873546, -2.72902118209903e-13)
2.095541165119158e-09

Calculate the bulk modulus of propane from the PR EOS at 294 K as a gas:

>>> 1/isothermal_compressibility(0.0024576770482135617, -3.5943321700795866e-09)
683764.5859979445
chemicals.utils.mix_component_flows(IDs1: list[str], IDs2: list[str], flow1: float, flow2: int, fractions1: list[float], fractions2: list[float]) tuple[list[str], list[float]][source]

Mix two flows of potentially different chemicals of given overall flow rates and flow fractions to determine the outlet components, flow rates, and compositions. The flows do not need to be of the same length.

Parameters:
IDs1list[str]

List of identifiers of the chemical species in flow one, [-]

IDs2list[str]

List of identifiers of the chemical species in flow two, [-]

flow1float

Total flow rate of the chemicals in flow one, [mol/s]

flow2float

Total flow rate of the chemicals in flow two, [mol/s]

fractions1list[float]

Mole fractions of each chemical in flow one, [-]

fractions2list[float]

Mole fractions of each chemical in flow two, [-]

Returns:
cmpslist[str]

List of identifiers of the chemical species in the combined flow, [-]

moleslist[float]

Flow rates of all chemical species in the combined flow, [mol/s]

Notes

Mass or volume flows and fractions can be used instead of molar ones.

If the two flows have the same components, the output list will be in the same order as the one given; otherwise they are sorted alphabetically.

Examples

>>> mix_component_flows(['7732-18-5', '64-17-5'], ['7732-18-5', '67-56-1'], 1, 1, [0.5, 0.5], [0.5, 0.5])
(['64-17-5', '67-56-1', '7732-18-5'], [0.5, 0.5, 1.0])
chemicals.utils.mix_component_partial_flows(IDs1, IDs2, ns1=None, ns2=None)[source]

Mix two flows of potentially different chemicals; with the feature that the mole flows of either or both streams may be unknown.

The flows do not need to be of the same length.

Parameters:
IDs1list[str]

List of identifiers of the chemical species in flow one, [-]

IDs2list[str]

List of identifiers of the chemical species in flow two, [-]

ns1list[float]

Total flow rate of the chemicals in flow one, [mol/s]

ns2list[float]

Total flow rate of the chemicals in flow two, [mol/s]

Returns:
cmpslist[str]

List of identifiers of the chemical species in the combined flow, [-]

moleslist[float]

Flow rates of all chemical species in the combined flow, [mol/s]

Notes

Mass or volume flows and fractions can be used instead of molar ones.

If the two flows have the same components, the output list will be in the same order as the one given; otherwise they are sorted alphabetically.

Examples

>>> mix_component_partial_flows(['7732-18-5', '64-17-5'], ['7732-18-5', '67-56-1'], [0.5, 0.5], [0.5, 0.5])
(['64-17-5', '67-56-1', '7732-18-5'], [0.5, 0.5, 1.0])
>>> mix_component_partial_flows(['7732-18-5', '64-17-5'], ['7732-18-5', '67-56-1'], None, [0.5, 0.5])
(['64-17-5', '67-56-1', '7732-18-5'], [0.0, 0.5, 0.5])
>>> mix_component_partial_flows(['7732-18-5', '64-17-5'], ['7732-18-5', '67-56-1'], [0.5, 0.5], None)
(['64-17-5', '67-56-1', '7732-18-5'], [0.5, 0.0, 0.5])
>>> mix_component_partial_flows(['7732-18-5', '64-17-5'], ['7732-18-5', '67-56-1'], None, None)
(['64-17-5', '67-56-1', '7732-18-5'], [0.0, 0.0, 0.0])
chemicals.utils.mix_multiple_component_flows(IDs: list[list[str]], flows: list[int], fractions: list[list[float]]) tuple[list[str], list[float]][source]

Mix multiple flows of potentially different chemicals of given overall flow rates and flow fractions to determine the outlet components, flow rates, and compositions. The flows do not need to be of the same length.

Parameters:
IDslist[list[str]]

List of lists of identifiers of the chemical species in the flows, [-]

flowslist[float]

List of total flow rates of the chemicals in the streams, [mol/s]

fractionslist[list[float]]

List of lists of mole fractions of each chemical in each flow, [-]

Returns:
cmpslist[str]

List of identifiers of the chemical species in the combined flow, [-]

moleslist[float]

Flow rates of all chemical species in the combined flow, [mol/s]

Notes

Mass or volume flows and fractions can be used instead of molar ones.

If the every flow have the same components, the output list will be in the same order as the one given; otherwise they are sorted alphabetically.

Examples

>>> mix_multiple_component_flows([['7732-18-5', '64-17-5'], ['7732-18-5', '67-56-1']],
... [1, 1], [[0.5, 0.5], [0.5, 0.5]])
(['64-17-5', '67-56-1', '7732-18-5'], [0.5, 0.5, 1.0])
chemicals.utils.mixing_logarithmic(fracs: list[float], props: list[float]) float | None[source]

Simple function calculates a property based on weighted averages of logarithmic properties.

y=ifraciln(propi)y = \sum_i \text{frac}_i \cdot \ln(\text{prop}_i)
Parameters:
fracsarray_like

Fractions of a mixture

propsarray_like

Properties

Returns:
propvalue

Calculated property

Notes

Does not work on negative values. Returns None if any fractions or properties are missing or are not of the same length.

Examples

>>> mixing_logarithmic([0.1, 0.9], [0.01, 0.02])
0.01866065983073615
chemicals.utils.mixing_power(fracs: list[float], props: list[float], r: int) float[source]

Power law mixing rule for any property, with a variable exponent r as input. Optimiezd routines are available for common powers.

propmixr=izi(propi)r\text{prop}_{mix}^r = \sum_i z_i \left(\text{prop}_i \right)^{r}
Parameters:
fracslist[float]

Mole fractions of components (or mass, or volume, etc.), [-]

propslist[float]

Properties of all components, [various]

rfloat

Power mixing exponent, [-]

Returns:
propfloat

Property for mixture, [props]

Notes

This equation is entirely dimensionless; all dimensions cancel.

The following recommendations in [1] exist for different properties:

Surface tension: r = 1 Recommended by an author in [1]; but often non-linear behavior is shown and r= -1 to r=-3 is recommended. r = -1 is most often used.

Liquid thermal conductivity: r = -2 in [1]; this is known also as procedure DIPPR9B.

References

[1] (1,2)

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

>>> mixing_power([0.258, 0.742], [0.1692, 0.1528], -2)
0.15657104706719646
chemicals.utils.mixing_simple(fracs: list[float], props: list[float]) float | None[source]

Simple function calculates a property based on weighted averages of properties. Weights could be mole fractions, volume fractions, mass fractions, or anything else.

y=ifracipropiy = \sum_i \text{frac}_i \cdot \text{prop}_i
Parameters:
fracsarray_like

Fractions of a mixture

propsarray_like

Properties

Returns:
propvalue

Calculated property

Examples

>>> mixing_simple([0.1, 0.9], [0.01, 0.02])
0.019000000000000003
chemicals.utils.molar_velocity_to_velocity(v_molar, MW)[source]

Calculate the mass-based velocity (m/s) from the molar velocity of the fluid.

v=vmolar1000MWv = \frac{v_{molar}\sqrt{1000}}{\sqrt{\text{MW}}}
Parameters:
v_molarfloat

Molar velcoity, [m*kg^0.5/s/mol^0.5]

MWfloat

Molecular weight, [g/mol]

Returns:
vfloat

Velocity, [m/s]

Examples

>>> molar_velocity_to_velocity(46., 40.445)
228.73
chemicals.utils.ms_to_Qls(ms, MWs, Vmls)[source]

Converts a list of mass flow rates to standard liquid volume flow rates. Requires molecular weights and standard molar liquid volumes for all species.

Qli=1000miVmliMWi{Ql}_i = \frac{1000 m_i {Vml}_i}{MW_i}
Parameters:
msiterable

Mass flow rates [kg/s]

MWsiterable

Molecular weights [g/mol]

Vmlsiterable

Standard liquid molar volumes [m^3/mol]

Returns:
Qlsiterable

Standard liquid volume flow rates [m^3/s]

Notes

Does not check that inputs are of the same length.

Examples

>>> ms_to_Qls([4.0, 5.0], [24, 45], [1e-4, 2e-4])
[0.0166666666, 0.0222222222]
chemicals.utils.ms_to_ns(ms, MWs)[source]

Converts a list of mass flow rates to mole flow rates. Requires molecular weights for all species.

ni=1000miMWin_i = \frac{1000 m_i}{MW_i}
Parameters:
msiterable

Mass flow rates [kg/s]

MWsiterable

Molecular weights [g/mol]

Returns:
nsiterable

Mole flow rates [mol/s]

Notes

Does not check that inputs are of the same length.

Examples

>>> ms_to_ns([4, 5], [24, 45])
[166.666, 111.111]
chemicals.utils.none_and_length_check(all_inputs: Any, length: int | None = None) bool[source]

Checks inputs for suitability of use by a mixing rule which requires all inputs to be of the same length and non-None. A number of variations were attempted for this function; this was found to be the quickest.

Parameters:
all_inputsarray_like of array_like

list of all the lists of inputs, [-]

lengthint, optional

Length of the desired inputs, [-]

Returns:
False/Truebool

Returns True only if all inputs are the same length (or length length) and none of the inputs contain None [-]

Notes

Does not check for nan values.

Examples

>>> none_and_length_check(([1, 1], [1, 1], [1, 30], [10,0]), length=2)
True
chemicals.utils.normalize(values: list[float]) list[float][source]

Simple function which normalizes a series of values to be from 0 to 1, and for their sum to add to 1.

x=xsumixix = \frac{x}{sum_i x_i}
Parameters:
valuesarray_like

array of values

Returns:
fractionsarray_like

Array of values from 0 to 1

Notes

Does not work on negative values, or handle the case where the sum is zero.

Examples

>>> normalize([3, 2, 1])
[0.5, 0.3333333333333333, 0.16666666666666666]
chemicals.utils.ns_to_Qls(ns, Vmls)[source]

Converts a list of mole flow rates to standard liquid volume flow rates. Requires standard liquid molar volumes for all species.

Qli=niVmli{Ql}_i = n_i {Vml}_i
Parameters:
nsiterable

Mole flow rates [mol/s]

Vmlsiterable

Standard molar liquid volumes of each component [m^3/mol]

Returns:
Qlsiterable

Standard liquid volume flow rates [m^3/s]

Notes

Does not check that inputs are of the same length.

Examples

>>> ns_to_Qls([2.0, 3.0], [1e-4, 2e-4])
[2e-4, 6e-4]
chemicals.utils.ns_to_ms(ns, MWs)[source]

Converts a list of mole flow rates to mass flow rates. Requires molecular weights for all species.

mi=niMWi1000m_i = \frac{n_i MW_i}{1000}
Parameters:
nsiterable

Mole flow rates [mol/s]

MWsiterable

Molecular weights [g/mol]

Returns:
msiterable

Mass flow rates [kg/s]

Notes

Does not check that inputs are of the same length.

Examples

>>> ns_to_ms([166.6666666666, 111.1111111111], [24, 45])
[4.0, 5.0]
chemicals.utils.phase_identification_parameter(V: float, dP_dT: float, dP_dV: float, d2P_dV2: float, d2P_dVdT: float) float[source]

Calculate the Phase Identification Parameter developed in [1] for the accurate and efficient determination of whether a fluid is a liquid or a gas based on the results of an equation of state. For supercritical conditions, this provides a good method for choosing which property correlations to use.

Π=V[2PVTPT2PV2PV]\Pi = V \left[\frac{\frac{\partial^2 P}{\partial V \partial T}} {\frac{\partial P }{\partial T}}- \frac{\frac{\partial^2 P}{\partial V^2}}{\frac{\partial P}{\partial V}} \right]
Parameters:
Vfloat

Molar volume at T and P, [m^3/mol]

dP_dTfloat

Derivative of P with respect to T, [Pa/K]

dP_dVfloat

Derivative of P with respect to V, [Pa*mol/m^3]

d2P_dV2float

Second derivative of P with respect to V, [Pa*mol^2/m^6]

d2P_dVdTfloat

Second derivative of P with respect to both V and T, [Pa*mol/m^3/K]

Returns:
PIPfloat

Phase Identification Parameter, [-]

Notes

Heuristics were used by process simulators before the invent of this parameter.

The criteria for liquid is Pi > 1; for vapor, Pi <= 1.

There is also a solid phase mechanism available. For solids, the Solid Phase Identification Parameter is greater than 1, like liquids; however, unlike liquids, d2P_dVdT is always >0; it is < 0 for liquids and gases.

References

[1]

Venkatarathnam, G., and L. R. Oellrich. “Identification of the Phase of a Fluid Using Partial Derivatives of Pressure, Volume, and Temperature without Reference to Saturation Properties: Applications in Phase Equilibria Calculations.” Fluid Phase Equilibria 301, no. 2 (February 25, 2011): 225-33. doi:10.1016/j.fluid.2010.12.001.

[2]

Jayanti, Pranava Chaitanya, and G. Venkatarathnam. “Identification of the Phase of a Substance from the Derivatives of Pressure, Volume and Temperature, without Prior Knowledge of Saturation Properties: Extension to Solid Phase.” Fluid Phase Equilibria 425 (October 15, 2016): 269-277. doi:10.1016/j.fluid.2016.06.001.

Examples

Calculated for hexane from the PR EOS at 299 K and 1 MPa (liquid):

>>> phase_identification_parameter(0.000130229900874, 582169.397484,
... -3.66431747236e+12, 4.48067893805e+17, -20518995218.2)
11.33428990564796
chemicals.utils.phase_identification_parameter_phase(d2P_dVdT: float, V: float | None = None, dP_dT: float | None = None, dP_dV: float | None = None, d2P_dV2: float | None = None) str[source]

Uses the Phase Identification Parameter concept developed in [1] and [2] to determine if a chemical is a solid, liquid, or vapor given the appropriate thermodynamic conditions.

The criteria for liquid is PIP > 1; for vapor, PIP <= 1.

For solids, PIP(solid) is defined to be d2P_dVdT. If it is larger than 0, the species is a solid. It is less than 0 for all liquids and gases.

Parameters:
d2P_dVdTfloat

Second derivative of P with respect to both V and T, [Pa*mol/m^3/K]

Vfloat, optional

Molar volume at T and P, [m^3/mol]

dP_dTfloat, optional

Derivative of P with respect to T, [Pa/K]

dP_dVfloat, optional

Derivative of P with respect to V, [Pa*mol/m^3]

d2P_dV2float, optional

Second derivative of P with respect to V, [Pa*mol^2/m^6]

Returns:
phasestr

Either ‘s’, ‘l’ or ‘g’

Notes

The criteria for being a solid phase is checked first, which only requires d2P_dVdT. All other inputs are optional for this reason. However, an exception will be raised if the other inputs become needed to determine if a species is a liquid or a gas.

References

[1]

Venkatarathnam, G., and L. R. Oellrich. “Identification of the Phase of a Fluid Using Partial Derivatives of Pressure, Volume, and Temperature without Reference to Saturation Properties: Applications in Phase Equilibria Calculations.” Fluid Phase Equilibria 301, no. 2 (February 25, 2011): 225-33. doi:10.1016/j.fluid.2010.12.001.

[2]

Jayanti, Pranava Chaitanya, and G. Venkatarathnam. “Identification of the Phase of a Substance from the Derivatives of Pressure, Volume and Temperature, without Prior Knowledge of Saturation Properties: Extension to Solid Phase.” Fluid Phase Equilibria 425 (October 15, 2016): 269-277. doi:10.1016/j.fluid.2016.06.001.

Examples

Calculated for hexane from the PR EOS at 299 K and 1 MPa (liquid):

>>> phase_identification_parameter_phase(-20518995218.2, 0.000130229900874,
... 582169.397484, -3.66431747236e+12, 4.48067893805e+17)
'l'
chemicals.utils.property_mass_to_molar(A_mass: float, MW: float) float[source]

Convert a quantity in mass units [thing/kg] to molar units [thing/mol]. The standard gram-mole is used here, as it is everwhere in this library.

Amolar=AmassMW1000A_{\text{molar}} = \frac{A_{\text{mass}} \text{MW}}{1000}
Parameters:
A_massfloat

Quantity in molar units [thing/kg]

MWfloat

Molecular weight, [g/mol]

Returns:
A_molarfloat

Quantity in molar units [thing/mol]

Notes

For legacy reasons, if the value A_mass is None, None is also returned and no exception is returned.

Examples

>>> property_mass_to_molar(20.0, 18.015)
0.3603
chemicals.utils.property_molar_to_mass(A_molar: int, MW: float) float[source]

Convert a quantity in molar units [thing/mol] to mass units [thing/kg]. The standard gram-mole is used here, as it is everwhere in this library.

Amass=1000AmolarMWA_{\text{mass}} = \frac{1000 A_{\text{molar}}}{\text{MW}}
Parameters:
A_molarfloat

Quantity in molar units [thing/mol]

MWfloat

Molecular weight, [g/mol]

Returns:
A_massfloat

Quantity in molar units [thing/kg]

Notes

For legacy reasons, if the value A_molar is None, None is also returned and no exception is returned.

Examples

>>> property_molar_to_mass(500, 18.015)
27754.648903691366
chemicals.utils.radius_of_gyration(MW, A, B, C, planar=False)[source]

Calculates the radius of gyration of a molecule using the DIPPR definition. The parameters A, B, and C must be obtained from either vibrational scpectra and analysis or quantum chemistry calculations of programs such as psi <https://psicode.org/>.

For planar molecules defined by only two moments of inertia,

Rg=ABNAMWR_g = \sqrt{\sqrt{AB}\frac{N_A}{\text{MW}}}

For non-planar molecules with three moments of inertia,

Rg=2π(ABC)1/3NAMWR_g = \sqrt{\frac{2\pi(ABC)^{1/3}N_A}{\text{MW}}}
Parameters:
MWfloat

Molecular weight, [g/mol]

Afloat

First principle moment of inertia, [kg*m^2]

Bfloat

Second principle moment of inertia, [kg*m^2]

Cfloat

Third principle moment of inertia, [kg*m^2]

planarbool

Whether the molecule is flat or not, [-]

Returns:
Rgfloat

Radius of gyration, [m]

Notes

There are many, many quantum chemistry models available which give different results.

References

[1]

Green, Don, and Robert Perry. Perry’s Chemical Engineers’ Handbook, 8E. McGraw-Hill Professional, 2007.

[2]

Johnson III, Russell D. “NIST 101. Computational Chemistry Comparison and Benchmark Database,” 1999. https://cccbdb.nist.gov

Examples

Example calcultion in [1] for hydrazine (optimized with HF/6-31G model):

>>> radius_of_gyration(MW=32.00452, planar=False, A=5.692E-47, B=3.367E-46, C=3.681E-46)
1.50581642e-10

The same calculation was performed with psi and somewhat different parameters obtained

>>> radius_of_gyration(MW=32.00452, planar=False, A=6.345205205562681e-47, B=3.2663291891213418e-46, C=3.4321304373822523e-46)
1.507895671e-10

A planar molecule, bromosilane, has two principle moments of inertia in [2]. They are 2.80700 cm^-1 and 0.14416 cm^-1. These can be converted to MHz as follows:

These can then be converted to units of AMU*Angstrom^2, and from there to kg*m^2.

>>> A, B = 2.80700, 0.14416
>>> from scipy.constants import atomic_mass, c, angstrom
>>> A, B = A*c*1e-4, B*c*1e-4 # from cm^-1 to MHz
>>> A, B = [505379.15/i for i in (A, B)] #  TODO which constants did this conversion factor come from, AMU*Angstrom^2
>>> A, B = [i*atomic_mass*angstrom**2 for i in (A, B)] # amu*angstrom^2 to kg*m^2
>>> radius_of_gyration(A=A, B=B, planar=True, MW=111.01, C=0)
4.8859e-11

Alternatively, doing the conversion all in one:

>>> A, B = 2.80700, 0.14416
>>> from scipy.constants import c, h, pi
>>> A, B = A*c*100, B*c*100 # from cm^-1 to Hz
>>> A, B = [h/(8*pi**2)/i for i in (A, B)] # from Hz to kg*m^2
>>> radius_of_gyration(A=A, B=B, planar=True, MW=111.01, C=0)
4.8859e-11

This is also nicely documented on this page: https://cccbdb.nist.gov/convertmomint.asp which was unfortunately found by the author after figuring it out the hard way.

chemicals.utils.remove_zeros(values: list[float] | ndarray, tol: float = 1e-06) ndarray | list[float][source]

Simple function which removes zero values from an array, and replaces them with a user-specified value, normally a very small number. Helpful for the case where a function can work with values very close to zero but not quite zero. The resulting array is normalized so the sum is still one.

Parameters:
valuesarray_like

array of values

tolfloat

The replacement value for zeroes

Returns:
fractionsarray_like

Array of values from 0 to 1

Notes

Works on numpy arrays, and returns numpy arrays only for that case.

Examples

>>> remove_zeros([0, 1e-9, 1], 1e-12)
[9.99999998999e-13, 9.99999998999e-10, 0.999999998999]
chemicals.utils.rho_to_API(rho, rho_ref=999.0170824078306)[source]

Calculates API of a liquid given its mass density, as shown in [1].

API gravity=141.5ρrefρ131.5\text{API gravity} = \frac{141.5\rho_{ref}}{\rho} - 131.5
Parameters:
rhofloat

Mass density the fluid at 60 degrees Farenheight [kg/m^3]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
APIfloat

API of the fluid [-]

Notes

Defined only at 60 degrees Fahrenheit.

References

[1]

API Technical Data Book: General Properties & Characterization. American Petroleum Institute, 7E, 2005.

Examples

>>> rho_to_API(820)
40.8913623
>>> SG_to_API(SG(820))
40.8913623
chemicals.utils.rho_to_Baume_heavy(rho, rho_ref=999.0170824078306)[source]

Calculates degrees Baumé of a liquid heavier than water given its mass density, as shown in [1].

Degrees Baumeˊ=145145SG=145145ρrefρ\text{Degrees Baumé} = 145 - \frac{145}{\text{SG}} = 145 - \frac{145\rho_{ref}}{\rho}
Parameters:
rhofloat

Mass density the fluid at 60 degrees Fahrenheit [kg/m^3]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
Baumefloat

Degrees Baumé of the fluid [-]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids heavier than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> rho_to_Baume_heavy(1200)
24.285
chemicals.utils.rho_to_Baume_light(rho, rho_ref=999.0170824078306)[source]

Calculates degrees Baumé of a liquid lighter than water given its mass density, as shown in [1].

Degrees Baumeˊ=140SG130=140ρrefρ130\text{Degrees Baumé} = \frac{140}{\text{SG}} - 130 = \frac{140\rho_{ref}}{\rho} - 130
Parameters:
rhofloat

Mass density of the fluid at 60 degrees Fahrenheit [kg/m^3]

rho_reffloat, optional

Density of the reference substance, [kg/m^3]

Returns:
Baumefloat

Degrees Baumé of the fluid [-]

Notes

Defined only at 60 degrees Fahrenheit. Only valid for liquids lighter than water.

References

[1]

GPSA Engineering Data Book, Gas Processors Suppliers Association, Tulsa, OK, 2004.

Examples

>>> rho_to_Baume_light(820)
40.563
chemicals.utils.rho_to_Vm(rho: float, MW: float) float[source]

Calculate the molar volume of a chemical, given its density and molecular weight.

Vm=(1000ρMW)1V_m = \left(\frac{1000 \rho}{MW}\right)^{-1}
Parameters:
rhofloat

Density, [kg/m^3]

MWfloat

Molecular weight, [g/mol]

Returns:
Vmfloat

Molar volume, [m^3/mol]

References

[1]

Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000.

Examples

>>> rho_to_Vm(652.9, 86.18)
0.0001319957114412621
chemicals.utils.solve_flow_composition_mix(Fs: list[float | None] | list[int | None] | list[float], zs: list[None] | list[float | None], ws: list[float | None] | list[None], MWs: list[float]) tuple[list[float], list[float], list[float]][source]

Solve a stream composition problem where some specs are mole flow rates; some are mass fractions; and some are mole fractions. This algorithm requires at least one mole flow rate; and for every other component, a single spec in mole or mass or a flow rate. It is permissible for no components to have mole fractions; or no components to have weight fractions; or both.

Parameters:
Fslist[float]

List of mole flow rates; None if not specified for a component, [mol/s]

zslist[float]

Mole fractions; None if not specified for a component [-]

wslist[float]

Mass fractions; None if not specified for a component [-]

MWslist[float]

Molecular weights, [g/mol]

Returns:
Fslist[float]

List of mole flow rates, [mol/s]

zslist[float]

Mole fractions, [-]

wslist[float]

Mass fractions, [-]

Notes

A fast path is used if no weight fractions are provided; the calculation is much simpler for that case.

This algorithm was derived using SymPy, and framed in a form which allows for explicit solving. This is capable of solving large-scale problems i.e. with 1000 components a solve time is 1 ms; with 10000 it is 10 ms.

Examples

>>> Fs = [3600, None, None, None, None]
>>> zs = [None, .1, .2, None, None]
>>> ws = [None, None, None, .01, .02]
>>> MWs = [18.01528, 46.06844, 32.04186, 72.151, 142.286]
>>> Fs, zs, ws = solve_flow_composition_mix(Fs, zs, ws, MWs)
>>> Fs
[3600, 519.3039148597746, 1038.6078297195493, 17.44015034881175, 17.687253669610733]
>>> zs
[0.6932356751002141, 0.1, 0.2, 0.0033583706669188186, 0.003405954232867038]
>>> ws
[0.5154077420893426, 0.19012206531421305, 0.26447019259644433, 0.01, 0.02]
chemicals.utils.speed_of_sound(V: float, dP_dV: float, Cp: float, Cv: float, MW: float | None = None) float[source]

Calculate a real fluid’s speed of sound. The required derivatives should be calculated with an equation of state, and Cp and Cv are both the real fluid versions. Expression is given in [1] and [2]; a unit conversion is further performed to obtain a result in m/s. If MW is not provided the result is returned in units of m*kg^0.5/s/mol^0.5.

w=[V2(PV)TCpCv]1/2w = \left[-V^2 \left(\frac{\partial P}{\partial V}\right)_T \frac{C_p} {C_v}\right]^{1/2}
Parameters:
Vfloat

Molar volume of fluid, [m^3/mol]

dP_dVfloat

Derivative of P with respect to V, [Pa*mol/m^3]

Cpfloat

Real fluid heat capacity at constant pressure, [J/mol/K]

Cvfloat

Real fluid heat capacity at constant volume, [J/mol/K]

MWfloat, optional

Molecular weight, [g/mol]

Returns:
wfloat

Speed of sound for a real gas, m/s or m*kg^0.5/s/mol^0.5 if MW missing

Notes

An alternate expression based on molar density is as follows:

w=[(Pρ)TCpCv]1/2w = \left[\left(\frac{\partial P}{\partial \rho}\right)_T \frac{C_p} {C_v}\right]^{1/2}

The form with the unit conversion performed inside it is as follows:

w=[V21000MW(PV)TCpCv]1/2w = \left[-V^2 \frac{1000}{MW}\left(\frac{\partial P}{\partial V} \right)_T \frac{C_p}{C_v}\right]^{1/2}

References

[1]

Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: Wiley-VCH, 2012.

[2] (1,2)

Pratt, R. M. “Thermodynamic Properties Involving Derivatives: Using the Peng-Robinson Equation of State.” Chemical Engineering Education 35, no. 2 (March 1, 2001): 112-115.

Examples

Example from [2]:

>>> speed_of_sound(V=0.00229754, dP_dV=-3.5459e+08, Cp=153.235, Cv=132.435, MW=67.152)
179.5868138460819
chemicals.utils.to_num(values: list[str]) list[str | float | None] | list[str | float][source]

Legacy function to turn a list of strings into either floats (if numeric), stripped strings (if not) or None if the string is empty. Accepts any numeric formatting the float function does.

Parameters:
valueslist

list of strings

Returns:
valueslist

list of floats, strings, and None values [-]

Examples

>>> to_num(['1', '1.1', '1E5', '0xB4', ''])
[1.0, 1.1, 100000.0, '0xB4', None]
chemicals.utils.v_molar_to_v(v_molar: float, MW: float) float[source]

Convert a velocity from units of the molar velocity form to standard m/s units.

v(m/s)=v(mkgsmol)MW (g/mol)0.5(1000g1kg)0.5v \text{(m/s)} = v\left(\frac{\text{m}\sqrt{\text{kg}} } {s \sqrt{\text{mol}}} \right) {\text{MW (g/mol)}}^{-0.5}\cdot \left(\frac{1000 \text{g}}{1 \text{kg}}\right)^{0.5}
Parameters:
v_molarfloat

Molar velocity, [m*kg^0.5/s/mol^0.5]

MWfloat

Molecular weight, [g/mol]

Returns:
vfloat

Velocity, [m/s]

Examples

>>> v_molar_to_v(67.10998435404377, 18.015)
499.99999999999994
chemicals.utils.v_to_v_molar(v: int, MW: float) float[source]

Convert a velocity from units of m/s to a “molar” form of velocity, compatible with thermodynamic calculations on a molar basis.

v(mkgsmol)=v(m/s)MW (g/mol)(1000g1kg)0.5v\left(\frac{\text{m}\sqrt{\text{kg}} }{s \sqrt{\text{mol}}} \right) = v \text{(m/s)} \sqrt{\text{MW (g/mol)}}\cdot \left(\frac{1000 \text{g}}{1 \text{kg}}\right)^{-0.5}
Parameters:
vfloat

Velocity, [m/s]

MWfloat

Molecular weight, [g/mol]

Returns:
v_molarfloat

Molar velocity, [m*kg^0.5/s/mol^0.5]

Examples

>>> v_to_v_molar(500, 18.015)
67.10998435404377
chemicals.utils.vapor_mass_quality(VF: float, MWl: int, MWg: int) float[source]

Calculates the vapor quality on a mass basis of a two-phase mixture; this is the most common definition, where 1 means a pure vapor and 0 means a pure liquid. The vapor quality on a mass basis is related to the mole basis vapor fraction according to the following relationship:

x=VFMWg(1VF)MWl+VFMWgx = \frac{\frac{V}{F}\cdot \text{MW}_g} {(1-\frac{V}{F})\text{MW}_l + \frac{V}{F}\text{MW}_g}
Parameters:
VFfloat

Mole-basis vapor fraction (0 = pure vapor, 1 = pure liquid), [-]

MWlfloat

Average molecular weight of the liquid phase, [g/mol]

MWgfloat

Average molecular weight of the vapor phase, [g/mol]

Returns:
qualityfloat

Vapor mass fraction of the two-phase system, [-]

Notes

Other definitions of vapor fraction use an enthalpy basis instead of a mass basis; still other less common ones take 1 to be the value of the liquid, and 0 as pure vapor.

References

[1]

Green, Don, and Robert Perry. Perry’s Chemical Engineers’ Handbook, 8E. McGraw-Hill Professional, 2007.

Examples

>>> vapor_mass_quality(0.5, 60, 30)
0.3333333333333333
chemicals.utils.velocity_to_molar_velocity(v, MW)[source]

Calculate the molar velocity from the mass-based (m/s) velocity of the fluid.

vmolar=vMW1000v_{molar} = \frac{v \sqrt{\text{MW}}}{\sqrt{1000}}
Parameters:
vfloat

Velocity, [m/s]

MWfloat

Molecular weight, [g/mol]

Returns:
v_molarfloat

Molar velcoity, [m*kg^0.5/s/mol^0.5]

Examples

>>> velocity_to_molar_velocity(228.73, 40.445)
46.
chemicals.utils.ws_to_zs(ws: list[float], MWs: list[int]) list[float][source]

Converts a list of mass fractions to mole fractions. Requires molecular weights for all species.

zi=wiMWiiwiMWiz_i = \frac{\frac{w_i}{MW_i}}{\sum_i \frac{w_i}{MW_i}}
Parameters:
wsiterable

Mass fractions [-]

MWsiterable

Molecular weights [g/mol]

Returns:
zsiterable

Mole fractions [-]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

Examples

>>> ws_to_zs([0.3333333333333333, 0.6666666666666666], [10, 20])
[0.5, 0.5]
chemicals.utils.zs_to_Vfs(zs: list[float], Vms: list[float]) list[float][source]

Converts a list of mole fractions to volume fractions. Requires molar volumes for all species.

Vfi=ziVm,iiziVm,i\text{Vf}_i = \frac{z_i V_{m,i}}{\sum_i z_i V_{m,i}}
Parameters:
zsiterable

Mole fractions [-]

Vmsiterable

Molar volumes of species [m^3/mol]

Returns:
Vfslist

Molar volume fractions [-]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

Molar volumes are specified in terms of pure components only. Function works with any phase.

Examples

Acetone and benzene example

>>> zs_to_Vfs([0.637, 0.363], [8.0234e-05, 9.543e-05])
[0.5960229712956298, 0.4039770287043703]
chemicals.utils.zs_to_ws(zs: list[float], MWs: list[int] | list[float]) list[float][source]

Converts a list of mole fractions to mass fractions. Requires molecular weights for all species.

wi=ziMWiMWavgw_i = \frac{z_i MW_i}{MW_{avg}}
MWavg=iziMWiMW_{avg} = \sum_i z_i MW_i
Parameters:
zsiterable

Mole fractions [-]

MWsiterable

Molecular weights [g/mol]

Returns:
wsiterable

Mass fractions [-]

Notes

Does not check that the sums add to one. Does not check that inputs are of the same length.

Examples

>>> zs_to_ws([0.5, 0.5], [10, 20])
[0.3333333333333333, 0.6666666666666666]