Example 6 from RP-1311ΒΆ

Note

The python script for this example is available in the source/bind/python/cea/samples directory of the CEA repository.

Here we describe how to run example 6 from RP-1311 [1] using the Python API. This example is a detonation problem with H2 and O2 as reactants, and includes computing transport properties.

First import the required libraries:

import numpy as np
import cea

Use cea.units for unit conversions.

Declare the reactant names. Currently, the Python API requires species names to be in bytes format, so we use the b"" syntax to create byte strings.

reac_names = [b"H2", b"O2"]

Define the temperature and pressure of the initial reactant mixture, in SI units.

p1 = np.array([1.0, 20.0]) # Initial pressure (bar)
T1 = np.array([298.15, 500.0])  # Initial temperature (K)

Define the amounts of each reactant; in this case, a chemical equivalence ratio eq_ratios is prescribed (\(r_{eq}\) in the RP-1311 [2]). The arrays fuel_weights and oxidant_weights correspond to the reac_names list, and sets the weight fraction of each that is part of the fuel and oxidant mixtures, respecttively. In this case, because we are using one fuel and one oxidizer, these are simply 1.0 to indicate which reactant is the fuel and which is the oxidizer.

fuel_weights = np.array([1.0, 0.0])
oxidant_weights = np.array([0.0, 1.0])
eq_ratios = np.array([1.0])

Now instantiate the reactant and product Mixture objects. To create the product Mixture, we pass the list of reactant names along with the flag products_from_reactants=True, which will return the full set of possible product species.

reac = cea.Mixture(reac_names)
prod = cea.Mixture(reac_names, products_from_reactants=True)

Now we instantiate the DetonationSolver and DetonationSolution objects. Note that this is the point where we set the transport flag equal to True, so that transport properties will be computed when we solve the problem later.

solver = cea.DetonationSolver(prod, reactants=reac, transport=True)
solution = cea.DetonationSolution(solver)

Next, we convert the chem_eq_ratios to oxidant-to-fuel ratios.

of_ratios = len(eq_ratios)*[0.0]
for i, eqrat in enumerate(eq_ratios):
    of_ratios[i] = reac.chem_eq_ratio_to_of_ratio(oxidant_weights,
                                                  fuel_weights,
                                                  eqrat)

We will now initialize an array to store each of the solution variables for printing the output later.

n = len(eq_ratios)*len(p1)*len(T1)
of_ratio_out = np.zeros(n)
T1_out = np.zeros(n)
P1_out = np.zeros(n)
H1 = np.zeros(n)
M1 = np.zeros(n)
gamma1 = np.zeros(n)
v_sonic1 = np.zeros(n)
P = np.zeros(n)
T = np.zeros(n)
rho = np.zeros(n)
enthalpy = np.zeros(n)
energy = np.zeros(n)
gibbs = np.zeros(n)
entropy = np.zeros(n)
mach = np.zeros(n)
velocity = np.zeros(n)
v_sonic = np.zeros(n)
gamma_s = np.zeros(n)
P_P1 = np.zeros(n)
T_T1 = np.zeros(n)
M_M1 = np.zeros(n)
rho_rho1 = np.zeros(n)
cp_eq = np.zeros(n)
cp_fr = np.zeros(n)
cv_eq = np.zeros(n)
cv_fr = np.zeros(n)
molecular_weight_M = np.zeros(n)
molecular_weight_MW = np.zeros(n)
visc = np.zeros(n)
cond_fr = np.zeros(n)
cond_eq = np.zeros(n)
prandtl_fr = np.zeros(n)
prandtl_eq = np.zeros(n)
mole_fractions = {}
trace_species = []
i = 0

Now we will loop over the arrays of temperature, pressure, and o/f ratio, and solve the detonation problem at each condition. Most of the lines of code here are storing the output for printing later. Note that the solve() method strictly requires an array of weight fractions, so we first compute that array using the reactant mixture object.

