peritheos 0.1.0__tar.gz → 0.2.0__tar.gz

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.
Files changed (28) hide show
  1. {peritheos-0.1.0 → peritheos-0.2.0}/PKG-INFO +2 -2
  2. {peritheos-0.1.0 → peritheos-0.2.0}/README.md +1 -1
  3. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/__init__.py +1 -1
  4. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/thermal/sokolova2016.py +82 -20
  5. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos.egg-info/PKG-INFO +2 -2
  6. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos.egg-info/SOURCES.txt +0 -2
  7. {peritheos-0.1.0 → peritheos-0.2.0}/tests/test_thermal_sokolova.py +98 -83
  8. peritheos-0.1.0/peritheos/eos/_reference/__init__.py +0 -0
  9. peritheos-0.1.0/peritheos/eos/_reference/sokolova2016.py +0 -527
  10. {peritheos-0.1.0 → peritheos-0.2.0}/LICENSE +0 -0
  11. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/constants.py +0 -0
  12. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/__init__.py +0 -0
  13. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/rt/__init__.py +0 -0
  14. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/rt/bm.py +0 -0
  15. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/rt/holzapfel.py +0 -0
  16. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/rt/vinet.py +0 -0
  17. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/eos/thermal/__init__.py +0 -0
  18. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos/utils.py +0 -0
  19. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos.egg-info/dependency_links.txt +0 -0
  20. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos.egg-info/requires.txt +0 -0
  21. {peritheos-0.1.0 → peritheos-0.2.0}/peritheos.egg-info/top_level.txt +0 -0
  22. {peritheos-0.1.0 → peritheos-0.2.0}/pyproject.toml +0 -0
  23. {peritheos-0.1.0 → peritheos-0.2.0}/setup.cfg +0 -0
  24. {peritheos-0.1.0 → peritheos-0.2.0}/tests/test_bm.py +0 -0
  25. {peritheos-0.1.0 → peritheos-0.2.0}/tests/test_eos_api.py +0 -0
  26. {peritheos-0.1.0 → peritheos-0.2.0}/tests/test_holzapfel.py +0 -0
  27. {peritheos-0.1.0 → peritheos-0.2.0}/tests/test_package_metadata.py +0 -0
  28. {peritheos-0.1.0 → peritheos-0.2.0}/tests/test_vinet.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: peritheos
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: A library for thermodynamic equations of state calculations
5
5
  Author-email: Clemens Prescher <clemens.prescher@gmail.com>
6
6
  License-Expression: MIT
@@ -36,7 +36,7 @@ A Python library for thermodynamic equations of state calculations for solid mat
36
36
  - Vinet
37
37
  - Holzapfel
38
38
  - Thermal equations of state (EOS) implementations
39
- - Sokolova 2016
39
+ - Sokolova 2016, including its complete thermal-pressure parameter set
40
40
 
41
41
  ## Unit conventions
42
42
 
@@ -9,7 +9,7 @@ A Python library for thermodynamic equations of state calculations for solid mat
9
9
  - Vinet
10
10
  - Holzapfel
11
11
  - Thermal equations of state (EOS) implementations
12
- - Sokolova 2016
12
+ - Sokolova 2016, including its complete thermal-pressure parameter set
13
13
 
14
14
  ## Unit conventions
15
15
 
@@ -1,3 +1,3 @@
1
1
  """Peritheos: thermodynamic equations of state calculations."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.2.0"
@@ -27,9 +27,20 @@ class Sokolova2016(ThermalEOS):
27
27
  m: float,
28
28
  g: float,
29
29
  e_0: float,
30
+ beta: float = 0.0,
31
+ QBo: float = 1.0,
32
+ d: float = 1.0,
33
+ mb: float = 0.0,
34
+ QB1o: float = 1.0,
35
+ d1: float = 1.0,
36
+ mb1: float = 0.0,
30
37
  ):
31
38
  """
32
- Original thermal pressure equation from sokolova et al. 2016.
39
+ Thermal pressure equation from Sokolova et al. (2016).
40
+
41
+ The optional ``beta`` and Bose-mode parameters reproduce the complete
42
+ pressure expression in the original calculation model. Their defaults
43
+ preserve the reduced form used by existing Peritheos releases.
33
44
 
34
45
  Parameters
35
46
  ----------
@@ -45,20 +56,28 @@ class Sokolova2016(ThermalEOS):
45
56
  Einstein characteristic temperature, Theta_02 in [K]
46
57
  mE2 : float
47
58
  The second Einstein number
48
- TK : float
49
- Temperature in [K]
50
59
  delta : float
51
60
  Additive normalizing constant for the Gruneisen parameter
52
61
  t : float
53
62
  Generalized Gruneisen parameter
54
63
  a_0 : float
55
- Intrinsic anharmonicity parameter (10e-6 [K])
64
+ Intrinsic anharmonicity parameter in 10^-6 K^-1
56
65
  m : float
57
66
  Anharmonic analogue of the Grüneisen parameter
58
67
  g : float
59
68
  Electronic analogue of the Grüneisen parameter
60
69
  e_0 : float
