Esempio n. 1
0
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
Esempio n. 2
0
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