for of_ratio in of_ratios:
    weights = reac.of_ratio_to_weights(oxidant_weights, fuel_weights, of_ratio)
    for t in T1:
        for p in p1:
            # Solve the detonation problem
            solver.solve(solution, weights, t, p)
            # Store the output
            of_ratio_out[i] = of_ratio
            T1_out[i] = solution.T1
            P1_out[i] = cea.units.bar_to_atm(solution.P1)
            H1[i] = cea.units.joule_to_cal(solution.H1)
            M1[i] = solution.M1
            gamma1[i] = solution.gamma1
            v_sonic1[i] = solution.sonic_velocity1
            P[i] = cea.units.bar_to_atm(solution.P)
            T[i] = solution.T
            rho[i] = solution.density*1.e-3
            enthalpy[i] = cea.units.joule_to_cal(solution.enthalpy)
            energy[i] = cea.units.joule_to_cal(solution.energy)
            gibbs[i] = cea.units.joule_to_cal(solution.gibbs_energy)
            entropy[i] = cea.units.joule_to_cal(solution.entropy)
            molecular_weight_M[i] = solution.M
            molecular_weight_MW[i] = solution.MW
            gamma_s[i] = solution.gamma_s
            cp_eq[i] = cea.units.joule_to_cal(solution.cp_eq)
            cp_fr[i] = cea.units.joule_to_cal(solution.cp_fr)
            cv_eq[i] = cea.units.joule_to_cal(solution.cv_eq)
            cv_fr[i] = cea.units.joule_to_cal(solution.cv_fr)
            v_sonic[i] = solution.sonic_velocity
            P_P1[i] = solution.P_P1
            T_T1[i] = solution.T_T1
            M_M1[i] = solution.M_M1
            rho_rho1[i] = solution.rho_rho1
            mach[i] = solution.Mach
            velocity[i] = solution.velocity
            visc[i] = solution.viscosity
            cond_fr[i] = cea.units.joule_to_cal(solution.conductivity_fr)
            cond_eq[i] = cea.units.joule_to_cal(solution.conductivity_eq)
            prandtl_fr[i] = solution.Pr_fr
            prandtl_eq[i] = solution.Pr_eq

            if i == 0:
                for prod in solution.mole_fractions:
                    mole_fractions[prod] = np.array([solution.mole_fractions[prod]])
            else:
                for prod in mole_fractions:
                    mole_fractions[prod] = np.append(mole_fractions[prod], solution.mole_fractions[prod])

            i += 1

Finally, print everything out in a formatted manner consistent with the legacy CEA output format.

