Thermodynamic Derivatives¶
Helmholtz energy derivatives¶
Thermodynamic derivatives are at the very heart of teqp. All models are defined in the form
Thereofore, to obtain the residual pressure, it is obtained as a derivative:
and other residual thermodynamic properties are defined likewise.
We can define the concise derivative
so we can re-write the derivative above as
Similar definitions apply for all the other thermodynamic properties, with the tot superscript indicating it is the sum of the residual and ideal-gas (not included in teqp) contributions:
Internal energy (
Enthalpy (
Entropy (
Gibbs energy (
Derivatives of pressure:
Isochoric specific heat (
Isobaric specific heat (
In teqp, these derivatives are obtained from methods like
where the A
in this context indicates the variable
[1]:
import teqp
teqp.__version__
[1]:
'0.22.0'
[2]:
import numpy as np
[3]:
Tc_K = [300]
pc_Pa = [4e6]
acentric = [0.01]
model = teqp.canonical_PR(Tc_K, pc_Pa, acentric)
[4]:
z = np.array([1.0])
model.get_Ar01(300,300,z)
[4]:
-0.06836660379313926
And there are additional methods to obtain all the derivatives up to a given order:
[5]:
model.get_Ar06n(300,300,z) # derivatives 00, 01, 02, ... 06
[5]:
array([-6.96613834e-02, -6.83666038e-02, 2.53578225e-03, -1.57011622e-04,
1.68186288e-05, -2.23059409e-06, 3.82592585e-07])
But more derivatives are slower than fewer:
[6]:
%timeit model.get_Ar01(300,300,z)
%timeit model.get_Ar04n(300,300,z)
567 ns ± 0.747 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
1.11 μs ± 4.12 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
Note: calling overhead is usually on the order of 1 microsecond
Virial coefficients¶
Virial coefficients represent the thermodynamics of the interaction of two-, three-, … bodies interacting with each other. They can be obtained rigorously if the potential energy surface of interaction is fully known. In general, such a surface can only be constructed for small rigid molecules. Many simple thermodynamic models do a poor job of predicting the thermodynamics captured by the virial coefficients.
The i-th virial coefficient is defined by
with the concise derivative term
teqp supports the virial coefficient directly, there is the get_B2vir
method for the second virial coefficient:
[7]:
model.get_B2vir(300, z)
[7]:
-0.00023661263734465424
And the get_Bnvir
method that allows for the calculation of higher virial coefficients:
[8]:
model.get_Bnvir(7, 300, z)
[8]:
{2: -0.0002366126373446542,
3: 3.001768410777936e-08,
4: -3.2409760373816364e-12,
5: 3.961781646633723e-16,
6: -4.5529239838367004e-20,
7: 5.375927851118494e-24}
The get_Bnvir
method was implemented because when doing automatic differentiation, all the intermediate derivatives are also retained.
There is also a method to calculate temperature derivatives of a given virial coefficient
[9]:
model.get_dmBnvirdTm(2, 3, 300, z) # third temperature derivative of the second virial coefficient
[9]:
1.0095625628421257e-10
Isochoric Thermodynamics Derivatives¶
In the isochoric thermodynamics formalism, the EOS is expressed in the Helmholtz energy density
with the chemical potential
The molar densities
In teqp, the isochoric derivative functions like get_fugacity_coefficients
, get_partial_molar_volumes
take as arguments the temperature T
and the vector of molar concentrations rhovec
=
Example:
[10]:
model = teqp.build_multifluid_model(["CO2","Argon"], teqp.get_datapath())
T, rhovec = 300, np.array([0.3,0.4])*300 # K, mol/m^3
display(model.get_fugacity_coefficients(T, rhovec))
display(model.get_partial_molar_volumes(T, rhovec))
array([0.97884567, 0.99866748])
array([0.00470644, 0.00480351])