def test_friction_Kumar(): from fluids.friction import Kumar_beta_list, Kumar_fd_Res fd = friction_plate_Kumar(2000, 30) assert_close(fd, 2.9760669055634517) all_ans_expect = [[[ 22.22222222222222, 18.900854099814858, 5.181226661414687, 5.139730745446174 ], [ 20.88888888888889, 17.09090909090909, 3.656954441625244, 3.609575756782771 ]], [[ 13.428571428571427, 12.000171923243482, 1.7788367041690634, 1.7788497785371564 ], [ 9.714285714285714, 8.5, 1.2332865464612235, 1.2320492987599356 ]], [[ 7.157894736842104, 6.590102034105372, 1.2332865464612235, 1.2320492987599356 ], [ 5.052631578947368, 4.571428571428571, 0.9576862861589914, 0.9547729646969146 ]], [[ 2.4615384615384617, 2.374448634025773, 0.8393834232628009, 0.8379103279437352 ], [ 2.4615384615384617, 2.3414634146341466, 0.7519331759748705, 0.7502394735017442 ]], [[ 1.9591836734693877, 1.9015330284979595, 0.6797898512309091, 0.6799788644298855 ], [ 1.9591836734693877, 1.9015330284979595, 0.6797898512309091, 0.6799788644298855 ]]] all_ans = [] for i, beta_main in enumerate(Kumar_beta_list): beta_ans = [] for beta in (beta_main - 1, beta_main + 1): Re_ans = [] for Re_main in Kumar_fd_Res[i]: for Re in [Re_main - 1, Re_main + 1]: ans = friction_plate_Kumar(Re, beta) Re_ans.append(ans) beta_ans.append(Re_ans) all_ans.append(beta_ans) assert_close3d(all_ans, all_ans_expect)
def check_numba_np_output_activity(model, modelnp, modelnp2): # model is flat, scalar, list-based model # modelnp is numba model # modelnp2 is created from the numba model with to_T_xs at a different composition vec_attrs = [ 'dGE_dxs', 'gammas', '_gammas_dGE_dxs', 'd2GE_dTdxs', 'dHE_dxs', 'gammas_infinite_dilution', 'dHE_dns', 'dnHE_dns', 'dSE_dxs', 'dSE_dns', 'dnSE_dns', 'dGE_dns', 'dnGE_dns', 'd2GE_dTdns', 'd2nGE_dTdns', 'dgammas_dT' ] for attr in vec_attrs: assert_close1d(getattr(model, attr)(), getattr(modelnp, attr)(), rtol=1e-13) assert_close1d(getattr(modelnp2, attr)(), getattr(modelnp, attr)(), rtol=1e-13) assert type(getattr(model, attr)()) is list assert type(getattr(modelnp, attr)()) is np.ndarray assert type(getattr(modelnp2, attr)()) is np.ndarray mat_attrs = ['d2GE_dxixjs', 'd2nGE_dninjs', 'dgammas_dns'] for attr in mat_attrs: assert_close2d(getattr(model, attr)(), getattr(modelnp, attr)(), rtol=1e-13) assert_close2d(getattr(modelnp2, attr)(), getattr(modelnp, attr)(), rtol=1e-13) assert type(getattr(model, attr)()) is list assert type(getattr(modelnp, attr)()) is np.ndarray assert type(getattr(modelnp2, attr)()) is np.ndarray attrs_3d = ['d3GE_dxixjxks'] for attr in attrs_3d: if hasattr(model, attr): # some models do not have this implemented assert_close3d(getattr(model, attr)(), getattr(modelnp, attr)(), rtol=1e-13) assert_close3d(getattr(modelnp2, attr)(), getattr(modelnp, attr)(), rtol=1e-13) assert type(getattr(model, attr)()) is list assert type(getattr(modelnp, attr)()) is np.ndarray assert type(getattr(modelnp2, attr)()) is np.ndarray
def test_4_components(): # m = Mixture(['acetone', 'chloroform', 'methanol', 'water'], zs=xs, T=300) xs = [.4, .3, .2, .1] SPs = [19570.2, 18864.7, 29261.4, 47863.5] Vs = [7.421e-05, 8.068e-05, 4.083e-05, 1.808e-05] N = 4 T = 300.0 # Made up asymmetric parameters lambda_coeffs = [[0.0, 0.01811, 0.01736, 0.02111], [0.00662, 0.0, 0.00774, 0.01966], [0.01601, 0.01022, 0.0, 0.00698], [0.0152, 0.00544, 0.02579, 0.0]] GE = RegularSolution(T, xs, Vs, SPs, lambda_coeffs) assert eval(str(GE)).GE() == GE.GE() dT = 1e-7 * T gammas_expect = [ 1.1928784349228994, 1.3043087978251762, 3.2795596493820955, 197.92137114651274 ] assert_close1d(GE.gammas(), gammas_expect, rtol=1e-12) assert_close1d(GibbsExcess.gammas(GE), gammas_expect) # Gammas assert_close(GE.GE(), 2286.257263714889, rtol=1e-12) gammas = GE.gammas() GE_from_gammas = R * T * sum(xi * log(gamma) for xi, gamma in zip(xs, gammas)) assert_close(GE_from_gammas, GE.GE(), rtol=1e-12) # dGE dT dGE_dT_numerical = ( (np.array(GE.to_T_xs(T + dT, xs).GE()) - np.array(GE.GE())) / dT) dGE_dT_analytical = GE.dGE_dT() assert_close(dGE_dT_analytical, 0, rtol=1e-12, atol=1e-9) assert_close(dGE_dT_numerical, dGE_dT_analytical) # d2GE dT2 d2GE_dT2_numerical = ( (np.array(GE.to_T_xs(T + dT, xs).dGE_dT()) - np.array(GE.dGE_dT())) / dT) d2GE_dT2_analytical = GE.d2GE_dT2() assert_close(d2GE_dT2_analytical, 0, rtol=1e-12, atol=1e-9) assert_close(d2GE_dT2_analytical, d2GE_dT2_numerical, rtol=1e-8) # d3GE dT3 d3GE_dT3_numerical = ((np.array(GE.to_T_xs(T + dT, xs).d2GE_dT2()) - np.array(GE.d2GE_dT2())) / dT) d3GE_dT3_analytical = GE.d3GE_dT3() assert_close(d3GE_dT3_analytical, 0, rtol=1e-12, atol=1e-9) assert_close(d3GE_dT3_numerical, d3GE_dT3_analytical, rtol=1e-7) # d2GE_dTdxs def dGE_dT_diff(xs): return GE.to_T_xs(T, xs).dGE_dT() d2GE_dTdxs_numerical = jacobian(dGE_dT_diff, xs, perturbation=1e-7) d2GE_dTdxs_analytical = GE.d2GE_dTdxs() d2GE_dTdxs_expect = [0] * 4 assert_close1d(d2GE_dTdxs_analytical, d2GE_dTdxs_expect, rtol=1e-12) assert_close1d(d2GE_dTdxs_numerical, d2GE_dTdxs_analytical, rtol=1e-7) # dGE_dxs def dGE_dx_diff(xs): return GE.to_T_xs(T, xs).GE() dGE_dxs_numerical = jacobian(dGE_dx_diff, xs, perturbation=1e-7) dGE_dxs_analytical = GE.dGE_dxs() dGE_dxs_expect = [ 439.92463410596037, 662.6790758115604, 2962.5490239819123, 13189.738825326536 ] assert_close1d(dGE_dxs_analytical, dGE_dxs_expect, rtol=1e-12) assert_close1d(dGE_dxs_analytical, dGE_dxs_numerical, rtol=1e-7) # d2GE_dxixjs d2GE_dxixjs_numerical = hessian(dGE_dx_diff, xs, perturbation=1e-5) d2GE_dxixjs_analytical = GE.d2GE_dxixjs() d2GE_dxixjs_expect = [[ -1022.4173091041094, -423.20895951381453, 1638.9017092099375, 2081.4926965380164 ], [ -423.20895951381453, -1674.3900233778054, 1920.6043029143648, 2874.797302359955 ], [ 1638.901709209937, 1920.6043029143648, -3788.1956922483323, -4741.028361086175 ], [ 2081.4926965380164, 2874.797302359955, -4741.028361086175, -7468.305971059591 ]] d2GE_dxixjs_sympy = [[ -1022.4173091041112, -423.208959513817, 1638.9017092099352, 2081.492696538016 ], [ -423.208959513817, -1674.3900233778083, 1920.6043029143652, 2874.7973023599534 ], [ 1638.9017092099352, 1920.6043029143652, -3788.1956922483323, -4741.028361086176 ], [ 2081.492696538016, 2874.7973023599534, -4741.028361086176, -7468.305971059591 ]] assert_close2d(d2GE_dxixjs_analytical, d2GE_dxixjs_sympy, rtol=1e-12) assert_close2d(d2GE_dxixjs_analytical, d2GE_dxixjs_expect, rtol=1e-12) assert_close2d(d2GE_dxixjs_analytical, d2GE_dxixjs_numerical, rtol=2.5e-4) d3GE_dxixjxks_analytical = GE.d3GE_dxixjxks() d3GE_dxixjxks_sympy = [[[ 3564.2598967437325, 2275.2388316927168, -3155.248707372427, -4548.085576267108 ], [ 2275.2388316927168, 3015.024292098843, -4031.740524903445, -5850.4575581223535 ], [ -3155.248707372427, -4031.740524903445, 2306.3682432066844, 3714.462825687298 ], [ -4548.085576267108, -5850.4575581223535, 3714.462825687298, 7499.862362680743 ]], [[ 2275.2388316927168, 3015.024292098843, -4031.740524903445, -5850.4575581223535 ], [ 3015.024292098843, 6346.017369615182, -3782.270609497761, -6789.70782446731 ], [ -4031.740524903445, -3782.270609497761, 2329.947090204009, 3607.836718555389 ], [ -5850.4575581223535, -6789.70782446731, 3607.836718555389, 7807.307245181044 ]], [[ -3155.248707372427, -4031.740524903445, 2306.3682432066844, 3714.462825687298 ], [ -4031.740524903445, -3782.270609497761, 2329.947090204009, 3607.836718555389 ], [ 2306.3682432066844, 2329.947090204009, 7265.918548487337, 7134.805582069884 ], [ 3714.462825687298, 3607.836718555389, 7134.805582069884, 7459.310988306651 ]], [[ -4548.085576267108, -5850.4575581223535, 3714.462825687298, 7499.862362680743 ], [ -5850.4575581223535, -6789.70782446731, 3607.836718555389, 7807.307245181044 ], [ 3714.462825687298, 3607.836718555389, 7134.805582069884, 7459.310988306651 ], [ 7499.862362680743, 7807.307245181044, 7459.310988306651, 6343.066547716518 ]]] assert_close3d(d3GE_dxixjxks_analytical, d3GE_dxixjxks_sympy, rtol=1e-12)
def test_DDBST_example(): # One good numerical example - acetone, chloroform, methanol T = 331.42 N = 3 Vs_ddbst = [74.04, 80.67, 40.73] as_ddbst = [[0, 375.2835, 31.1208], [-1722.58, 0, -1140.79], [747.217, 3596.17, 0.0]] bs_ddbst = [[0, -3.78434, -0.67704], [6.405502, 0, 2.59359], [-0.256645, -6.2234, 0]] cs_ddbst = [[0.0, 7.91073e-3, 8.68371e-4], [-7.47788e-3, 0.0, 3.1e-5], [-1.24796e-3, 3e-5, 0.0]] dis = eis = fis = [[0.0] * N for _ in range(N)] params = Wilson.from_DDBST_as_matrix(Vs=Vs_ddbst, ais=as_ddbst, bis=bs_ddbst, cis=cs_ddbst, dis=dis, eis=eis, fis=fis, unit_conversion=False) A_expect = [[0.0, 3.870101271243586, 0.07939943395502425], [-6.491263271243587, 0.0, -3.276991837288562], [0.8542855660449756, 6.906801837288562, 0.0]] B_expect = [[0.0, -375.2835, -31.1208], [1722.58, 0.0, 1140.79], [-747.217, -3596.17, -0.0]] D_expect = [[-0.0, -0.00791073, -0.000868371], [0.00747788, -0.0, -3.1e-05], [0.00124796, -3e-05, -0.0]] C_expect = E_expect = F_expect = [[0.0] * N for _ in range(N)] assert_close2d(params[0], A_expect, rtol=1e-12, atol=0) assert_close2d(params[1], B_expect, rtol=1e-12, atol=0) assert_close2d(params[2], C_expect, rtol=1e-12, atol=0) assert_close2d(params[3], D_expect, rtol=1e-12, atol=0) assert_close2d(params[4], E_expect, rtol=1e-12, atol=0) assert_close2d(params[5], F_expect, rtol=1e-12, atol=0) xs = [0.229, 0.175, 0.596] GE = Wilson(T=T, xs=xs, ABCDEF=params) # Test __repr__ contains the needed information assert eval(str(GE)).GE() == GE.GE() GE2 = Wilson.from_JSON(GE.as_JSON()) assert GE2.__dict__ == GE.__dict__ gammas_expect = [1.223393433488855, 1.1009459024701462, 1.2052899281172034] assert_close1d(GE.gammas(), gammas_expect, rtol=1e-12) assert_close1d(GibbsExcess.gammas(GE), gammas_expect) lambdas = GE.lambdas() lambdas_expect = [[1.0, 1.1229699812593041, 0.7391181616283594], [3.2694762162029805, 1.0, 1.1674967844769508], [0.37280197780931773, 0.019179096486191153, 1.0]] assert_close2d(lambdas, lambdas_expect, rtol=1e-12) dlambdas_dT = GE.dlambdas_dT() dlambdas_dT_expect = [[0.0, -0.005046703220379676, -0.0004324140595259853], [-0.026825598419319092, 0.0, -0.012161812924715213], [0.003001348681882189, 0.0006273541924400231, 0.0]] assert_close2d(dlambdas_dT, dlambdas_dT_expect) dT = T * 1e-8 dlambdas_dT_numerical = (np.array(GE.to_T_xs(T + dT, xs).lambdas()) - GE.to_T_xs(T, xs).lambdas()) / dT assert_close2d(dlambdas_dT, dlambdas_dT_numerical, rtol=1e-7) d2lambdas_dT2 = GE.d2lambdas_dT2() d2lambdas_dT2_expect = [ [0.0, -4.73530781420922e-07, -1.0107624477842068e-06], [0.000529522489227112, 0.0, 0.0001998633344112975], [8.85872572550323e-06, 1.6731622007033546e-05, 0.0] ] assert_close2d(d2lambdas_dT2, d2lambdas_dT2_expect, rtol=1e-12) d2lambdas_dT2_numerical = (np.array(GE.to_T_xs(T + dT, xs).dlambdas_dT()) - GE.to_T_xs(T, xs).dlambdas_dT()) / dT assert_close2d(d2lambdas_dT2, d2lambdas_dT2_numerical, rtol=2e-5) d3lambdas_dT3 = GE.d3lambdas_dT3() d3lambdas_dT3_expect = [ [0.0, 4.1982403087995867e-07, 1.3509359183777608e-08], [-1.2223067176509094e-05, 0.0, -4.268843384910971e-06], [-3.6571009680721684e-08, 3.3369718709496133e-07, 0.0] ] assert_close2d(d3lambdas_dT3, d3lambdas_dT3_expect, rtol=1e-12) d3lambdas_dT3_numerical = ( np.array(GE.to_T_xs(T + dT, xs).d2lambdas_dT2()) - GE.to_T_xs(T, xs).d2lambdas_dT2()) / dT assert_close2d(d3lambdas_dT3, d3lambdas_dT3_numerical, rtol=1e-7) # Gammas assert_allclose(GE.GE(), 480.2639266306882, rtol=1e-12) gammas = GE.gammas() GE_from_gammas = R * T * sum(xi * log(gamma) for xi, gamma in zip(xs, gammas)) assert_close(GE_from_gammas, GE.GE(), rtol=1e-12) # dGE dT dGE_dT_numerical = ( (np.array(GE.to_T_xs(T + dT, xs).GE()) - np.array(GE.GE())) / dT) dGE_dT_analytical = GE.dGE_dT() assert_close(dGE_dT_analytical, 4.355962766232997, rtol=1e-12) assert_close(dGE_dT_numerical, dGE_dT_analytical) # d2GE dT2 d2GE_dT2_numerical = ( (np.array(GE.to_T_xs(T + dT, xs).dGE_dT()) - np.array(GE.dGE_dT())) / dT) d2GE_dT2_analytical = GE.d2GE_dT2() assert_close(d2GE_dT2_analytical, -0.02913038452501723, rtol=1e-12) assert_close(d2GE_dT2_analytical, d2GE_dT2_numerical, rtol=1e-8) # d3GE dT3 d3GE_dT3_numerical = ((np.array(GE.to_T_xs(T + dT, xs).d2GE_dT2()) - np.array(GE.d2GE_dT2())) / dT) d3GE_dT3_analytical = GE.d3GE_dT3() assert_close(d3GE_dT3_analytical, -0.00019988744724590656, rtol=1e-12) assert_close(d3GE_dT3_numerical, d3GE_dT3_analytical, rtol=1e-7) # d2GE_dTdxs def dGE_dT_diff(xs): return GE.to_T_xs(T, xs).dGE_dT() d2GE_dTdxs_numerical = jacobian(dGE_dT_diff, xs, perturbation=1e-7) d2GE_dTdxs_analytical = GE.d2GE_dTdxs() d2GE_dTdxs_expect = [ -10.187806161151178, 13.956324059647034, -6.825249918548414 ] assert_close1d(d2GE_dTdxs_analytical, d2GE_dTdxs_expect, rtol=1e-12) assert_close1d(d2GE_dTdxs_numerical, d2GE_dTdxs_analytical, rtol=1e-7) # dGE_dxs def dGE_dx_diff(xs): return GE.to_T_xs(T, xs).GE() dGE_dxs_numerical = jacobian(dGE_dx_diff, xs, perturbation=1e-7) dGE_dxs_analytical = GE.dGE_dxs() dGE_dxs_expect = [ -2199.97589893946, -2490.5759162306463, -2241.05706053718 ] assert_close1d(dGE_dxs_analytical, dGE_dxs_expect, rtol=1e-12) assert_close1d(dGE_dxs_analytical, dGE_dxs_numerical, rtol=1e-7) # d2GE_dxixjs d2GE_dxixjs_numerical = hessian(dGE_dx_diff, xs, perturbation=1e-5) d2GE_dxixjs_analytical = GE.d2GE_dxixjs() d2GE_dxixjs_expect = [ [-3070.205333938506, -7565.029777297412, -1222.5200812237945], [-7565.029777297412, -2156.7810946064815, -1083.4743126696396], [-1222.5200812237945, -1083.4743126696396, -3835.5941234746824] ] assert_close2d(d2GE_dxixjs_analytical, d2GE_dxixjs_expect, rtol=1e-12) assert_close2d(d2GE_dxixjs_analytical, d2GE_dxixjs_numerical, rtol=1e-4) # d3GE_dxixjxks - very limited accuracy. def d2GE_dxixj_diff(xs): return GE.to_T_xs(T, xs).dGE_dxs() d3GE_dxixjxks_numerical = hessian(d2GE_dxixj_diff, xs, perturbation=2e-5, scalar=False) d3GE_dxixjxks_analytical = GE.d3GE_dxixjxks() d3GE_dxixjxks_expect = [ [[614.0681113650099, 14845.66663517824, 556.3625424156468], [14845.66663517824, 8308.935636377626, 4549.175136703878], [556.3625424156469, 4549.175136703878, 501.6902853815983]], [[14845.66663517824, 8308.935636377626, 4549.175136703878], [8308.935636377626, 173.08338078843053, 375.4114802651511], [4549.175136703877, 375.411480265151, -40.24127966770044]], [[556.3625424156469, 4549.175136703877, 501.6902853815977], [4549.175136703877, 375.411480265151, -40.241279667700574], [501.6902853815964, -40.24127966770071, 6254.612872590844]] ] assert_close3d(d3GE_dxixjxks_analytical, d3GE_dxixjxks_expect, rtol=1e-12) assert_close3d(d3GE_dxixjxks_numerical, d3GE_dxixjxks_analytical, rtol=1e-3) ### TEST WHICH ARE COMMON TO ALL GibbsExcess classes HE_expected = -963.3892533542517 HE_analytical = GE.HE() assert_allclose(HE_expected, HE_analytical, rtol=1e-12) def diff_for_HE(T): return GE.to_T_xs(T, xs).GE() / T HE_numerical = -derivative(diff_for_HE, T, order=13) * T**2 assert_close(HE_analytical, HE_numerical, rtol=1e-12) SE_expected = -4.355962766232997 SE_analytical = GE.SE() assert_allclose(SE_expected, SE_analytical, rtol=1e-12) SE_check = (GE.HE() - GE.GE()) / T assert_close(SE_analytical, SE_check, rtol=1e-12) def diff_for_Cp(T): return GE.to_T_xs(T, xs).HE() Cp_expected = 9.65439203928121 Cp_analytical = GE.CpE() assert_close(Cp_expected, Cp_analytical, rtol=1e-12) Cp_numerical = derivative(diff_for_Cp, T, order=13) assert_close(Cp_numerical, Cp_analytical, rtol=1e-12) def diff_for_dS_dT(T): return GE.to_T_xs(T, xs).SE() dS_dT_expected = 0.02913038452501723 dS_dT_analytical = GE.dSE_dT() assert_close(dS_dT_expected, dS_dT_analytical, rtol=1e-12) dS_dT_numerical = derivative(diff_for_dS_dT, T, order=9) assert_close(dS_dT_analytical, dS_dT_numerical, rtol=1e-12) def diff_for_dHE_dx(xs): return GE.to_T_xs(T, xs).HE() dHE_dx_expected = [ 1176.4668189892636, -7115.980836078867, 20.96726746813556 ] dHE_dx_analytical = GE.dHE_dxs() assert_close1d(dHE_dx_expected, dHE_dx_analytical, rtol=1e-12) dHE_dx_numerical = jacobian(diff_for_dHE_dx, xs, perturbation=5e-7) assert_close1d(dHE_dx_expected, dHE_dx_numerical, rtol=4e-6) def diff_for_dHE_dn(xs): xs = normalize(xs) return GE.to_T_xs(T, xs).HE() dHE_dn_expected = [ 2139.856072343515, -6152.591582724615, 984.3565208223869 ] dHE_dn_analytical = GE.dHE_dns() assert_close1d(dHE_dn_expected, dHE_dn_analytical, rtol=1e-12) dHE_dn_numerical = jacobian(diff_for_dHE_dn, xs, perturbation=5e-7) assert_close1d(dHE_dn_expected, dHE_dn_numerical, rtol=1e-6) def diff_for_dnHE_dn(xs): nt = sum(xs) xs = normalize(xs) return nt * GE.to_T_xs(T, xs).HE() dnHE_dn_expected = [ 1176.4668189892634, -7115.980836078867, 20.967267468135258 ] dnHE_dn_analytical = GE.dnHE_dns() assert_close1d(dnHE_dn_expected, dnHE_dn_analytical, rtol=1e-12) dnHE_dn_numerical = jacobian(diff_for_dnHE_dn, xs, perturbation=5e-7) assert_close1d(dnHE_dn_analytical, dnHE_dn_numerical, rtol=2e-6) def diff_for_dSE_dx(xs): return GE.to_T_xs(T, xs).SE() dSE_dx_expected = [ 10.187806161151178, -13.956324059647036, 6.825249918548415 ] dSE_dx_analytical = GE.dSE_dxs() assert_close1d(dSE_dx_expected, dSE_dx_analytical, rtol=1e-12) dSE_dx_numerical = jacobian(diff_for_dSE_dx, xs, perturbation=5e-7) assert_close1d(dSE_dx_expected, dSE_dx_numerical, rtol=4e-6) def diff_for_dSE_dns(xs): xs = normalize(xs) return GE.to_T_xs(T, xs).SE() dSE_dns_expected = [ 6.2293063092309335, -17.91482391156728, 2.8667500666281707 ] dSE_dns_analytical = GE.dSE_dns() assert_close1d(dSE_dns_expected, dSE_dns_analytical, rtol=1e-12) dSE_dns_numerical = jacobian(diff_for_dSE_dns, xs, perturbation=5e-7) assert_close1d(dSE_dns_expected, dSE_dns_numerical, rtol=1e-6) def diff_for_dnSE_dn(xs): nt = sum(xs) xs = normalize(xs) return nt * GE.to_T_xs(T, xs).SE() dnSE_dn_expected = [ 1.8733435429979384, -22.270786677800274, -1.489212699604825 ] dnSE_dn_analytical = GE.dnSE_dns() assert_close1d(dnSE_dn_expected, dnSE_dn_analytical, rtol=1e-12) dnSE_dn_numerical = jacobian(diff_for_dnSE_dn, xs, perturbation=5e-7) assert_close1d(dnSE_dn_analytical, dnSE_dn_numerical, rtol=2e-6) def diff_for_dGE_dn(xs): xs = normalize(xs) return GE.to_T_xs(T, xs).GE() dGE_dn_expected = [75.3393753381988, -215.2606419529875, 34.25821374047882] dGE_dn_analytical = GE.dGE_dns() assert_close1d(dGE_dn_expected, dGE_dn_analytical, rtol=1e-12) dGE_dn_numerical = jacobian(diff_for_dGE_dn, xs, perturbation=5e-7) assert_close1d(dGE_dn_expected, dGE_dn_numerical, rtol=1e-5) def diff_for_dnGE_dn(xs): nt = sum(xs) xs = normalize(xs) return nt * GE.to_T_xs(T, xs).GE() dnGE_dn_expected = [ 555.6033019688871, 265.0032846777008, 514.5221403711671 ] dnGE_dn_analytical = GE.dnGE_dns() assert_close1d(dnGE_dn_expected, dnGE_dn_analytical, rtol=1e-12) dnGE_dn_numerical = jacobian(diff_for_dnGE_dn, xs, perturbation=5e-7) assert_close1d(dnGE_dn_analytical, dnGE_dn_numerical, rtol=2e-6) lambdas = GE.lambdas() def gammas_to_diff(xs): xs = normalize(xs) return np.array(Wilson_gammas(xs, lambdas)) dgammas_dns_analytical = GE.dgammas_dns() dgammas_dn_numerical = jacobian(gammas_to_diff, xs, scalar=False) dgammas_dn_expect = [ [-0.13968444275751782, -2.135249914756224, 0.6806316652245148], [-1.9215360979146614, 0.23923983797040177, 0.668061736204089], [0.6705598284218852, 0.7313784266789759, -0.47239836472723573] ] assert_close2d(dgammas_dns_analytical, dgammas_dn_numerical, rtol=1e-5) assert_close2d(dgammas_dns_analytical, dgammas_dn_expect, rtol=1e-11) '''# Using numdifftools, the result was confirmed to the four last decimal places (rtol=12-13). from numdifftools import Jacobian (Jacobian(gammas_to_diff, step=1e-6, order=37)(xs)/dgammas_dns_analytical).tolist() ''' dgammas_dT_numerical = ( (np.array(GE.to_T_xs(T + dT, xs).gammas()) - np.array(GE.gammas())) / dT) dgammas_dT_analytical = GE.dgammas_dT() dgammas_dT_expect = [ -0.001575992756074107, 0.008578456201039092, -2.7672076632932624e-05 ] assert_close1d(dgammas_dT_analytical, dgammas_dT_expect, rtol=1e-12) assert_close1d(dgammas_dT_numerical, dgammas_dT_analytical, rtol=2e-6) d2GE_dTdns_expect = [ -6.229306309230934, 17.91482391156728, -2.8667500666281702 ] d2GE_dTdns_analytical = GE.d2GE_dTdns() d2GE_dTdns_numerical = ( (np.array(GE.to_T_xs(T + dT, xs).dGE_dns()) - np.array(GE.dGE_dns())) / dT) assert_close1d(d2GE_dTdns_expect, d2GE_dTdns_analytical, rtol=1e-12) assert_close1d(d2GE_dTdns_analytical, d2GE_dTdns_numerical, rtol=1e-7) d2nGE_dTdns_expect = [ -1.8733435429979375, 22.270786677800274, 1.4892126996048267 ] d2nGE_dTdns_analytical = GE.d2nGE_dTdns() d2nGE_dTdns_numerical = ((np.array(GE.to_T_xs(T + dT, xs).dnGE_dns()) - np.array(GE.dnGE_dns())) / dT) assert_close1d(d2nGE_dTdns_expect, d2nGE_dTdns_analytical, rtol=1e-12) assert_close1d(d2nGE_dTdns_analytical, d2nGE_dTdns_numerical, rtol=1e-6) def to_diff_dnGE2_dninj(ns): nt = sum(ns) xs = normalize(ns) return nt * GE.to_T_xs(T, xs).GE() d2nGE_dninjs_numerical = hessian(to_diff_dnGE2_dninj, xs, perturbation=4e-5) d2nGE_dninjs_analytical = GE.d2nGE_dninjs() d2nGE_dninjs_expect = [ [-314.62613303015996, -4809.450576389065, 1533.0591196845521], [-4809.450576389066, 598.7981063018656, 1672.104888238707], [1533.0591196845517, 1672.1048882387074, -1080.0149225663358] ] assert_close2d(d2nGE_dninjs_analytical, d2nGE_dninjs_expect, rtol=1e-12) assert_close2d(d2nGE_dninjs_numerical, d2nGE_dninjs_analytical, rtol=1e-4) # Test with some results stored GE2 = Wilson.from_JSON(GE.as_JSON()) assert GE2.__dict__ == GE.__dict__
def test_UNIQUAC_madeup_ternary(): N = 3 T = 331.42 xs = [0.229, 0.175, 0.596] rs = [2.5735, 2.87, 1.4311] qs = [2.336, 2.41, 1.432] # madeup numbers to match Wilson example roughly tausA = [[0.0, -1.05e-4, -2.5e-4], [3.9e-4, 0.0, 1.6e-4], [-1.123e-4, 6.5e-4, 0]] tausB = [[0.0, 235.0, -169.0], [-160, 0.0, -715.0], [11.2, 144.0, 0.0]] tausC = [[0.0, -4.23e-4, 2.9e-4], [6.1e-4, 0.0, 8.2e-5], [-7.8e-4, 1.11e-4, 0]] tausD = [[0.0, -3.94e-5, 2.22e-5], [8.5e-5, 0.0, 4.4e-5], [-7.9e-5, 3.22e-5, 0]] tausE = [[0.0, -4.2e2, 8.32e2], [2.7e2, 0.0, 6.8e2], [3.7e2, 7.43e2, 0]] tausF = [[0.0, 9.64e-8, 8.94e-8], [1.53e-7, 0.0, 1.11e-7], [7.9e-8, 2.276e-8, 0]] ABCDEF = (tausA, tausB, tausC, tausD, tausE, tausF) GE = UNIQUAC(T=T, xs=xs, rs=rs, qs=qs, ABCDEF=ABCDEF) assert eval(str(GE)).GE() == GE.GE() with pytest.raises(ValueError): UNIQUAC(T=T, xs=xs, rs=rs, qs=qs, ABCDEF=(tausA, None, None, [])) with pytest.raises(ValueError): UNIQUAC(T=T, xs=xs, rs=rs, qs=qs, ABCDEF=(tausA, None, None, [1, 1])) with pytest.raises(ValueError): UNIQUAC(T=T, xs=xs, rs=rs, qs=qs, ABCDEF=(tausA, None, None, [1, 1, 1])) with pytest.raises(ValueError): UNIQUAC(T=T, xs=xs, rs=rs, qs=qs, ABCDEF=(tausA, None, None, [[0.0, 9.64e-8], [1.53e-7, 0.0, 1.11e-7], [7.9e-8, 2.276e-8, 0]])) with pytest.raises(ValueError): UNIQUAC(T=T, xs=xs, rs=rs, qs=qs, ABCDEF=(tausA, None, None, [[0.0, 9.64e-8, 8.94e-8], [1.53e-7, 0.0, 1.11e-7]])) GE2 = UNIQUAC.from_json(GE.as_json()) assert GE2.__dict__ == GE.__dict__ # GE GE_expect = 415.5805110962149 GE_analytical = GE.GE() assert_close(GE_expect, GE_analytical, rtol=1e-13) gammas = UNIQUAC_gammas(taus=GE.taus(), rs=rs, qs=qs, xs=xs) GE_identity = R * T * sum(xi * log(gamma) for xi, gamma in zip(xs, gammas)) assert_close(GE_identity, GE_analytical, rtol=1e-12) # dGE_dT dGE_dT_expect = 0.9907140284750982 dGE_dT_analytical = GE.dGE_dT() dGE_dT_numerical = derivative(lambda T: GE.to_T_xs(T, xs).GE(), T, order=7, dx=T * 1e-3) assert_close(dGE_dT_analytical, dGE_dT_numerical, rtol=1e-12) assert_close(dGE_dT_expect, dGE_dT_analytical, rtol=1e-13) # d2GE_dT2 d2GE_dT2_expect = -0.007148011229475758 d2GE_dT2_analytical = GE.d2GE_dT2() d2GE_dT2_numerical = derivative(lambda T: GE.to_T_xs(T, xs).dGE_dT(), T, order=7, dx=T * 1e-3) assert_close(d2GE_dT2_expect, d2GE_dT2_analytical, rtol=1e-12) assert_close(d2GE_dT2_analytical, d2GE_dT2_numerical, rtol=1e-12) # d3GE_dT3 d3GE_dT3_expect = 2.4882477326368877e-05 d3GE_dT3_analytical = GE.d3GE_dT3() assert_close(d3GE_dT3_expect, d3GE_dT3_analytical, rtol=1e-13) d3GE_dT3_numerical = derivative(lambda T: GE.to_T_xs(T, xs).d2GE_dT2(), T, order=11, dx=T * 1e-2) assert_close(d3GE_dT3_analytical, d3GE_dT3_numerical, rtol=1e-12) # dphis_dxs dphis_dxs_analytical = GE.dphis_dxs() dphis_dxs_expect = [ [0.9223577846000854, -0.4473196931643269, -0.2230519905531248], [-0.3418381934661886, 1.094722540086528, -0.19009311780433752], [-0.5805195911338968, -0.6474028469222008, 0.41314510835746243] ] assert_close2d(dphis_dxs_expect, dphis_dxs_analytical, rtol=1e-12) dphis_dxs_numerical = jacobian(lambda xs: GE.to_T_xs(T, xs).phis(), xs, scalar=False, perturbation=2e-8) assert_close2d(dphis_dxs_numerical, dphis_dxs_analytical, rtol=3e-8) # d2phis_dxixjs - checked to the last decimal with sympy d2phis_dxixjs_expect = [ [[-2.441416183656415, 0.9048216556030662, 1.536594528053349], [-0.7693373390462084, -0.9442924629794809, 1.7136298020256895], [-0.3836232285397313, 0.5031631130108988, -0.11953988447116741]], [[-0.7693373390462084, -0.9442924629794809, 1.7136298020256895], [1.3204383950972896, -3.231500191022578, 1.9110617959252876], [0.658424873597119, -0.5251124708645561, -0.13331240273256284]], [[-0.3836232285397313, 0.5031631130108987, -0.11953988447116741], [0.6584248735971189, -0.5251124708645561, -0.13331240273256284], [0.32831771310273056, 0.27980444182238084, -0.6081221549251116]] ] d2phis_dxixjs_analytical = GE.d2phis_dxixjs() assert_close3d(d2phis_dxixjs_analytical, d2phis_dxixjs_expect, rtol=1e-12) d2phis_dxixjs_numerical = hessian(lambda xs: GE.to_T_xs(T, xs).phis(), xs, scalar=False, perturbation=1e-5) assert_close3d(d2phis_dxixjs_numerical, d2phis_dxixjs_analytical, rtol=8e-5) d2thetas_dxixjs_expect = [ [[-2.346422740416712, 0.7760247163009644, 1.5703980241157476], [-0.7026345706138027, -0.9175106511836936, 1.6201452217974965], [-0.4174990477672056, 0.47571378156805694, -0.05821473380085118]], [[-0.7026345706138027, -0.9175106511836936, 1.6201452217974965], [1.0476523499983839, -2.7191206652946023, 1.6714683152962189], [0.6225054627376287, -0.5624465978146614, -0.06005886492296719]], [[-0.4174990477672056, 0.47571378156805694, -0.05821473380085118], [0.6225054627376287, -0.5624465978146614, -0.06005886492296719], [0.3698870633362176, 0.2916190647283637, -0.6615061280645813]] ] d2thetas_dxixjs_analytical = GE.d2thetas_dxixjs() assert_close3d(d2thetas_dxixjs_analytical, d2thetas_dxixjs_expect, rtol=1e-12) d2thetas_dxixjs_numerical = hessian(lambda xs: GE.to_T_xs(T, xs).thetas(), xs, scalar=False, perturbation=2e-5) assert_close3d(d2thetas_dxixjs_numerical, d2thetas_dxixjs_analytical, rtol=1e-4) def to_jac(xs): return GE.to_T_xs(T, xs).GE() # Obtained 12 decimals of precision with numdifftools dGE_dxs_analytical = GE.dGE_dxs() dGE_dxs_expect = [ -2651.3181821109024, -2085.574403592012, -2295.0860830203587 ] assert_close1d(dGE_dxs_analytical, dGE_dxs_expect, rtol=1e-12) dGE_dxs_numerical = jacobian(to_jac, xs, perturbation=1e-8) assert_close1d(dGE_dxs_numerical, dGE_dxs_analytical, rtol=1e-6) # d2GE_dTdxs def to_jac(xs): return GE.to_T_xs(T, xs).dGE_dT() d2GE_dTdxs_expect = [ -9.940433543371945, -3.545963210296949, -7.427593534302016 ] d2GE_dTdxs = GE.d2GE_dTdxs() d2GE_dTdxs_numerical = jacobian(to_jac, xs, perturbation=1e-8) assert_close1d(d2GE_dTdxs_numerical, d2GE_dTdxs, rtol=1e-6) assert_close1d(d2GE_dTdxs, d2GE_dTdxs_expect, rtol=1e-12) # d2GE_dxixjs def to_hess(xs): return GE.to_T_xs(T, xs).GE() d2GE_dxixjs_numerical = hessian(to_hess, xs, perturbation=1e-4) d2GE_dxixjs_sympy = [ [-2890.4327598108343, -6687.099054095988, -1549.3754436994557], [-6687.099054095988, -2811.283290487096, -1228.622385377738], [-1549.3754436994557, -1228.622385377738, -3667.3880987585053] ] d2GE_dxixjs_analytical = GE.d2GE_dxixjs() assert_close2d(d2GE_dxixjs_numerical, d2GE_dxixjs_analytical, rtol=1e-4) assert_close2d(d2GE_dxixjs_analytical, d2GE_dxixjs_sympy, rtol=1e-12) # Check json storage again, with some results GE2 = UNIQUAC.from_json(GE.as_json()) assert GE2.__dict__ == GE.__dict__