print()
print("UNBURNED GAS")
print()
print("o/f             ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(of_ratio_out[i]), end=" ")
    else:
        print("{0:10.3f}".format(of_ratio_out[i]))

print("P1, atm         ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(P1_out[i]), end=" ")
    else:
        print("{0:10.3f}".format(P1_out[i]))

print("T1, K           ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(T1_out[i]), end=" ")
    else:
        print("{0:10.3f}".format(T1_out[i]))

print("H1, cal/g       ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(H1[i]), end=" ")
    else:
        print("{0:10.3f}".format(H1[i]))

print("M1 (1/n)        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(M1[i]), end=" ")
    else:
        print("{0:10.3f}".format(M1[i]))

print("Gamma1          ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(gamma1[i]), end=" ")
    else:
        print("{0:10.3f}".format(gamma1[i]))

print("Son. Vel.1, m/s ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(v_sonic1[i]), end=" ")
    else:
        print("{0:10.3f}".format(v_sonic1[i]))

print()
print("BURNED GAS")
print()
print("P, atm          ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(P[i]), end=" ")
    else:
        print("{0:10.3f}".format(P[i]))

print("T, K            ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(T[i]), end=" ")
    else:
        print("{0:10.3f}".format(T[i]))

print("Density, g/cc   ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3e}".format(rho[i]), end=" ")
    else:
        print("{0:10.3e}".format(rho[i]))

print("H, cal/g        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(enthalpy[i]), end=" ")
    else:
        print("{0:10.3f}".format(enthalpy[i]))

print("U, cal/g        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(energy[i]), end=" ")
    else:
        print("{0:10.3f}".format(energy[i]))

print("G, cal/g        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.1f}".format(gibbs[i]), end=" ")
    else:
        print("{0:10.1f}".format(gibbs[i]))

print("S, cal/g-K      ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(entropy[i]), end=" ")
    else:
        print("{0:10.3f}".format(entropy[i]))

print("M, (1/n)        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(molecular_weight_M[i]), end=" ")
    else:
        print("{0:10.3f}".format(molecular_weight_M[i]))

print("MW              ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.3f}".format(molecular_weight_MW[i]), end=" ")
    else:
        print("{0:10.3f}".format(molecular_weight_MW[i]))

print("Gamma_s         ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(gamma_s[i]), end=" ")
    else:
        print("{0:10.4f}".format(gamma_s[i]))

print("Cp_eq, cal/g-K  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cp_eq[i]), end=" ")
    else:
        print("{0:10.4f}".format(cp_eq[i]))

print("Cp_fr, cal/g-K  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cp_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(cp_fr[i]))

print("Cv_eq, cal/g-K  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cv_eq[i]), end=" ")
    else:
        print("{0:10.4f}".format(cv_eq[i]))

print("Cv_fr, cal/g-K  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cv_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(cv_fr[i]))

print("Son. Vel., m/s  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(v_sonic[i]), end=" ")
    else:
        print("{0:10.4f}".format(v_sonic[i]))

print("")
print("Transport properties:")
print("")

print("Viscosity, mP   ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(visc[i]), end=" ")
    else:
        print("{0:10.4f}".format(visc[i]))

print("")
print("with equilibrium reaction:")
print("")

print("Cp, cal/g-K     ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cp_eq[i]), end=" ")
    else:
        print("{0:10.4f}".format(cp_eq[i]))

print("Cv, cal/g-K     ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cv_eq[i]), end=" ")
    else:
        print("{0:10.4f}".format(cv_eq[i]))

print("Conductivity    ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cond_eq[i]), end=" ")
    else:
        print("{0:10.4f}".format(cond_eq[i]))

print("Prandtl number  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(prandtl_eq[i]), end=" ")
    else:
        print("{0:10.4f}".format(prandtl_eq[i]))

print("")
print("with frozen reaction:")
print("")

print("Cp, cal/g-K     ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cp_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(cp_fr[i]))

print("Cv, cal/g-K     ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cv_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(cv_fr[i]))

print("Conductivity    ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(cond_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(cond_fr[i]))

print("Prandtl number  ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(prandtl_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(prandtl_fr[i]))

print()
print("DETONATION PARAMETERS")
print()

print("P/P1            ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(P_P1[i]), end=" ")
    else:
        print("{0:10.4f}".format(P_P1[i]))

print("T/T1            ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(T_T1[i]), end=" ")
    else:
        print("{0:10.4f}".format(T_T1[i]))

print("M/M1            ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(M_M1[i]), end=" ")
    else:
        print("{0:10.4f}".format(M_M1[i]))

print("rho/rho1        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(rho_rho1[i]), end=" ")
    else:
        print("{0:10.4f}".format(rho_rho1[i]))

print("Mach            ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(mach[i]), end=" ")
    else:
        print("{0:10.4f}".format(mach[i]))

print("Velocity        ", end="")
for i in range(n):
    if i < n-1:
        print("{0:10.4f}".format(velocity[i]), end=" ")
    else:
        print("{0:10.4f}".format(velocity[i]))

print()
print("MOLE FRACTIONS")
print("")
trace_species = []
for prod in mole_fractions:
    if np.any(mole_fractions[prod] > 5e-6):
        print("{0:15s}".format(prod), end=" ")
        for j in range(n):
            if j < n-1:
                print("{0:10.5g}".format(mole_fractions[prod][j]), end=" ")
            else:
                print("{0:10.5g}".format(mole_fractions[prod][j]))
    else:
        trace_species.append(prod)

print()
print("TRACE SPECIES:")
max_cols = 8
nrows = (len(trace_species) + max_cols - 1) // max_cols
for i in range(nrows):
    print(" ".join("{0:15s}".format(trace_species[j]) for j in range(i * max_cols, min((i + 1) * max_cols, len(trace_species)))))

This results in the following output to the terminal:

UNBURNED GAS

o/f                  7.937      7.937      7.937      7.937
P1, atm              0.987     19.738      0.987     19.738
T1, K              298.150    298.150    500.000    500.000
H1, cal/g           -0.000     -0.000    118.410    118.410
M1 (1/n)            12.010     12.010     12.010     12.010
Gamma1               1.402      1.402      1.386      1.386
Son. Vel.1, m/s    537.868    537.868    692.592    692.592

BURNED GAS

P, atm              18.523    409.027     10.813    240.197
T, K              3674.283   4283.382   3600.034   4209.491
Density, g/cc    8.908e-04  1.775e-02  5.219e-04  1.042e-02
H, cal/g           676.647    752.006    758.260    836.596
U, cal/g           173.085    194.015    256.508    278.369
G, cal/g          -14625.8   -15395.6   -14583.5   -15410.9
S, cal/g-K           4.165      3.770      4.262      3.860
M, (1/n)            14.500     15.255     14.258     14.985
MW                  14.500     15.255     14.258     14.985
Gamma_s             1.1288     1.1438     1.1266     1.1423
Cp_eq, cal/g-K      3.8874     2.4544     4.3162     2.7219
Cp_fr, cal/g-K      0.7784     0.7936     0.7765     0.7920
Cv_eq, cal/g-K      3.1830     2.0235     3.5188     2.2326
Cv_fr, cal/g-K      0.6413     0.6633     0.6372     0.6593
Son. Vel., m/s   1542.1580  1634.1166  1537.8972  1633.4041

Transport properties:

Viscosity, mP       1.1412     1.2740     1.1244     1.2589

with equilibrium reaction:

Cp, cal/g-K         3.8874     2.4544     4.3162     2.7219
Cv, cal/g-K         3.1830     2.0235     3.5188     2.2326
Conductivity        9.1031     5.9556    10.0641     6.6597
Prandtl number      0.4873     0.5250     0.4822     0.5145

with frozen reaction:

Cp, cal/g-K         0.7784     0.7936     0.7765     0.7920
Cv, cal/g-K         0.6413     0.6633     0.6372     0.6593
Conductivity        1.2903     1.4211     1.2823     1.4170
Prandtl number      0.6884     0.7115     0.6809     0.7036

DETONATION PARAMETERS

P/P1               18.7688    20.7227    10.9569    12.1691
T/T1               12.3236    14.3665     7.2001     8.4190
M/M1                1.2073     1.2701     1.1872     1.2477
rho/rho1            1.8387     1.8321     1.8066     1.8035
Mach                5.2718     5.5661     4.0115     4.2533
Velocity         2835.5321  2993.8052  2778.3142  2945.7966

MOLE FRACTIONS

H                 0.080079   0.047166   0.090963    0.05644
H2                 0.16211    0.14397    0.16681    0.15214
H2O                0.53189    0.60992    0.50727    0.57898
H2O2             2.004e-05 0.00016339 1.3838e-05 0.00011628
HO2             0.00018402  0.0006771 0.00014829 0.00056843
O                 0.037436    0.02347   0.042144   0.027923
O2                0.046851   0.037051   0.049053   0.039695
OH                 0.14143    0.13758     0.1436    0.14414

TRACE SPECIES:
O3              H2O(L)          H2O(cr)