def PV(data, B, E, f, jacb, jacd, fix): N = 64 # Number of pts. for best fit curve. x = np.linspace(B[-1], data.V.min()-1, N) # B[-1] is the last element of B, V0 # Plot the data and the best fit line figfit = plt.figure(figsize=(9,9)) fig = plt.gcf() titlestring = 'Fitting Results for '+ data.EOS_type + '-' + str(data.EOS_order) fig.canvas.set_window_title(titlestring) plt.subplot(221) plt.errorbar(x=data.V, y=data.P, xerr=data.Verr, yerr=data.Perr, fmt='ko', label="Data") plt.plot(x, f(B,x), 'r', linewidth=3, label="Fit") plt.xlabel(r"Volume, $\AA^{3}$", fontsize=14) plt.ylabel(r"Pressure, GPa", fontsize=14) plt.legend(numpoints=1, loc="upper right") plt.tight_layout() plt.subplot(222) K = GEOST_thermo.BM3_V_K(B,x) plt.plot(x, K, 'r', linewidth=3) plt.xlabel(r"Volume, $\AA^{3}$", fontsize=14) plt.ylabel(r"Bulk Modulus, GPa", fontsize=14) plt.tight_layout() plt.subplot(223) fe = GEOST_thermo.EULERIAN_STRAIN(B[-1],x) dKdP = GEOST_thermo.birch_murnaghan(B,fe).dKdP plt.plot(x, dKdP, 'r', linewidth=3) plt.xlabel(r"Volume, $\AA^{3}$", fontsize=14) plt.ylabel(r"$\partial K / \partial P$", fontsize=14) plt.tight_layout() plt.subplot(224) fe = GEOST_thermo.EULERIAN_STRAIN(B[-1],x) d2KdP2 = GEOST_thermo.birch_murnaghan(B,fe).d2KdP2 plt.plot(x, d2KdP2, 'r', linewidth=3) plt.xlabel(r"Volume, $\AA^{3}$", fontsize=14) plt.ylabel(r"$\partial^{2} K / \partial P^{2}$", fontsize=14) plt.tight_layout() return 0
def ON_REFINE_PRESS(): global data name = thermo.types().names[0] # Which EOS fix = np.zeros(4, dtype=int) # Fix flags for refinement beta = np.zeros(4, dtype=float) # Refineable param 1st guesses fix, beta = GEOST_gui.GUI().FIX_FLAG() # Assign fix flags, and parameter guesses # Sort out which EOS to work with, derivatives, etc. if name == app.EOS_names[0]: # Birch-Murnaghan if app.EOS_order.get() == 2: f = thermo.BM2_V jacb = thermo.BM2_V_JACB jacd = thermo.BM2_V_JACD elif app.EOS_order.get() == 3: f = thermo.BM3_V jacb = thermo.BM3_V_JACB jacd = thermo.BM3_V_JACD elif app.EOS_order.get() == 4: f = thermo.BM4_V jacb = thermo.BM4_V_JACB jacd = thermo.BM4_V_JACD elif name == app.EOS_names[1]: # Natural Strain if app.EOS_order.get() == 2: f = thermo.NS2_V jacb = thermo.NS2_V_JACB jacd = thermo.NS2_V_JACD elif app.EOS_order.get() == 3: f = thermo.NS3_V jacb = thermo.NS3_V_JACB jacd = thermo.NS3_V_JACD elif app.EOS_order.get() == 4: f = thermo.NS4_V jacb = thermo.NS4_V_JACB jacd = thermo.NS4_V_JACD elif name == app.EOS_names[2]: # Vinet f = thermo.VINET_V jacb = thermo.VINET_V_JACB jacd = thermo.VINET_V_JACD # ODR SETUP # model contains information about the ODR functions. # fcn = model function to refine parameters from # fjacb = derivatives of fcn w.r.t. parameters # fjacd = derivatives of fcn w.r.t. independent var. odr_model = odrpack.Model(fcn=f, fjacb=jacb, fjacd=jacd) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=beta, ifixb=fix, maxit=100) odr.set_job(fit_type=0, deriv=2, var_calc=0) # Use user-supplied derivatives, but CHECK THEM!!! # ======== ODR RESULTS ========= output = odr.run() # Output of ODR run ref_B = output.beta # LSQ best-fit parameters err = output.sd_beta # Parameter errors (1-sigma) cov_B = output.cov_beta # Covariance matrix # The following was implemented for testing purposes to understand # how ODR was computing the covariance matrix, and how to generate # correlated random data using the Cholesky decomposition. # Most of this is now out of date. -JPT feb 2015 ''' # ODR covariance matrix print "ODR covariance:" print cov_B # Homemade covariance matrix from C = inv(JtJ), J = jacobian at optimum params. # NB: ODR wants the TRANSPOSE of J, so we need to transpose this guy J = jacb(ref_B,V).T for i in range(J.shape[0]): J[i,:] = (-1./Perr[i])*J[i,:] Jt = np.transpose(J) cov = np.linalg.inv(np.dot(Jt,J)) # Defn. of the covariance print 'Homemade cov (see Craigs PDF):' print cov cor = np.empty(cov.shape, dtype=float) # Correlation matrix. Need for correlated draws for i in range(cov.shape[0]): for j in range(cov.shape[1]): cor[i,j] = cov[i,j]/np.sqrt(np.dot(cov[i,i],cov[j,j])) # Spit results to stdout, will remove once it's finalized. print "cor (See Hughes & Hase pp. 94 eqn. 7.30):" print cor print "" print "Why does ODR cov_beta and homemade cov differ?" print "Because Hughes & Hase compute cov = inv(A)" print "Where Aij = 1/2 * d2 (chi_sq)/dBi dBj" print "Therefore one gets cor = 1/4 * inv(A)" print "As a result, multiply sqrt of diagonal elements" print "by 2 to compare with ODR std_beta." print "" print "spectrum of cor" # Check that cor is positive definite u,w = np.linalg.eig(cor) print u # Compute the Cholesky of the correlation matrix, # NB: Scipy returns a lower triangular Cholesky, we want upper triangular. U = np.linalg.cholesky(cor).T print "Cholesky(cor)" print U print "Best fit params:" print ref_B print "Standard error:" print err ''' # Print the results and plot if ODR was successful if output.stopreason[0] == 'Iteration limit reached': app.LOG_PRINT('ITERATION LIMIT REACHED, LSQ NOT CONVERGED!') else: RESULTS(ref_B, err, cov_B, output, f) PLOTS(ref_B, err, f, jacb, jacd, cov_B) return 0
def f34test(data, B, fix): F = np.zeros(2, dtype=float) # pdf C = np.zeros(2, dtype=float) # p-values B3 = np.zeros(3, dtype=float) # for the 2nd order EOS, assign K0 and V0 from user guesses B3[0] = B[0] B3[1] = B[1] B3[2] = B[3] if data.EOS_type == GEOST_thermo.types().names[0]: # Figure out what EOS's to use # If birch murnaghan odr_model = odrpack.Model(fcn=GEOST_thermo.BM3_V, fjacb=GEOST_thermo.BM3_V_JACB, fjacd=GEOST_thermo.BM3_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B3, ifixb=[fix[0],fix[1],fix[3]]) odr.set_job(deriv=3) # Use user-supplied derivatives output = odr.run() # Output of ODR run ref_B3 = output.beta # LSQ best-fit parameters err_B3 = output.sd_beta # Parameter errors (1-sigma) f3 = GEOST_thermo.BM3_V(ref_B3,data.V) df3 = data.V.shape[0] - 3 odr_model = odrpack.Model(fcn=GEOST_thermo.BM4_V, fjacb=GEOST_thermo.BM4_V_JACB, fjacd=GEOST_thermo.BM4_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B, ifixb=fix) odr.set_job(deriv=3) # Use user-supplied derivatives, but CHECK THEM!!! output = odr.run() # Output of ODR run ref_B4 = output.beta # LSQ best-fit parameters err_B4 = output.sd_beta # Parameter errors (1-sigma) f4 = GEOST_thermo.BM3_V(ref_B3,data.V) df4 = data.V.shape[0] - 4 elif data.EOS_type == GEOST_thermo.types().names[1]: # If Natural strain odr_model = odrpack.Model(fcn=GEOST_thermo.NS3_V, fjacb=GEOST_thermo.NS3_V_JACB, fjacd=GEOST_thermo.NS3_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B3, ifixb=[fix[0], fix[1], fix[3]]) odr.set_job(deriv=3) # Use user-supplied derivatives, but CHECK THEM!!! output = odr.run() # Output of ODR run ref_B3 = output.beta # LSQ best-fit parameters err_B3 = output.sd_beta # Parameter errors (1-sigma) f3 = GEOST_thermo.NS3_V(ref_B3,data.V) df3 = data.V.shape[0] - 3 odr_model = odrpack.Model(fcn=GEOST_thermo.NS4_V, fjacb=GEOST_thermo.NS4_V_JACB, fjacd=GEOST_thermo.NS4_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B, ifixb=fix) odr.set_job(deriv=3) # Use user-supplied derivatives, but CHECK THEM!!! output = odr.run() # Output of ODR run ref_B4 = output.beta # LSQ best-fit parameters err_B4 = output.sd_beta # Parameter errors (1-sigma) f4 = GEOST_thermo.NS4_V(ref_B4,data.V) df4 = data.V.shape[0] - 4 elif data.EOS_type == GEOST_thermo.types().names[2]: self.LOG_PRINT("ERROR in PLOTS: Cannot do F-test using Vinet EOS.") else: self.LOG_PRINT("ERROR in PLOTS: Unrecognized value of EOS_SELECT") chisq_3 = float(0) chisq_4 = float(0) for i in range(data.P.shape[0]): # Compute the chi-squared for each EOS chisq_3 += (data.P[i] - f3[i])**2 chisq_4 += (data.P[i] - f4[i])**2 # Compute the F-statistic Fx34 = (chisq_3 - chisq_4)/(chisq_4/df4) x1 = np.linspace(0.01, 2*Fx34, 128) pdf34 = f_dist.pdf(x1, 1, df4) cdf34 = f_dist.cdf(x1, 1, df4) # Use Scipy's built-in F-distribution methods F = f_dist.pdf(Fx34, 1, df4) # Compute the P-value C = 1 - f_dist.cdf(Fx34, 1, df4) # Finally, Make the plot. SHould be a 1 row 2 column plot showing # f-test for 2nd to 3rd order EOS and 3rd to 4th order EOS. plt.figure() fig = plt.gcf() fig.canvas.set_window_title("F-Test Results") plt.plot(x1, pdf34, 'r', linewidth=3, alpha=0.8) plt.plot(x1, cdf34, 'b', linewidth=3, alpha=0.8) plt.plot(Fx34, f_dist.pdf(Fx34, 1, df4), 'ko') plt.fill_between(x1, 0, pdf34, where=f_dist.cdf(Fx34, 1, df4)<cdf34, facecolor='red', alpha=0.2) plt.xticks(fontsize=14) plt.ylim([-0.01,1.01]) plt.title("Comparing 3rd vs. 4th order EOS", fontsize=14) plt.xlabel(r"$\left( \chi^{2}_{3} - \chi^{2}_{4} \right) / \left(\chi^{2}_{4} / \nu_{4} \right)$", fontsize=12) plt.legend(['PDF', 'CDF', r"$F_{X}$"], loc='upper right', numpoints=1) plt.text(Fx34, f_dist.pdf(Fx34, 1, df4)+0.05, "p-value= {:8.4f}".format(1-f_dist.cdf(Fx34, 1, df4)), fontsize=14) plt.tight_layout() return [chisq_3/df3, chisq_4/df4, Fx34, f_dist.cdf(Fx34, 1, df4)]
def f23test(data, B, fix): F = np.zeros(2, dtype=float) # pdf C = np.zeros(2, dtype=float) # p-values B2 = np.zeros(2, dtype=float) # for the 2nd order EOS, assign K0 and V0 from user guesses B2[0] = B[0] B2[1] = B[-1] if data.EOS_type == GEOST_thermo.types().names[0]: # Figure out what EOS's to use # If birch murnaghan odr_model = odrpack.Model(fcn=GEOST_thermo.BM2_V, fjacb=GEOST_thermo.BM2_V_JACB, fjacd=GEOST_thermo.BM2_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B2, ifixb=[fix[0],fix[-1]]) odr.set_job(deriv=3) # Use user-supplied derivatives output = odr.run() # Output of ODR run ref_B2 = output.beta # LSQ best-fit parameters err_B2 = output.sd_beta # Parameter errors (1-sigma) f2 = GEOST_thermo.BM2_V(ref_B2,data.V) df2 = data.V.shape[0] - 2 odr_model = odrpack.Model(fcn=GEOST_thermo.BM3_V, fjacb=GEOST_thermo.BM3_V_JACB, fjacd=GEOST_thermo.BM3_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B, ifixb=fix) odr.set_job(deriv=3) # Use user-supplied derivatives, but CHECK THEM!!! output = odr.run() # Output of ODR run ref_B3 = output.beta # LSQ best-fit parameters err_B3 = output.sd_beta # Parameter errors (1-sigma) f3 = GEOST_thermo.BM3_V(ref_B3,data.V) df3 = data.V.shape[0] - 3 elif data.EOS_type == GEOST_thermo.types().names[1]: # If Natural strain odr_model = odrpack.Model(fcn=GEOST_thermo.NS2_V, fjacb=GEOST_thermo.NS2_V_JACB, fjacd=GEOST_thermo.NS2_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B2, ifixb=[fix[0],fix[-1]]) odr.set_job(deriv=3) # Use user-supplied derivatives output = odr.run() # Output of ODR run ref_B2 = output.beta # LSQ best-fit parameters err_B2 = output.sd_beta # Parameter errors (1-sigma) f2 = GEOST_thermo.NS2_V(ref_B2,data.V) df2 = data.V.shape[0] - 2 odr_model = odrpack.Model(fcn=GEOST_thermo.NS3_V, fjacb=GEOST_thermo.NS3_V_JACB, fjacd=GEOST_thermo.NS3_V_JACD) odr_data = odrpack.RealData(x=data.V, y=data.P, sx=data.Verr, sy=data.Perr) odr = odrpack.ODR(odr_data, odr_model, beta0=B, ifixb=fix) odr.set_job(deriv=3) # Use user-supplied derivatives, but CHECK THEM!!! output = odr.run() # Output of ODR run ref_B3 = output.beta # LSQ best-fit parameters err_B3 = output.sd_beta # Parameter errors (1-sigma) f3 = GEOST_thermo.NS3_V(ref_B3,data.V) df3 = data.V.shape[0] - 3 chisq_2 = float(0) chisq_3 = float(0) for i in range(data.P.shape[0]): # Compute the chi-squared for each EOS chisq_2 += (data.P[i] - f2[i])**2 chisq_3 += (data.P[i] - f3[i])**2 # Compute the F-statistic Fx23 = (chisq_2 - chisq_3)/(chisq_3/df3) # Use Scipy's built-in F-distribution methods F = f_dist.pdf(Fx23, 1, df3) # Compute the P-value C = 1 - f_dist.cdf(Fx23, 1, df3) x1 = np.linspace(0.01, 2*Fx23, 128) pdf23 = f_dist.pdf(x1, 1, df3) cdf23 = f_dist.cdf(x1, 1, df3) # Results plt.figure() fig = plt.gcf() fig.canvas.set_window_title("F-Test Results") plt.plot(x1, pdf23, 'r', linewidth=3, alpha=0.8) plt.plot(x1, cdf23, 'b', linewidth=3, alpha=0.8) plt.plot(Fx23, f_dist.pdf(Fx23, 1, df3), 'ko') plt.fill_between(x1, 0, pdf23, where=f_dist.cdf(Fx23, 1, df3)<cdf23, facecolor='red', alpha=0.2) plt.xticks(fontsize=14) plt.ylim([-0.01,1.01]) plt.title("F test for 2nd vs. 3rd order EOS", fontsize=14) plt.xlabel(r"$\left( \chi^{2}_{2} - \chi^{2}_{3} \right) / \left(\chi^{2}_{3} / \nu_{3} \right)$", fontsize=12) plt.ylabel(r"PDF/CDF") plt.legend(['PDF', 'CDF', r"$F_{X}$"], loc='upper right', numpoints=1) plt.text(Fx23, f_dist.pdf(Fx23, 1, df3)+0.05, "p-value= {:8.4f}".format(1-f_dist.cdf(Fx23, 1, df3)), fontsize=14) plt.tight_layout() return [chisq_2/df2, chisq_3/df3, Fx23, f_dist.cdf(Fx23, 1, df3)]
#!/usr/bin/env python import numpy as np import GEOST_thermo as thermo import matplotlib.pyplot as plt kB = 8.6173324E-05 #eV/K B = [1, 100., 300.] D = thermo.debye(B) X = np.zeros((2,24), dtype=float) for i in range(X.shape[1]): X[0,i] = 100. - float(i) X[1,i] = 1000. B = np.zeros(3) B[0] = 1000. B[1] = 1.5 B[2] = 1. TD = np.zeros(X.shape[1]) U = np.zeros(X.shape[1]) Cv = np.zeros(X.shape[1]) for i in range(U.shape[0]): TD[i] = 1000.*np.exp(B[1] - B[1]*(100./X[0,i])**(-B[2])) U[i] = D.U(TD[i], X[1,i]) Cv[i] = D.Cv(TD[i], X[1,i]) plt.figure() plt.subplot(221) plt.title(r'$\Theta_{D}$') plt.xlabel("Volume")
VTerr[0,i+1*n] = Verrhit[i+1*n] VT[0,i+2*n] = Vhit[i+2*n] VTerr[0,i+2*n] = Verrhit[i+2*n] VT[1,i+0*n] = 1000. # Hi-T's VTerr[1,i+0*n] = 10. VT[1,i+1*n] = 1500. VTerr[1,i+1*n] = 20. VT[1,i+2*n] = 2000. VTerr[1,i+2*n] = 30. # Generate pressures A = np.zeros(3, dtype=float) A[0] = 700. # ThetaD0 A[1] = 1.5 # gD0 A[2] = 1. # q D = GEOST_thermo.debye([20, ref_Biso[-1], 273.]) # Instantiate debye Phit = D.P_thermal(A, VT) + np.random.normal(0,0.5,3*n) print 'Phit', Phit Perrhit = abs(np.random.normal(0,1,3*n)) Perrhit = np.sort(Perrhit) print "Thermal EOS refinement using Debye" print "True values & initial guesses:", A # ODR SETUP for isothermal EOS # model contains information about the ODR functions. # fcn = model function to refine parameters from # fjacb = derivatives of fcn w.r.t. parameters # fjacd = derivatives of fcn w.r.t. independent var. odr_model = odrpack.Model(fcn=D.P_thermal) odr_data = odrpack.RealData(x=VT, y=Phit, sx=VTerr, sy=Perrhit) odr = odrpack.ODR(odr_data, odr_model, beta0=A, maxit=100)
A = np.zeros(3) # Debye setup A[0] = 20. # No. atoms/cell A[1] = B[1] # V0 A[2] = 273. # Reference temperature (K) data273 = data(N,B) X273 = np.zeros((2,N), dtype=float) # Volume X273[0,:] = data(N,B).V X273[1,:] = 273. Y273 = data(N,B).P e273 = np.zeros((2,N), dtype=float) # errs e273[0,:] = data(N,B).Verr e273[1,:] = data(N,B).Perr debye273 = thermo.debye(A) C = np.zeros(3) C[0] = 1000. C[1] = 1.5 C[2] = 1. ### # 700 K N = 24 K0 = 100. V0 = 202. B = np.ones(2) # isothermal EOS initial parameters B[0] = K0 # K0 B[1] = V0 # V0