def function_inner_loop(pressure, temperature, global_molar_fraction, max_iter=100, tolerance=1.0e-12, stability=False): T = temperature P = pressure logging.debug('pressure' + str(P)) yi = z = global_molar_fraction f_V, Z_V = eos_obj.calculate_fugacities_with_minimum_gibbs_energy( P, T, yi, 'vapor') PHI_V = f_V / (yi * P) initial_K_values = calculate_K_values_wilson(P, T, eos_obj.Pc, eos_obj.Tc, eos_obj.ω) is_stable, K_michelsen = michelsen_obj(eos_obj, P, T, z, initial_K_values, max_iter, tolerance) if stability: if not is_stable: msg = str('===> two-phases can be in equilibrium') else: msg = str('===> one phase in this @') print(msg) logging.debug('K_michelsen' + str(K_michelsen)) logging.debug('One-phase = ' + str(is_stable)) xi = yi #yi / K_michelsen Sx = np.sum(xi) Sx0 = 2 * Sx itermax = 2 for counter in np.arange(itermax): if is_stable: Sx = ( Sx + 3.0 ) # To force the program stores wrong Sx's value [avoid the solver seeks minimum values of (Sx - 1)] break else: pass f_L, Z_L = eos_obj.calculate_fugacities_with_minimum_gibbs_energy( P, T, xi, 'liquid') PHI_L = f_L / (xi * P) K = PHI_L / PHI_V xi = yi / K Sx = np.sum(xi) logging.debug('iteracao' + str(counter)) logging.debug('K' + str(K)) logging.debug('xi' + str(xi)) logging.debug('Sx = ' + str(Sx) + '\n----') if (np.abs(Sx - Sx0) < tolerance): break else: xi /= Sx Sx0 = np.copy(Sx) return Sx, xi
def inner_loop(self, eos_obj, p, T, z, iteration_michelsen, tolerance_michelsen): ''' This function is responsible for a more realistic K (vapor-liquid ratio) value. So, the first estimation of K is made with Wilson equation. After that, this K_Wilson is fed in Michelsen's code. This, on the other hand, notifies us if this mixture is stable. Besides that, in case of not stable phase (split in 2 phases), Michelsen's code also provides a better K estimation. :iteration_michelsen: is max iteration number used in Michelsen algorithm :tolerance_michelsen: is the tolerance exigence in Michelsen algorithm ''' K_wilson = calculate_K_values_wilson(p, T, self.pC, self.Tc, self.AcF) is_stable, K = michelsen_obj(eos_obj, p, T, z, K_wilson, iteration_michelsen, tolerance_michelsen) return is_stable, K
def getting_the_results_from_FlashAlgorithm_main(p, T, pC, Tc, AcF, z): initial_K_values = calculate_K_values_wilson(p, T, pC, Tc, AcF) is_stable, K_michelsen = michelsen_obj(eos_obj, p, T, z, initial_K_values, max_iter=100, tolerance=1.0e-12) K_flash, F_V_flash = flash_obj(rr_obj, eos_obj, p, T, z, K_michelsen) Vector_ToBe_Optimized = np.append(K_flash, F_V_flash) result = fsolve(func=flash_obj.flash_residual_function, x0=Vector_ToBe_Optimized, args=(T, p, eos_obj, z)) size = result.shape[0] K_values_newton = np.array(result[0:size - 1]) F_V = result[-1] return (F_V, is_stable, K_values_newton, initial_K_values)
def function_inner_loop(temperature, pressure, global_molar_fraction, max_iter = 100, tolerance = 1.0e-12, stability=False): P = pressure T = temperature xi = z = global_molar_fraction f_L, Z_L = eos_obj.calculate_fugacities_with_minimum_gibbs_energy(P, T, xi, 'liquid') PHI_L = f_L / (xi * P) initial_K_values = calculate_K_values_wilson(P, T, eos_obj.Pc, eos_obj.Tc, eos_obj.ω) is_stable, K_michelsen = michelsen_obj(eos_obj, P, T, z, initial_K_values, max_iter, tolerance) if stability: if not is_stable: msg = str('===> two-phases can be in equilibrium') else: msg = str('===> one phase in this @') print(str(msg)) logging.debug('temperature' + str(T)) logging.debug('K_michelsen' + str(K_michelsen)) logging.debug('One-phase = ' + str(is_stable)) yi = xi * K_michelsen Sy = np.sum(yi) Sy0 = 2 * Sy itermax = 2 for counter in np.arange(itermax): if is_stable: break else: pass f_V, Z_V = eos_obj.calculate_fugacities_with_minimum_gibbs_energy(P, T, yi, 'vapor') PHI_V = f_V / (yi * P) K = PHI_L / PHI_V yi = xi * K Sy = np.sum(yi) logging.debug('iteracao' + str(counter)) logging.debug('K' + str(K)) logging.debug('yi' + str(yi)) logging.debug('Sy' + str(Sy) + '\n----') if (np.abs(Sy - Sy0) < tolerance): break else: yi /= Sy Sy0 = np.copy(Sy) return Sy, yi
def calculate_vapor_liquid_equilibrium(eos_obj, michelsen_obj, flash_obj, prop_obj, pressure, temperature, molar_mass, global_molar_fractions, max_iter, tolerance, print_statistics=None): P = pressure T = temperature z = global_molar_fractions Mi = molar_mass #size = z.shape[0] # Estimate initial K-values initial_K_values = calculate_K_values_wilson(pressure, temperature, eos_obj.Pc, eos_obj.Tc, eos_obj.ω) # Check if the mixture is stable and takes Michelsen's K is_stable, K_michelsen = michelsen_obj(eos_obj, P, T, z, initial_K_values, max_iter, tolerance) # Executing the Flash K_flash, F_V_flash = flash_obj(rr_obj, eos_obj, pressure, temperature, global_molar_fractions, K_michelsen) # Good estimate! Vector_ToBe_Optimized = np.append(K_flash, F_V_flash) ## Use estimates from flash (successive substitutions)!!! if 0.0 <= F_V_flash <= 1.0: result, infodict, ier, mesg = fsolve( func=flash_obj.flash_residual_function, x0=Vector_ToBe_Optimized, args=(T, P, eos_obj, z), full_output=True) size = result.shape[0] K_values_newton = result[0:size - 1] F_V = result[size - 1] x_i = global_molar_fractions / (F_V * (K_values_newton - 1) + 1) y_i = K_values_newton * x_i f_L, Z_L = eos_obj.calculate_fugacities_with_minimum_gibbs_energy( P, T, x_i, 'liquid') f_V, Z_V = eos_obj.calculate_fugacities_with_minimum_gibbs_energy( P, T, y_i, 'vapor') rho_L = prop_obj.calculate_density_phase(P, T, Mi, x_i, 'liquid') rho_V = prop_obj.calculate_density_phase(P, T, Mi, y_i, 'vapor') if print_statistics: print('Newton flash converged? %d, %s' % (ier, mesg)) elif F_V_flash < 0.0: x_i = z y_i = np.zeros_like(z) K_values_newton = initial_K_values rho_L = prop_obj.calculate_densite_phase(P, T, Mi, x_i, 'liquid') rho_V = 0.0 F_V = 0.0 elif F_V_flash > 1.0: y_i = z x_i = np.zeros_like(z) K_values_newton = initial_K_values rho_L = 0.0 rho_V = prop_obj.calculate_densite_phase(P, T, Mi, y_i, 'vapor') F_V = 1.0 else: raise Exception( "Nenhuma das @ foram dectadas na calculate_vapor_liquid_equilibrium" ) return F_V, K_values_newton, x_i, y_i, rho_V, rho_L
def function_inner_loop(p, T, z, max_iter=20, tolerance=1.0e-20, stability=False): ''' These function_inner_loop and function_outer_loop are functions based on Elliott's BUBBLE P algorithm (pg 595) INTRODUCTORY CHEMICAL ENGINEERING THERMODYNAMICS, 2nd edition, 2012 J. RICHARD ELLIOTT and CARL T. LIRA ''' logging.debug('Updating the Pressure =====> ' + str(p)) xi = z Sz = np.sum(z) assert np.abs( Sz - 1.0 ) < 1.e-5, 'YOUR GLOBAL MOLAR FRACTION MUST BE EQUAL = 1. Check your data' + str( Sz) initial_K_values = calculate_K_values_wilson(p, T, pC, Tc, AcF) is_stable, K = michelsen_obj(eos_obj, p, T, z, initial_K_values, max_iter, tolerance) if is_stable == True: Sy = 1e10 yi = np.zeros_like(z) else: if stability: if not is_stable: msg = str('===> two-phases can be in equilibrium') else: msg = str('===> one phase in this @') print(str(msg)) logging.debug('K_wilson = ' + str(initial_K_values)) logging.debug('K_michelsen = ' + str(K)) logging.debug( 'One-phase ================================================ > ' + str(is_stable)) yi = xi * K f_L, Z_L = eos_obj.calculate_fugacities_with_minimum_gibbs_energy( p, T, xi, 'liquid') Sy = np.sum(yi) Sy0 = 2 * Sy max_loop = 2 for counter in np.arange(max_loop): f_V, Z_V = eos_obj.calculate_fugacities_with_minimum_gibbs_energy( p, T, yi, 'vapor') np.seterr( divide='ignore', invalid='ignore' ) #Because we can have PHI_V near zero for the no volatile component K *= f_L / f_V yi = xi * K Sy = np.sum(yi) logging.debug('iteracao' + str(counter)) logging.debug('K' + str(K)) logging.debug('yi' + str(yi)) logging.debug('Sy = ' + str(Sy) + '\n----') if (np.abs(Sy - Sy0) < tolerance): break else: yi /= Sy Sy0 = np.copy(Sy) return Sy, yi