Example 11 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 11 from RP-1311 [1] using the Python API. This is a rocket problem assuming an infinite-area combustor (IAC), using Li(cr) and F2(L) as reactants. The problem includes the use of ionized species, and computes transport properties of the resulting mixture. The result of this problem also includes condensed species.

First import the required libraries:

import numpy as np
import cea

Use cea.units for unit conversions and cea.R inline when normalizing enthalpy.

Declare the reactants and set their amounts and initial temperatures. Currently, the Python API requires species names to be in bytes format, so we use the b"" syntax to create byte strings. The initial reactant temperatures, T_reactant, will be used later to compute the chamber enthalpy. The amounts of each are specified through the fuel_moles and oxidant_moles variables specified here.

reac_names = [b"Li(cr)", b"F2(L)"]
T_reactant = np.array([298.15, 85.02])  # Reactant temperatures (K)
fuel_moles = np.array([1.0, 0.0])
oxidant_moles = np.array([0.0, 0.5556])

Now we will 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. Note that both of these initializations set ions=True to ensure that ionized species are included.

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

Now initialize the RocketSolver and RocketSolution class instances. We again set ions=True during the RocketSolver class initialization, and at this point, we also set transport=True which sets the flag to compute transport properties later when we call solve().

solver = cea.RocketSolver(prod, reactants=reac, transport=True, ions=True)
solution = cea.RocketSolution(solver)

Compute the array of weight fractions for the reactant mixture:

fuel_weights = reac.moles_to_weights(fuel_moles)
oxidant_weights = reac.moles_to_weights(oxidant_moles)
weights = fuel_weights + oxidant_weights

Compute the chamber enthalpy value based on the reactants weights and temperatures. We will pass this in later when we call solve(). Note that this value is normalized by R here.

hc = reac.calc_property(cea.ENTHALPY, weights, T_reactant)/cea.R

Now we can solve the solve() function:

solver.solve(solution, weights, pc, pi_p, subar=subar, supar=supar, iac=True, hc=hc)

Finally, querry the solution variables and print them out:

num_pts = solution.num_pts
T = solution.T
P = solution.P
rho = solution.density
enthalpy = solution.enthalpy
energy = solution.energy
gibbs = solution.gibbs_energy
entropy = solution.entropy
n = solution.n
M_1n = solution.M
MW = solution.MW
cp_eq = solution.cp_eq
cp_fr = solution.cp_fr
cv_eq = solution.cv_eq
cv_fr = solution.cv_fr
visc = solution.viscosity
cond_fr = solution.conductivity_fr
cond_eq = solution.conductivity_eq
prandtl_fr = solution.Pr_fr
prandtl_eq = solution.Pr_eq
Mach = solution.Mach
gamma_s = solution.gamma_s
v_sonic = solution.sonic_velocity
ae_at = solution.ae_at
c_star = solution.c_star
Cf = solution.coefficient_of_thrust
Isp = solution.Isp
Isp_vac = solution.Isp_vacuum

