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.
- peritheos/__init__.py +3 -0
- peritheos/constants.py +22 -0
- peritheos/eos/__init__.py +234 -0
- peritheos/eos/_reference/__init__.py +0 -0
- peritheos/eos/_reference/sokolova2016.py +527 -0
- peritheos/eos/rt/__init__.py +7 -0
- peritheos/eos/rt/bm.py +281 -0
- peritheos/eos/rt/holzapfel.py +196 -0
- peritheos/eos/rt/vinet.py +86 -0
- peritheos/eos/thermal/__init__.py +5 -0
- peritheos/eos/thermal/sokolova2016.py +242 -0
- peritheos/utils.py +118 -0
- peritheos-0.1.0.dist-info/METADATA +145 -0
- peritheos-0.1.0.dist-info/RECORD +17 -0
- peritheos-0.1.0.dist-info/WHEEL +5 -0
- peritheos-0.1.0.dist-info/licenses/LICENSE +21 -0
- peritheos-0.1.0.dist-info/top_level.txt +1 -0
peritheos/eos/rt/bm.py
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Non-thermal equations of state module
|
|
3
|
+
|
|
4
|
+
This module implements various non-thermal equations of state commonly used in
|
|
5
|
+
high-pressure physics and materials science, including:
|
|
6
|
+
|
|
7
|
+
1. Birch-Murnaghan equation of state (2nd, 3rd, and 4th order)
|
|
8
|
+
2. Object-oriented implementation with a base class and specific EOS implementations
|
|
9
|
+
|
|
10
|
+
These equations describe the relationship between pressure and volume (or density)
|
|
11
|
+
at constant temperature, and are particularly useful for modeling the behavior of
|
|
12
|
+
solids under compression.
|
|
13
|
+
|
|
14
|
+
References:
|
|
15
|
+
-----------
|
|
16
|
+
1. Birch, F. (1947). Finite elastic strain of cubic crystals. Physical Review, 71(11), 809.
|
|
17
|
+
2. Birch, F. (1978). Finite strain isotherm and velocities for single-crystal and
|
|
18
|
+
polycrystalline NaCl at high pressures and 300 K. Journal of Geophysical Research,
|
|
19
|
+
83(B3), 1257-1268.
|
|
20
|
+
3. Anderson, O.L. (1995) Equations of State of Solids for Geophysics and Ceramic Science,
|
|
21
|
+
Oxford University Press, Oxford, UK.
|
|
22
|
+
4. Poirier, J.P., (2000), Introduction to the Physics of the Earth's
|
|
23
|
+
Interior, Cambridge University Press, Cambridge, UK.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from peritheos.eos import (
|
|
27
|
+
EosBase,
|
|
28
|
+
NumericType,
|
|
29
|
+
validate_finite_scalar,
|
|
30
|
+
validate_positive_scalar,
|
|
31
|
+
validate_volume,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class BM2(EosBase):
|
|
36
|
+
"""
|
|
37
|
+
2nd-order Birch-Murnaghan equation of state.
|
|
38
|
+
|
|
39
|
+
The 2nd-order Birch-Murnaghan EOS is defined as:
|
|
40
|
+
P(V) = (3/2) * K0 * [(V0/V)^(7/3) - (V0/V)^(5/3)]
|
|
41
|
+
|
|
42
|
+
or in terms of the Eulerian strain f = [(V0/V)^(2/3) - 1]/2:
|
|
43
|
+
P(V) = 3 * K0 * f * (1 + 2f)^(5/2)
|
|
44
|
+
|
|
45
|
+
Equations from:
|
|
46
|
+
Poirier, J.P., 2000, Introduction to the Physics of the Earth's
|
|
47
|
+
Interior, Cambridge University Press, Cambridge, UK.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, V0: float, K0: float) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Initialize the 2nd-order Birch-Murnaghan EOS.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
V0 : float
|
|
57
|
+
Reference volume (in cubic angstroms or any consistent unit)
|
|
58
|
+
K0 : float
|
|
59
|
+
Bulk modulus at reference volume (in GPa or any consistent unit)
|
|
60
|
+
"""
|
|
61
|
+
self.V0 = validate_positive_scalar(V0, "V0")
|
|
62
|
+
self.K0 = validate_positive_scalar(K0, "K0")
|
|
63
|
+
|
|
64
|
+
def pressure(self, V: NumericType) -> NumericType:
|
|
65
|
+
"""
|
|
66
|
+
Calculate pressure using the 2nd-order Birch-Murnaghan EOS.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
V : float or numpy.ndarray
|
|
71
|
+
Volume (in the same units as V0)
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
float or numpy.ndarray
|
|
76
|
+
Pressure (in the same units as K0)
|
|
77
|
+
"""
|
|
78
|
+
V = validate_volume(V)
|
|
79
|
+
f = ((self.V0 / V) ** (2 / 3) - 1) / 2
|
|
80
|
+
return 3 * self.K0 * f * (1 + 2 * f) ** (5 / 2)
|
|
81
|
+
|
|
82
|
+
def bulk_modulus(self, V: NumericType) -> NumericType:
|
|
83
|
+
"""
|
|
84
|
+
Return the bulk modulus at the given volume.
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
V : float or numpy.ndarray
|
|
89
|
+
Volume (in the same units as V0)
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
float or numpy.ndarray
|
|
94
|
+
Bulk modulus (in the same units as K0)
|
|
95
|
+
"""
|
|
96
|
+
V = validate_volume(V)
|
|
97
|
+
eta = ((self.V0 / V) ** (2 / 3) - 1) / 2
|
|
98
|
+
return self.K0 * (1 + 7 * eta) * (1 + 2 * eta) ** (5 / 2)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class BM3(EosBase):
|
|
102
|
+
"""
|
|
103
|
+
3rd-order Birch-Murnaghan equation of state.
|
|
104
|
+
|
|
105
|
+
The 3rd-order Birch-Murnaghan EOS is defined as:
|
|
106
|
+
P(V) = (3/2) * K0 * [(V0/V)^(7/3) - (V0/V)^(5/3)] *
|
|
107
|
+
{1 + (3/4) * (K0' - 4) * [(V0/V)^(2/3) - 1]}
|
|
108
|
+
|
|
109
|
+
or in terms of the Eulerian strain f = [(V0/V)^(2/3) - 1]/2:
|
|
110
|
+
P(V) = 3 * K0 * f * (1 + 2f)^(5/2) * [1 + (3/2) * (K0' - 4) * f]
|
|
111
|
+
|
|
112
|
+
Equations from:
|
|
113
|
+
Anderson, O.L., (1995) Equations of State of Solids for Geophysics and Ceramic Science,
|
|
114
|
+
Oxford University Press, Oxford, UK.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def __init__(self, V0: float, K0: float, K0_prime: float) -> None:
|
|
118
|
+
"""
|
|
119
|
+
Initialize the 3rd-order Birch-Murnaghan EOS.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
V0 : float
|
|
124
|
+
Reference volume (in cubic angstroms or any consistent unit)
|
|
125
|
+
K0 : float
|
|
126
|
+
Bulk modulus at reference volume (in GPa or any consistent unit)
|
|
127
|
+
K0_prime : float
|
|
128
|
+
Pressure derivative of the bulk modulus at reference volume (dimensionless)
|
|
129
|
+
"""
|
|
130
|
+
self.V0 = validate_positive_scalar(V0, "V0")
|
|
131
|
+
self.K0 = validate_positive_scalar(K0, "K0")
|
|
132
|
+
self.K0_prime = validate_finite_scalar(K0_prime, "K0_prime")
|
|
133
|
+
|
|
134
|
+
def pressure(self, V: NumericType) -> NumericType:
|
|
135
|
+
"""
|
|
136
|
+
Calculate pressure using the 3rd-order Birch-Murnaghan EOS.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
V : float or numpy.ndarray
|
|
141
|
+
Volume (in the same units as V0)
|
|
142
|
+
|
|
143
|
+
Returns
|
|
144
|
+
-------
|
|
145
|
+
float or numpy.ndarray
|
|
146
|
+
Pressure (in the same units as K0)
|
|
147
|
+
"""
|
|
148
|
+
V = validate_volume(V)
|
|
149
|
+
f = ((self.V0 / V) ** (2 / 3) - 1) / 2
|
|
150
|
+
return (
|
|
151
|
+
3
|
|
152
|
+
* self.K0
|
|
153
|
+
* f
|
|
154
|
+
* (1 + 2 * f) ** (5 / 2)
|
|
155
|
+
* (1 + (3 / 2) * (self.K0_prime - 4) * f)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def bulk_modulus(self, V: NumericType) -> NumericType:
|
|
159
|
+
"""
|
|
160
|
+
Calculate the bulk modulus at the given volume.
|
|
161
|
+
|
|
162
|
+
For the 3rd-order Birch-Murnaghan EOS, the bulk modulus at V0 is:
|
|
163
|
+
K(V) = K0 * (1 + 2f)^(5/2) * [K0 + (3K0*K0'-5K0)f + 27/2(K0*K0'-4K0)f^2]
|
|
164
|
+
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
V : float or numpy.ndarray
|
|
168
|
+
Volume (in the same units as V0)
|
|
169
|
+
|
|
170
|
+
Returns
|
|
171
|
+
-------
|
|
172
|
+
float or numpy.ndarray
|
|
173
|
+
Bulk modulus (in the same units as K0)
|
|
174
|
+
"""
|
|
175
|
+
V = validate_volume(V)
|
|
176
|
+
f = ((self.V0 / V) ** (2 / 3) - 1) / 2
|
|
177
|
+
return (1.0 + 2.0 * f) ** (5.0 / 2.0) * (
|
|
178
|
+
self.K0
|
|
179
|
+
+ (3.0 * self.K0 * self.K0_prime - 5 * self.K0) * f
|
|
180
|
+
+ 27.0 / 2.0 * (self.K0 * self.K0_prime - 4.0 * self.K0) * f * f
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
class BM4(EosBase):
|
|
184
|
+
"""
|
|
185
|
+
4th-order Birch-Murnaghan equation of state.
|
|
186
|
+
|
|
187
|
+
The 4th-order Birch-Murnaghan EOS is defined as:
|
|
188
|
+
P(V) = (3/2) * K0 * [(V0/V)^(-7/3) - (V0/V)^(-5/3)] *
|
|
189
|
+
{ 1 + (3/4) * (K0'- 4) * ((V0/V)^(-2/3) - 1) + (3/8) * [K0 * K0'' + (K0'- 4) * (K0' - 3) + (35/9)] * ((V0/V)^(-2/3) - 1)
|
|
190
|
+
|
|
191
|
+
or in terms of the Eulerian strain f = [(V0/V)^(2/3) - 1]/2, zeta = (3/4) * (4 - K0'), and xi = (3/8) * [K0 * K0'' + (K0'- 4) * (K0' - 3) + (35/9)]:
|
|
192
|
+
P(f) = 3 * K0 *f * (1 + 2f)^(5/2) * [1 + 2 * zeta * f + 4 * xi * f ** 2]
|
|
193
|
+
|
|
194
|
+
Equations from:
|
|
195
|
+
Anderson, O.L., (1995) Equations of State of Solids for Geophysics and Ceramic Science,
|
|
196
|
+
Oxford University Press, Oxford, UK.
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
def __init__(self, V0: float, K0: float, K0_prime: float, K0_double_prime: float) -> None:
|
|
200
|
+
"""
|
|
201
|
+
Initialize the 4th-order Birch-Murnaghan EOS.
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
V0 : float
|
|
206
|
+
Reference volume (in cubic angstroms or any consistent unit)
|
|
207
|
+
K0 : float
|
|
208
|
+
Bulk modulus at reference volume (in GPa or any consistent unit)
|
|
209
|
+
K0_prime : float
|
|
210
|
+
Pressure derivative of the bulk modulus at reference volume (dimensionless)
|
|
211
|
+
K0_double_prime : float
|
|
212
|
+
Second pressure derivative of the bulk modulus at reference volume
|
|
213
|
+
(inverse pressure, e.g. GPa^-1 when K0 is in GPa)
|
|
214
|
+
"""
|
|
215
|
+
self.V0 = validate_positive_scalar(V0, "V0")
|
|
216
|
+
self.K0 = validate_positive_scalar(K0, "K0")
|
|
217
|
+
self.K0_prime = validate_finite_scalar(K0_prime, "K0_prime")
|
|
218
|
+
self.K0_double_prime = validate_finite_scalar(
|
|
219
|
+
K0_double_prime, "K0_double_prime"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
def pressure(self, V: NumericType) -> NumericType:
|
|
223
|
+
"""
|
|
224
|
+
Calculate pressure using the 4th-order Birch-Murnaghan EOS.
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
V : float or numpy.ndarray
|
|
229
|
+
Volume (in the same units as V0)
|
|
230
|
+
|
|
231
|
+
Returns
|
|
232
|
+
-------
|
|
233
|
+
float or numpy.ndarray
|
|
234
|
+
Pressure (in the same units as K0)
|
|
235
|
+
"""
|
|
236
|
+
V = validate_volume(V)
|
|
237
|
+
f = ((self.V0/V) ** (2 / 3) - 1) / 2
|
|
238
|
+
zeta = (3 / 4) * (4 - self.K0_prime)
|
|
239
|
+
xi = (3 / 8) * (self.K0 * self.K0_double_prime + (self.K0_prime - 4) * (self.K0_prime - 3) + (35 / 9))
|
|
240
|
+
return (
|
|
241
|
+
3
|
|
242
|
+
* self.K0
|
|
243
|
+
* f
|
|
244
|
+
* (1 + 2 * f) ** (5/2)
|
|
245
|
+
* (1 - 2 * zeta * f + 4 * xi * f ** 2)
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def bulk_modulus(self, V: NumericType) -> NumericType:
|
|
249
|
+
"""
|
|
250
|
+
Calculate the bulk modulus at the given volume.
|
|
251
|
+
|
|
252
|
+
For the 4th-order Birch-Murnaghan EOS, the bulk modulus at V0 with f = f = ((V0/V) ** (2 / 3) - 1) / 2
|
|
253
|
+
zeta = (3 / 4) * (4 - K0_prime)
|
|
254
|
+
xi = (3 / 8) * [K0 * K0_double_prime + (K0_prime - 4) * (K0_prime - 3) + (35 / 9)]
|
|
255
|
+
K(f) = 5 * self.K0 * (1 + 2 * f) ** (5 / 2) * (1 - 2 * zeta * f + 4 * xi * f ** 2) + self.K0 * (1 + 2 * f) ** (7 / 2)
|
|
256
|
+
* (1 - 4 * zeta * f + 12 * xi * f ** 2)
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
V : float or numpy.ndarray
|
|
261
|
+
Volume (in the same units as V0)
|
|
262
|
+
|
|
263
|
+
Returns
|
|
264
|
+
-------
|
|
265
|
+
float or numpy.ndarray
|
|
266
|
+
Bulk modulus (in the same units as K0)
|
|
267
|
+
"""
|
|
268
|
+
V = validate_volume(V)
|
|
269
|
+
f = ((self.V0/V) ** (2 / 3) - 1) / 2
|
|
270
|
+
zeta = (3 / 4) * (4 - self.K0_prime)
|
|
271
|
+
xi = (3 / 8) * (self.K0 * self.K0_double_prime + (self.K0_prime - 4) * (self.K0_prime - 3) + (35 / 9))
|
|
272
|
+
return (
|
|
273
|
+
5
|
|
274
|
+
* f
|
|
275
|
+
* self.K0
|
|
276
|
+
* (1 + 2 * f) ** (5 / 2)
|
|
277
|
+
* (1 - 2 * zeta * f + 4 * xi * f ** 2)
|
|
278
|
+
+ self.K0
|
|
279
|
+
* (1 + 2 * f) ** (7 / 2)
|
|
280
|
+
* (1 - 4 * zeta * f + 12 * xi * f ** 2)
|
|
281
|
+
)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from peritheos.eos import (
|
|
3
|
+
EosBase,
|
|
4
|
+
NumericType,
|
|
5
|
+
validate_finite_scalar,
|
|
6
|
+
validate_positive_scalar,
|
|
7
|
+
validate_volume,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Holzapfel(EosBase):
|
|
12
|
+
"""
|
|
13
|
+
Holzapfel equation of state. Introduced in Holzapfel et al. 2001. And here implemented as described in
|
|
14
|
+
Sokolova et al. 2016.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, V0: float, K0: float, K0_prime: float, n: float, Z: int) -> None:
|
|
18
|
+
"""
|
|
19
|
+
Initialize the Holzapfel equation of state.
|
|
20
|
+
|
|
21
|
+
**Note:**
|
|
22
|
+
Contrary to other EOS implementations, the reference values need to be provided in the correct units.
|
|
23
|
+
For consistency with the equation of states, the pressure unit is GPa - contrary to excel spreadsheets from
|
|
24
|
+
Sokolova et al. 2016 where the bulk modulus is given in kbar.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
V0 : float
|
|
29
|
+
Reference volume [JBar^-1] (same as [cm^3/mol]/10)
|
|
30
|
+
K0 : float
|
|
31
|
+
Bulk modulus at reference volume in [GPa]
|
|
32
|
+
K0_prime : float
|
|
33
|
+
Pressure derivative of bulk modulus at reference volume
|
|
34
|
+
n : float
|
|
35
|
+
Number of atoms in a chemical formula
|
|
36
|
+
Z : int
|
|
37
|
+
Atomic number of the forumala unit
|
|
38
|
+
"""
|
|
39
|
+
super().__init__()
|
|
40
|
+
self.V0 = validate_positive_scalar(V0, "V0")
|
|
41
|
+
self.K0 = validate_positive_scalar(K0, "K0")
|
|
42
|
+
self.K0_prime = validate_finite_scalar(K0_prime, "K0_prime")
|
|
43
|
+
self.n = validate_positive_scalar(n, "n")
|
|
44
|
+
self.Z = validate_positive_scalar(Z, "Z")
|
|
45
|
+
|
|
46
|
+
self._P_FG0 = 1003.6 * (self.Z * self.n / (self.V0 * 10)) ** (5 / 3)
|
|
47
|
+
self._c0 = -np.log(3 * self.K0 / self._P_FG0)
|
|
48
|
+
self._c2 = 1.5 * (self.K0_prime - 3) - self._c0
|
|
49
|
+
|
|
50
|
+
def pressure(self, V: NumericType) -> NumericType:
|
|
51
|
+
"""
|
|
52
|
+
Calculate pressure using the Holzapfel equation of state.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
V : float or np.ndarray
|
|
57
|
+
Volume in [JBar^-1] (same as [cm^3/mol]/10)
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
float or np.ndarray
|
|
62
|
+
Pressure in [GPa]
|
|
63
|
+
"""
|
|
64
|
+
V = validate_volume(V)
|
|
65
|
+
x = (V / self.V0) ** (1 / 3)
|
|
66
|
+
return (
|
|
67
|
+
3
|
|
68
|
+
* self.K0
|
|
69
|
+
* np.exp(self._c0 * (1 - x))
|
|
70
|
+
* (1 / x**5 - 1 / x**4)
|
|
71
|
+
* (1 + self._c2 * x - self._c2 * x**2)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def bulk_modulus(self, V: NumericType) -> NumericType:
|
|
75
|
+
"""
|
|
76
|
+
Calculate bulk modulus using the Holzapfel equation of state.
|
|
77
|
+
|
|
78
|
+
Parameters
|
|
79
|
+
----------
|
|
80
|
+
V : float or np.ndarray
|
|
81
|
+
Volume in [JBar^-1] (same as [cm^3/mol]/10)
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
float or np.ndarray
|
|
86
|
+
Bulk modulus in [GPa]
|
|
87
|
+
"""
|
|
88
|
+
V = validate_volume(V)
|
|
89
|
+
x = (V / self.V0) ** (1 / 3)
|
|
90
|
+
term1 = self.K0 * x**-5 * np.exp(self._c0 * (1 - x))
|
|
91
|
+
|
|
92
|
+
bracket_1 = (5 - 4 * x) * (1 + self._c2 * x * (1 - x))
|
|
93
|
+
bracket_2 = self._c0 * x * (1 - x) * (1 + self._c2 * x * (1 - x))
|
|
94
|
+
bracket_3 = -(1 - x) * (self._c2 * x - 2 * self._c2 * x**2)
|
|
95
|
+
term2 = bracket_1 + bracket_2 + bracket_3
|
|
96
|
+
return term1 * term2
|
|
97
|
+
|
|
98
|
+
def bulk_modulus_derivative(self, V: NumericType, eps: float = 1e-6) -> NumericType:
|
|
99
|
+
"""
|
|
100
|
+
Compute the pressure derivative of the bulk modulus using a
|
|
101
|
+
numerical approximation.
|
|
102
|
+
|
|
103
|
+
This method provides a faster alternative to the analytical approach implemented in
|
|
104
|
+
`bulk_modulus_derivative_analytical`, which is more than twice as slow. The numerical
|
|
105
|
+
derivative is computed using a small relative perturbation in volume with a step size of `eps`.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
V : float or np.ndarray
|
|
110
|
+
Volume in [JBar^-1] (same as [cm^3/mol]/10)
|
|
111
|
+
eps : float
|
|
112
|
+
Step size for the numerical derivative, default is 1e-6. This value is used as the
|
|
113
|
+
relative difference between the two perturbed volumes. The accuracy of the numerical
|
|
114
|
+
derivative is approximately `eps * 100%`.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
float or np.ndarray
|
|
119
|
+
Pressure derivative of bulk modulus (unitless)
|
|
120
|
+
"""
|
|
121
|
+
V = validate_volume(V)
|
|
122
|
+
eps = validate_positive_scalar(eps, "eps")
|
|
123
|
+
if eps >= 1:
|
|
124
|
+
raise ValueError("eps must be smaller than one")
|
|
125
|
+
V = np.array([V * (1 + eps), V * (1 - eps)])
|
|
126
|
+
P = self.pressure(V)
|
|
127
|
+
K = self.bulk_modulus(V)
|
|
128
|
+
return (K[0] - K[1]) / (P[0] - P[1])
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def bulk_modulus_derivative_analytical(V0, V, KT, K0, c0, c2):
|
|
132
|
+
"""
|
|
133
|
+
Calculate the pressure derivative of bulk modulus using the Holzapfel equation of state.
|
|
134
|
+
Equation have been taken from excel sheets provided in Sokolova et al. 2016. The listed equation (5) on page
|
|
135
|
+
163 in this paper seems to be incorrect.
|
|
136
|
+
Values have been verified against the excel sheets provided by Sokolova et al. 2016 and the numerical
|
|
137
|
+
derivative (see test_holzapfel.py).
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
V : float or np.ndarray
|
|
142
|
+
Volume in [JBar^-1] (same as [cm^3/mol]/10)
|
|
143
|
+
KT : float or np.ndarray
|
|
144
|
+
Bulk modulus in [kbar]
|
|
145
|
+
K0 : float
|
|
146
|
+
Bulk modulus at reference volume in [kbar]
|
|
147
|
+
c0 : float
|
|
148
|
+
Constant in the Holzapfel equation of state
|
|
149
|
+
c2 : float
|
|
150
|
+
Constant in the Holzapfel equation of state
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
"""
|
|
154
|
+
x = (V / V0) ** (1 / 3)
|
|
155
|
+
|
|
156
|
+
# convert moduli from GPa to bar
|
|
157
|
+
K0 = K0 * 10000
|
|
158
|
+
KT = KT * 10000
|
|
159
|
+
|
|
160
|
+
term1 = (
|
|
161
|
+
3
|
|
162
|
+
/ x**4
|
|
163
|
+
* K0
|
|
164
|
+
* np.exp(c0 * (1 - x))
|
|
165
|
+
* (
|
|
166
|
+
(-5 / x**2 + 4 / x) * (1 + c2 * x - c2 * x**2)
|
|
167
|
+
- (1 / x - 1) * (1 + c2 * x - c2 * x**2) * c0
|
|
168
|
+
+ (1 / x - 1) * (c2 - 2 * c2 * x)
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
term2 = (
|
|
172
|
+
1
|
|
173
|
+
/ x**3
|
|
174
|
+
* K0
|
|
175
|
+
* np.exp(c0 * (1 - x))
|
|
176
|
+
* c0
|
|
177
|
+
* (
|
|
178
|
+
(-5 / x**2 + 4 / x) * (1 + c2 * x - c2 * x**2)
|
|
179
|
+
- (1 / x - 1) * (1 + c2 * x - c2 * x**2) * c0
|
|
180
|
+
+ (1 / x - 1) * (c2 - 2 * c2 * x)
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
term3 = (
|
|
184
|
+
K0
|
|
185
|
+
* np.exp(c0 * (1 - x))
|
|
186
|
+
* (
|
|
187
|
+
(10 / x**3 - 4 / x**2) * (1 + c2 * x - c2 * x**2)
|
|
188
|
+
+ (-5 / x**2 + 4 / x) * (c2 - 2 * c2 * x)
|
|
189
|
+
+ c0 / x**2 * (1 + c2 * x - c2 * x**2)
|
|
190
|
+
- (1 / x - 1) * (c2 - 2 * c2 * x) * c0
|
|
191
|
+
- (c2 - 2 * c2 * x) / x**2
|
|
192
|
+
- 2 * c2 * (1 / x - 1)
|
|
193
|
+
)
|
|
194
|
+
/ x**3
|
|
195
|
+
)
|
|
196
|
+
return (term1 + term2 - term3) / (-KT / x) / 3
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Vinet equation of state
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from peritheos.eos import (
|
|
7
|
+
EosBase,
|
|
8
|
+
NumericType,
|
|
9
|
+
validate_finite_scalar,
|
|
10
|
+
validate_positive_scalar,
|
|
11
|
+
validate_volume,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Vinet(EosBase):
|
|
16
|
+
"""
|
|
17
|
+
Vinet equation of state. It has been presented multiple times in the literature. But has been
|
|
18
|
+
attributed finally to Vinet 1986, 1987. An earlier description can be found in the work of
|
|
19
|
+
Stacey et al. 1981. The Vinet EOS is based on a variant of the Morse potential, the Rydberg
|
|
20
|
+
potential which was introduced by Rydberg in 1932.
|
|
21
|
+
|
|
22
|
+
The Vinet EOS is defined as:
|
|
23
|
+
P(V) = 3 * K0 * (1 - f)/ f^2 * exp(3/2 * (K0_prime - 1) * (1 - f))
|
|
24
|
+
where f = (V / V0)^(1/3)
|
|
25
|
+
|
|
26
|
+
The bulk modulus is given by:
|
|
27
|
+
K(V) = K0 * f^(-2) * (1 + (eta * f + 1) * (1 - f) * exp(eta * (1 - f)))
|
|
28
|
+
where f = (V / V0)^(1/3)
|
|
29
|
+
and eta = 3/2 * (K0_prime - 1)
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, V0: float, K0: float, K0_prime: float) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Initialize the Vinet equation of state.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
V0 : float
|
|
39
|
+
Reference volume (in cubic angstroms or any consistent unit)
|
|
40
|
+
K0 : float
|
|
41
|
+
Bulk modulus at reference volume (in GPa or any consistent unit)
|
|
42
|
+
K0_prime : float
|
|
43
|
+
Pressure derivative of bulk modulus at reference volume
|
|
44
|
+
"""
|
|
45
|
+
self.V0 = validate_positive_scalar(V0, "V0")
|
|
46
|
+
self.K0 = validate_positive_scalar(K0, "K0")
|
|
47
|
+
self.K0_prime = validate_finite_scalar(K0_prime, "K0_prime")
|
|
48
|
+
|
|
49
|
+
def pressure(self, V: NumericType) -> NumericType:
|
|
50
|
+
"""
|
|
51
|
+
Calculate pressure using the Vinet equation of state.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
V : float or numpy.ndarray
|
|
56
|
+
Volume (in cubic angstroms or any consistent unit)
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
float or numpy.ndarray
|
|
61
|
+
Pressure (in the same units as K0)
|
|
62
|
+
"""
|
|
63
|
+
V = validate_volume(V)
|
|
64
|
+
f = (V / self.V0) ** (1 / 3)
|
|
65
|
+
return (
|
|
66
|
+
3 * self.K0 * (1 - f) / f**2 * np.exp(3 / 2 * (self.K0_prime - 1) * (1 - f))
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def bulk_modulus(self, V: NumericType) -> NumericType:
|
|
70
|
+
"""
|
|
71
|
+
Calculate the bulk modulus using the Vinet equation of state.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
V : float or numpy.ndarray
|
|
76
|
+
Volume (in cubic angstroms or any consistent unit)
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
float or numpy.ndarray
|
|
81
|
+
Bulk modulus (in the same units as K0)
|
|
82
|
+
"""
|
|
83
|
+
V = validate_volume(V)
|
|
84
|
+
f = (V / self.V0) ** (1 / 3)
|
|
85
|
+
eta = 3 / 2 * (self.K0_prime - 1)
|
|
86
|
+
return self.K0 * f**-2 * (1 + (eta * f + 1) * (1 - f)) * np.exp(eta * (1 - f))
|