def test_condensing_equil(pypropep): kno3 = pypropep.PROPELLANTS['POTASSIUM NITRATE'] sugar = pypropep.PROPELLANTS['SUCROSE (TABLE SUGAR)'] p = pypropep.Equilibrium() p.add_propellants([(kno3, 0.65 / kno3.mw), (sugar, 0.35 / sugar.mw)]) p.set_state(P=30) assert len(p.composition_condensed) > 0
def test_simp_equil(pypropep): e = pypropep.Equilibrium() o2 = pypropep.PROPELLANTS['OXYGEN (GAS)'] ch4 = pypropep.PROPELLANTS['METHANE'] e.add_propellants([(o2, 1.), (ch4, 1.)]) e.set_state(P=1.0, T=3000., type='TP') assert e.equilibrated is True assert e.properties_computed is True
def test_equil_modes(pypropep): e = pypropep.Equilibrium() with pytest.raises(ValueError): e.set_state(P=1., type='TP') with pytest.raises(ValueError): e.set_state(P=1., T=300., type='HP') with pytest.raises(ValueError): e.set_state(P=1., T=300., type='SP')
def test_TP_composition(pypropep): e = pypropep.Equilibrium() n2 = pypropep.PROPELLANTS['NITROGEN (GASEOUS)'] e.add_propellant(n2, 1.0) with pytest.raises(RuntimeError): print(e._compute_product_composition()) # Compostion should be None prior to equilibration assert e.composition is None assert e.composition_sorted is None assert e.composition_condensed is None # equilibrate e.set_state(P=1.0, T=273., type='TP') assert e.equilibrated is True assert e.properties_computed is True assert 'N2' in e.composition for k, v in list(e.composition.items()): if k == 'N2': assert v == pytest.approx(1.0, 1e-6) else: assert v == pytest.approx(0.0, 1e-6)
def test_properties(pypropep): p = pypropep.FrozenPerformance() ps = pypropep.ShiftingPerformance() e = pypropep.Equilibrium() lh2 = pypropep.PROPELLANTS['RP-1 (RPL)'] lox = pypropep.PROPELLANTS['OXYGEN (LIQUID)'] OF = 0.13 p.add_propellants_by_mass([(lh2, 1.0), (lox, OF)]) p.set_state(P=30, Ae_At=25.) ps.add_propellants_by_mass([(lh2, 1.0), (lox, OF)]) ps.set_state(P=30, Ae_At=25.) e.add_propellants_by_mass([(lh2, 1.0), (lox, OF)]) e.set_state(P=30, type='HP') assert p.properties[0].T == pytest.approx(ps.properties[0].T, 1e-2) assert p.properties[0].Cp == pytest.approx(ps.properties[0].Cp, 1e-2) assert p.properties[0].Isex == pytest.approx(ps.properties[0].Isex, 1e-2) assert p.properties[0].Cv == pytest.approx(ps.properties[0].Cv, 1e-2) assert p.properties[0].T == pytest.approx(e.properties.T, 1e-2) assert p.properties[0].Cp == pytest.approx(e.properties.Cp, 1e-2) assert p.properties[0].Isex == pytest.approx(e.properties.Isex, 1e-2) assert p.properties[0].Cv == pytest.approx(e.properties.Cv, 1e-2)
R = 8.314 Tref = 298.15 Pref = 1e5 Rref = Pref / R / Tref T = np.linspace(500, 6000, 30) # O2 <-> 2O N_O = 2 N_O2 = 1 log_K_p = (N_O * f_T(o_tbl, T, 'log Kf') + N_O2 * f_T(o2_tbl, T, 'log Kf')) K_p = 10**log_K_p n_o = 0.5 * (np.sqrt(K_p) * np.sqrt(K_p + 4) - K_p) n_o2 = 1. - n_o equil = ppp.Equilibrium() equil.add_propellants([(ppp.PROPELLANTS['OXYGEN (GAS)'], N_O2)]) comp = {'O2': [], 'O': []} for i, Ti in enumerate(T): equil.set_state(P=1, T=Ti, type='TP') for k in comp: comp[k].append(equil.composition[k]) f = plt.figure() for k in comp: plt.plot(T, comp[k], label=k) plt.legend() f = plt.figure() plt.plot(T, n_o, label='O') plt.plot(T, n_o2, label='O2')
def test_add_propellants_by_mass(pypropep): e = pypropep.Equilibrium() o2 = pypropep.PROPELLANTS['OXYGEN (GAS)'] ch4 = pypropep.PROPELLANTS['METHANE'] e.add_propellants_by_mass([(o2, 1.), (ch4, 1.)]) print(e)
def test_simp_equilibrium(pypropep): e = pypropep.Equilibrium() return e.__str__()
def white_dwarf_cooling_data(water_mass_fraction): '''Engine dimensions''' Ac = np.pi*0.1**2 #Chamber cross-sectional area (m^2) L_star = 1.5 #L_star = Volume_c/Area_t wall_thickness = 2e-3 '''Chamber conditions''' pc = 15e5 #Chamber pressure (Pa) p_tank = 20e5 #Tank / inlet coolant stagnation pressure (Pa) - used for cooling jacket mdot = 5.4489 #Mass flow rate (kg/s) p_amb = 1.01325e5 #Ambient pressure (Pa). 1.01325e5 is sea level atmospheric. OF_ratio = 3.5 #Oxidiser/fuel mass ratio '''Coolant jacket''' wall_material = bam.materials.CopperC700 mdot_coolant = mdot/(OF_ratio + 1) inlet_T = 298.15 #Coolant inlet temperature '''Get combustion properties from pypropep''' #Initialise and get propellants ppp.init() e = ppp.Equilibrium() p = ppp.ShiftingPerformance() ipa = ppp.PROPELLANTS['ISOPROPYL ALCOHOL'] water = ppp.PROPELLANTS['WATER'] n2o = ppp.PROPELLANTS['NITROUS OXIDE'] #Add propellants by mass fractions (note the mass fractions can add up to more than 1) e.add_propellants_by_mass([(ipa, 1), (water, water_mass_fraction), (n2o, OF_ratio)]) p.add_propellants_by_mass([(ipa, 1), (water, water_mass_fraction), (n2o, OF_ratio)]) #Adiabatic combustion e.set_state(P = pc/p_amb, type = 'HP') #Set chamber pressure and exit pressure in atmospheres p.set_state(P = pc/p_amb, Pe = 1) gamma = e.properties.Isex #I don't know why they use 'Isex' for gamma. cp = 1000*e.properties.Cp #Cp is given in kJ/kg/K, we want J/kg/K Tc = e.properties.T '''Choose the models we want to use for transport properties of the coolant and exhaust gas''' thermo_coolant = thermo.mixture.Mixture(['isopropanol', 'water'], ws = [1 - water_mass_fraction, water_mass_fraction]) thermo_gas = thermo.mixture.Mixture(['N2', 'H2O', 'CO2'], zs = [e.composition['N2'], e.composition['H2O'], e.composition['CO2']]) gas_transport = cool.TransportProperties(model = "thermo", thermo_object = thermo_gas, force_phase = 'g') coolant_transport = cool.TransportProperties(model = "thermo", thermo_object = thermo_coolant, force_phase = 'l') '''Create the engine object''' perfect_gas = bam.PerfectGas(gamma = gamma, cp = cp) #Gas for frozen flow chamber_conditions = bam.ChamberConditions(pc, Tc, mdot) nozzle = bam.Nozzle.from_engine_components(perfect_gas, chamber_conditions, p_amb, type = "rao", length_fraction = 0.8) white_dwarf = bam.Engine(perfect_gas, chamber_conditions, nozzle) chamber_length = L_star*nozzle.At/Ac '''Add the cooling system to the engine''' white_dwarf.add_geometry(chamber_length, Ac, wall_thickness) white_dwarf.add_exhaust_transport(gas_transport) #Spiral channels #white_dwarf.add_cooling_jacket(wall_material, inlet_T, p_tank, coolant_transport, mdot_coolant, # configuration = "spiral", channel_shape = "semi-circle", channel_width = 0.020) #Or vertical channels white_dwarf.add_cooling_jacket(wall_material, inlet_T, p_tank, coolant_transport, mdot_coolant, configuration = "vertical", channel_height = 0.001) '''Run the heating analysis''' cooling_data = white_dwarf.steady_heating_analysis(number_of_points = 250, to_json = False) return cooling_data, white_dwarf.isp(p_amb)