print("P, bar         ", end=" ")
for i in range(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-1:
        print("{0:10.3f}".format(T[i]), end=" ")
    else:
        print("{0:10.3f}".format(T[i]))

print("Density, kg/m^3", end=" ")
for i in range(num_pts):
    if i < num_pts-1:
        print("{0:10.3f}".format(rho[i]), end=" ")
    else:
        print("{0:10.3f}".format(rho[i]))

print("H, kJ/kg       ", end=" ")
for i in range(num_pts):
    if i < num_pts-1:
        print("{0:10.2f}".format(enthalpy[i]), end=" ")
    else:
        print("{0:10.2f}".format(enthalpy[i]))

print("U, kJ/kg       ", end=" ")
for i in range(num_pts):
    if i < num_pts-1:
        print("{0:10.2f}".format(energy[i]), end=" ")
    else:
        print("{0:10.2f}".format(energy[i]))

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

print("S, kJ/kg-K     ", end=" ")
for i in range(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-1:
        print("{0:10.3f}".format(M_1n[i]), end=" ")
    else:
        print("{0:10.3f}".format(M_1n[i]))

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

print("Cp, kJ/kg-K    ", end=" ")
for i in range(num_pts):
    if i < num_pts-1:
        print("{0:10.3f}".format(cp_eq[i]), end=" ")
    else:
        print("{0:10.3f}".format(cp_eq[i]))

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

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

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

print("")
print("TRANSPORT PROPERTIES")
print("")

print("Viscosity, mP   ", end="")
for i in range(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-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(num_pts):
    if i < num_pts-1:
        print("{0:10.4f}".format(prandtl_fr[i]), end=" ")
    else:
        print("{0:10.4f}".format(prandtl_fr[i]))

print("")
print("PERFORMANCE PARAMETERS")
print("")

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

print("C*, m/s        ", end=" ")
for i in range(num_pts):
    if i < num_pts-1:
        print("{0:10.2f}".format(c_star[i]), end=" ")
    else:
        print("{0:10.2f}".format(c_star[i]))

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

print("Isp, vac., m/s ", end=" ")
for i in range(num_pts):
    if i < num_pts-1:
        print("{0:10.3f}".format(Isp_vac[i]), end=" ")
    else:
        print("{0:10.3f}".format(Isp_vac[i]))

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

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

P, bar              68.948     39.299      1.013     68.804      0.942      0.368      0.044
T, K              5680.808   5332.680   3508.666   5679.461   3470.831   2926.665   1955.978
Density, kg/m^3      3.218      1.994      0.087      3.212      0.082      0.038      0.007
H, kJ/kg           -259.28   -1414.52   -7031.63    -263.73   -7115.90   -8109.52   -9765.47
U, kJ/kg          -2402.02   -3385.05   -8196.38   -2405.80   -8266.77   -9072.36  -10394.18
G, kJ/kg          -64725.7   -61930.3   -46848.3   -64714.9   -46503.3   -41321.6   -31962.1
S, kJ/kg-K          11.348     11.348     11.348     11.348     11.348     11.348     11.348
M, (1/n)            22.043     22.501     25.047     22.045     25.075     25.273     25.867
MW                  22.043     22.501     25.047     22.045     25.075     25.273     25.867
Cp, kJ/kg-K          6.742      6.570      2.645      6.741      2.529      1.631      3.122
Gamma_s              1.178      1.173      1.195      1.178      1.199      1.267      1.196
Son. vel., m/s     1588.67    1520.02    1179.71    1588.41    1174.84    1104.36     866.99
Mach                 0.000      1.000      3.120      0.059      3.152      3.588      5.029

TRANSPORT PROPERTIES

Viscosity, mP       1.4414     1.3880     1.0810     1.4412     1.0734     0.9580     0.7308

with equilibrium reaction:

Cp, cal/g-K         6.7418     6.5700     2.6448     6.7414     2.5293     1.6315     3.1219
Cv, cal/g-K         5.2923     5.2263     2.1940     5.2922     2.0924     1.2854     2.5518
Conductivity       14.4426    13.6926     4.3206    14.4401     4.0891     2.2075     2.6678
Prandtl number      0.6729     0.6660     0.6617     0.6728     0.6640     0.7080     0.8552

with frozen reaction:

Cp, cal/g-K         1.6854     1.6503     1.5156     1.6852     1.5137     1.4904     1.4584
Cv, cal/g-K         1.3082     1.2807     1.1836     1.3081     1.1822     1.1614     1.1370
Conductivity        3.1552     3.0168     2.2918     3.1547     2.2744     2.0066     1.4888
Prandtl number      0.7700     0.7593     0.7148     0.7699     0.7144     0.7115     0.7159

PERFORMANCE PARAMETERS

Ae/At                0.000      1.000      9.468     10.000     10.000     20.000    100.000
C*, m/s            2274.40    2274.40    2274.40    2274.40    2274.40    2274.40    2274.40
Cf                   0.000      0.668      1.618      0.041      1.628      1.742      1.917
Isp, vac., m/s       0.000   2816.400   3996.792  22791.160   4013.922   4205.378   4504.509
Isp, m/s             0.000   1520.029   3680.312     94.377   3703.139   3962.382   4360.319

MOLE FRACTIONS

F                  0.20853    0.19341     0.1076    0.20848    0.10664    0.10062    0.10253
F-               0.0045774  0.0035905 0.00028192  0.0045735 0.00025498 3.6579e-05 3.7622e-08
F2              1.5866e-05 1.0131e-05 6.6385e-07  1.584e-05   6.47e-07 6.8415e-07   2.69e-06
Li                 0.11766     0.1016  0.0082205     0.1176  0.0071628 0.00043266 2.0646e-08
Li+              0.0073265  0.0058435 0.00037576  0.0073207 0.00033424 3.8991e-05 3.7631e-08
Li-             2.3779e-05 1.2161e-05 6.1699e-09 2.3723e-05 4.4374e-09 7.1984e-12 1.4196e-21
Li2             0.00020698 0.00010255 6.6038e-08 0.00020646 4.8707e-08 1.4744e-10 3.9217e-19
Li2+            0.00016743 8.3248e-05 6.1651e-08 0.00016701  4.669e-08  2.969e-10 2.1021e-17
Li2F2            0.0014414  0.0012625 0.00083528  0.0014407 0.00085229   0.001579   0.023952
Li3F3           3.7935e-06 2.6207e-06 6.4793e-07 3.7882e-06 6.6756e-07   1.99e-06 0.00034821
LiF                0.65715    0.69175    0.88259    0.65727    0.88467    0.89729    0.87316
e-               0.0028928  0.0023241 9.3897e-05  0.0028905 7.9304e-05  2.412e-06 9.0735e-12

TRACE SPECIES:
F+              Li3+            Li(L)           Li(cr)          LiF(L)          LiF(cr)