예제 #1
0
    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
예제 #2
0
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()
예제 #3
0
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
예제 #4
0
    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)
예제 #5
0
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()
예제 #6
0
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 = []
예제 #7
0
    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')
예제 #8
0
    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)
예제 #9
0
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 = []
예제 #10
0
    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
예제 #12
0
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)')
예제 #13
0
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)

예제 #14
0
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])
예제 #15
0
    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' %
예제 #16
0
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)
예제 #17
0

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