11import os
22import numpy as np
33import yaml
4+ import matplotlib .pyplot as plt
5+ import warnings
46
57def 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