def calc_cjspeed(self): if self.cjspeed is False: # Calculation for the Chapman-Jouget speeds self.cjspeed = CJspeed(P1=self.P1, T1=self.T1, q=self.q, mech=self.mech, fullOutput=False) return self.cjspeed
def Errorcontour(diluent='Ar', mechanism='GRI_red2'): # initialise mushroompy study = m1d.DetonationTube() # get all the data folder names from the 1D_AMROC_data folder pathcaselist = glob.glob(f'{study.simdata_path}/*') caselist = [os.path.basename(i) for i in pathcaselist] # extract initial conditions from cases pdriver = [] pdriven = [] dilmoles = [] error = [] desiredmech = diluent + '_' + mechanism for case in caselist: # get a list of the available mechanism folders inside the particular case folder pathmechanismlist = glob.glob(f'{study.simdata_path}/{case}/*') mechanismlist = [os.path.basename(i) for i in pathmechanismlist] # filter for the desired mechanism/diluent combination for mech in mechanismlist: if mech == desiredmech: pr, pn, dm, _ = case.split('_') if pr != '10' and pr != '20': pdriver.append(int(pr)) pdriven.append(int(pn)) dilmoles.append(int(dm)) # generate theoretical cj speeds for each case P1 = float(pn)*1000 q = q = 'C2H4:1. O2:3 ' + diluent + ':' + dm cj = CJspeed(P1=P1, T1=298., q=q, mech='gri30_highT.cti', fullOutput=False) # get all the data for the relevant case study.case_read(pressurestudy = case) # calculate velocity using Rayleigh line equation vdic = rayleighMethodMax(study, [case], [desiredmech]) # Find index of position x=300cm xtarget = 300 lst = list(vdic[case][desiredmech][0]) closest = lst[min(range(len(lst)), key = lambda i: abs(lst[i]-xtarget))] k = lst.index(closest) # average velocity from x = 300cm onwards vray = statistics.mean(list(vdic[case][desiredmech][1])[k:]) err = abs( (vray-cj)/cj*100 ) error.append(err) # generate array of weighted average pressures wp = np.array([pdriver[i]*50/350+pdriven[i]*300/350 for i in range(len(pdriver))]) # converd molar fractions into percentages dperc = np.array([mpu.mol2perc(dilmols=d) for d in dilmoles]) # plot error = np.array(error) fig = plt.figure() ax1 = plt.tricontourf(wp, dperc, error, cmap='viridis') #ax1 = plt.contourf(wp, dperc, error, cmap='viridis') plt.colorbar(ax1) plt.show()
def CJmethod(study, caselist, mechanismlist): velocityDict = {} for case in caselist: velocityDict[case] = {} for mechanism in mechanismlist: finalXposition = list(study.volatilecatalogue[case][mechanism]["dat_0.txt"]["DataframeObj"]["x"])[-1] _, p2, moles, _ = case.split('_') # pressures in kpa dil, _, _ = mechanism.split('_') T1 = 298 # kelvin q = 'C2H4:1. O2:3 ' + dil + ':' + moles mech = 'gri30_highT.cti' cj = CJspeed(P1=int(p2)*1000, T1=T1, q=q, mech=mech, fullOutput=False) xvalues = np.linspace(0,finalXposition,10) cjvalues = np.zeros(10) for i in range(len(cjvalues)): cjvalues[i] = cj velocityDict[case][mechanism] = np.array([xvalues, cjvalues]) return velocityDict
def __init__(self, P1=10000., T1=298., diluent='Ar', dilpercent=50.): # Find the dataroot directory, or prompt user to choose one if non-existent self.data_path = mpyconf.parse_configfile()["dataroot"] # Python module name self.module = os.path.basename(__file__).replace(".py", "") # Python class name self.classname = type(self).__name__ # Define input and output directories self.output_path = os.path.join(self.data_path, "_output", self.module, self.classname) self.mushroompath = os.path.dirname(os.path.realpath(__file__)) self.input_path = os.path.join(self.mushroompath, "templates") # Check that templates folder exists if not os.path.exists(self.input_path): warnmsg = f"Templates path does not exist, generating a new one: {self.input_path}\n\nPlease, provide init.dat and solver.in example files in the specified directory.\n" warnings.warn(warnmsg) os.makedirs(self.input_path) # Check that the templates folder actually has templates """ WRITE LATER """ # Check that prep output folder exists if not os.path.exists(self.output_path): warnmsg = f"Path for {self.classname} folder does not exist, generating a new one: {self.output_path}" # Use initial conditions to find CJ speed self.P1 = P1 self.T1 = T1 self.diluent = diluent self.dilpercent = dilpercent self.dilmoles = self.perc2mol(self.dilpercent) self.SDTmech = 'gri30_highT.cti' self.q = 'C2H4:1. O2:3 ' + self.diluent + ':' + str(self.dilmoles) self.cj_speed = CJspeed(self.P1, self.T1, self.q, self.SDTmech, fullOutput=False)
def CJcontour(P0=10000., Pf=100000., T=298., diluent='Ar', percent0=0., percentf=90., n=4): mech = 'gri30_highT.cti' # generate array of pressures p = np.linspace(P0, Pf, n) # generate array of dilution ratios dil = np.linspace(percent0, percentf, n) # generate array of cj speeds cj = np.zeros(len(p)*len(dil)) for i in range(len(dil)): dilmoles = mpu.perc2mol(percent=dil[i]) q = 'C2H4:1. O2:3 ' + diluent + ':' + str(dilmoles) for j in range(len(p)): cj[i*len(p)+j] = CJspeed(P1=p[j], T1=T, q=q, mech=mech, fullOutput=False) # produce arrays in the proper format for contour plotting X, Y = np.meshgrid(p, dil) Z = cj.reshape(X.shape) # plot fig = plt.figure() ax1 = plt.contourf(X, Y, Z, levels=10, cmap='viridis') plt.colorbar(ax1) plt.show()
from sdtoolbox.postshock import CJspeed from sdtoolbox.postshock import PostShock_eq import matplotlib.pyplot as plt T1 = 295 mech = 'gri30.cti' gas = ct.Solution(mech) for phi in range(50, 175, 25): P1 = [] X = 'O2:0.5, N2:1.88, H2:' + str(phi / 100) cjspeed = [] for P in range(100000, 1250000, 250000): gas.TPX = T1, P, X P1.append(P / 100000) U = CJspeed(P, T1, X, mech) cjspeed.append(U) plt.plot(P1, cjspeed, label="phi=%.2f" % (phi / 100)) plt.legend() plt.xlabel('Initial pressure [bar]') plt.ylabel('CJ speed [m/s]') plt.title('Cj detonation speed of hydrogen-air mixture', fontweight='bold') plt.grid() plt.savefig('hydrogen_cjspeed(P1).png', dpi=1000) plt.show() for phi in range(50, 175, 25): P1 = [] X = 'O2:0.5, N2:1.88, H2:' + str(phi / 100) PostShock_T = []
driver_gas.equilibrate('UV') P4 = driver_gas.P T4 = driver_gas.T a3 = [soundspeed_eq(driver_gas)] u3 = [0] elif CASE_DRIVER=='cj': ## Detonation driver with CJ wave moving away from diaphragm EQ_EXP = True P_driver_fill = P1; T_driver_fill = T1; q4 = 'C2H2:1.0 O2:2.5' driver_mech = 'gri30_highT.cti' driver_gas = ct.Solution(driver_mech) driver_gas.TPX = T_driver_fill,P_driver_fill,q4 rho4 = driver_gas.density cj_speed = CJspeed(P_driver_fill, T_driver_fill, q4, driver_mech) driver_gas = PostShock_eq(cj_speed,P_driver_fill, T_driver_fill, q4, driver_mech) P4 = driver_gas.P T4 = driver_gas.T a3 = [soundspeed_eq(driver_gas)] w3 = cj_speed*rho4/driver_gas.density u3 = [w3-cj_speed] ## Evaluate initial state for expansion computation rho3 = [driver_gas.density] P3 = [driver_gas.P] T3 = [driver_gas.T] S4 = driver_gas.entropy_mass ## compute unsteady expansion (frozen) print('Generating points on isentrope P-u curve')
gas.equilibrate('HP') hp_rho.append(gas.density) hp_exp.append(init_rho/hp_rho[-1]) hp_T.append(gas.T) hp_ae.append(soundspeed_eq(gas)) # Constant Volume Explosion State gas.TPX = T1,P1,x gas.equilibrate('UV') uv_P.append(gas.P) uv_T.append(gas.T) uv_ae.append(soundspeed_eq(gas)) # CJ speed gas.TPX = T1,P1,x Ucj.append(CJspeed(P1, T1, x, mech)) # vN state gas1 = PostShock_fr(Ucj[-1], P1, T1, x, mech) vn_T.append(gas1.T) vn_P.append(gas1.P) vn_rho.append(gas1.density) vn_af.append(soundspeed_fr(gas1)) # ZND Structure ZNDout = zndsolve(gas1,gas,Ucj[-1],advanced_output=True) ind_len_ZND.append(ZNDout['ind_len_ZND']) exo_len_ZND.append(ZNDout['exo_len_ZND']) # CJ state gas1 = PostShock_eq(Ucj[-1],P1, T1,x,mech)
from sdtoolbox.postshock import CJspeed from sdtoolbox.postshock import PostShock_eq import matplotlib.pyplot as plt P1 = 100000 mech = 'gri30.cti' gas = ct.Solution(mech) for phi in range(50, 175, 25): T1 = [] X = 'O2:2, N2:7.52, CH4:' + str(phi / 100) cjspeed = [] for T in range(250, 2500, 250): gas.TPX = T, P1, X T1.append(T) U = CJspeed(P1, T, X, mech) cjspeed.append(U) plt.plot(T1, cjspeed, label="phi=%.2f" % (phi / 100)) plt.legend() plt.xlabel('Initial temperature [Kelvins]') plt.ylabel('CJ speed [m/s]') plt.title('Cj detonation speed of methane-air mixture', fontweight='bold') plt.grid() plt.savefig('methane_cjspeed(T1).png', dpi=1000) plt.show() for phi in range(50, 175, 25): T1 = [] X = 'O2:2, N2:7.52, CH4:' + str(phi / 100) PostShock_T = []
N2_comp = (1 - HC_comp) * 0.79 q = {'C3H8': HC_comp, 'O2': O_comp, 'N2': N2_comp} mech = 'gri30.cti' print('\nCJ computation for ' + mech + ' with composition:') print(q) print('Initial conditions: P1 = %.3e atm & T1 = %.2f K' % (initpress, inittemp)) # generate gas solution and set initial conditions preshockgas = ct.Solution(mech) preshockgas.TPX = inittemp, initpress * ct.one_atm, q # calculate CJ speed for gas mixture cj_speed = CJspeed(initpress * ct.one_atm, inittemp, q, mech, fullOutput=False) # calculate postshock gas condition postshockgas = PostShock_fr(cj_speed, initpress * ct.one_atm, inittemp, q, mech) # save and print initial shock temp and pressure shockedpress = postshockgas.P / 101325 shockedtemp = postshockgas.T print(f' PostShock Pressure: {postshockgas.P/101325} atm') print(f' PostShock Temperature: {postshockgas.T} K') # Resolution: The PFR will be simulated by 'n_steps' time steps n_steps = 3000000
ind_len_ZND = np.zeros(npoints,float) Tf_ZND = np.zeros(npoints,float) theta_effective_ZND = np.zeros(npoints,float) # find Hydrogen nitrogen, and oxygen indices ih2 = gas.species_index('H2') io2 = gas.species_index('O2') in2 = gas.species_index('N2') x = 'H2:2.0,O2:1.0,N2:3.76' T1 = 300 P1 = ct.one_atm; P1atm = P1/ct.one_atm print('Initial Conditions') print(x + ', Pressure = %.2f atm, Temperature = %.2f K' % (P1atm,T1)) print('For %s values of overdrive' % (npoints)) cj_speed = CJspeed(P1, T1, x, mech) for i in range(npoints): overdrive[i] = (1.0 +0.6/npoints*(i)) #Overdrive = U/Ucj ratio = overdrive[i] print('%i : Overdrive = %.2f ' % (i+1,ratio)) # Find post shock state for given speed gas.TPX = T1,P1,x gas = PostShock_fr(cj_speed*overdrive[i], P1, T1, x, mech) Ts[i] = gas.T # frozen shock temperature Ps[i] = gas.P # frozen shock pressure ### Constant Volume Explosion Data ### # Solve constant volume explosion ODEs
R1 = ct.gas_constant/w1 gamma1_fr = a1_fr**2*rho1/P1 print('Layer detonation computation for '+mech+' with composition '+q) print('State 1 - Initial state of reacting layer') print(' Pressure '+str(P1)+' (Pa)') print(' Temperature '+str(T1)+' (K)') print(' Density '+str(rho1)+' (kg/m3)') print(' Sound speed (frozen) '+str(a1_fr)+' (m/s)') print(' Enthalpy '+str(h1)+' (J/kg)') print(' Entropy '+str(s1)+' (J/kg K)') print(' gamma (frozen) '+str(gamma1_fr)+' ') ## # Find CJ speed U_CJ = CJspeed(P1, T1, q, mech) # Evaluate CJ gas state gas = PostShock_eq(U_CJ,P1, T1, q, mech) x2 = gas.X P2 = gas.P T2 = gas.T rho2 = gas.density a2_eq = soundspeed_eq(gas) s2 = gas.entropy_mass h2 = gas.enthalpy_mass w2 = rho1*U_CJ/rho2 u2 = U_CJ-w2 gamma2_eq = a2_eq**2*rho2/P2 print('State 2 - CJ ') print(' CJ speed '+str(U_CJ)+' (m/s)')
mech = 'gri30.xml' #substance + oxygen gas_initial2 = ct.Solution(mech) gas_initial2.TPX = T0, P0, q1 # compute CJ speed for different prssures speed2 = np.zeros(npoints) P = np.linspace(0.1*ct.one_atm, ct.one_atm*3, npoints) for i in range(npoints): [cj_speed,R2,plot_data] = CJspeed(P[i], T0, q1, mech, fullOutput=True) speed2[i] = cj_speed print('V(p) for H2-oxygen mixture') fig, ax = plt.subplots() ax.plot(P/100000, speed2) ax.set(xlabel='Pressure [bar]', ylabel='Detonation speed [m/s]') ax.get_yaxis().get_major_formatter().set_useOffset(False) plt.show() # compute CJ speed fo different temperatures speed5 = np.zeros(npoints)
T = np.zeros(T_steps) cj_speed = np.zeros((p_steps, T_steps)) T_index = 0 p_index = 0 while p_index < p_steps: P[p_index] = P1 + p_index * (Pmax - P1) / (p_steps - 1) pbar[p_index] = P[p_index] / 100000 while T_index < T_steps: T[T_index] = T1 + T_index * (Tmax - T1) / (T_steps - 1) cj_speed[p_index, T_index] = CJspeed(P[p_index], T[T_index], q, mech) T_index += 1 p_index += 1 T_index = 0 print('CJ computation for ' + mech + ' with composition ' + q) print('CJ speed ' + str(np.round(cj_speed, 1)) + ' (m/s)') font = {'family': 'DejaVu Sans', 'weight': 'normal', 'size': 18} plt.rc('font', **font) plt.figure(figsize=(20, 10)) for i in range(T_steps // 2): plt.plot(pbar, cj_speed[:, 2 * i], label='T = %.0f K' % T[2 * i])
Windows 8.1, Windows 10, Linux (Debian 9) """ from sdtoolbox.postshock import CJspeed, PostShock_fr from sdtoolbox.znd import zndsolve from sdtoolbox.utilities import CJspeed_plot, znd_plot, znd_fileout import cantera as ct P1 = 100000 T1 = 300 q = 'H2:2 O2:1 N2:3.76' mech = 'Mevel2017.cti' file_name = 'h2air' # Find CJ speed and related data, make CJ diagnostic plots cj_speed, R2, plot_data = CJspeed(P1, T1, q, mech, fullOutput=True) CJspeed_plot(plot_data, cj_speed) # Set up gas object gas1 = ct.Solution(mech) gas1.TPX = T1, P1, q # Find post shock state for given speed gas = PostShock_fr(cj_speed, P1, T1, q, mech) # Solve ZND ODEs, make ZND plots znd_out = zndsolve(gas, gas1, cj_speed, t_end=1e-5, advanced_output=True) znd_plot(znd_out) znd_fileout(file_name, znd_out) print('Reaction zone pulse width (exothermic length) = %.4g m' %
start = rho0; stop = 4*rho0; step = 0.5*rho0 nsteps = int((stop-start)/step) for rho1 in np.linspace(start,stop,num=nsteps): gas1.SVX = s0,1/rho1,x0 P1 = gas1.P T1 = gas1.T print('Density '+str(rho1)+' (kg/m^3)') fid.write('# Initial conditions\n') fid.write('# Temperature (K) %4.1f\n' % T1) fid.write('# Pressure (Pa) %2.1f\n' % P1) fid.write('# Density (kg/m^3) %1.4e\n' % rho1) # Find CJ speed cj_speed = CJspeed(P1, T1, q, mech) print('CJspeed '+str(cj_speed)+' (m/s)'); gas = PostShock_eq(cj_speed,P1, T1, q, mech) P2 = gas.P # Evaluate overdriven detonations and reflected shocks fstart = 1.; fstop = 1.5; fstep = 0.05 fnsteps = int((fstop-fstart)/fstep) speed = []; vs = []; ps = []; pr = []; vr = [] for f in np.linspace(fstart,fstop,num=fnsteps): u_shock = f*cj_speed speed.append(u_shock) print(' Detonation Speed '+str(speed[-1])+' (m/s)') gas = PostShock_eq(u_shock,P1, T1, q, mech) # Evaluate properties of gas object vs.append(1./gas.density)
print('Initial Conditions') print(x + ', Temperature = %.2f K' % (T1)) print('For %s initial pressures' % (npoints)) for i in range(npoints): P1[i] = Po*(0.1 +1.1/npoints*(i)) P = P1[i] print('%i : P1 = %.2f atm' % (i+1,P/ct.one_atm)) gas.TPX = T1,P1[i],x ### Constant Volume Explosion Data ### # FIND POST SHOCK STATE FOR GIVEN SPEED cj_speed[i] = CJspeed(P1[i], T1, x, mech) gas = PostShock_fr(cj_speed[i], P1[i], T1, x, mech) Ts[i] = gas.T #frozen shock temperature Ps[i] = gas.P #frozen shock pressure # SOLVE CONSTANT VOLUME EXPLOSION ODES CVout = cvsolve(gas,t_end=1e-4) exo_time_CV[i] = CVout['exo_time'] ind_time_CV[i] = CVout['ind_time'] ### ZND Detonation Data ### # FIND POST SHOCK STATE FOR GIVEN SPEED gas1.TPX = T1,P1[i],x gas = PostShock_fr(cj_speed[i], P1[i], T1, x, mech) Ts[i] = gas.T #frozen shock temperature Ps[i] = gas.P #frozen shock pressure