def test_fuzz_dV_dP_and_d2V_dP2_derivatives(): from thermo import eos eos_list = list(eos.__all__); eos_list.remove('GCEOS') eos_list.remove('ALPHA_FUNCTIONS'); eos_list.remove('VDW') phase_extensions = {True: '_l', False: '_g'} derivative_bases_dV_dP = {0:'V', 1:'dV_dP', 2:'d2V_dP2'} def dV_dP(P, T, eos, order=0, phase=True, Tc=507.6, Pc=3025000., omega=0.2975): eos = globals()[eos_list[eos]](Tc=Tc, Pc=Pc, omega=omega, T=T, P=P) phase_base = phase_extensions[phase] attr = derivative_bases_dV_dP[order]+phase_base return getattr(eos, attr) x, y = [], [] for eos in range(len(eos_list)): for T in np.linspace(.1, 1000, 50): for P in np.logspace(np.log10(3E4), np.log10(1E6), 50): T, P = float(T), float(P) for phase in [True, False]: for order in [1, 2]: try: # If dV_dx_phase doesn't exist, will simply abort and continue the loop numer = derivative(dV_dP, P, dx=15., args=(T, eos, order-1, phase)) ana = dV_dP(T=T, P=P, eos=eos, order=order, phase=phase) except: continue x.append(numer) y.append(ana) assert allclose_variable(x, y, limits=[.02, .04, .04, .05, .15, .45, .95], rtols=[1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-9])
def test_fuzz_dPsat_dT(): from thermo import eos eos_list = list(eos.__all__); eos_list.remove('GCEOS') eos_list.remove('ALPHA_FUNCTIONS'); eos_list.remove('eos_list') eos_list.remove('GCEOS_DUMMY') Tc = 507.6 Pc = 3025000 omega = 0.2975 e = PR(T=400, P=1E5, Tc=507.6, Pc=3025000, omega=0.2975) dPsats_dT_expect = [938.7777925283981, 10287.225576267781, 38814.74676693623] assert_allclose([e.dPsat_dT(300), e.dPsat_dT(400), e.dPsat_dT(500)], dPsats_dT_expect) # Hammer the derivatives for each EOS in a wide range; most are really # accurate. There's an error around the transition between polynomials # though - to be expected; the derivatives are discontinuous there. dPsats_derivative = [] dPsats_analytical = [] for eos in range(len(eos_list)): for T in np.linspace(0.2*Tc, Tc*.999, 50): e = globals()[eos_list[eos]](Tc=Tc, Pc=Pc, omega=omega, T=T, P=1E5) anal = e.dPsat_dT(T) numer = derivative(e.Psat, T, order=9) dPsats_analytical.append(anal) dPsats_derivative.append(numer) assert allclose_variable(dPsats_derivative, dPsats_analytical, limits=[.02, .06], rtols=[1E-5, 1E-7])
def test_SRK_Psat(): eos = SRK(Tc=507.6, Pc=3025000, omega=0.2975, T=299., P=1E6) # ERROR actually for RK not SRK Cs_SRK = [-3.0486334, -5.2157649E-2, 0.55002312, -0.44506984, 3.1735078E-2, 4.1819219E-2, -1.18709865E-2, 1.79267167E-3, -1.47491666E-4, 5.19352748E-6] def Psat(T, Tc, Pc, omega): Tr = T/Tc e = SRK(Tc=Tc, Pc=Pc, omega=omega, T=T, P=1E5) alpha = e.a_alpha/e.a tot = 0 for k, Ck in enumerate(Cs_SRK[0:4]): tot += Ck*(alpha/Tr-1)**((k+2)/2.) for k, Ck in enumerate(Cs_SRK[4:]): tot += Ck*(alpha/Tr-1)**(k+3) P = exp(tot)*Tr*Pc return P Ts = np.linspace(160, 504, 100) Psats_lit = [Psat(T, Tc=507.6, Pc=3025000, omega=0.2975) for T in Ts] Psats_eos = [eos.Psat(T) for T in Ts] assert_allclose(Psats_lit, Psats_eos, rtol=5E-2) # Not sure why the fit was so poor for the original author fugacity_ls, fugacity_gs = [], [] for T, P in zip(Ts, Psats_eos): eos = SRK(Tc=507.6, Pc=3025000, omega=0.2975, T=T, P=P) fugacity_ls.append(eos.fugacity_l) fugacity_gs.append(eos.fugacity_g) assert allclose_variable(fugacity_ls, fugacity_gs, limits=[0, .1, .5], rtols=[3E-2, 1E-3, 3E-4])