# ideal-shock-test.py # # $ prep-gas ideal-air.inp ideal-air-gas-model.lua # $ python3 ideal-shock-test.py # # PJ, 2019-11-28 # import math from eilmer.gas import GasModel, GasState, GasFlow gmodel = GasModel('ideal-air-gas-model.lua') state1 = GasState(gmodel) state1.p = 125.0e3 # Pa state1.T = 300.0 # K state1.update_thermo_from_pT() state1.update_sound_speed() print("state1: %s" % state1) print("normal shock (in ideal gas), given shock speed") vs = 2414.0 state2 = GasState(gmodel) flow = GasFlow(gmodel) v2, vg = flow.ideal_shock(state1, vs, state2) print("v2=%g vg=%g" % (v2, vg)) print("state2: %s" % state2)
# $ python3 conical-shock-test.py # # PJ, 2019-12-01 # import math def approxEqual(a, b): result = math.isclose(a, b, rel_tol=1.0e-2, abs_tol=1.0e-5) # print("a=",a, "b=",b, "rel=",(a-b)/b, "abs=",a-b, "result=",result) return result from eilmer.gas import GasModel, GasState, GasFlow m1 = 1.5 print("Conical-shock demo for m1=%g" % m1) gmodel = GasModel('cea-air13species-gas-model.lua') state1 = GasState(gmodel) state1.p = 100.0e3 # Pa state1.T = 300.0 # K ideal air, not high T state1.update_thermo_from_pT() state1.update_sound_speed() print("state1: %s" % state1) v1 = m1*state1.a print("v1=%g" % v1) beta = 45.0 * math.pi/180.0 print(" given beta(degrees)=%g" % (beta*180/math.pi)) state_c = GasState(gmodel) flow = GasFlow(gmodel) theta_c, v_c = flow.theta_cone(state1, v1, beta, state_c) print(" theta_c=%g degrees" % (theta_c*180/math.pi)) print(" v_c=%g" % (v_c))
# A script to compute the viscosity and thermal conductivity # of air (as a mixture of N2 and O2) from 200 -- 20000 K. # # Author: Peter J. and Rowan J. Gollan # Date: 2019-11-21 # # To run this script: # $ prep-gas thermally-perfect-N2-O2.inp thermally-perfect-N2-O2.lua # $ python3 transport-properties-for-air.py # from eilmer.gas import GasModel, GasState gasModelFile = 'thermally-perfect-N2-O2.lua' gmodel = GasModel(gasModelFile) gs = GasState(gmodel) gs.p = 1.0e5 # Pa gs.massf = {"N2":0.78, "O2":0.22} # approximation for the composition of air outputFile = 'trans-props-air.dat' print("Opening file for writing: %s" % outputFile) f = open(outputFile, "w") f.write("# 1:T[K] 2:mu[Pa.s] 3:k[W/(m.K)]\n") lowT = 200.0 dT = 100.0 for i in range(199): gs.T = dT*i + lowT gs.update_thermo_from_pT() gs.update_trans_coeffs()
# Typical use: # $ python3 poshax.py # #------------------------------------------------------------------ from eilmer.gas import GasModel, GasState, GasFlow, ThermochemicalReactor debug = False print("Initialise a gas model.") print("air 7 species Gupta-et-al reactions") gmodel = GasModel("air-7sp-gas-model.lua") nsp = gmodel.n_species nmodes = gmodel.n_modes if debug: print("nsp=", nsp, " nmodes=", nmodes, " gmodel=", gmodel) reactor = ThermochemicalReactor(gmodel, "air-7sp-chemistry.lua") # The example here matches the case discussed on page 63 of the thesis. state1 = GasState(gmodel) state1.p = 133.3 # Pa state1.T = 300.0 # degree K state1.massf = {"N2": 0.78, "O2": 0.22} print("Free stream conditions, before the shock.") state1.update_thermo_from_pT() state1.update_sound_speed() print(" state1: %s" % state1) mach1 = 12.28 v1 = mach1 * state1.a print("mach1:", mach1, "v1:", v1) print("Stationary normal shock with chemically-frozen gas.") flow = GasFlow(gmodel) state2 = GasState(gmodel) v2, vg = flow.normal_shock(state1, v1, state2)
def eos_derivatives(gas0, gmodel, tol=0.0001): # Finite difference evaluation, assuming that gas0 is valid state already. gas1 = GasState(gmodel) gas1.copy_values(gas0) p0 = gas0.p rho0 = gas0.rho u0 = gas0.u # drho = rho0 * tol gas1.rho = rho0 + drho gas1.update_thermo_from_rhou() dpdrho = (gas1.p - p0) / drho # gas1.rho = rho0 du = u0 * tol gas1.u = u0 + du gas1.update_thermo_from_rhou() dpdu = (gas1.p - p0) / du # return dpdrho, dpdu
# Step through a steady isentropic expansion, # from stagnation condition to sonic condition. # # $ prep-gas ideal-air.inp ideal-air-gas-model.lua # $ python3 isentropic-air-expansion.py # # Python port, PJ, 2019-11-21 # import math from eilmer.gas import GasModel, GasState gmodel = GasModel('ideal-air-gas-model.lua') gs = GasState(gmodel) gs.p = 500e3 # Pa gs.T = 300.0 # K gs.update_thermo_from_pT() # Compute enthalpy and entropy at stagnation conditions h0 = gs.enthalpy s0 = gs.entropy # Set up for stepping process dp = 1.0 # Pa, use 1 Pa as pressure step size gs.p = gs.p - dp mach_tgt = 1.0 # Begin stepping until Mach = mach_tgt while True: gs.update_thermo_from_ps(s0) h1 = gs.enthalpy v1 = math.sqrt(2*(h0 - h1)) m1 = v1/gs.a if m1 >= mach_tgt: print("Stopping at Mach=%g" % m1)
# $ python3 co2_scheme_validation.py # #------------------------------------------------------------------ from eilmer.gas import GasModel, GasState, GasFlow, ThermochemicalReactor debug = False print("Initialise a gas model.") print("Park et al mars atmosphere reaction scheme.") gmodel = GasModel("mars-atm-with-ions.lua") nsp = gmodel.n_species nmodes = gmodel.n_modes if debug: print("nsp=", nsp, " nmodes=", nmodes, " gmodel=", gmodel) reactor = ThermochemicalReactor(gmodel, "mars-atm-with-ions-chemistry.lua") # The example here matches the case on p.17 of Park's publication v1 = 8000 state1 = GasState(gmodel) state1.rho = 0.15 * 101300 / v1**2 # freestream density according to Park to keep p after the shock at 0.15atm print("Free stream desnity:", state1.rho) state1.T = 210.0 # K, Mars surface temp state1.massf = { "CO2": 0.9664, "N2": 0.0174, "Ar": 0.0147, "O2": 0.001, "CO": 0.0005 } print("Free stream conditions, before the shock.") state1.update_thermo_from_rhoT() state1.update_sound_speed() print(" state1: %s" % state1) mach1 = v1 / state1.a
# You will need to "make install" the loadable library # and then invoke this script from a location where # the gas-model Lua file is visible, as given by the path below. # # PJ 2019-07-24 direct use of FFI # 2019-07-25 using Pythonic wrapper # from eilmer.gas import GasModel, GasState gmodel = GasModel("ideal-air-gas-model.lua") print("gmodel=", gmodel) print("n_species=", gmodel.n_species, ", n_modes=", gmodel.n_modes) print("species_names=", gmodel.species_names) print("mol_masses=", gmodel.mol_masses) gs = GasState(gmodel) print("freshly minted gs=", gs) gs.rho=1.1; gs.p=1.0e5; gs.T=300.0; gs.u=1.44e6; gs.massf=[1.0] print("after setting some values") print(" gs.rho=%g p=%g T=%g u=%g massf=%s a=%g k=%g mu=%g" % (gs.rho, gs.p, gs.T, gs.u, gs.massf, gs.a, gs.k, gs.mu)) gmodel.update_thermo_from_pT(gs) # the way that we do the update in D gmodel.update_sound_speed(gs) # not necessary from Python but is available gmodel.update_trans_coeffs(gs) print("after update thermo from pT") print(" gs.rho=%g p=%g T=%g u=%g massf=%s a=%g k=%g mu=%g" % (gs.rho, gs.p, gs.T, gs.u, gs.massf, gs.a, gs.k, gs.mu)) gs.p=3000.0; gs.T=99.0; gs.massf={'air':1.0} gs.update_thermo_from_rhou() # update another way gs.update_trans_coeffs() print("after update thermo from rhou")
#------------------------------------------------------------------ # Start the main script... debug = False print("# Reacting pipe flow -- Bittker-Scullin test case 3.") print(sample_header) # Gas model setup gmodel = GasModel("h2-o2-n2-9sp.lua") nsp = gmodel.n_species nmodes = gmodel.n_modes if debug: print("nsp=", nsp, " nmodes=", nmodes, " gmodel=", gmodel) print("# Gas properties at the start of the pipe.") gas0 = GasState(gmodel) gas0.p = 96.87e3 # Pa x = 0.0 # m (inlet of pipe) v = 4551.73 # m/s gas0.T = 1559.0 # degree K gas0.molef = {"O2": 0.1480, "N2": 0.5562, "H2": 0.2958} gas0.update_thermo_from_pT() dt_suggest = 1.0e-8 # suggested starting time-step for chemistry updater print(sample_data(x, v, gas0, dt_suggest)) print("# Start reactions...") reactor = ThermochemicalReactor(gmodel, "h2-o2-n2-9sp-18r.lua") t = 0 # time is in seconds t_final = 22.0e-6 t_inc = 0.05e-6 nsteps = int(t_final / t_inc)
# A script to output Cp and h for O2 over temperature range 200--20000 K. # # Author: Peter J. and Rowan J. Gollan # Date: 2019-11-21 # # To run this script: # $ prep-gas O2.inp O2-gas-model.lua # $ python3 thermo-curves-for-O2.py # from eilmer.gas import GasModel, GasState gasModelFile = 'O2-gas-model.lua' gmodel = GasModel(gasModelFile) gs = GasState(gmodel) gs.p = 1.0e5 # Pa gs.massf = {"O2": 1.0} outputFile = 'O2-thermo.dat' print("Opening file for writing: %s" % outputFile) f = open(outputFile, "w") f.write("# 1:T[K] 2:Cp[J/kg/K] 3:h[J/kg]\n") lowT = 200.0 dT = 100.0 for i in range(199): gs.T = dT * i + lowT gs.update_thermo_from_pT() f.write(" %12.6e %12.6e %12.6e\n" % (gs.T, gs.Cp, gs.enthalpy))
return dpdrho, dpdu #------------------------------------------------------------------ # Start the main script... debug = False print("# Reacting nozzle flow.") print(sample_header) # Gas model setup gmodel = GasModel("h2-o2-n2-5sp.lua") nsp = gmodel.n_species nmodes = gmodel.n_modes if debug: print("nsp=", nsp, " nmodes=", nmodes, " gmodel=", gmodel) print("# Gas properties at the start of the pipe.") gas0 = GasState(gmodel) gas0.p = 81.0e3 # Pa x = 0.0 # m (inlet of duct) area = duct_area(x) v = 1230.0 # m/s gas0.T = 1900.0 # degree K gas0.molef = {"O2":0.1865, "N2":0.7016, "H2":0.1119} gas0.update_thermo_from_pT() dt_suggest = 1.0e-12 # suggested starting time-step for chemistry print(sample_data(x, area, v, gas0, dt_suggest)) if debug: print("# species=", gmodel.species_names) print("# massf=", gas0.massf) print("# Start reactions...")
default="302.0", help="Temperature (degree K) at which to evaluate the internal energy offset.") (options, args) = parser.parse_args() if options.tableName == None or options.gasModelFile == None: parser.print_help() print("") print("Example 1: build-uniform-lut --gas-model=cea-air5species-gas-model.lua"+ " --table-name=air5species") print("Example 2: build-uniform-lut --gas-model=cea-air13species-gas-model.lua"+ " --table-name=air13species --bounds=\"500,20000,-6.0,2.0\"") print("Example 3: build-uniform-lut --gas-model=cea-co2-gas-model.lua"+ " --table-name=co2 --T-for-offset=650.0 --bounds=\"1000.0,20000,-6.0,2.0\"") print("Example 4: build-uniform-lut --gas-model=cea-co2-ions-gas-model.lua"+ " --table-name=co2-ions --T-for-offset=1000.0 --bounds=\"1000.0,20000,-6.0,2.0\"") print("") print("Sometimes CEA2 has problems and the table will fail to build.") print("The best approach to fixing the problem seems to be to raise") print("the lower temperatures, as shown in examples 2, 3 and 4 (above).") sys.exit() T_min, T_max, log_rho_min, log_rho_max = [float(item) for item in options.bounds.split(',')] T_for_offset = float(options.T_for_offset) print("Density, Temperature ranges:") print(" log_rho_min=", log_rho_min, "log_rho_max=", log_rho_max) print(" T_min=", T_min, "T_max=", T_max) print("Building table for gas model:", options.gasModelFile) gmodel = GasModel(options.gasModelFile) assert gmodel.n_modes == 0, "Use only a single-temperature gas model." gs = GasState(gmodel) build_table(gs, options.tableName, T_min, T_max, log_rho_min, log_rho_max, T_for_offset) print("Done.")
# gasModelFile = "ideal-air-gas-model.lua" # Alternative gmodel = GasModel(gasModelFile) if gmodel.n_species == 1: print("Ideal air gas model.") air_massf = {"air": 1.0} else: print("Thermally-perfect air model.") air_massf = {"N2": 0.78, "O2": 0.22} print("Compute cycle states:") gs = [] # We will build up a list of gas states h = [] # and enthalpies. # Note that we want to use indices consistent with the Lua script, # so we set up 5 elements but ignore the one with 0 index. for i in range(5): gs.append(GasState(gmodel)) h.append(0.0) for i in range(1, 5): gs[i].massf = air_massf print(" Start with ambient air") gs[1].p = 100.0e3 gs[1].T = 300.0 gs[1].update_thermo_from_pT() s12 = gs[1].entropy h[1] = gs[1].enthalpy print(" Isentropic compression with a pressure ratio of 8") gs[2].p = 8 * gs[1].p gs[2].update_thermo_from_ps(s12) h[2] = gs[2].enthalpy
# A simple fixed-volume reactor. # PJ & RJG 2019-11-25 # # To prepare: # $ prep-gas nitrogen-2sp.inp nitrogen-2sp.lua # $ prep-chem nitrogen-2sp.lua nitrogen-2sp-2r.lua chem.lua # # To run: # $ python3 fvreactor.py from eilmer.gas import GasModel, GasState, ThermochemicalReactor gm = GasModel("nitrogen-2sp.lua") reactor = ThermochemicalReactor(gm, "chem.lua") gs = GasState(gm) gs.p = 1.0e5 # Pa gs.T = 4000.0 # degree K gs.molef = {'N2': 2 / 3, 'N': 1 / 3} gs.update_thermo_from_pT() tFinal = 200.0e-6 # s t = 0.0 dt = 1.0e-6 dtSuggest = 1.0e-11 print("# Start integration") f = open("fvreactor.data", 'w') f.write( '# 1:t(s) 2:T(K) 3:p(Pa) 4:massf_N2 5:massf_N 6:conc_N2 7:conc_N\n') f.write("%10.3e %10.3f %10.3e %20.12e %20.12e %20.12e %20.12e\n" % (t, gs.T, gs.p, gs.massf[0], gs.massf[1], gs.conc[0], gs.conc[1]))