def create_eos(kind, pc, tc, **kwargs): """ Create an EoS object. Parameters ---------- kind : string Type of EoS: VDW, SRK, or PR pc : float Critical pressure tc : float Critical temperature omega : float Acentric factor. Required for SDK and PR. Returns ------- VanDerWaalsEos, SoaveRedlichKwongEos, or PengRobinsonEos """ if kind == 'VDW': return VanDerWaalsEos(pc, tc) elif kind == 'SRK': if 'omega' not in kwargs: raise KeyError("Key 'omega' is not found!") omega = kwargs['omega'] return SoaveRedlichKwongEos(pc, tc, omega) elif kind == 'PR': if 'omega' not in kwargs: raise KeyError("Key 'omega' is not found!") omega = kwargs['omega'] return PengRobinsonEos(pc, tc, omega) else: raise ValueError('kind must be VDW, SRK, or PR.')
def test_near_critical_point(): # PENG-ROBINSON props = input_properties_case_dissertation_PR() (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props eos_pr = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) # temperature = 366.5 # [K] Easy ss flash converges temperature = 408.0 # [K] Hard, number of iter reached! pressure = np.linspace(30.0, 80.0, num=200) * 1.0e5 # [Pa] result_pr = calculate_molar_fraction_curve( eos_pr, pressure, temperature, global_molar_fractions, print_statistics=False ) pressure_bar = pressure / 1.0e5 plt.plot(pressure_bar, result_pr, label='Peng-Robinson') plt.xlabel('Pressure [bar]') plt.ylabel('Vapor molar fraction [mol/mol]') plt.legend(loc='upper center') plt.axis([np.min(pressure_bar), np.max(pressure_bar), 0.0, 1.0]) plt.show()
def test_retrograde_condensation(): # PENG-ROBINSON props = input_properties_case_7_psudocomponents() (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props eos_pr = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) temperature = 350.0 # [K] pressure = np.linspace(1.0, 250.0, num=200) * 1.0e5 # [Pa] result_pr = calculate_molar_fraction_curve(eos_pr, pressure, temperature, global_molar_fractions) pressure_bar = pressure / 1.0e5 plt.plot(pressure_bar, result_pr, label='Peng-Robinson') plt.xlabel('Pressure [bar]') plt.ylabel('Vapor molar fraction [mol/mol]') plt.legend(loc='upper center') plt.axis([np.min(pressure_bar), np.max(pressure_bar), 0.0, 1.0]) plt.show()
def test_different_eos(): # PENG-ROBINSON props = input_properties_case_whitson_problem_18_PR() (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props eos_pr = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) # SOAVE-REDLICH-KWONG props = input_properties_case_whitson_problem_18_SRK() (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props eos_srk = SoaveRedlichKwongEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) # VAN DER WAALS props = input_properties_case_whitson_problem_18_VDW() (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props eos_vdw = VanDerWaalsEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) temperature = 350.0 # [K] pressure = np.linspace(1, 135.0, num=200) * 1.0e5 # [Pa] result_pr = calculate_molar_fraction_curve(eos_pr, pressure, temperature, global_molar_fractions) result_srk = calculate_molar_fraction_curve(eos_srk, pressure, temperature, global_molar_fractions) result_vdw = calculate_molar_fraction_curve(eos_vdw, pressure, temperature, global_molar_fractions) pressure_bar = pressure / 1.0e5 plt.plot(pressure_bar, result_pr, label='Peng-Robinson') plt.plot(pressure_bar, result_srk, label='Soave-Redlich-Kwong') plt.plot(pressure_bar, result_vdw, label='Van der Waals') plt.xlabel('Pressure [bar]') plt.ylabel('Vapor molar fraction [mol/mol]') plt.legend(loc='upper center') plt.axis([np.min(pressure_bar), np.max(pressure_bar), 0.0, 1.0]) plt.show()
def test_vapor_liquid_curves(): temperature = 350.0 # [K] pressure = np.linspace(2.5, 150.0, num=200) * 1.0e5 # [Pa] # Create EoS object and set properties props = input_properties_case_whitson_problem_18_PR() (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props eos = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) result = calculate_molar_fraction_curve(eos, pressure, temperature, global_molar_fractions) pressure_bar = pressure / 1.0e5 plt.plot(pressure_bar, result, label='Vapor molar fraction') plt.plot(pressure_bar, 1.0-result, label='Liquid molar fraction') plt.xlabel('Pressure [bar]') plt.ylabel('Phase molar fraction [mol/mol]') plt.legend(loc='upper center') plt.axis([np.min(pressure_bar), np.max(pressure_bar), 0.0, 1.0]) plt.show()
def test_phase_equilibria(): # Get input properties #props = input_properties_case_7_psudocomponents() props = input_properties_case_whitson_problem_18_PR() #props = input_properties_case_whitson_problem_18_SRK() #props = input_properties_case_whitson_problem_18_VDW() (pressure, temperature, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props #temperature = 350.0 # [K] #pressure = 50.0 * 1e5 # [Pa] # Estimate initial K-values initial_K_values = calculate_K_values_wilson(pressure, temperature, critical_pressure, critical_temperature, acentric_factor) # Create EoS object and set properties #eos = VanDerWaalsEos, PengRobinsonEos, SoaveRedlichKwongEos eos = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) is_stable, K_values_est = calculate_stability_test(eos, pressure, temperature, global_molar_fractions, initial_K_values) print('System is stable?', is_stable) print('K_values estimates:', K_values_est) K_values_from_ss_flash, F_V, f_L = ss_flash(eos, pressure, temperature, global_molar_fractions, K_values_est, tolerance=1.0e-1) fugacity_expected = np.array([294.397, 148.342, 3.02385]) * 6894.75729 K_values_expected = np.array([6.65071, 0.890061, 0.03624]) x_expected = np.array([0.08588, 0.46349, 0.45064]) y_expected = np.array([0.57114, 0.41253, 0.01633]) print('K_values Successive Subst:', K_values_from_ss_flash) print('Vapor molar fraction:', F_V) print('\n-----\nFugacities obtained:', f_L) print('Fugacities expected:', fugacity_expected) # Use estimates from Wilson's Equation!!! #x0 = np.append(initial_K_values, F_V) # It does not work! # Use estimates from stability test!!! #x0 = np.append(K_values_est, F_V) # It does not work! # Use estimates from successive substitutions!!! x0 = np.append(K_values_from_ss_flash, F_V) # Good estimate! result = fsolve( func=flash_residual_function, x0=x0, args=(temperature, pressure, eos, global_molar_fractions), ) size = result.shape[0] K_values_newton = result[0:size - 1] F_V = result[size - 1] print('K_values newton:', K_values_newton) print('K_values expected:', K_values_expected) print('Norm difference:', np.linalg.norm(K_values_expected - K_values_newton)) print('Vapor molar fraction:', F_V) assert np.allclose(K_values_newton, K_values_expected, rtol=0.01) assert np.allclose(fugacity_expected, f_L, rtol=0.1)
def test_multiphase_flash_residual_function(): # Get input properties temperature = 278.0 # [K] pressure = 0.5 * 1e5 # [Pa] props = input_properties_case_Ghafri(temperature) (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props # Estimate initial K-values initial_K_values = calculate_K_values_wilson(pressure, temperature, critical_pressure, critical_temperature, acentric_factor) # Create EoS object and set properties eos = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) P, T = pressure, temperature z = global_molar_fractions K_values_est = initial_K_values x0 = np.r_[K_values_est, K_values_est, 0.1, 0.2] n_extra_phases = 2 result, infodict, ier, mesg = fsolve( func=multiphase_flash_residual_function, x0=x0, args=(T, P, eos, z, n_extra_phases), full_output=1) print(mesg) shape = (n_extra_phases, z.size) # Get values from unknown vector K_values = result[:-n_extra_phases].reshape(shape) β = result[-n_extra_phases:] print('K_values:\n', K_values) print('Molar phase fractions:', β) assert ier == 1 Mi = molar_mass K = K_values denominator = 1 + (β[:, np.newaxis] * (K - 1)).sum(axis=0) y_iF = z / denominator y_i = K * y_iF print('Molar component phase fractions:\n', y_i) # Reference phase density ρ_F = calculate_density(y_iF, P, T, Mi, eos) ρ = [] for j in range(n_extra_phases): ρ_j = calculate_density(y_i[j], P, T, Mi, eos) ρ = np.r_[ρ, ρ_j] ρ = np.r_[ρ, ρ_F] print('Obtained Densities:', ρ)
def test_phase_equilibria_CO2(): # Get input properties temperature = 290.0 # [K] pressure = 1.0 * 1e5 # [Pa] props = input_properties_case_Ghafri(temperature) (_, _, global_molar_fractions, critical_pressure, critical_temperature, acentric_factor, molar_mass, omega_a, omega_b, binary_interaction) = props # Estimate initial K-values initial_K_values = calculate_K_values_wilson(pressure, temperature, critical_pressure, critical_temperature, acentric_factor) # Create EoS object and set properties #eos = VanDerWaalsEos, PengRobinsonEos, SoaveRedlichKwongEos eos = PengRobinsonEos(critical_pressure, critical_temperature, acentric_factor, omega_a, omega_b, binary_interaction) is_stable, K_values_est = calculate_stability_test(eos, pressure, temperature, global_molar_fractions, initial_K_values) print('System is stable?', is_stable) #print ('K_values estimates:', K_values_est) K_values_from_ss_flash, F_V, f_L = ss_flash(eos, pressure, temperature, global_molar_fractions, K_values_est, tolerance=1.0e-1, print_statistics=True) print('K_values Successive Subst:', K_values_from_ss_flash) print('Vapor molar fraction:', F_V) print('\n-----\nFugacities obtained:', f_L) # Use estimates from Wilson's Equation!!! #x0 = np.append(initial_K_values, F_V) # It does not work! K_values_est = np.array([ 2.71350413e+01, 9.23075054e+01, 1.17478417e+01, 2.84833217e+00, 8.98083183e-02, 1.48315222e-02, 2.65989146e-03, 7.30566453e-04, 7.76675634e-04, 1.00536144e-04, 4.54130173e-05, 3.11385702e-05, 1.71481448e-06, 2.66939726e-06, 1.64767536e-07, 2.36654995e-08, 1.10913280e-08, 1.60469889e-09, 8.82593963e-11, 1.10828717e-13, 5.96510411e-03 ]) # Use estimates from stability test!!! x0 = np.append(K_values_est, 0.749313901696) # It does not work! # Use estimates from successive substitutions!!! #x0 = np.append(K_values_from_ss_flash, F_V) # Good estimate! result = fsolve(func=flash_residual_function, x0=x0, args=(temperature, pressure, eos, global_molar_fractions), full_output=1) converged = result[2] msg = result[3] print(msg) X = result[0] size = X.shape[0] K_values_newton = X[0:size - 1] F_V = X[size - 1] print('K_values newton:', K_values_newton) print('Vapor molar fraction:', F_V) assert converged == 1 Mi = molar_mass P, T = pressure, temperature z = global_molar_fractions K = K_values_newton x_L = z / (F_V * (K - 1) + 1) x_V = K * x_L ρ_V = calculate_density(x_V, P, T, Mi, eos) ρ_L = calculate_density(x_L, P, T, Mi, eos) print('Vapor density:', ρ_V) print('Liquid density:', ρ_L)