Skip to content

Commit 151c420

Browse files
committed
added LogNormal anharmonic model, restructured
1 parent df4c968 commit 151c420

File tree

8 files changed

+1000
-415
lines changed

8 files changed

+1000
-415
lines changed

burnman/eos/anharmonic_debye.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# This file is part of BurnMan - a thermoelastic and thermodynamic toolkit for the Earth and Planetary Sciences
2+
# Copyright (C) 2012 - 2025 by the BurnMan team, released under the GNU
3+
# GPL v2 or later.
4+
5+
6+
class AnharmonicDebye:
7+
"""
8+
Class providing methods to compute the anharmonic contribution to the
9+
Helmholtz free energy, pressure, entropy, isochoric heat capacity,
10+
isothermal bulk modulus and thermal expansion coefficient
11+
multiplied by the isothermal bulk modulus.
12+
13+
The Helmholtz energy is defined as
14+
:math:`F(V, T) = A(V) (F_a(T, \\Theta(V)) - F_a(T_0, \\Theta(V)))`
15+
where :math:`A(V)` is the anharmonic prefactor,
16+
:math:`F_a(T, \\Theta)` is the anharmonic Helmholtz energy,
17+
and :math:`\\Theta(V)` is the Debye temperature.
18+
19+
These three functions and their derivatives with respect to
20+
their arguments are provided as class instances contained within
21+
the params dictionary, with keys "anharmonic_prefactor_model",
22+
"debye_temperature_model", and "anharmonic_thermal_model".
23+
24+
:return: _description_
25+
:rtype: _type_
26+
"""
27+
28+
@staticmethod
29+
def helmholtz_energy(temperature, volume, params):
30+
x = volume / params["V_0"]
31+
A = params["anharmonic_prefactor_model"].value(x, params)
32+
theta_model = params["debye_temperature_model"]
33+
anharmonic_model = params["anharmonic_thermal_model"]
34+
debye_T = theta_model(x, params)
35+
F_a = anharmonic_model.nondimensional_helmholtz_energy(
36+
temperature, debye_T, params
37+
)
38+
F_a0 = anharmonic_model.nondimensional_helmholtz_energy(
39+
params["T_0"], debye_T, params
40+
)
41+
return A * (F_a - F_a0)
42+
43+
@staticmethod
44+
def entropy(temperature, volume, params):
45+
x = volume / params["V_0"]
46+
A = params["anharmonic_prefactor_model"].value(x, params)
47+
theta_model = params["debye_temperature_model"]
48+
anharmonic_model = params["anharmonic_thermal_model"]
49+
debye_T = theta_model(x, params)
50+
S_a = anharmonic_model.nondimensional_entropy(temperature, debye_T, params)
51+
return A * S_a
52+
53+
@staticmethod
54+
def heat_capacity_v(temperature, volume, params):
55+
x = volume / params["V_0"]
56+
A = params["anharmonic_prefactor_model"].value(x, params)
57+
theta_model = params["debye_temperature_model"]
58+
anharmonic_model = params["anharmonic_thermal_model"]
59+
debye_T = theta_model(x, params)
60+
Cv_a = anharmonic_model.nondimensional_heat_capacity(
61+
temperature, debye_T, params
62+
)
63+
return A * Cv_a
64+
65+
@staticmethod
66+
def pressure(temperature, volume, params):
67+
x = volume / params["V_0"]
68+
A = params["anharmonic_prefactor_model"].value(x, params)
69+
dAdV = params["anharmonic_prefactor_model"].dVrel(x, params) / params["V_0"]
70+
theta_model = params["debye_temperature_model"]
71+
anharmonic_model = params["anharmonic_thermal_model"]
72+
debye_T = theta_model(x, params)
73+
F_a = anharmonic_model.nondimensional_helmholtz_energy(
74+
temperature, debye_T, params
75+
)
76+
F_a0 = anharmonic_model.nondimensional_helmholtz_energy(
77+
params["T_0"], debye_T, params
78+
)
79+
F_ad = anharmonic_model.nondimensional_dhelmholtz_dTheta(
80+
temperature, debye_T, params
81+
)
82+
F_ad0 = anharmonic_model.nondimensional_dhelmholtz_dTheta(
83+
params["T_0"], debye_T, params
84+
)
85+
return -(
86+
dAdV * (F_a - F_a0)
87+
+ A * (theta_model.dVrel(x, params) / params["V_0"]) * (F_ad - F_ad0)
88+
)
89+
90+
@staticmethod
91+
def isothermal_bulk_modulus(temperature, volume, params):
92+
x = volume / params["V_0"]
93+
A = params["anharmonic_prefactor_model"].value(x, params)
94+
dAdV = params["anharmonic_prefactor_model"].dVrel(x, params) / params["V_0"]
95+
d2AdV2 = (
96+
params["anharmonic_prefactor_model"].d2dVrel2(x, params)
97+
/ params["V_0"] ** 2
98+
)
99+
theta_model = params["debye_temperature_model"]
100+
anharmonic_model = params["anharmonic_thermal_model"]
101+
debye_T = theta_model(x, params)
102+
103+
F_a = anharmonic_model.nondimensional_helmholtz_energy(
104+
temperature, debye_T, params
105+
)
106+
F_a0 = anharmonic_model.nondimensional_helmholtz_energy(
107+
params["T_0"], debye_T, params
108+
)
109+
F_ad = anharmonic_model.nondimensional_dhelmholtz_dTheta(
110+
temperature, debye_T, params
111+
)
112+
F_ad0 = anharmonic_model.nondimensional_dhelmholtz_dTheta(
113+
params["T_0"], debye_T, params
114+
)
115+
F_add = anharmonic_model.nondimensional_d2helmholtz_dTheta2(
116+
temperature, debye_T, params
117+
)
118+
F_add0 = anharmonic_model.nondimensional_d2helmholtz_dTheta2(
119+
params["T_0"], debye_T, params
120+
)
121+
122+
return volume * (
123+
d2AdV2 * (F_a - F_a0)
124+
+ 2 * dAdV * (F_ad - F_ad0) * theta_model.dVrel(x, params) / params["V_0"]
125+
+ A * (F_add - F_add0) * (theta_model.dVrel(x, params) / params["V_0"]) ** 2
126+
+ A * (F_ad - F_ad0) * theta_model.d2dVrel2(x, params) / params["V_0"] ** 2
127+
)
128+
129+
@staticmethod
130+
def dSdV(temperature, volume, params):
131+
x = volume / params["V_0"]
132+
A = params["anharmonic_prefactor_model"].value(x, params)
133+
dAdV = params["anharmonic_prefactor_model"].dVrel(x, params) / params["V_0"]
134+
theta_model = params["debye_temperature_model"]
135+
anharmonic_model = params["anharmonic_thermal_model"]
136+
debye_T = theta_model(x, params)
137+
138+
S_a = anharmonic_model.nondimensional_entropy(temperature, debye_T, params)
139+
S_ad = anharmonic_model.nondimensional_dentropy_dTheta(
140+
temperature, debye_T, params
141+
)
142+
143+
aK_T = dAdV * S_a + A * (theta_model.dVrel(x, params) / params["V_0"]) * S_ad
144+
145+
return aK_T

0 commit comments

Comments
 (0)