61
- Free electrons parameter (10e-6 [K])
70
+ Free-electron parameter in 10^-6 K^-1
71
+ beta : float
72
+ Volume-dependent correction to ``t``. The model uses
73
+ ``t - beta * (V/V0)^(1/3)``.
74
+ QBo, QB1o : float
75
+ Reference characteristic temperatures of the two generalized
76
+ Bose-Einstein modes in [K].
77
+ d, d1 : float
78
+ Positive dispersion parameters for the Bose-Einstein modes.
79
+ mb, mb1 : float
80
+ Non-negative multiplicities of the Bose-Einstein modes.
62
81
  """
63
82
  if not isinstance(rt_eos, Holzapfel):
64
83
  raise TypeError("Sokolova2016 requires a Holzapfel room-temperature EOS")
@@ -76,6 +95,15 @@ class Sokolova2016(ThermalEOS):
76
95
  self.m = validate_finite_scalar(m, "m")
77
96
  self.g = validate_finite_scalar(g, "g")
78
97
  self.e_0 = validate_finite_scalar(e_0, "e_0")
98
+ self.beta = validate_finite_scalar(beta, "beta")
99
+ self.QBo = validate_positive_scalar(QBo, "QBo")
100
+ self.d = validate_positive_scalar(d, "d")
101
+ self.mb = validate_finite_scalar(mb, "mb")
102
+ self.QB1o = validate_positive_scalar(QB1o, "QB1o")
103
+ self.d1 = validate_positive_scalar(d1, "d1")
104
+ self.mb1 = validate_finite_scalar(mb1, "mb1")
105
+ if self.mb < 0 or self.mb1 < 0:
106
+ raise ValueError("Bose-Einstein multiplicities must not be negative")
79
107
 
80
108
  def thermal_pressure(self, V: NumericType, T: NumericType) -> NumericType:
81
109
  """
@@ -107,27 +135,35 @@ class Sokolova2016(ThermalEOS):
107
135
  KT = self.rt_eos.bulk_modulus(V)
108
136
  kkx = self.rt_eos.bulk_modulus_derivative(V)
109
137
 
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
138
+ # Equation (10), following the original calculation model.
139
+ generalized_t = self.t - self.beta * np.cbrt(x)
140
+ gamV = (
141
+ -3 * KT + 2 * Px * generalized_t + 9 * KT * kkx - 6 * generalized_t * KT
142
+ ) / 6 / (
143
+ 3 * KT - 2 * Px * generalized_t
113
144
  ) + self.delta
114
145
 
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))
146
+ # Exponent in equation (9), obtained by integrating gamma(V) / V.
147
+ expp = np.exp(I_gamV(x, self.delta, self.t, self.rt_eos, self.beta))
120
148
 
121
149
  # Equation (9)
150
+ QB = self.QBo * expp
151
+ QB1 = self.QB1o * expp
122
152
  QE1 = self.QE1o * expp
123
153
  QE2 = self.QE2o * expp
124
154
 
125
155
  # Equation (12) for the different Einstein contributions at the temperature TK
156
+ PB = self.mb * R * (_bose_energy(QB, T, self.d) * gamV / V)
157
+ PB1 = self.mb1 * R * (_bose_energy(QB1, T, self.d1) * gamV / V)
126
158
  PE1 = self.mE1 * R * (_einstein_energy(QE1, T) * gamV / V)
127
159
 
128
160
  PE2 = self.mE2 * R * (_einstein_energy(QE2, T) * gamV / V)
129
161
 
130
162
  # Equation (12) for the different Einstein contributions at the reference temperature
163
+ PBr = self.mb * R * (_bose_energy(QB, self.Tr, self.d) * gamV / V)
164
+ PB1r = self.mb1 * R * (
165
+ _bose_energy(QB1, self.Tr, self.d1) * gamV / V
166
+ )
131
167
  PE1r = self.mE1 * R * (_einstein_energy(QE1, self.Tr) * gamV / V)
132
168
 
133
169
  PE2r = self.mE2 * R * (_einstein_energy(QE2, self.Tr) * gamV / V)
@@ -159,7 +195,7 @@ class Sokolova2016(ThermalEOS):
159
195
  )
160
196
 
161
197
  # 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
198
+ Pth_bar = PB + PB1 + PE1 + PE2 - PBr - PB1r - PE1r - PE2r + Pee + Pea
163
199
  Pth_gpa = Pth_bar / 10000
164
200
  if Pth_gpa.ndim == 0:
165
201
  return float(Pth_gpa)
@@ -174,7 +210,23 @@ def _einstein_energy(theta, temperature):
174
210
  return theta / 2 + thermal_part
175
211
 
176
212
 
177
- def I_gamV(x, delta, t, rt_eos):
213
+ def _bose_energy(theta, temperature, dispersion):
214
+ """Return generalized Bose-mode energy in kelvin without overflow."""
215
+ exponent = dispersion * np.log1p(theta / (temperature * dispersion))
216
+ decay = np.exp(-exponent)
217
+ occupation = decay / (-np.expm1(-exponent))
218
+ zero_point = theta * (dispersion - 1) / (2 * dispersion)
219
+ thermal_part = (
220
+ temperature
221
+ * theta
222
+ * dispersion
223
+ * occupation
224
+ / (temperature * dispersion + theta)
225
+ )
226
+ return zero_point + thermal_part
227
+
228
+
229
+ def I_gamV(x, delta, t, rt_eos, beta=0.0):
178
230
  """
179
231
  Integral of the Gruneisen parameter over the volume ratio (from x to 1).
180
232
 
@@ -188,6 +240,8 @@ def I_gamV(x, delta, t, rt_eos):
188
240
  Generalized Gruneisen parameter
189
241
  rt_eos : RT_EOS
190
242
  room temperature equation of state object used for the calculation
243
+ beta : float
244
+ Volume-dependent correction to ``t``
191
245
 
192
246
  Returns
193
247
  -------
@@ -201,7 +255,7 @@ def I_gamV(x, delta, t, rt_eos):
201
255
  Px_x = rt_eos.pressure(x * V0)
202
256
  KT_x = rt_eos.bulk_modulus(x * V0)
203
257
  kkx_x = rt_eos.bulk_modulus_derivative(x * V0)
204
- return f_gamV(x, Px_x, KT_x, kkx_x, delta, t)
258
+ return f_gamV(x, Px_x, KT_x, kkx_x, delta, t, beta)
205
259
 
206
260
  x_values = np.asarray(x, dtype=float)
207
261
  if not np.all(np.isfinite(x_values)) or np.any(x_values <= 0):
@@ -214,7 +268,7 @@ def I_gamV(x, delta, t, rt_eos):
214
268
  return integrals
215
269
 
216
270
 
217
- def f_gamV(x, Px, KT, kkx, delta, t):
271
+ def f_gamV(x, Px, KT, kkx, delta, t, beta=0.0):
218
272
  """
