peritheos 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,242 @@
1
+ import numpy as np
2
+ from scipy.integrate import quad
3
+ from scipy.constants import R
4
+
5
+ from ..rt.holzapfel import Holzapfel
6
+ from .. import (
7
+ NumericType,
8
+ ThermalEOS,
9
+ validate_finite_scalar,
10
+ validate_positive_scalar,
11
+ validate_volume,
12
+ )
13
+
14
+
15
+ class Sokolova2016(ThermalEOS):
16
+ def __init__(
17
+ self,
18
+ rt_eos: Holzapfel,
19
+ Tr: float,
20
+ QE1o: float,
21
+ mE1: float,
22
+ QE2o: float,
23
+ mE2: float,
24
+ delta: float,
25
+ t: float,
26
+ a_0: float,
27
+ m: float,
28
+ g: float,
29
+ e_0: float,
30
+ ):
31
+ """
32
+ Original thermal pressure equation from sokolova et al. 2016.
33
+
34
+ Parameters
35
+ ----------
36
+ rt_eos : Holzapfel
37
+ Room temperature equation of state (Holzapfel EOS)
38
+ Tr : float
39
+ Reference temperature in [K] for the EOS (typically 298.15 K)
40
+ QE1o : float
41
+ Einstein characteristic temperature, Theta_1 in [K]
42
+ mE1 : float
43
+ The first Einstein number
44
+ QE2o : float
45
+ Einstein characteristic temperature, Theta_02 in [K]
46
+ mE2 : float
47
+ The second Einstein number
48
+ TK : float
49
+ Temperature in [K]
50
+ delta : float
51
+ Additive normalizing constant for the Gruneisen parameter
52
+ t : float
53
+ Generalized Gruneisen parameter
54
+ a_0 : float
55
+ Intrinsic anharmonicity parameter (10e-6 [K])
56
+ m : float
57
+ Anharmonic analogue of the Grüneisen parameter
58
+ g : float
59
+ Electronic analogue of the Grüneisen parameter
60
+ e_0 : float
61
+ Free electrons parameter (10e-6 [K])
62
+ """
63
+ if not isinstance(rt_eos, Holzapfel):
64
+ raise TypeError("Sokolova2016 requires a Holzapfel room-temperature EOS")
65
+ super().__init__(rt_eos)
66
+ self.Tr = validate_positive_scalar(Tr, "Tr")
67
+ self.QE1o = validate_positive_scalar(QE1o, "QE1o")
68
+ self.mE1 = validate_finite_scalar(mE1, "mE1")
69
+ self.QE2o = validate_positive_scalar(QE2o, "QE2o")
70
+ self.mE2 = validate_finite_scalar(mE2, "mE2")
71
+ if self.mE1 < 0 or self.mE2 < 0:
72
+ raise ValueError("Einstein multiplicities must not be negative")
73
+ self.delta = validate_finite_scalar(delta, "delta")
74
+ self.t = validate_finite_scalar(t, "t")
75
+ self.a_0 = validate_finite_scalar(a_0, "a_0")
76
+ self.m = validate_finite_scalar(m, "m")
77
+ self.g = validate_finite_scalar(g, "g")
78
+ self.e_0 = validate_finite_scalar(e_0, "e_0")
79
+
80
+ def thermal_pressure(self, V: NumericType, T: NumericType) -> NumericType:
81
+ """
82
+ Calculate the thermal pressure using the Sokolova et al. 2016 model.
83
+
84
+ Parameters
85
+ ----------
86
+ V : NumericType
87
+ Molar volume in [J bar^-1], equal to [cm^3/mol] / 10
88
+ T : NumericType
89
+ Temperature in [K]
90
+
91
+ Returns
92
+ -------
93
+ thermal_pressure : NumericType
94
+ Thermal pressure in [GPa]
95
+ """
96
+ V = validate_volume(V)
97
+ temperatures = np.asarray(T, dtype=float)
98
+ if not np.all(np.isfinite(temperatures)) or np.any(temperatures <= 0):
99
+ raise ValueError("Temperature must be finite and greater than zero")
100
+ try:
101
+ V, T = np.broadcast_arrays(np.asarray(V, dtype=float), temperatures)
102
+ except ValueError as error:
103
+ raise ValueError("V and T must have broadcast-compatible shapes") from error
104
+
105
+ x = V / self.rt_eos.V0 # fractional volume
106
+ Px = self.rt_eos.pressure(V)
107
+ KT = self.rt_eos.bulk_modulus(V)
108
+ kkx = self.rt_eos.bulk_modulus_derivative(V)
109
+
110
+ # Equation (10) - seems not the same as in the original paper
111
+ gamV = (-3 * KT + 2 * Px * self.t + 9 * KT * kkx - 6 * self.t * KT) / 6 / (
112
+ 3 * KT - 2 * Px * self.t
113
+ ) + self.delta
114
+
115
+ # Exponent part in equation (9) - However this is not the correct value - the Excel spreadsheet
116
+ # calculation has a more elaborate calculation included
117
+
118
+ # expp_test = np.exp(0.5 * ao * TK * 1e6 * (V / V0) ** (1 / 3))
119
+ expp = np.exp(I_gamV(x, self.delta, self.t, self.rt_eos))
120
+
121
+ # Equation (9)
122
+ QE1 = self.QE1o * expp
123
+ QE2 = self.QE2o * expp
124
+
125
+ # Equation (12) for the different Einstein contributions at the temperature TK
126
+ PE1 = self.mE1 * R * (_einstein_energy(QE1, T) * gamV / V)
127
+
128
+ PE2 = self.mE2 * R * (_einstein_energy(QE2, T) * gamV / V)
129
+
130
+ # Equation (12) for the different Einstein contributions at the reference temperature
131
+ PE1r = self.mE1 * R * (_einstein_energy(QE1, self.Tr) * gamV / V)
132
+
133
+ PE2r = self.mE2 * R * (_einstein_energy(QE2, self.Tr) * gamV / V)
134
+
135
+ # Equation (12) second additive term
136
+ Pea = (
137
+ 3
138
+ / 2
139
+ * self.rt_eos.n
140
+ * R
141
+ * self.a_0
142
+ / 1000000
143
+ * x ** (self.m)
144
+ * (self.m)
145
+ / V
146
+ * (T**2 - self.Tr**2)
147
+ )
148
+ Pee = (
149
+ 3
150
+ / 2
151
+ * self.rt_eos.n
152
+ * R
153
+ * self.e_0
154
+ / 1000000
155
+ * x ** (self.g)
156
+ * (self.g)
157
+ / V
158
+ * (T**2 - self.Tr**2)
159
+ )
160
+
161
+ # R [J mol^-1 K^-1] divided by V [J bar^-1 mol^-1] produces bar.
162
+ Pth_bar = PE1 + PE2 - PE1r - PE2r + Pee + Pea
163
+ Pth_gpa = Pth_bar / 10000
164
+ if Pth_gpa.ndim == 0:
165
+ return float(Pth_gpa)
166
+ return Pth_gpa
167
+
168
+
169
+ def _einstein_energy(theta, temperature):
170
+ """Return Einstein oscillator energy in kelvin without exponential overflow."""
171
+ ratio = theta / temperature
172
+ decay = np.exp(-ratio)
173
+ thermal_part = theta * decay / (-np.expm1(-ratio))
174
+ return theta / 2 + thermal_part
175
+
176
+
177
+ def I_gamV(x, delta, t, rt_eos):
178
+ """
179
+ Integral of the Gruneisen parameter over the volume ratio (from x to 1).
180
+
181
+ Parameters
182
+ ----------
183
+ x : float
184
+ Fractional volume (V/Vo)
185
+ delta : float
186
+ Additive normalizing constant for the Gruneisen parameter
187
+ t : float
188
+ Generalized Gruneisen parameter
189
+ rt_eos : RT_EOS
190
+ room temperature equation of state object used for the calculation
191
+
192
+ Returns
193
+ -------
194
+ I_gamV : float
195
+ Integral of the Gruneisen parameter over the volume ratio (from x to 1)
196
+ """
197
+
198
+ V0 = rt_eos.V0
199
+
200
+ def f_gamV_x(x):
201
+ Px_x = rt_eos.pressure(x * V0)
202
+ KT_x = rt_eos.bulk_modulus(x * V0)
203
+ kkx_x = rt_eos.bulk_modulus_derivative(x * V0)
204
+ return f_gamV(x, Px_x, KT_x, kkx_x, delta, t)
205
+
206
+ x_values = np.asarray(x, dtype=float)
207
+ if not np.all(np.isfinite(x_values)) or np.any(x_values <= 0):
208
+ raise ValueError("Volume ratio must be finite and greater than zero")
209
+ integrals = np.array(
210
+ [quad(f_gamV_x, float(x_i), 1)[0] for x_i in x_values.flat]
211
+ ).reshape(x_values.shape)
212
+ if integrals.ndim == 0:
213
+ return float(integrals)
214
+ return integrals
215
+
216
+
217
+ def f_gamV(x, Px, KT, kkx, delta, t):
218
+ """
219
+ Helper function to calculate the Gruneisen parameter at a given temperature and pressure.
220
+
221
+ Parameters
222
+ ----------
223
+ x : float
224
+ Fractional volume (V/Vo)
225
+ Px : float
226
+ Pressure in [GPa]
227
+ KT: float
228
+ Bulk modulus at temperature in [GPa]
229
+ kkx: float
230
+ Bulk modulus derivative at temperature
231
+ delta: float
232
+ Additive normalizing constant for the Gruneisen parameter
233
+ gb: float
234
+ Generalized Gruneisen parameter
235
+ """
236
+ f_gamV_value = (
237
+ delta
238
+ + (-3 * KT + 2 * Px * t + 9 * KT * kkx - 6 * t * KT)
239
+ / (6 * (3 * KT - 2 * Px * t))
240
+ ) / x
241
+
242
+ return f_gamV_value
peritheos/utils.py ADDED
@@ -0,0 +1,118 @@
1
+ """
2
+ Utility functions for thermodynamic calculations
3
+ """
4
+
5
+ from .constants import R, N_A, k_B
6
+
7
+
8
+ def convert_pressure(value, from_unit, to_unit):
9
+ """
10
+ Convert pressure between different units
11
+
12
+ Parameters
13
+ ----------
14
+ value : float
15
+ Pressure value to convert
16
+ from_unit : str
17
+ Original unit ('pa', 'mpa', 'gpa', 'bar', 'kbar', 'atm', 'torr', 'psi')
18
+ to_unit : str
19
+ Target unit ('pa', 'mpa', 'gpa', 'bar', 'kbar', 'atm', 'torr', 'psi')
20
+
21
+ Returns
22
+ -------
23
+ float
24
+ Converted pressure value
25
+ """
26
+ # Conversion factors to Pa
27
+ to_pa = {
28
+ 'pa': 1.0,
29
+ 'mpa': 1e6,
30
+ 'gpa': 1e9,
31
+ 'bar': 1e5,
32
+ 'kbar': 1e8,
33
+ 'atm': 101325.0,
34
+ 'torr': 133.322,
35
+ 'psi': 6894.76
36
+ }
37
+
38
+ from_unit = from_unit.lower()
39
+ to_unit = to_unit.lower()
40
+ if from_unit not in to_pa:
41
+ raise ValueError(f"Unsupported pressure unit: {from_unit}")
42
+ if to_unit not in to_pa:
43
+ raise ValueError(f"Unsupported pressure unit: {to_unit}")
44
+
45
+ # Convert to Pa first
46
+ pa_value = value * to_pa[from_unit]
47
+
48
+ # Convert from Pa to target unit
49
+ return pa_value / to_pa[to_unit]
50
+
51
+
52
+ def convert_temperature(value, from_unit, to_unit):
53
+ """
54
+ Convert temperature between different units
55
+
56
+ Parameters
57
+ ----------
58
+ value : float
59
+ Temperature value to convert
60
+ from_unit : str
61
+ Original unit ('k', 'c', 'f')
62
+ to_unit : str
63
+ Target unit ('k', 'c', 'f')
64
+
65
+ Returns
66
+ -------
67
+ float
68
+ Converted temperature value
69
+ """
70
+ from_unit = from_unit.lower()
71
+ to_unit = to_unit.lower()
72
+
73
+ # Convert to Kelvin first
74
+ if from_unit == 'k':
75
+ kelvin = value
76
+ elif from_unit == 'c':
77
+ kelvin = value + 273.15
78
+ elif from_unit == 'f':
79
+ kelvin = (value - 32) * 5/9 + 273.15
80
+ else:
81
+ raise ValueError(f"Unsupported temperature unit: {from_unit}")
82
+
83
+ # Convert from Kelvin to target unit
84
+ if to_unit == 'k':
85
+ return kelvin
86
+ elif to_unit == 'c':
87
+ return kelvin - 273.15
88
+ elif to_unit == 'f':
89
+ return (kelvin - 273.15) * 9/5 + 32
90
+ else:
91
+ raise ValueError(f"Unsupported temperature unit: {to_unit}")
92
+
93
+
94
+ def compressibility_factor(pressure, volume, temperature, moles):
95
+ """
96
+ Calculate the compressibility factor Z = PV/nRT
97
+
98
+ Parameters
99
+ ----------
100
+ pressure : float
101
+ Pressure in Pascal
102
+ volume : float
103
+ Volume in cubic meters
104
+ temperature : float
105
+ Temperature in Kelvin
106
+ moles : float
107
+ Number of moles
108
+
109
+ Returns
110
+ -------
111
+ float
112
+ Compressibility factor (dimensionless)
113
+ """
114
+ return pressure * volume / (moles * R * temperature)
115
+
116
+ def derivative(f, x, dx=1e-6):
117
+ """Compute the derivative of f at x using finite differences"""
118
+ return (f(x + dx) - f(x - dx)) / (2 * dx)
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.4
2
+ Name: peritheos
3
+ Version: 0.1.0
4
+ Summary: A library for thermodynamic equations of state calculations
5
+ Author-email: Clemens Prescher <clemens.prescher@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/cprescher/peritheos
8
+ Project-URL: Bug Tracker, https://github.com/cprescher/peritheos/issues
9
+ Keywords: equation-of-state,high-pressure,thermodynamics
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Topic :: Scientific/Engineering :: Physics
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: numpy>=1.20.0
25
+ Requires-Dist: scipy>=1.7.0
26
+ Dynamic: license-file
27
+
28
+ # Peritheos
29
+
30
+ A Python library for thermodynamic equations of state calculations for solid materials.
31
+
32
+ ## Features
33
+
34
+ - Room temperature equations of state (EOS) implementations
35
+ - Birch-Murnaghan
36
+ - Vinet
37
+ - Holzapfel
38
+ - Thermal equations of state (EOS) implementations
39
+ - Sokolova 2016
40
+
41
+ ## Unit conventions
42
+
43
+ - Public pressure and bulk-modulus values are in GPa.
44
+ - Temperatures are in K.
45
+ - Birch-Murnaghan and Vinet accept any consistent volume unit.
46
+ - Holzapfel and Sokolova 2016 require molar volume in J bar^-1, which is
47
+ equivalent to cm^3/mol divided by 10.
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install peritheos
53
+ ```
54
+
55
+ The latest development version can instead be installed directly from GitHub:
56
+
57
+ ```bash
58
+ pip install git+https://github.com/CPrescher/peritheos.git
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ### Room-temperature equations of state
64
+
65
+ Third-order Birch-Murnaghan equation of state:
66
+
67
+ ```python
68
+ from peritheos.eos.rt import BM3
69
+
70
+ # V0 may use any volume unit for a room-temperature EOS; K0 is in GPa here.
71
+ eos = BM3(V0=50, K0=130, K0_prime=4.3)
72
+
73
+ # Calculate pressure and bulk modulus at a given volume.
74
+ pressure = eos.pressure(V=40)
75
+ bulk_modulus = eos.bulk_modulus(V=40)
76
+
77
+ # Invert the EOS to calculate volume at a given pressure.
78
+ volume = eos.volume(P=pressure)
79
+
80
+ print(f"Pressure: {pressure} GPa")
81
+ print(f"Bulk modulus: {bulk_modulus} GPa")
82
+ print(f"Recovered volume: {volume}")
83
+ ```
84
+
85
+ ### Thermal equations of state
86
+
87
+ Diamond thermal equation of state from sokolova et al. 2016
88
+
89
+ ```python
90
+ from peritheos.eos.rt.holzapfel import Holzapfel
91
+ from peritheos.eos.thermal.sokolova2016 import Sokolova2016
92
+
93
+ # Diamond parameters from Sokolova et al. 2016.
94
+ # The thermal model requires molar volume in J bar^-1 (= [cm^3/mol] / 10),
95
+ # pressure parameters in GPa, and temperatures in K.
96
+ V0 = 0.3414
97
+ K0 = 441.5
98
+ K0_prime = 3.9 # pressure derivative of bulk modulus at reference volume
99
+ QE1o = 684 # first Einstein characteristic temperature
100
+ mE1 = 0.564 # first Einstein number
101
+ QE2o = 1561 # second Einstein characteristic temperature
102
+ mE2 = 2.436 # second Einstein number
103
+ delta = -0.506 # additive normalizing constant for the Gruneisen parameter
104
+ t = 1.085 # generalized Gruneisen parameter
105
+ a_0 = 0 # intrinsic anharmonicity parameter
106
+ m = 0 # anharmonic analogue of the Grüneisen parameter
107
+ e_0 = 0 # free electrons parameter
108
+ g = 0 # electronic analogue of the Grüneisen parameter
109
+
110
+ n = 1 # number of atoms in the formula unit
111
+ z = 6 # atomic number of the formula unit
112
+ Tr = 298.15 # in K - Reference temperature
113
+
114
+ # Initialize the Holzapfel EOS
115
+ holzapfel = Holzapfel(V0=V0, K0=K0, K0_prime=K0_prime, n=n, Z=z)
116
+
117
+ # Initialize the Sokolova 2016 EOS
118
+ sokolova = Sokolova2016(
119
+ rt_eos=holzapfel,
120
+ Tr=Tr,
121
+ QE1o=QE1o,
122
+ mE1=mE1,
123
+ QE2o=QE2o,
124
+ mE2=mE2,
125
+ delta=delta,
126
+ t=t,
127
+ a_0=a_0,
128
+ m=m,
129
+ g=g,
130
+ e_0=e_0,
131
+ )
132
+
133
+ # Calculate the thermal pressure at a given volume and temperature
134
+ V = V0 * 0.8
135
+ T = 3000 # in K
136
+ thermal_pressure = sokolova.thermal_pressure(V, T)
137
+ rt_pressure = holzapfel.pressure(V)
138
+ pressure = sokolova.pressure(V, T)
139
+ recovered_volume = sokolova.volume(pressure, T)
140
+
141
+ print(f"Thermal pressure: {thermal_pressure} GPa")
142
+ print(f"RT pressure: {rt_pressure} GPa")
143
+ print(f"Total pressure: {pressure} GPa")
144
+ print(f"Recovered volume: {recovered_volume} J bar^-1")
145
+ ```
@@ -0,0 +1,17 @@
1
+ peritheos/__init__.py,sha256=X_pGbkp4m0S4wrg4Fb17KSaNdfPYW1Gp7_O5MbUZIaQ,87
2
+ peritheos/constants.py,sha256=FV9T191qCnmiS8COSYincjsZSFCWmiWpploiyFvKBPM,521
3
+ peritheos/utils.py,sha256=SL6KkLc5aEWi1QZABChgu0mVViW0qZEIuNF8eIjLRuw,2909
4
+ peritheos/eos/__init__.py,sha256=W9Ls4PyN5HE99oI0k6ERINUAkS4KEkWSxfQgjBHrfF4,8253
5
+ peritheos/eos/_reference/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ peritheos/eos/_reference/sokolova2016.py,sha256=OLuIzchEVW671q1ilC5OU-40e0Bp9SipEtkbuQDVJ_E,13618
7
+ peritheos/eos/rt/__init__.py,sha256=CMsI32S_9xeMbALTKNIVmIfMAoOv6IEKWiLxXTJjTgA,181
8
+ peritheos/eos/rt/bm.py,sha256=m7-b1377UlRZUtw9_HfrCs0FPhfMJh2b41OxmkTW998,9611
9
+ peritheos/eos/rt/holzapfel.py,sha256=BleJHqFyrsYcxYzLmbkc-Jicp5jeuD27FyJ-yAxDg4Q,6463
10
+ peritheos/eos/rt/vinet.py,sha256=m51cG3SNF-qA92bozfcOtkvq8dnhQ6oZnuPyfqD_xqQ,2700
11
+ peritheos/eos/thermal/__init__.py,sha256=A9UdhMQzNNuip6TL6BHzWSXVZ54TRqkGr8UC-1GfRqA,123
12
+ peritheos/eos/thermal/sokolova2016.py,sha256=EKlNA6qLeIaTx4qY3JYGBhGadLEt-oiDw6sfQJytVos,7697
13
+ peritheos-0.1.0.dist-info/licenses/LICENSE,sha256=Jv-O3-lgGTwh-_iFdgkgKJVlRumuV9pnYYbtxU9cV0A,1073
14
+ peritheos-0.1.0.dist-info/METADATA,sha256=wdZ-NQvkEndzKxGJHTxhvkrC11AmoVAVZsEDEhYNgO8,4381
15
+ peritheos-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
16
+ peritheos-0.1.0.dist-info/top_level.txt,sha256=CdcVZr-nDIv7L-66y4zgjJMVzcDBFY1vVY27afjB9E0,10
17
+ peritheos-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Clemens Prescher
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ peritheos