def main(gas,liquid,species_name,reaction_tuple,chamber_params,inlet_conds,Hrefchoice=None,T_boilo=None): """ main - main(gas,liquid,species_name,reaction_tuple,chamber_params,inlet_conds,Hrefchoice=None,T_boilo=None) INPUTS/Parameters ----------------- gas - <cantera.Solution or Cantera Phase object> liquid - <cantera.Solution or Cantera Phase object> reaction_tuple - <namedtuple defined as Reaction_tuple> Reaction_tuple(Fuelstr=<string>, Oxstr=<string>, n_F=<int>, # number of moles of Fuel in stoichiometric reaction n_Ox=<int>, # number of moles of oxidizer in stoichiometric reaction Prod_str=<string>) chamber_params = CHAMBER_PARAMS - <namedtuple defined as Chamber_Params> Chamber_Params(A_totinj=<float>, A_cc=<float> l_cc=<float> inlet_conds = INLET_CONDS - <namedtuple defined as Inlet_Conds> Inlet_Conds(TP=(<float>,<float>), phi_g=<float>, phi_overall=<float>, v_d=<float>, D=<float>) """ P = inlet_conds.TP[1] Fu_ind = gas.species_index(reaction_tuple.Fuelstr) Ox_ind = gas.species_index(reaction_tuple.Oxstr) # Grab Clausius-Clapeyron relation from NIST Chemistry Webbook if T_boilo == None: try: dat = LiquidVaporEq.cleaned_Phase_data(species_name) print "Done with accessing online the NIST Chemistry Website. \n" T_boil0 = dat.T_boil['Value'] # T_boil0, T_boil at "standard" pressure reference of ct.one_atm, 1 atm except: print "Check if species name (species_name) is in the NIST Chemistry Webbook \n or if LiquidVaporEq file is there\n" T_boil0 = raw_input("Meanwhile, enter a T_boil at 1 atm:") T_boil0 = float(T_boil0) else: T_boil0 = T_boilo h_fg, T_boil, rho_l, h_l = _process_liquid_Droplet(gas,liquid,reaction_tuple,T_boil0,P,Hrefchoice=Hrefchoice) # Compute (F/O)_{\Phi=1} gas.X = phi_to_X(1, reaction_tuple) F_over_O_Phi1_mass = gas.Y[Fu_ind]/gas.Y[Ox_ind] ## Compute flow rates at inlet FLOW_INLET,INITIAL_CONDS=get_initial_flow_vals(gas,reaction_tuple,chamber_params,inlet_conds,rho_l,F_over_O_Phi1_mass) #### Call ODE cc_ode = ode_creator(gas,reaction_tuple,inlet_conds,chamber_params,FLOW_INLET,h_fg,F_over_O_Phi1_mass, T_boil,rho_l,h_l) cc_int_ode = integrate.ode(cc_ode) # at this point, there are many ODE integrators that can be used. # Matlab's ode45 is scipy's dopri5, a Runge-Kutta method # there's also vode, Real-valued Variable-coefficient ODE solver cc_int_ode.set_integrator("dopri5") # set initial conditions T_g0 = INITIAL_CONDS.T_g Dsq0 = INITIAL_CONDS.D**2 v_d0 = INITIAL_CONDS.v_d cc_int_ode.set_initial_value([T_g0,Dsq0,v_d0],0) # x_0 = 0 # Additional Python step: create vectors to store data x = np.zeros(NUM_STEPS+1) Temp_g = np.zeros(NUM_STEPS+1) Dsquared = np.zeros(NUM_STEPS+1) v_droplet = np.zeros(NUM_STEPS+1) x[0] = 0. Temp_g[0] = T_g0 Dsquared[0] = Dsq0 v_droplet[0] = v_d0 ## Integrate the ODE(s) across each delta_x timestep delta_x = (chamber_params.l_cc -0.)/(float(NUM_STEPS)) # return cc_int_ode #, x, , Temp_g, Dsquared, v_droplet print "Initiating quasi-static inlet flows into combustion chamber, and timing it \n" start_time=time.time() k = 1 while cc_int_ode.successful() and k <= NUM_STEPS and cc_int_ode.y[1]>=0.: # cc_int_ode.y[1]>=0. is a check if the droplet diameter isn't negative i.e. droplet has evaporated away and died. # and cc_int_ode.y[0] > 0: # check T_g >0K (no negative temperatures) try: cc_int_ode.integrate(cc_int_ode.t + delta_x) # Store the results to plot later x[k] = cc_int_ode.t Temp_g[k] = cc_int_ode.y[0] Dsquared[k] = cc_int_ode.y[1] v_droplet[k] = cc_int_ode.y[2] k += 1 except RuntimeError: print "Runtime Error \n" # for the "cleaned" data points, we cut off if the droplet dies, i.e. when # droplet diameter is less than 0 x_clean = x[:k-1] Temp_g_clean = Temp_g[:k-1] Dsquared_clean = Dsquared[:k-1] v_droplet_clean = v_droplet[:k-1] print "Completed loop, integrating over entire chamber.\n Took --- %s seconds ---" % (time.time()-start_time) # return cc_int_ode, x,Temp_g, Dsquared, v_droplet results = {'ODEobj' :cc_int_ode, 'x' :x, 'xclean' :x_clean, 'rawdat' :T_gDv_d_Tuple(T_g=Temp_g,D=np.sqrt(Dsquared),v_d=v_droplet), 'cleandat':T_gDv_d_Tuple(T_g=Temp_g_clean,D=np.sqrt(Dsquared_clean),v_d=v_droplet_clean) #, # 'flow_inlet':FLOW_INLET } return results
def _process_liquid_Droplet(gas,liquid,reaction_tuple,T_boilo,P, Hrefchoice=None): """ _process_liquid_Droplet _process_liquid_Droplet does 3 things: 1. grab the Clausius-Clapeyron relation (CCEqn) 2. Calculate the new T_boil at the desired pressure P, and use that to calculate enthalpies 3. Armed with (T_boil(P),P) \in \Sigma^liquid, grab liquid density from Cantera """ # let's try to use Cantera as much as possible gas.X = reaction_tuple.Fuelstr+':1' gas.TP = T_boilo, ct.one_atm # Calculating L, latent heat of vaporization, heat required to put a # liquid molecule into gas phase # complications arise from 1. difference choices of standard enthalpy that # people choose (e.g. Cantera vs. NIST), so hence the following, accounting # for these differences h_g = gas.enthalpy_mass h_g_mole = gas.enthalpy_mole liquid.TP = T_boilo, ct.one_atm if liquid.X > 0.0: # making sure you have purely liquid right below boiling h_g_vap = liquid.enthalpy_mass h_g_vap_mole = liquid.enthalpy_mole k = 1 # get the enthalpy of the liquid at temperature slightly below T_boil so that there's no more vapor, i.e. vapor fraction = 0 deltaT = 0.01 while liquid.X > 0.0: liquid.TP = T_boilo-k*deltaT, ct.one_atm k += 1 h_l = liquid.enthalpy_mass h_l_mole = liquid.enthalpy_mole else: h_l = liquid.enthalpy_mass h_l_mole = liquid.enthalpy_mole k=1 # get the enthalpy of the liquid at temperature slightly above T_boil so that it's all vapor, i.e. vapor fraction = 1 deltaT=0.01 while liquid.X <= 0.0: liquid.TP = T_boilo+k*deltaT, ct.one_atm k += 1 h_g_vap = liquid.enthalpy_mass h_g_vap_mole = liquid.enthalpy_mole if Hrefchoice == None: Delta_vapHchoice = raw_input("For ENTHALPY of VAPORIZATION, \Delta_{vap}H or Delta_vap H, type 'y' if you want to calculate Delta_vap H from the difference, at T_boil, from the file for gas with the built-in Phase Object for liquid ('Pure Fluid'), or from an arbitrary temperature above and below the T_boil off the liquid ('Pure Fluid') object: the danger is that the choice of reference for enthalpy of an EXTERNAL file (not built into Cantera) is DIFFERENT from reference enthalpy chosen for Cantera (which is more honest, as it's referenced off of the elements alone). (y/n)?") elif Hrefchoice != 'y' and Hrefchoice != 'n': Delta_vapHchoice = 'y' else: Delta_vapHchoice = Hrefchoice if Delta_vapHchoice =='y': h_fg = h_g - h_l h_fg_mole = h_g_mole-h_l_mole # J/kmol else: h_fg = h_g_vap - h_l h_fg_mole = h_g_vap_mole - h_l_mole # sanity check print "Enthalpy of vaporization per kg mass: %s \n " , h_fg print "Enthalpy of vaporization per kmol : %s \n " , h_fg_mole # armed with h_fg_mole, latent heat of vaporization, we can get the # Clausius-Clapeyron relation, CCeqn CCeqn =LiquidVaporEq.fit_ClausClapEqn(T_boilo,h_fg_mole) T_boil_lambd = sympy.lambdify(LiquidVaporEq.T,CCeqn.rhs-P) T_boil = newton( T_boil_lambd, T_boilo) # K ## Done with grabbing and using the Clausius-Clapeyron relation and ## computing the new T_boil = T_boil(P) at the new desired pressure P. gas.X = reaction_tuple.Fuelstr+':1' gas.TP = T_boil, P h_g = gas.enthalpy_mass liquid.TP = T_boil, P if liquid.X > 0.0: # making sure you have purely liquid right below boiling h_g_vap = liquid.enthalpy_mass k = 1 # get the enthalpy of the liquid at temperature slightly below T_boil so that there's no more vapor, i.e. vapor fraction = 0 deltaT = 0.01 while liquid.X > 0.0: liquid.TP = T_boil-k*deltaT, P k += 1 h_l = liquid.enthalpy_mass # J/kg rho_l = liquid.density # kg/m^3 else: rho_l = liquid.density # kg/m^3 h_l = liquid.enthalpy_mass # J/kg k=1 # get the enthalpy of the liquid at temperature slightly above T_boil so that it's all vapor, i.e. vapor fraction = 1 deltaT=0.01 while liquid.X <= 0.0: liquid.TP = T_boil+k*deltaT, P k += 1 h_g_vap = liquid.enthalpy_mass # Note: Use Cantera for fluids as much as possible, # if fluid/liquid phase is available. # Otherwise, external files for the gas phase, other than the # built-in Cantera data files such as "gri30.cti", # may have reference temperatures, reference enthalpies that are # NOT the same as Cantera. # case of, we trust that gas and liquid both que off the same reference temperature, reference enthalpy if Delta_vapHchoice =='y': h_fg = h_g-h_l # case of, we DON'T trust that gas and liquid both que off the same reference temperature, reference enthalpy, so we'll have to subtract away this H(To,p) difference else: h_fg = h_g_vap - h_l # at new T_boil for P # now we have to fix the reference enthalpy that the given gas cues off of # to the reference enthalpy that the liquid cues off of # to obtain a h_l H_1 = h_g_vap H_2 = h_g Deltah_12 = h_g_vap - h_g h_l = h_l - Deltah_12 return h_fg, T_boil, rho_l, h_l