Skip to content

Commit a0d4d74

Browse files
committed
add transition temperature method
1 parent 63565d1 commit a0d4d74

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

calphy/postprocessing.py

+82-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
22
import numpy as np
33
import yaml
4+
import matplotlib.pyplot as plt
5+
import warnings
46

57
def read_report(folder):
68
"""
@@ -145,4 +147,83 @@ def gather_results(mainfolder):
145147
datadict['error_code'][-1] = _extract_error(errfile)
146148

147149
df = pd.DataFrame(data=datadict)
148-
return df
150+
return df
151+
152+
def find_transition_temperature(folder1, folder2, fit_order=4, plot=True):
153+
"""
154+
Find transition temperature where free energy of two phases are equal.
155+
156+
Parameters
157+
----------
158+
folder1: string
159+
directory with temperature scale calculation
160+
161+
folder2: string
162+
directory with temperature scale calculation
163+
164+
fit_order: int, optional
165+
default 4. Order for polynomial fit of temperature vs free energy
166+
167+
plot: bool, optional
168+
default True. Plot the results.
169+
"""
170+
file1 = os.path.join(folder1, 'temperature_sweep.dat')
171+
file2 = os.path.join(folder2, 'temperature_sweep.dat')
172+
if not os.path.exists(file1):
173+
raise FileNotFoundError(f'{file1} does not exist')
174+
if not os.path.exists(file2):
175+
raise FileNotFoundError(f'{file2} does not exist')
176+
177+
t1, f1 = np.loadtxt(file1, unpack=True, usecols=(0,1))
178+
t2, f2 = np.loadtxt(file2, unpack=True, usecols=(0,1))
179+
180+
#do some fitting to determine temps
181+
t1min = np.min(t1)
182+
t2min = np.min(t2)
183+
t1max = np.max(t1)
184+
t2max = np.max(t2)
185+
186+
tmin = np.min([t1min, t2min])
187+
tmax = np.max([t1max, t2max])
188+
189+
#warn about extrapolation
190+
if not t1min == t2min:
191+
warnings.warn(f'free energy is being extrapolated!')
192+
if not t1max == t2max:
193+
warnings.warn(f'free energy is being extrapolated!')
194+
195+
#now fit
196+
f1fit = np.polyfit(t1, f1, fit_order)
197+
f2fit = np.polyfit(t2, f2, fit_order)
198+
199+
#reevaluate over the new range
200+
fit_t = np.arange(tmin, tmax+1, 1)
201+
fit_f1 = np.polyval(f1fit, fit_t)
202+
fit_f2 = np.polyval(f2fit, fit_t)
203+
204+
#now evaluate the intersection temp
205+
arg = np.argsort(np.abs(fit_f1-fit_f2))[0]
206+
transition_temp = fit_t[arg]
207+
208+
#warn if the temperature is shady
209+
if np.abs(transition_temp-tmin) < 1E-3:
210+
warnings.warn('It is likely there is no intersection of free energies')
211+
elif np.abs(transition_temp-tmax) < 1E-3:
212+
warnings.warn('It is likely there is no intersection of free energies')
213+
214+
#plot
215+
if plot:
216+
c1lo = '#ef9a9a'
217+
c1hi = '#b71c1c'
218+
c2lo = '#90caf9'
219+
c2hi = '#0d47a1'
220+
221+
plt.plot(fit_t, fit_f1, color=c1lo, label=f'{folder1} fit')
222+
plt.plot(fit_t, fit_f2, color=c2lo, label=f'{folder2} fit')
223+
plt.plot(t1, f1, color=c1hi, label=folder1, ls='dashed')
224+
plt.plot(t2, f2, color=c2hi, label=folder2, ls='dashed')
225+
plt.axvline(transition_temp, ls='dashed', c='#37474f')
226+
plt.ylabel('Free energy (eV/atom)')
227+
plt.xlabel('Temperature (K)')
228+
plt.legend(frameon=False)
229+
return transition_temp

0 commit comments

Comments
 (0)