def test_NRTL_chemsep(): from thermo.interaction_parameters import IPDB tausB = IPDB.get_ip_asymmetric_matrix('ChemSep NRTL', ['64-17-5', '7732-18-5'], 'bij') alphaC = IPDB.get_ip_asymmetric_matrix('ChemSep NRTL', ['64-17-5', '7732-18-5'], 'alphaij') N = 2 T = 343.15 xs = [0.252, 0.748] tausA = tausE = tausF = tausG = tausH = alphaD = [[0.0] * N for i in range(N)] ABEFGHCD = (tausA, tausB, tausE, tausF, tausG, tausH, alphaC, alphaD) GE = NRTL(T=T, xs=xs, ABEFGHCD=ABEFGHCD) gammas = GE.gammas() assert_close1d(gammas, [1.985383485664009, 1.146380779201308], rtol=1e-7) # Table of values right from ChemSep gammas_ethanol = [ 5.66232, 4.283, 3.3749, 2.75365, 2.31475, 1.99622, 1.75984, 1.58121, 1.44425, 1.33807, 1.25512, 1.19003, 1.13894, 1.09896, 1.06796, 1.0443, 1.02671, 1.0142, 1.00598, 1.00142, 1 ] gammas_water = [ 1, 1.00705, 1.02657, 1.05673, 1.09626, 1.14429, 1.20021, 1.26357, 1.33405, 1.41139, 1.49541, 1.58593, 1.68281, 1.78591, 1.89509, 2.0102, 2.1311, 2.25761, 2.38956, 2.52675, 2.66895 ] pts = 21 xs_ethanol = linspace(0, 1, 21) for i in range(pts): GE2 = GE.to_T_xs(T=T, xs=[xs_ethanol[i], 1 - xs_ethanol[i]]) gammas = GE2.gammas() assert_close(gammas[0], gammas_ethanol[i], rtol=1e-5) assert_close(gammas[1], gammas_water[i], rtol=1e-5)
def test_NRTL_asymmetric_alpha(): GE = NRTL(T=343.15, xs=[0.252, 0.748], tau_bs=[[0, -61.02497992981518], [673.2359767158717, 0]], alpha_cs=[[0, 0.2974], [0.35, 0]]) assert_close1d(GE.gammas(), [1.8254928709184535, 1.1578302838386516], rtol=1e-12)
def test_NRTL_missing_inputs(): alphas = [[[0.0, 2e-05], [0.2937, 7e-05], [0.2999, 0.0001]], [[0.2937, 1e-05], [0.0, 4e-05], [0.3009, 8e-05]], [[0.2999, 1e-05], [0.3009, 3e-05], [0.0, 5e-05]]] taus = [[[6e-05, 0.0, 7e-05, 7e-05, 0.00788, 3.6e-07], [3e-05, 624.868, 9e-05, 7e-05, 0.00472, 8.5e-07], [3e-05, 398.953, 4e-05, 1e-05, 0.00279, 5.6e-07]], [[1e-05, -29.167, 8e-05, 9e-05, 0.00256, 1e-07], [2e-05, 0.0, 7e-05, 6e-05, 0.00587, 4.2e-07], [0.0, -35.482, 8e-05, 4e-05, 0.00889, 8.2e-07]], [[9e-05, -95.132, 6e-05, 1e-05, 0.00905, 5.2e-07], [9e-05, 33.862, 2e-05, 6e-05, 0.00517, 1.4e-07], [0.0001, 0.0, 6e-05, 2e-05, 0.00095, 7.4e-07]]] N = 3 T = 273.15 + 70 dT = T * 1e-8 xs = [.2, .3, .5] GE = NRTL(T, xs, tau_coeffs=taus) assert_close1d(GE.gammas(), [1, 1, 1], rtol=1e-13) GE = NRTL(T, xs, taus) assert_close1d(GE.gammas(), [1, 1, 1], rtol=1e-13) GE = NRTL(T, xs, alpha_coeffs=alphas) assert_close1d(GE.gammas(), [1, 1, 1], rtol=1e-13)
def test_NRTL_gammas_binaries_vs_object(): GE = NRTL(T=343.15, xs=[.2, .8], tau_bs=[[0, -61.02497992981518], [673.2359767158717, 0]], alpha_cs=[[0, 0.2974], [0.35, 0]]) gammas_calc = NRTL_gammas_binaries(GE.xs, GE.taus()[0][1], GE.taus()[1][0], GE.alphas()[0][1], GE.alphas()[1][0]) assert_close1d(gammas_calc, GE.gammas(), rtol=1e-13)
def test_NRTL_numpy_output_correct_array_internal_ownership(): '''Without the array calls and the order bit, performance was probably bad and pypy gave a different object hash.''' alphas = [[[0.0, 2e-05], [0.2937, 7e-05], [0.2999, 0.0001]], [[0.2937, 1e-05], [0.0, 4e-05], [0.3009, 8e-05]], [[0.2999, 1e-05], [0.3009, 3e-05], [0.0, 5e-05]]] taus = [[[6e-05, 0.0, 7e-05, 7e-05, 0.00788, 3.6e-07], [3e-05, 624.868, 9e-05, 7e-05, 0.00472, 8.5e-07], [3e-05, 398.953, 4e-05, 1e-05, 0.00279, 5.6e-07]], [[1e-05, -29.167, 8e-05, 9e-05, 0.00256, 1e-07], [2e-05, 0.0, 7e-05, 6e-05, 0.00587, 4.2e-07], [0.0, -35.482, 8e-05, 4e-05, 0.00889, 8.2e-07]], [[9e-05, -95.132, 6e-05, 1e-05, 0.00905, 5.2e-07], [9e-05, 33.862, 2e-05, 6e-05, 0.00517, 1.4e-07], [0.0001, 0.0, 6e-05, 2e-05, 0.00095, 7.4e-07]]] N = 3 T = 273.15 + 70 dT = T * 1e-8 xs = [.2, .3, .5] modelnp = NRTL(T=T, xs=np.array(xs), tau_coeffs=np.array(taus), alpha_coeffs=np.array(alphas)) for name in ('tau_as', 'tau_bs', 'tau_es', 'tau_fs', 'tau_gs', 'tau_hs', 'alpha_cs', 'alpha_ds'): obj = getattr(modelnp, name) assert obj.flags.c_contiguous assert obj.flags.owndata
def test_madeup_NRTL(): N = 6 alphas = make_alphas(N) taus = make_taus(N) xs = normalize([random() for i in range(N)]) T = 350.0 GE = NRTL(T, xs, taus, alphas)
def test_NRTL_one_component(): GE = NRTL(T=350.0, xs=[1.0], ABEFGHCD=([[0.0]], [[0.0]], [[0.0]], [[0.0]], [[0.0]], [[0.0]], [[0.0]], [[0.0]])) for s in GE._point_properties: if hasattr(GE, s): res = getattr(GE, s)()
def test_NRTL_numpy_output(): alphas = [[[0.0, 2e-05], [0.2937, 7e-05], [0.2999, 0.0001]], [[0.2937, 1e-05], [0.0, 4e-05], [0.3009, 8e-05]], [[0.2999, 1e-05], [0.3009, 3e-05], [0.0, 5e-05]]] taus = [[[6e-05, 0.0, 7e-05, 7e-05, 0.00788, 3.6e-07], [3e-05, 624.868, 9e-05, 7e-05, 0.00472, 8.5e-07], [3e-05, 398.953, 4e-05, 1e-05, 0.00279, 5.6e-07]], [[1e-05, -29.167, 8e-05, 9e-05, 0.00256, 1e-07], [2e-05, 0.0, 7e-05, 6e-05, 0.00587, 4.2e-07], [0.0, -35.482, 8e-05, 4e-05, 0.00889, 8.2e-07]], [[9e-05, -95.132, 6e-05, 1e-05, 0.00905, 5.2e-07], [9e-05, 33.862, 2e-05, 6e-05, 0.00517, 1.4e-07], [0.0001, 0.0, 6e-05, 2e-05, 0.00095, 7.4e-07]]] N = 3 T = 273.15 + 70 dT = T * 1e-8 xs = [.2, .3, .5] model = NRTL(T, xs, taus, alphas) modelnp = NRTL(T=T, xs=np.array(xs), tau_coeffs=np.array(taus), alpha_coeffs=np.array(alphas)) modelnp2 = modelnp.to_T_xs(T=T, xs=np.array(xs)) check_np_output_activity(model, modelnp, modelnp2) json_string = modelnp.as_json() new = NRTL.from_json(json_string) assert new == modelnp assert model.model_hash() == modelnp.model_hash() assert new.model_hash() == modelnp.model_hash() assert new.model_hash() == modelnp2.model_hash() # Pickle checks modelnp_pickle = pickle.loads(pickle.dumps(modelnp)) assert modelnp_pickle == modelnp model_pickle = pickle.loads(pickle.dumps(model)) assert model_pickle == model
def test_NRTL_regression_basics(): # ethanol-water GE = UNIFAC.from_subgroups(T=298.15, xs=[.9, .1], chemgroups=[{ 1: 1, 2: 1, 14: 1 }, { 16: 1 }]) pts = 10 xs_points = [[xi, 1 - xi] for xi in linspace(0.01, 0.99, pts)] many_gammas_expect = [ GE.to_T_xs(T=GE.T, xs=xs_points[i]).gammas() for i in range(pts) ] res, stats = NRTL.regress_binary_parameters(gammas=many_gammas_expect, xs=xs_points, use_numba=False, symmetric_alphas=True, multiple_tries=False) assert_close(res['tau12'], 0.38703486403040827) assert_close(res['tau21'], 1.7353246253228976) assert_close(res['alpha12'], 0.64618267549806) assert stats['MAE'] < 0.01 # Regression without symmetry res, stats = NRTL.regress_binary_parameters(gammas=many_gammas_expect, xs=xs_points, use_numba=False, symmetric_alphas=False, multiple_tries=False) assert_close(res['tau12'], 0.229234995043471) assert_close(res['tau21'], 1.974654718742523) assert_close(res['alpha12'], 6.207804509017788) assert_close(res['alpha21'], 0.4898957291346906) assert stats['MAE'] < 0.001
def test_NRTL_partial_inputs(): from fluids.constants import R, calorie N = 2 T = 70.0 + 273.15 xs = [0.252, 0.748] tau_bs = [[0, -121.2691 / R * calorie], [1337.8574 / R * calorie, 0]] alpha_cs = [[0, 0.2974], [.2974, 0]] GE = NRTL(T=T, xs=xs, tau_bs=tau_bs, alpha_cs=alpha_cs) gammas_expect = [1.936051651447544, 1.1536630452052914] assert_close1d(GE.gammas(), gammas_expect, rtol=1e-13) # String tests s = str(GE) assert 'tau_cs' not in s assert 'alpha_ds' not in s with pytest.raises(ValueError): NRTL(T=T, xs=xs, tau_bs=tau_bs, alpha_cs=alpha_cs, alpha_ds=[[0], [.2974, 0]]) with pytest.raises(ValueError): NRTL(T=T, xs=xs, tau_bs=tau_bs, alpha_cs=alpha_cs, tau_es=[[0], [.2974, 0]]) with pytest.raises(ValueError): NRTL(T=T, xs=xs, tau_bs=tau_bs, alpha_cs=alpha_cs, tau_es=[[0, 3]]) with pytest.raises(ValueError): NRTL(T=T, xs=xs, tau_bs=tau_bs, alpha_cs=alpha_cs, tau_es=[None, 3]) with pytest.raises(ValueError): NRTL(T=T, xs=xs, tau_bs=tau_bs, alpha_cs=alpha_cs, ABEFGHCD=(tau_bs, ))
def test_NRTL_ideal_ones(): T = 70.0 + 273.15 xs = [0.252, 0.748] GE = NRTL(T=T, xs=xs) assert_close1d(GE.gammas(), [1.0, 1.0], rtol=1e-13)
def test_water_ethanol_methanol_madeup(): alphas = [[[0.0, 2e-05], [0.2937, 7e-05], [0.2999, 0.0001]], [[0.2937, 1e-05], [0.0, 4e-05], [0.3009, 8e-05]], [[0.2999, 1e-05], [0.3009, 3e-05], [0.0, 5e-05]]] taus = [[[6e-05, 0.0, 7e-05, 7e-05, 0.00788, 3.6e-07], [3e-05, 624.868, 9e-05, 7e-05, 0.00472, 8.5e-07], [3e-05, 398.953, 4e-05, 1e-05, 0.00279, 5.6e-07]], [[1e-05, -29.167, 8e-05, 9e-05, 0.00256, 1e-07], [2e-05, 0.0, 7e-05, 6e-05, 0.00587, 4.2e-07], [0.0, -35.482, 8e-05, 4e-05, 0.00889, 8.2e-07]], [[9e-05, -95.132, 6e-05, 1e-05, 0.00905, 5.2e-07], [9e-05, 33.862, 2e-05, 6e-05, 0.00517, 1.4e-07], [0.0001, 0.0, 6e-05, 2e-05, 0.00095, 7.4e-07]]] N = 3 T = 273.15 + 70 dT = T * 1e-8 xs = [.2, .3, .5] GE = NRTL(T, xs, taus, alphas) assert eval(str(GE)).GE() == GE.GE() assert NRTL.from_json(GE.as_json()).__dict__ == GE.__dict__ GEnp = NRTL(T, np.array(xs), np.array(taus), np.array(alphas)) assert_close(GEnp.GE(), GE.GE(), rtol=1e-12) # gammas assert_close1d( GE.gammas(), [1.7795902383749216, 1.1495597830749005, 1.0736702352016942]) assert_close1d(GEnp.gammas(), GE.gammas(), rtol=1e-12) ### Tau and derivatives taus_expected = [ [0.06687993075720595, 1.9456413587531054, 1.2322559725492486], [-0.04186204696272491, 0.07047352903742096, 0.007348860249786843], [-0.21212866478360642, 0.13596095401379812, 0.0944497207779701] ] assert_close2d(taus_expected, GE.taus(), rtol=1e-14) # Tau temperature derivative dtaus_dT_numerical = (np.array(GE.to_T_xs(T + dT, xs).taus()) - GE.taus()) / dT dtaus_dT_analytical = GE.dtaus_dT() dtaus_dT_expected = [[ 0.000317271602387579, -0.004653030923421638, -0.0029936361350323625 ], [0.000406561723402744, 0.00034844970187634483, 0.0009043271077256468], [ 0.0011749522864265571, -0.00013143064874333648, 0.0005280368036263511 ]] assert_close2d(dtaus_dT_analytical, dtaus_dT_expected, rtol=1e-12) assert_close2d(dtaus_dT_numerical, dtaus_dT_analytical, rtol=4e-7) # tau second derivative d2taus_dT2_analytical = GE.d2taus_dT2() d2taus_dT2_expected = [[ 7.194089397742681e-07, 3.2628265646047626e-05, 2.0866597625703075e-05 ], [ -1.2443543228779117e-06, 8.394080699905074e-07, -1.169244972344292e-07 ], [-3.669244570181493e-06, 1.955896362917401e-06, 1.4794908652710361e-06]] assert_close2d(d2taus_dT2_analytical, d2taus_dT2_expected, rtol=1e-12) d2taus_dT2_numerical = (np.array(GE.to_T_xs(T + dT, xs).dtaus_dT()) - GE.dtaus_dT()) / dT assert_close2d(d2taus_dT2_analytical, d2taus_dT2_numerical, rtol=4e-7) # tau third derivative d3taus_dT3_analytical = GE.d3taus_dT3() d3taus_dT3_expected = [[ 3.425034691577827e-12, -2.703935984244539e-07, -1.7263626338812435e-07 ], [1.2625331389834536e-08, 3.4351735085462344e-12, 1.535797829031479e-08], [ 4.116922701015044e-08, -1.4652079774338131e-08, 2.9650219270685846e-12 ]] # Not sure why precision of numerical test is so low, but confirmed with sympy. assert_close2d(d3taus_dT3_analytical, d3taus_dT3_expected, rtol=1e-12) d3taus_dT3_numerical = (np.array(GE.to_T_xs(T + dT, xs).d2taus_dT2()) - GE.d2taus_dT2()) / dT assert_close2d(d3taus_dT3_numerical, d3taus_dT3_analytical, rtol=2e-5) # alphas alphas_expect = [[0.006863, 0.3177205, 0.334215], [0.2971315, 0.013726, 0.328352], [0.3033315, 0.3111945, 0.0171575]] assert_close2d(alphas_expect, GE.alphas(), rtol=1e-12) # dalphas_dT dalphas_dT_expect = [[2e-05, 7e-05, 0.0001], [1e-05, 4e-05, 8e-05], [1e-05, 3e-05, 5e-05]] dalphas_dT_analytical = GE.dalphas_dT() assert_close2d(dalphas_dT_expect, dalphas_dT_analytical, rtol=1e-12) dalphas_dT_numerical = (np.array(GE.to_T_xs(T + 1e-4, xs).alphas()) - GE.alphas()) / 1e-4 assert_close2d(dalphas_dT_expect, dalphas_dT_numerical) # d2alphas_d2T d2alphas_d2T_numerical = (np.array(GE.to_T_xs(T + dT, xs).dalphas_dT()) - GE.dalphas_dT()) / dT d2alphas_d2T_analytical = GE.d2alphas_dT2() assert_close2d(d2alphas_d2T_analytical, [[0] * N for _ in range(N)]) assert_close2d(d2alphas_d2T_numerical, d2alphas_d2T_analytical, rtol=1e-12) # d3alphas_d3T d3alphas_d3T_numerical = (np.array(GE.to_T_xs(T + dT, xs).d2alphas_dT2()) - GE.d2alphas_dT2()) / dT d3alphas_d3T_analytical = GE.d3alphas_dT3() assert_close2d(d3alphas_d3T_analytical, [[0] * N for _ in range(N)]) assert_close2d(d3alphas_d3T_numerical, d3alphas_d3T_analytical, rtol=1e-12) # Gs Gs_expect = [[0.9995411083582052, 0.5389296989069797, 0.6624312965198783], [1.0125162130984628, 0.999033148043276, 0.9975898960147673], [1.0664605905163351, 0.9585722883795924, 0.9983807912510595]] assert_close2d(Gs_expect, GE.Gs()) # dGs_dT dGs_dT_expect = [[ -3.513420602780159e-06, 0.0007233344205287423, 0.000581146010596799 ], [ -0.00012189042196807427, -7.594411991210204e-06, -0.00029680845584651057 ], [ -0.000377824327942326, 3.529622902294454e-05, -1.3759961112813966e-05 ]] dGs_dT_analytical = GE.dGs_dT() assert_close2d(dGs_dT_expect, dGs_dT_analytical, rtol=1e-12) dGs_dT_numerical = (np.array(GE.to_T_xs(T + 2.5e-5, xs).Gs()) - GE.Gs()) / 2.5e-5 assert_close2d(dGs_dT_numerical, dGs_dT_expect, rtol=3e-7) # Closest I could get # d2Gs_dT2 d2Gs_dT2_expect = [[ -1.7607728438831442e-08, -4.264997204215131e-06, -3.7132987505208185e-06 ], [ 3.808051820202208e-07, -3.9301868673119065e-08, -1.773565965539868e-08 ], [1.2957622532360591e-06, -5.745898135094948e-07, -7.78717985147786e-08]] d2Gs_dT2_analytical = GE.d2Gs_dT2() assert_close2d(d2Gs_dT2_expect, d2Gs_dT2_analytical, rtol=1e-12) d2Gs_dT2_numerical = (np.array(GE.to_T_xs(T + 4e-6, xs).dGs_dT()) - GE.dGs_dT()) / 4e-6 assert_close2d(d2Gs_dT2_numerical, d2Gs_dT2_analytical, rtol=2e-6) # d3Gs_dT3 d3Gs_dT3_analytical = GE.d3Gs_dT3() d3Gs_dT3_expect = [[ -4.298246167557067e-11, 2.282743128709054e-08, 2.3406412447900822e-08 ], [ -3.894534156411875e-09, -9.978151596051988e-11, -4.934296656436311e-09 ], [ -1.448282405010784e-08, 4.1384450135276364e-09, -2.1839009944794027e-10 ]] d3Gs_dT3_numerical = (np.array(GE.to_T_xs(T + dT, xs).d2Gs_dT2()) - GE.d2Gs_dT2()) / dT assert_close2d(d3Gs_dT3_analytical, d3Gs_dT3_numerical, rtol=1e-7) assert_close2d(d3Gs_dT3_expect, d3Gs_dT3_analytical, rtol=1e-12) # dGE_dT dGE_dT_expect = 2.258093406765717 dGE_dT_analytical = GE.dGE_dT() assert_close(dGE_dT_expect, dGE_dT_analytical, rtol=1e-12) def to_diff(T): return GE.to_T_xs(T, xs).GE() dGE_dT_numerical = derivative(to_diff, T, dx=1, order=17) assert_close(dGE_dT_analytical, dGE_dT_numerical, rtol=1e-12) # d2GE_dT2 def to_diff(T): return GE.to_T_xs(T, xs).dGE_dT() d2GE_dT2_numerical = derivative(to_diff, T, dx=5, order=17) d2GE_dT2_expected = 0.007412479461681191 d2GE_dT2_analytical = GE.d2GE_dT2() assert_close(d2GE_dT2_expected, d2GE_dT2_analytical, rtol=1e-12) assert_close(d2GE_dT2_numerical, d2GE_dT2_analytical, rtol=1e-12) # dGE_dxs def to_jac(xs): return GE.to_T_xs(T, xs).GE() dGE_dxs_analytical = GE.dGE_dxs() dGE_dxs_expected = [ 1644.4832445701338, 397.6635234141318, 202.8071951151063 ] assert_close1d(dGE_dxs_analytical, dGE_dxs_expected, rtol=1e-12) dGE_dxs_numerical = jacobian(to_jac, xs, perturbation=1e-8) assert_close1d(dGE_dxs_numerical, dGE_dxs_expected, rtol=1e-7) # d2GE_dxixjs - more decimals in numdifftools def to_hess(xs): return GE.to_T_xs(T, xs).GE() d2GE_dxixjs_expect = [ [-1690.7876619180952, 1208.6126803238276, -48.852543427058286], [1208.6126803238276, -468.99032836115686, -202.0508751128366], [-48.852543427058606, -202.0508751128365, 140.77154243852513] ] d2GE_dxixjs_analytical = GE.d2GE_dxixjs() assert_close2d(d2GE_dxixjs_expect, d2GE_dxixjs_analytical, rtol=1e-12) d2GE_dxixjs_numerical = hessian(to_hess, xs, perturbation=5e-5) assert_close2d(d2GE_dxixjs_numerical, d2GE_dxixjs_analytical, rtol=3e-4) # d2GE_dTdxs - matched really well d2GE_dTdxs_expect = [ 3.053720836458414, 1.8759446742883084, 2.1691316743750826 ] d2GE_dTdxs_analytical = GE.d2GE_dTdxs() assert_close1d(d2GE_dTdxs_expect, d2GE_dTdxs_analytical, rtol=1e-12) def to_jac(xs): return GE.to_T_xs(T, xs).dGE_dT() d2GE_dTdxs_numerical = jacobian(to_jac, xs, perturbation=3e-8) assert_close1d(d2GE_dTdxs_analytical, d2GE_dTdxs_numerical, rtol=1e-7)