int kinetics_example2(int job) { try { std::cout << "Ignition simulation using class GRI30." << std::endl; if (job >= 1) { std::cout << "Constant-pressure ignition of a hydrogen/oxygen/nitrogen" " mixture \nbeginning at T = 1001 K and P = 1 atm." << std::endl; } if (job < 2) return 0; // create a GRI30 object GRI30 gas; gas.setState_TPX(1001.0, OneAtm, "H2:2.0, O2:1.0, N2:4.0"); int kk = gas.nSpecies(); // create a reactor Reactor r; // create a reservoir to represent the environment Reservoir env; // specify the thermodynamic property and kinetics managers r.setThermoMgr(gas); r.setKineticsMgr(gas); env.setThermoMgr(gas); // create a flexible, insulating wall between the reactor and the // environment Wall w; w.install(r,env); // set the "Vdot coefficient" to a large value, in order to // approach the constant-pressure limit; see the documentation // for class Reactor w.setExpansionRateCoeff(1.e9); w.setArea(1.0); // create a container object to run the simulation // and add the reactor to it ReactorNet* sim_ptr = new ReactorNet(); ReactorNet& sim = *sim_ptr; sim.addReactor(&r); double tm; double dt = 1.e-5; // interval at which output is written int nsteps = 100; // number of intervals // create a 2D array to hold the output variables, // and store the values for the initial state Array2D soln(kk+4, 1); saveSoln(0, 0.0, gas, soln); // main loop for (int i = 1; i <= nsteps; i++) { tm = i*dt; sim.advance(tm); saveSoln(tm, gas, soln); } // make a Tecplot data file and an Excel spreadsheet std::string plotTitle = "kinetics example 2: constant-pressure ignition"; plotSoln("kin2.dat", "TEC", plotTitle, gas, soln); plotSoln("kin2.csv", "XL", plotTitle, gas, soln); // print final temperature std::cout << " Tfinal = " << r.temperature() << std::endl; std::cout << "Output files:" << std::endl << " kin2.csv (Excel CSV file)" << std::endl << " kin2.dat (Tecplot data file)" << std::endl; return 0; } // handle exceptions thrown by Cantera catch (CanteraError) { showErrors(std::cout); std::cout << " terminating... " << std::endl; appdelete(); return -1; } }
void runexample() { // use reaction mechanism GRI-Mech 3.0 IdealGasMix gas("gri30.cti", "gri30"); // create a reservoir for the fuel inlet, and set to pure methane. Reservoir fuel_in; gas.setState_TPX(300.0, OneAtm, "CH4:1.0"); fuel_in.insert(gas); double fuel_mw = gas.meanMolecularWeight(); // create a reservoir for the air inlet Reservoir air_in; IdealGasMix air("air.cti"); gas.setState_TPX(300.0, OneAtm, "N2:0.78, O2:0.21, AR:0.01"); double air_mw = air.meanMolecularWeight(); air_in.insert(gas); // to ignite the fuel/air mixture, we'll introduce a pulse of radicals. // The steady-state behavior is independent of how we do this, so we'll // just use a stream of pure atomic hydrogen. gas.setState_TPX(300.0, OneAtm, "H:1.0"); Reservoir igniter; igniter.insert(gas); // create the combustor, and fill it in initially with N2 gas.setState_TPX(300.0, OneAtm, "N2:1.0"); Reactor combustor; combustor.insert(gas); combustor.setInitialVolume(1.0); // create a reservoir for the exhaust. The initial composition // doesn't matter. Reservoir exhaust; exhaust.insert(gas); // lean combustion, phi = 0.5 double equiv_ratio = 0.5; // compute fuel and air mass flow rates double factor = 0.1; double air_mdot = factor*9.52*air_mw; double fuel_mdot = factor*equiv_ratio*fuel_mw; // create and install the mass flow controllers. Controllers // m1 and m2 provide constant mass flow rates, and m3 provides // a short Gaussian pulse only to ignite the mixture MassFlowController m1; m1.install(fuel_in, combustor); m1.setMassFlowRate(fuel_mdot); // Now create the air mass flow controller. Note that this connects // two reactors with different reaction mechanisms and different // numbers of species. Downstream and upstream species are matched by // name. MassFlowController m2; m2.install(air_in, combustor); m2.setMassFlowRate(air_mdot); // The igniter will use a Gaussian 'functor' object to specify the // time-dependent igniter mass flow rate. double A = 0.1; double FWHM = 0.2; double t0 = 0.5; Gaussian igniter_mdot(A, t0, FWHM); MassFlowController m3; m3.install(igniter, combustor); m3.setFunction(&igniter_mdot); // put a valve on the exhaust line to regulate the pressure Valve v; v.install(combustor, exhaust); double Kv = 1.0; v.setParameters(1, &Kv); // the simulation only contains one reactor ReactorNet sim; sim.addReactor(combustor); // take single steps to 6 s, writing the results to a CSV file // for later plotting. double tfinal = 1.0; double tnow = 0.0; double tres; std::ofstream f("combustor_cxx.csv"); std::vector<size_t> k_out { gas.speciesIndex("CH4"), gas.speciesIndex("O2"), gas.speciesIndex("CO2"), gas.speciesIndex("H2O"), gas.speciesIndex("CO"), gas.speciesIndex("OH"), gas.speciesIndex("H"), gas.speciesIndex("C2H6") }; while (tnow < tfinal) { tnow += 0.005; sim.advance(tnow); tres = combustor.mass()/v.massFlowRate(); f << tnow << ", " << combustor.temperature() << ", " << tres << ", "; ThermoPhase& c = combustor.contents(); for (size_t i = 0; i < k_out.size(); i++) { f << c.moleFraction(k_out[i]) << ", "; } f << std::endl; } f.close(); }