219
273
  Helper function to calculate the Gruneisen parameter at a given temperature and pressure.
220
274
 
@@ -230,13 +284,21 @@ def f_gamV(x, Px, KT, kkx, delta, t):
230
284
  Bulk modulus derivative at temperature
231
285
  delta: float
232
286
  Additive normalizing constant for the Gruneisen parameter
233
- gb: float
287
+ t: float
234
288
  Generalized Gruneisen parameter
289
+ beta: float
290
+ Volume-dependent correction to ``t``
235
291
  """
292
+ generalized_t = t - beta * np.cbrt(x)
236
293
  f_gamV_value = (
237
294
  delta
238
- + (-3 * KT + 2 * Px * t + 9 * KT * kkx - 6 * t * KT)
239
- / (6 * (3 * KT - 2 * Px * t))
295
+ + (
296
+ -3 * KT
297
+ + 2 * Px * generalized_t
298
+ + 9 * KT * kkx
299
+ - 6 * generalized_t * KT
300
+ )
301
+ / (6 * (3 * KT - 2 * Px * generalized_t))
240
302
  ) / x
241
303
 
242
304
  return f_gamV_value
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: peritheos
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: A library for thermodynamic equations of state calculations
5
5
  Author-email: Clemens Prescher <clemens.prescher@gmail.com>
6
6
  License-Expression: MIT
@@ -36,7 +36,7 @@ A Python library for thermodynamic equations of state calculations for solid mat
36
36
  - Vinet
37
37
  - Holzapfel
38
38
  - Thermal equations of state (EOS) implementations
39
- - Sokolova 2016
39
+ - Sokolova 2016, including its complete thermal-pressure parameter set
40
40
 
41
41
  ## Unit conventions
42
42
 
@@ -10,8 +10,6 @@ peritheos.egg-info/dependency_links.txt
10
10
  peritheos.egg-info/requires.txt
11
11
  peritheos.egg-info/top_level.txt
12
12
  peritheos/eos/__init__.py
13
- peritheos/eos/_reference/__init__.py
14
- peritheos/eos/_reference/sokolova2016.py
15
13
  peritheos/eos/rt/__init__.py
16
14
  peritheos/eos/rt/bm.py
17
15
  peritheos/eos/rt/holzapfel.py
@@ -5,7 +5,6 @@ from peritheos.eos.thermal.sokolova2016 import (
5
5
  I_gamV,
6
6
  )
7
7
 
8
- import peritheos.eos._reference.sokolova2016 as sokolova2016_original
9
8
  from peritheos.eos.rt.holzapfel import Holzapfel
10
9
  from peritheos.eos.thermal.sokolova2016 import Sokolova2016
11
10
 
@@ -36,80 +35,15 @@ T = 3000 # in K
36
35
  x = V / V0
37
36
 
38
37
 
39
- def test_original_thermal_pressure_calculation():
40
- expp = 1.09427641040855
41
- Pth = sokolova2016_original.P_thermal(
42
- n,
43
- z,
44
- V0,
45
- K0_kbar,
46
- K0_prime,
47
- Tr,
48
- x,
49
- expp,
50
- V,
51
- 1,
52
- 1,
53
- 0,
54
- 1,
55
- 1,
56
- 0,
57
- Theta_1,
58
- m1,
59
- Theta_2,
60
- m2,
61
- T,
62
- delta,
63
- 0,
64
- t,
65
- a_0,
66
- m,
67
- g,
68
- e_0,
69
- )
70
- assert np.isclose(Pth, 148604.90047369, rtol=1e-4)
71
-
72
-
73
- def test_compare_original_with_modified_thermal_pressure_calculation():
74
- # original implementation
75
- expp = 1.09427641040855
76
- P1 = sokolova2016_original.P_thermal(
77
- n,
78
- z,
79
- V0,
80
- K0_kbar,
81
- K0_prime,
82
- Tr,
83
- x,
84
- expp,
85
- V,
86
- 1,
87
- 1,
88
- 0,
89
- 1,
90
- 1,
91
- 0,
92
- Theta_1,
93
- m1,
94
- Theta_2,
95
- m2,
96
- T,
97
- delta,
98
- 0,
99
- t,
100
- a_0,
101
- m,
102
- g,
103
- e_0,
104
- )
105
-
106
- # class based implementation
38
+ def test_diamond_thermal_pressure_regression():
107
39
  rt_eos = Holzapfel(V0, K0, K0_prime, n, z)
108
40
  sokolova_eos = Sokolova2016(
109
41
  rt_eos, Tr, Theta_1, m1, Theta_2, m2, delta, t, a_0, m, g, e_0
110
42
  )
111
- P2 = sokolova_eos.thermal_pressure(V, T)
112
- assert np.isclose(P1 / 10000, P2)
43
+
44
+ assert np.isclose(
45
+ sokolova_eos.thermal_pressure(V, T), 14.860490047369, rtol=1e-4
46
+ )
113
47
 
114
48
 
115
49
  def test_f_gamV():
@@ -124,10 +58,7 @@ def test_f_gamV():
124
58
  g0 = delta
125
59
  gb = t
126
60
 
127
- gamV0_1 = sokolova2016_original.f_gamV(x, n, z, V0, K0_kbar, K0_prime, g0, gb, 0)
128
- gamV0_2 = f_gamV(x, Px, KT, kkx, g0, gb)
129
-
130
- assert np.isclose(gamV0_1, gamV0_2)
61
+ assert np.isclose(f_gamV(x, Px, KT, kkx, g0, gb), 0.879820464953846)
131
62
 
132
63
 
133
64
  def test_I_gamV_compression():
@@ -139,11 +70,9 @@ def test_I_gamV_compression():
139
70
  g0 = delta
140
71
  gb = t
141
72
 
142
- I_gamV_1 = sokolova2016_original.I_gamV(z, n, x, V0, K0_kbar, K0_prime, g0, gb, 0)
143
- I_gamV_2 = I_gamV(x, g0, gb, rt_eos=rt_eos)
73
+ integral = I_gamV(x, g0, gb, rt_eos=rt_eos)
144
74
 
145
- assert np.isclose(I_gamV_1, I_gamV_2)
146
- assert np.isclose(np.exp(I_gamV_2), 1.09427641040855)
75
+ assert np.isclose(np.exp(integral), 1.09427641040855)
147
76
 
148
77
 
149
78
  def test_I_gamV_expansion():
@@ -155,11 +84,9 @@ def test_I_gamV_expansion():
155
84
  g0 = delta
156
85
  gb = t
157
86
 
158
- I_gamV_1 = sokolova2016_original.I_gamV(z, n, x, V0, K0_kbar, K0_prime, g0, gb, 0)
159
- I_gamV_2 = I_gamV(x, g0, gb, rt_eos=rt_eos)
87
+ integral = I_gamV(x, g0, gb, rt_eos=rt_eos)
160
88
 
161
- assert np.isclose(I_gamV_1, I_gamV_2)
162
- assert np.isclose(np.exp(I_gamV_2), 0.910574451622214)
89
+ assert np.isclose(np.exp(integral), 0.910574451622214)
163
90
 
164
91
 
165
92
  def test_I_gamV_multiple_volumes():
@@ -175,6 +102,94 @@ def test_I_gamV_multiple_volumes():
175
102
  assert len(I_gamV_1) == len(V)
176
103
 
177
104
 
105
+ def test_complete_pressure_terms_regression():
106
+ """Exercise pressure terms that were previously omitted from the class API."""
107
+ rt_eos = Holzapfel(V0, K0, K0_prime, n, z)
108
+ parameters = {
109
+ "beta": 0.35,
110
+ "QBo": 480.0,
111
+ "d": 2.4,
112
+ "mb": 0.75,
113
+ "QB1o": 1120.0,
114
+ "d1": 1.6,
115
+ "mb1": 0.4,
116
+ "a_0": 5.2,
117
+ "m": 1.3,
118
+ "g": 0.8,
119
+ "e_0": 2.7,
120
+ }
121
+ eos = Sokolova2016(
122
+ rt_eos,
123
+ Tr,
124
+ Theta_1,
125
+ m1,
126
+ Theta_2,
127
+ m2,
128
+ delta,
129
+ t,
130
+ parameters["a_0"],
131
+ parameters["m"],
132
+ parameters["g"],
133
+ parameters["e_0"],
134
+ beta=parameters["beta"],
135
+ QBo=parameters["QBo"],
136
+ d=parameters["d"],
137
+ mb=parameters["mb"],
138
+ QB1o=parameters["QB1o"],
139
+ d1=parameters["d1"],
140
+ mb1=parameters["mb1"],
141
+ )
142
+
143
+ expected_pressures = (
144
+ (0.72, 900.0, 3.097984574947913),
145
+ (0.88, 2400.0, 17.277569642979014),
146
+ (1.05, 700.0, 2.6221802405808816),
147
+ )
148
+ for volume_ratio, temperature, expected_pressure in expected_pressures:
149
+ volume = V0 * volume_ratio
150
+
151
+ assert np.isclose(
152
+ eos.thermal_pressure(volume, temperature),
153
+ expected_pressure,
154
+ rtol=1e-4,
155
+ atol=1e-7,
156
+ )
157
+
158
+
159
+ @pytest.mark.parametrize(
160
+ ("keyword", "value"),
161
+ [
162
+ ("QBo", 0),
163
+ ("d", -1),
164
+ ("mb", -0.1),
165
+ ("QB1o", np.nan),
166
+ ("d1", 0),
167
+ ("mb1", -1),
168
+ ("beta", np.inf),
169
+ ],
170
+ )
171
+ def test_complete_pressure_parameters_are_validated(keyword, value):
172
+ rt_eos = Holzapfel(V0, K0, K0_prime, n, z)
173
+ kwargs = {keyword: value}
174
+
175
+ with pytest.raises(ValueError):
176
+ Sokolova2016(
177
+ rt_eos,
178
+ Tr,
179
+ Theta_1,
180
+ m1,
181
+ Theta_2,
182
+ m2,
183
+ delta,
184
+ t,
185
+ a_0,
186
+ m,
187
+ g,
188
+ e_0,
189
+ **kwargs,
190
+ )
191
+
192
+
178
193
  def test_thermal_pressure_multiple_volumes_single_temperature():
179
194
  rt_eos = Holzapfel(V0, K0, K0_prime, n, z)
180
195
  sokolova_eos = Sokolova2016(
File without changes
@@ -1,527 +0,0 @@
1
- """
2
- Original thermal pressure equation of states formalisms from Sokolova et al. 2016.
3
- """
4
-
5
- import numpy as np
6
-
7
-
8
- def P_thermal(
9
- n,
10
- z,
11
- Vo,
12
- Ko,
13
- kk,
14
- Tr,
15
- x,
16
- expp,
17
- V,
18
- QBo,
19
- d,
20
- mb,
21
- QB1o,
22
- d1,
23
- mb1,
24
- QE1o,
25
- mE1,
26
- QE2o,
27
- mE2,
28
- TK,
29
- gamVo,
30
- beta,
31
- gb,
32
- ao,
33
- m,
34
- mm,
35
- ae,
36
- ):
37
- """
38
- Original thermal pressure equation from sokolova et al. 2016.
39
-
40
- Parameters
41
- ----------
42
- n : float
43
- Number of atoms in the chemical formula
44
- z : float
45
- Atomic number of the chemical formula unit
46
- Vo : float
47
- Reference volume in [JBar^-1] (same as [cm^3/mol]/10)
48
- Ko : float
49
- Bulk modulus at reference volume [kbar]
50
- kk : float
51
- Bulk modulus derivative at reference volume
52
- Tr : float
53
- Reference temperature in [K] for the EOS (typically 298.15 K)
54
- x : float
55
- Fractional volume (V/Vo)
56
- expp : float
57
- unused in function
58
- V : float
59
- Volume in [JBar^-1] (same as [cm^3/mol]/10)
60
- QBo : float
61
- should be 1
62
- d : float
63
- should be 1
64
- mb : float
65
- should be 0
66
- QB1o : float
67
- should be 1
68
- d1 : float
69
- should be 1
70
- mb1 : float
71
- should be 0
72
- QE1o : float
73
- Einstein characteristic temperature, Theta_1 in [K]
74
- mE1 : float
75
- The first Einstein number
76
- QE2o : float
77
- Einstain characteristic temperature, Theta_02 in [K]
78
- mE2 : float
79
- The second Einstein number
80
- TK : float
81
- Temperature in [K]
82
- gamVo : float
83
- Additive normalizing constant for the Gruneisen parameter, (given as delta in Sokolova et al. 2016)
84
- beta : float
85
- Should be 0
86
- gb : float
87
- Generalized Gruneisen parameter, given as t in Sokolova et al. 2016
88
- ao : float
89
- Intrinsic anharmonicity parameter (10e-6 [K]), given as a_0 in Sokolova et al. 2016
90
- m : float
91
- Anharmonic analogue of the Grüneisen parameter
92
- mm : float
93
- Electronic analogue of the Grüneisen parameter, given as g in Sokolova et al. 2016
94
- ae : float
95
- Free electrons parameter (10e-6 [K]), given as e_0 in Sokolova et al. 2016
96
-
97
- Returns
98
- -------
99
- Pth : float
100
- Thermal pressure in [bar]
101
- """
102
- R = 8.31451
103
-
104
- fw = -np.log(3 * Ko / 10 / (1003.6 * (z * n / (Vo * 10)) ** (5 / 3)))
105
- ff = x ** (1 / 3)
106
- aa = 1.5 * (kk - 3) - fw
107
- Px = (
108
- 3
109
- * Ko
110
- * 1000
111
- * np.exp(fw * (1 - ff))
112
- * (1 / ff**5 - 1 / ff**4)
113
- * (1 + aa * ff - aa * ff**2)
114
- )
115
- KT = (
116
- Ko
117
- * 1000
118
- / ff**6
119
- * np.exp(fw * (1 - ff))
120
- * (
121
- (-5 / ff**2 + 4 / ff) * (1 + aa * ff - aa * ff**2)
122
- + (1 / ff - 1) * (1 + aa * ff - aa * ff**2) * (-fw)
123
- + (1 / ff - 1) * (aa - 2 * aa * ff)
124
- )
125
- * (-x)
126
- )
127
- ex = (
128
- 3
129
- / ff**4
130
- * Ko
131
- * 1000
132
- * np.exp(fw * (1 - ff))
133
- * (
134
- (-5 / ff**2 + 4 / ff) * (1 + aa * ff - aa * ff**2)
135
- - (1 / ff - 1) * (1 + aa * ff - aa * ff**2) * fw
136
- + (1 / ff - 1) * (aa - 2 * aa * ff)
137
- )
138
- )
139
- ex1 = (
140
- 1
141
- / ff**3
142
- * Ko
143
- * 1000
144
- * np.exp(fw * (1 - ff))
145
- * fw
146
- * (
147
- (-5 / ff**2 + 4 / ff) * (1 + aa * ff - aa * ff**2)
148
- - (1 / ff - 1) * (1 + aa * ff - aa * ff**2) * fw
149
- + (1 / ff - 1) * (aa - 2 * aa * ff)
150
- )
151
- )
152
- ex2 = (
153
- Ko
154
- * 1000
155
- * np.exp(fw * (1 - ff))
156
- * (
157
- (10 / ff**3 - 4 / ff**2) * (1 + aa * ff - aa * ff**2)
158
- + (-5 / ff**2 + 4 / ff) * (aa - 2 * aa * ff)
159
- + fw / ff**2 * (1 + aa * ff - aa * ff**2)
160
- - (1 / ff - 1) * (aa - 2 * aa * ff) * fw
161
- - (aa - 2 * aa * ff) / ff**2
162
- - 2 * aa * (1 / ff - 1)
163
- )
164
- / ff**3
165
- )
166
- kkx = (ex + ex1 - ex2) / (-KT / ff) / 3
167
-
168
- gt = gb - beta * x ** (1 / 3)
169
- gtx = -beta / 3 * x ** (-2 / 3)
170
- gamV = (-3 * KT + 2 * Px * gt + 9 * KT * kkx - 6 * gt * KT) / 6 / (
171
- 3 * KT - 2 * Px * gt
172
- ) + gamVo
173
- ff2 = (x + 0.00001) ** (1 / 3)
174
- KT2 = (
175
- Ko
176
- * 1000
177
- / ff2**6
178
- * np.exp(fw * (1 - ff2))
179
- * (
180
- (-5 / ff2**2 + 4 / ff2) * (1 + aa * ff2 - aa * ff2**2)
181
- + (1 / ff2 - 1) * (1 + aa * ff2 - aa * ff2**2) * (-fw)
182
- + (1 / ff2 - 1) * (aa - 2 * aa * ff2)
183
- )
184
- * (-(x + 0.00001))
185
- )
186
- ex = (
187
- 3
188
- / ff2**4
189
- * Ko
190
- * 1000
191
- * np.exp(fw * (1 - ff2))
192
- * (
193
- (-5 / ff2**2 + 4 / ff2) * (1 + aa * ff2 - aa * ff2**2)
194
- - (1 / ff2 - 1) * (1 + aa * ff2 - aa * ff2**2) * fw
195
- + (1 / ff2 - 1) * (aa - 2 * aa * ff2)
196
- )
197
- )
198
- ex1 = (
199
- 1
200
- / ff2**3
201
- * Ko
202
- * 1000
203
- * np.exp(fw * (1 - ff2))
204
- * fw
205
- * (
206
- (-5 / ff2**2 + 4 / ff2) * (1 + aa * ff2 - aa * ff2**2)
207
- - (1 / ff2 - 1) * (1 + aa * ff2 - aa * ff2**2) * fw
208
- + (1 / ff2 - 1) * (aa - 2 * aa * ff2)
209
- )
210
- )
211
- ex2 = (
212
- Ko
213
- * 1000
214
- * np.exp(fw * (1 - ff2))
215
- * (
216
- (10 / ff2**3 - 4 / ff2**2) * (1 + aa * ff2 - aa * ff2**2)
217
- + (-5 / ff2**2 + 4 / ff2) * (aa - 2 * aa * ff2)
218
- + fw / ff2**2 * (1 + aa * ff2 - aa * ff2**2)
219
- - (1 / ff2 - 1) * (aa - 2 * aa * ff2) * fw
220
- - (aa - 2 * aa * ff2) / ff2**2
221
- - 2 * aa * (1 / ff2 - 1)
222
- )
223
- / ff2**3
224
- )
225
- kkx2 = (ex + ex1 - ex2) / (-KT2 / ff2) / 3
226
- ff1 = (x - 0.00001) ** (1 / 3)
227
- KT1 = (
228
- Ko
229
- * 1000
230
- / ff1**6
231
- * np.exp(fw * (1 - ff1))
232
- * (
233
- (-5 / ff1**2 + 4 / ff1) * (1 + aa * ff1 - aa * ff1**2)
234
- + (1 / ff1 - 1) * (1 + aa * ff1 - aa * ff1**2) * (-fw)
235
- + (1 / ff1 - 1) * (aa - 2 * aa * ff1)
236
- )
237
- * (-(x - 0.00001))
238
- )
239
- ex = (
240
- 3
241
- / ff1**4
242
- * Ko
243
- * 1000
244
- * np.exp(fw * (1 - ff1))
245
- * (
246
- (-5 / ff1**2 + 4 / ff1) * (1 + aa * ff1 - aa * ff1**2)
247
- - (1 / ff1 - 1) * (1 + aa * ff1 - aa * ff1**2) * fw
248
- + (1 / ff1 - 1) * (aa - 2 * aa * ff1)
249
- )
250
- )
251
- ex1 = (
252
- 1
253
- / ff1**3
254
- * Ko
255
- * 1000
256
- * np.exp(fw * (1 - ff1))
257
- * fw
258
- * (
259
- (-5 / ff1**2 + 4 / ff1) * (1 + aa * ff1 - aa * ff1**2)
260
- - (1 / ff1 - 1) * (1 + aa * ff1 - aa * ff1**2) * fw
261
- + (1 / ff1 - 1) * (aa - 2 * aa * ff1)
262
- )
263
- )
264
- ex2 = (
265
- Ko
266
- * 1000
267
- * np.exp(fw * (1 - ff1))
268
- * (
269
- (10 / ff1**3 - 4 / ff1**2) * (1 + aa * ff1 - aa * ff1**2)
270
- + (-5 / ff1**2 + 4 / ff1) * (aa - 2 * aa * ff1)
271
- + fw / ff1**2 * (1 + aa * ff1 - aa * ff1**2)
272
- - (1 / ff1 - 1) * (aa - 2 * aa * ff1) * fw
273
- - (aa - 2 * aa * ff1) / ff1**2
274
- - 2 * aa * (1 / ff1 - 1)
275
- )
276
- / ff1**3
277
- )
278
- kkx1 = (ex + ex1 - ex2) / (-KT1 / ff1) / 3
279
-
280
- dkkdx = (kkx2 - kkx1) / (0.00002)
281
-
282
- qV = (
283
- -1
284
- / 2
285
- * (
286
- -6 * KT * kkx**2 * Px * gt / x
287
- + 6 * KT * dkkdx * Px * gt
288
- + 6 * KT * kkx * KT * gt / x
289
- - 6 * KT * kkx * Px * gtx
290
- + 4 * gt**2 * KT * kkx * Px / x
291
- - 4 * gt**2 * KT**2 / x
292
- - 9 * KT**2 * dkkdx
293
- + 6 * gtx * KT**2
294
- )
295
- / (3 * KT - 2 * Px * gt) ** 2
296
- * x
297
- / gamV
298
- )
299
- a = ao / 1000000 * x**m
300
-
301
- QB = QBo * expp
302
- QB1 = QB1o * expp
303
- QE1 = QE1o * expp
304
- QE2 = QE2o * expp
305
-
306
- ggr = d * np.log(1 + QB / Tr / d)
307
- br = 1 / (np.exp(ggr) - 1)
308
- ex1r = np.exp(QB / Tr)
309
- PBr = (
310
- mb * R * ((QB * (d - 1) / 2 / d + Tr * QB * d * br / (Tr * d + QB)) * gamV / V)
311
- )
312
-
313
- gg = d * np.log(1 + QB / TK / d)
314
- b = 1 / (np.exp(gg) - 1)
315
- ex1 = np.exp(QB / TK)
316
- PB = mb * R * ((QB * (d - 1) / 2 / d + TK * QB * d * b / (TK * d + QB)) * gamV / V)
317
-
318
- gg1r = d1 * np.log(1 + QB1 / Tr / d1)
319
- b1r = 1 / (np.exp(gg1r) - 1)
320
- ex2r = np.exp(QB1 / Tr)
321
- PB1r = (
322
- mb1
323
- * R
324
- * ((QB1 * (d1 - 1) / 2 / d1 + Tr * QB1 * d1 * b1r / (Tr * d1 + QB1)) * gamV / V)
325
- )
326
-
327
- gg1 = d1 * np.log(1 + QB1 / TK / d1)
328
- b1 = 1 / (np.exp(gg1) - 1)
329
- ex2 = np.exp(QB1 / TK)
330
- PB1 = (
331
- mb1
332
- * R
333
- * ((QB1 * (d1 - 1) / 2 / d1 + TK * QB1 * d1 * b1 / (TK * d1 + QB1)) * gamV / V)
334
- )
335
-
336
- e1 = np.exp(QE1 / TK)
337
- PE1 = mE1 * R * ((QE1 / 2 + QE1 / (e1 - 1)) * gamV / V)
338
-
339
- e2 = np.exp(QE2 / TK)
340
- PE2 = mE2 * R * ((QE2 / 2 + QE2 / (e2 - 1)) * gamV / V)
341
-
342
- e1r = np.exp(QE1 / Tr)
343
- PE1r = mE1 * R * ((QE1 / 2 + QE1 / (e1r - 1)) * gamV / V)
344
-
345
- e2r = np.exp(QE2 / Tr)
346
- PE2r = mE2 * R * ((QE2 / 2 + QE2 / (e2r - 1)) * gamV / V)
347
- Pea = 3 / 2 * n * R * ao / 1000000 * x ** (m) * (m) / V * (TK**2 - Tr**2)
348
- Pee = 3 / 2 * n * R * ae / 1000000 * x ** (mm) * (mm) / V * (TK**2 - Tr**2)
349
-
350
- Pth = PB + PB1 + PE1 + PE2 - PBr - PB1r - PE1r - PE2r + Pee + Pea
351
- return Pth
352
-
353
-
354
- def I_gamV(z, n, b, Vo, Ko, kk, gamVo, gb, beta, e=0.001):
355
- """
356
- Integral of the Gruneisen parameter over the volume.
357
-
358
- Parameters
359
- ----------
360
- z : float
361
- Atomic number of the chemical formula unit
362
- n : float
363
- Number of atoms in the chemical formula
364
- b : float
365
- Fractional volume (V/V0)
366
- Vo : float
367
- Reference volume in [JBar^-1] (same as [cm^3/mol]/10)
368
- Ko : float
369
- Bulk modulus at reference volume [kbar]
370
- kk : float
371
- Bulk modulus derivative at reference volume
372
- gamVo : float
373
- Additive normalizing constant for the Gruneisen parameter, (given as delta in Sokolova et al. 2016)
374
- gb : float
375
- Generalized Gruneisen parameter, given as t in Sokolova et al. 2016
376
- beta : float
377
- Anharmonic analogue of the Grüneisen parameter
378
- e : float
379
- Tolerance for the integration
380
-
381
- Returns
382
- -------
383
- I_gamV : float
384
- Integral of the Gruneisen parameter over the volume
385
-
386
- """
387
- # check whether b is greater than 1
388
- a = min(b, 1)
389
- b = max(b, 1)
390
-
391
- # calculate the integral using the trapezoidal rule
392
- s2 = 1
393
- h = b - a
394
- S = f_gamV(a, n, z, Vo, Ko, kk, gamVo, gb, beta) + f_gamV(
395
- b, n, z, Vo, Ko, kk, gamVo, gb, beta
396
- )
397
-
398
- while True:
399
- s3 = s2
400
- h /= 2
401
- s1 = 0
402
- x = a + h
403
-
404
- while x < b:
405
- s1 += 2 * f_gamV(x, n, z, Vo, Ko, kk, gamVo, gb, beta)
406
- x += 2 * h
407
-
408
- S += s1
409
- s2 = (S + s1) * h / 3
410
- error = abs(s3 - s2) / 15
411
-
412
- if error < e:
413
- break
414
-
415
- return -s2 if b > 1 else s2
416
-
417
-
418
- def f_gamV(x, n, z, Vo, Ko, kk, gamVo, gb, beta):
419
- """
420
- Helper function to calculate the Gruneisen parameter at a given temperature and pressure.
421
-
422
- Parameters
423
- ----------
424
- x : float
425
- Fractional volume (V/Vo)
426
- n : float
427
- Number of atoms in the chemical formula
428
- z : float
429
- Atomic number of the chemical formula unit
430
- Vo : float
431
- Reference volume in [JBar^-1] (same as [cm^3/mol]/10)
432
- Ko : float
433
- Bulk modulus at reference volume [kbar]
434
- kk : float
435
- Bulk modulus derivative at reference volume
436
- gamVo : float
437
- Additive normalizing constant for the Gruneisen parameter, (given as delta in Sokolova et al. 2016)
438
- gb : float
439
- Generalized Gruneisen parameter, given as t in Sokolova et al. 2016
440
- beta : float
441
- Anharmonic analogue of the Grüneisen parameter
442
-
443
- Returns
444
- -------
445
- f_gamV_value : float
446
- Gruneisen parameter at a given temperature and pressure
447
- """
448
- fw = -np.log(3 * Ko / 10 / (1003.6 * (z * n / (Vo * 10)) ** (5 / 3)))
449
- ff = x ** (1 / 3)
450
- aa = 1.5 * (kk - 3) - fw
451
-
452
- KT = (
453
- Ko
454
- * 1000
455
- / ff**6
456
- * np.exp(fw * (1 - ff))
457
- * (
458
- (-5 / ff**2 + 4 / ff) * (1 + aa * ff - aa * ff**2)
459
- + (1 / ff - 1) * (1 + aa * ff - aa * ff**2) * (-fw)
460
- + (1 / ff - 1) * (aa - 2 * aa * ff)
461
- )
462
- * (-x)
463
- )
464
-
465
- Px = (
466
- 3
467
- * Ko
468
- * 1000
469
- * np.exp(fw * (1 - ff))
470
- * (1 / ff**5 - 1 / ff**4)
471
- * (1 + aa * ff - aa * ff**2)
472
- )
473
-
474
- ex = (
475
- 3
476
- / ff**4
477
- * Ko
478
- * 1000
479
- * np.exp(fw * (1 - ff))
480
- * (
481
- (-5 / ff**2 + 4 / ff) * (1 + aa * ff - aa * ff**2)
482
- - (1 / ff - 1) * (1 + aa * ff - aa * ff**2) * fw
483
- + (1 / ff - 1) * (aa - 2 * aa * ff)
484
- )
485
- )
486
-
487
- ex1 = (
488
- 1
489
- / ff**3
490
- * Ko
491
- * 1000
492
- * np.exp(fw * (1 - ff))
493
- * fw
494
- * (
495
- (-5 / ff**2 + 4 / ff) * (1 + aa * ff - aa * ff**2)
496
- - (1 / ff - 1) * (1 + aa * ff - aa * ff**2) * fw
497
- + (1 / ff - 1) * (aa - 2 * aa * ff)
498
- )
499
- )
500
-
501
- ex2 = (
502
- Ko
503
- * 1000
504
- * np.exp(fw * (1 - ff))
505
- * (
506
- (10 / ff**3 - 4 / ff**2) * (1 + aa * ff - aa * ff**2)
507
- + (-5 / ff**2 + 4 / ff) * (aa - 2 * aa * ff)
508
- + fw / ff**2 * (1 + aa * ff - aa * ff**2)
509
- - (1 / ff - 1) * (aa - 2 * aa * ff) * fw
510
- - (aa - 2 * aa * ff) / ff**2
511
- - 2 * aa * (1 / ff - 1)
512
- )
513
- / ff**3
514
- )
515
-
516
- kkx = (ex + ex1 - ex2) / (-KT / ff) / 3
517
-
518
- gt = gb - beta * x ** (1 / 3)
519
- gtx = -beta / 3 * x ** (-2 / 3)
520
-
521
- f_gamV_value = (
522
- gamVo
523
- + (-3 * KT + 2 * Px * gt + 9 * KT * kkx - 6 * gt * KT)
524
- / (6 * (3 * KT - 2 * Px * gt))
525
- ) / x
526
-
527
- return f_gamV_value
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes