double Reactor::evalSurfaces(double t, double* ydot) { const vector_fp& mw = m_thermo->molecularWeights(); fill(m_sdot.begin(), m_sdot.end(), 0.0); size_t loc = 0; // offset into ydot double mdot_surf = 0.0; // net mass flux from surface for (size_t i = 0; i < m_wall.size(); i++) { Kinetics* kin = m_wall[i]->kinetics(m_lr[i]); SurfPhase* surf = m_wall[i]->surface(m_lr[i]); if (surf && kin) { double rs0 = 1.0/surf->siteDensity(); size_t nk = surf->nSpecies(); double sum = 0.0; surf->setTemperature(m_state[0]); m_wall[i]->syncCoverages(m_lr[i]); kin->getNetProductionRates(&m_work[0]); size_t ns = kin->surfacePhaseIndex(); size_t surfloc = kin->kineticsSpeciesIndex(0,ns); for (size_t k = 1; k < nk; k++) { ydot[loc + k] = m_work[surfloc+k]*rs0*surf->size(k); sum -= ydot[loc + k]; } ydot[loc] = sum; loc += nk; double wallarea = m_wall[i]->area(); for (size_t k = 0; k < m_nsp; k++) { m_sdot[k] += m_work[k]*wallarea; mdot_surf += m_sdot[k] * mw[k]; } } } return mdot_surf; }
void IdealGasReactor::getInitialConditions(double t0, size_t leny, double* y) { m_init = true; if (m_thermo == 0) { cout << "Error: reactor is empty." << endl; return; } m_thermo->restoreState(m_state); // set the first component to the total mass m_mass = m_thermo->density() * m_vol; y[0] = m_mass; // set the second component to the total volume y[1] = m_vol; // Set the third component to the temperature y[2] = m_thermo->temperature(); // set components y+3 ... y+K+2 to the mass fractions of each species m_thermo->getMassFractions(y+3); // set the remaining components to the surface species // coverages on the walls size_t loc = m_nsp + 3; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->getCoverages(m_lr[m], y + loc); loc += surf->nSpecies(); } } }
void IdealGasReactor::updateState(doublereal* y) { for (size_t i = 0; i < m_nv; i++) { AssertFinite(y[i], "IdealGasReactor::updateState", "y[" + int2str(i) + "] is not finite"); } // The components of y are [0] the total mass, [1] the total volume, // [2] the temperature, [3...K+3] are the mass fractions of each species, // and [K+3...] are the coverages of surface species on each wall. m_mass = y[0]; m_vol = y[1]; m_thermo->setMassFractions_NoNorm(y+3); m_thermo->setState_TR(y[2], m_mass / m_vol); size_t loc = m_nsp + 3; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->setCoverages(m_lr[m], y+loc); loc += surf->nSpecies(); } } // save parameters needed by other connected reactors m_enthalpy = m_thermo->enthalpy_mass(); m_pressure = m_thermo->pressure(); m_intEnergy = m_thermo->intEnergy_mass(); m_thermo->saveState(m_state); }
void IdealGasConstPressureReactor:: getInitialConditions(double t0, size_t leny, double* y) { m_init = true; if (m_thermo == 0) { throw CanteraError("getInitialConditions", "Error: reactor is empty."); } m_thermo->restoreState(m_state); // set the first component to the total mass y[0] = m_thermo->density() * m_vol; // set the second component to the temperature y[1] = m_thermo->temperature(); // set components y+2 ... y+K+1 to the mass fractions Y_k of each species m_thermo->getMassFractions(y+2); // set the remaining components to the surface species // coverages on the walls size_t loc = m_nsp + 2; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->getCoverages(m_lr[m], y + loc); loc += surf->nSpecies(); } } }
void IdealGasConstPressureReactor::updateState(doublereal* y) { // The components of y are [0] the total mass, [1] the temperature, // [2...K+2) are the mass fractions of each species, and [K+2...] are the // coverages of surface species on each wall. m_mass = y[0]; m_thermo->setMassFractions_NoNorm(y+2); m_thermo->setState_TP(y[1], m_pressure); m_vol = m_mass / m_thermo->density(); size_t loc = m_nsp + 2; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->setCoverages(m_lr[m], y+loc); loc += surf->nSpecies(); } } // save parameters needed by other connected reactors m_enthalpy = m_thermo->enthalpy_mass(); m_intEnergy = m_thermo->intEnergy_mass(); m_thermo->saveState(m_state); }
void Reactor::getSurfaceInitialConditions(double* y) { size_t loc = 0; for (size_t m = 0; m < m_wall.size(); m++) { SurfPhase* surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->getCoverages(m_lr[m], y + loc); loc += surf->nSpecies(); } } }
void Reactor::updateSurfaceState(double* y) { size_t loc = 0; for (size_t m = 0; m < m_wall.size(); m++) { SurfPhase* surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->setCoverages(m_lr[m], y+loc); loc += surf->nSpecies(); } } }
void Reactor::updateState(doublereal* y) { ThermoPhase& mix = *m_thermo; // define for readability // The components of y are the total internal energy, // the total volume, and the mass of each species. // Set the mass fractions and density of the mixture. doublereal u = y[0]; m_vol = y[1]; doublereal* mss = y + 2; doublereal mass = accumulate(y+2, y+2+m_nsp, 0.0); m_thermo->setMassFractions(mss); m_thermo->setDensity(mass/m_vol); doublereal temp = temperature(); mix.setTemperature(temp); if (m_energy) { // Decreased the tolerance on delta_T to 1.0E-7 so that T is // accurate to 9 sig digits, because this is // used in the numerical jacobian routines where relative values // of 1.0E-7 are used in the deltas. m_thermo->setState_UV(u/mass,m_vol/mass, 1.0e-7); temp = mix.temperature(); //mix.setTemperature(temp); } //m_state[0] = temp; size_t loc = m_nsp + 2; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { // surf->setTemperature(temp); //surf->setCoverages(y+loc); m_wall[m]->setCoverages(m_lr[m], y+loc); loc += surf->nSpecies(); } } // save parameters needed by other connected reactors m_enthalpy = m_thermo->enthalpy_mass(); m_pressure = m_thermo->pressure(); m_intEnergy = m_thermo->intEnergy_mass(); m_thermo->saveState(m_state); }
//! iRef is the index of the corresponding reaction in the reference mech void check_rates(int iRef) { ASSERT_EQ((size_t) 1, kin.nReactions()); std::string X = "H2:0.2 O2:0.5 H2O:0.1 N2:0.2"; std::string Xs = "H(m):0.1 O(m):0.2 OH(m):0.3 (m):0.4"; gas.setState_TPX(1200, 5*OneAtm, X); gas_ref.setState_TPX(1200, 5*OneAtm, X); surf.setState_TP(1200, 5*OneAtm); surf_ref.setState_TP(1200, 5*OneAtm); surf.setCoveragesByName(Xs); surf_ref.setCoveragesByName(Xs); vector_fp k(1), k_ref(kin_ref.nReactions()); kin.getFwdRateConstants(&k[0]); kin_ref.getFwdRateConstants(&k_ref[0]); EXPECT_DOUBLE_EQ(k_ref[iRef], k[0]); kin.getRevRateConstants(&k[0]); kin_ref.getRevRateConstants(&k_ref[0]); EXPECT_DOUBLE_EQ(k_ref[iRef], k[0]); }
// overloaded method of FuncEval. Called by the integrator to // get the initial conditions. void Reactor::getInitialConditions(double t0, size_t leny, double* y) { m_init = true; if (m_thermo == 0) { cout << "Error: reactor is empty." << endl; return; } m_time = t0; m_thermo->restoreState(m_state); // total mass doublereal mass = m_thermo->density() * m_vol; // set components y + 2 ... y + K + 1 to the // mass M_k of each species m_thermo->getMassFractions(y+2); scale(y + 2, y + m_nsp + 2, y + 2, mass); // set the first component to the total internal // energy y[0] = m_thermo->intEnergy_mass() * mass; // set the second component to the total volume y[1] = m_vol; // set the remaining components to the surface species // coverages on the walls size_t loc = m_nsp + 2; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { m_wall[m]->getCoverages(m_lr[m], y + loc); //surf->getCoverages(y+loc); loc += surf->nSpecies(); } } }
/* * Called by the integrator to evaluate ydot given y at time 'time'. */ void Reactor::evalEqs(doublereal time, doublereal* y, doublereal* ydot, doublereal* params) { m_time = time; m_thermo->restoreState(m_state); // process sensitivity parameters if (params) { size_t npar = m_pnum.size(); for (size_t n = 0; n < npar; n++) { double mult = m_kin->multiplier(m_pnum[n]); m_kin->setMultiplier(m_pnum[n], mult*params[n]); } size_t ploc = npar; for (size_t m = 0; m < m_nwalls; m++) { if (m_nsens_wall[m] > 0) { m_wall[m]->setSensitivityParameters(m_lr[m], params + ploc); ploc += m_nsens_wall[m]; } } } m_vdot = 0.0; m_Q = 0.0; // compute wall terms size_t loc = m_nsp+2; fill(m_sdot.begin(), m_sdot.end(), 0.0); for (size_t i = 0; i < m_nwalls; i++) { int lr = 1 - 2*m_lr[i]; double vdot = lr*m_wall[i]->vdot(time); m_vdot += vdot; m_Q += lr*m_wall[i]->Q(time); Kinetics* kin = m_wall[i]->kinetics(m_lr[i]); SurfPhase* surf = m_wall[i]->surface(m_lr[i]); if (surf && kin) { double rs0 = 1.0/surf->siteDensity(); size_t nk = surf->nSpecies(); double sum = 0.0; surf->setTemperature(m_state[0]); m_wall[i]->syncCoverages(m_lr[i]); kin->getNetProductionRates(DATA_PTR(m_work)); size_t ns = kin->surfacePhaseIndex(); size_t surfloc = kin->kineticsSpeciesIndex(0,ns); for (size_t k = 1; k < nk; k++) { ydot[loc + k] = m_work[surfloc+k]*rs0*surf->size(k); sum -= ydot[loc + k]; } ydot[loc] = sum; loc += nk; double wallarea = m_wall[i]->area(); for (size_t k = 0; k < m_nsp; k++) { m_sdot[k] += m_work[k]*wallarea; } } } // volume equation ydot[1] = m_vdot; /* species equations * Equation is: * \dot M_k = \hat W_k \dot\omega_k + \dot m_{in} Y_{k,in} * - \dot m_{out} Y_{k} + A \dot s_k. */ const vector_fp& mw = m_thermo->molecularWeights(); if (m_chem) { m_kin->getNetProductionRates(ydot+2); // "omega dot" } else { fill(ydot + 2, ydot + 2 + m_nsp, 0.0); } for (size_t n = 0; n < m_nsp; n++) { ydot[n+2] *= m_vol; // moles/s/m^3 -> moles/s ydot[n+2] += m_sdot[n]; ydot[n+2] *= mw[n]; } /* * Energy equation. * \f[ * \dot U = -P\dot V + A \dot q + \dot m_{in} h_{in} * - \dot m_{out} h. * \f] */ if (m_energy) { ydot[0] = - m_thermo->pressure() * m_vdot - m_Q; } else { ydot[0] = 0.0; } // add terms for open system if (m_open) { const doublereal* mf = m_thermo->massFractions(); doublereal enthalpy = m_thermo->enthalpy_mass(); // outlets for (size_t i = 0; i < m_nOutlets; i++) { double mdot_out = m_outlet[i]->massFlowRate(time); for (size_t n = 0; n < m_nsp; n++) { ydot[2+n] -= mdot_out * mf[n]; } if (m_energy) { ydot[0] -= mdot_out * enthalpy; } } // inlets for (size_t i = 0; i < m_nInlets; i++) { double mdot_in = m_inlet[i]->massFlowRate(time); for (size_t n = 0; n < m_nsp; n++) { ydot[2+n] += m_inlet[i]->outletSpeciesMassFlowRate(n); } if (m_energy) { ydot[0] += mdot_in * m_inlet[i]->enthalpy_mass(); } } } // reset sensitivity parameters if (params) { size_t npar = m_pnum.size(); for (size_t n = 0; n < npar; n++) { double mult = m_kin->multiplier(m_pnum[n]); m_kin->setMultiplier(m_pnum[n], mult/params[n]); } size_t ploc = npar; for (size_t m = 0; m < m_nwalls; m++) { if (m_nsens_wall[m] > 0) { m_wall[m]->resetSensitivityParameters(m_lr[m]); ploc += m_nsens_wall[m]; } } } }
void IdealGasReactor::evalEqs(doublereal time, doublereal* y, doublereal* ydot, doublereal* params) { m_thermo->restoreState(m_state); // process sensitivity parameters if (params) { size_t npar = m_pnum.size(); for (size_t n = 0; n < npar; n++) { double mult = m_kin->multiplier(m_pnum[n]); m_kin->setMultiplier(m_pnum[n], mult*params[n]); } size_t ploc = npar; for (size_t m = 0; m < m_nwalls; m++) { if (m_nsens_wall[m] > 0) { m_wall[m]->setSensitivityParameters(m_lr[m], params + ploc); ploc += m_nsens_wall[m]; } } } m_vdot = 0.0; m_Q = 0.0; double mcvdTdt = 0.0; // m * c_v * dT/dt double dmdt = 0.0; // dm/dt (gas phase) double* dYdt = ydot + 3; m_thermo->getPartialMolarIntEnergies(&m_uk[0]); // compute wall terms size_t loc = m_nsp+3; fill(m_sdot.begin(), m_sdot.end(), 0.0); for (size_t i = 0; i < m_nwalls; i++) { int lr = 1 - 2*m_lr[i]; double vdot = lr*m_wall[i]->vdot(time); m_vdot += vdot; m_Q += lr*m_wall[i]->Q(time); Kinetics* kin = m_wall[i]->kinetics(m_lr[i]); SurfPhase* surf = m_wall[i]->surface(m_lr[i]); if (surf && kin) { double rs0 = 1.0/surf->siteDensity(); size_t nk = surf->nSpecies(); double sum = 0.0; surf->setTemperature(m_state[0]); m_wall[i]->syncCoverages(m_lr[i]); kin->getNetProductionRates(DATA_PTR(m_work)); size_t ns = kin->surfacePhaseIndex(); size_t surfloc = kin->kineticsSpeciesIndex(0,ns); for (size_t k = 1; k < nk; k++) { ydot[loc + k] = m_work[surfloc+k]*rs0*surf->size(k); sum -= ydot[loc + k]; } ydot[loc] = sum; loc += nk; double wallarea = m_wall[i]->area(); for (size_t k = 0; k < m_nsp; k++) { m_sdot[k] += m_work[k]*wallarea; } } } const vector_fp& mw = m_thermo->molecularWeights(); const doublereal* Y = m_thermo->massFractions(); if (m_chem) { m_kin->getNetProductionRates(&m_wdot[0]); // "omega dot" } double mdot_surf = 0.0; // net mass flux from surfaces for (size_t k = 0; k < m_nsp; k++) { // production in gas phase and from surfaces dYdt[k] = (m_wdot[k] * m_vol + m_sdot[k]) * mw[k] / m_mass; mdot_surf += m_sdot[k] * mw[k]; } dmdt += mdot_surf; // compression work and external heat transfer mcvdTdt += - m_pressure * m_vdot - m_Q; for (size_t n = 0; n < m_nsp; n++) { // heat release from gas phase and surface reations mcvdTdt -= m_wdot[n] * m_uk[n] * m_vol; mcvdTdt -= m_sdot[n] * m_uk[n]; // dilution by net surface mass flux dYdt[n] -= Y[n] * mdot_surf / m_mass; } // add terms for open system if (m_open) { // outlets for (size_t i = 0; i < m_nOutlets; i++) { double mdot_out = m_outlet[i]->massFlowRate(time); dmdt -= mdot_out; // mass flow out of system mcvdTdt -= mdot_out * m_pressure * m_vol / m_mass; // flow work } // inlets for (size_t i = 0; i < m_nInlets; i++) { double mdot_in = m_inlet[i]->massFlowRate(time); dmdt += mdot_in; // mass flow into system mcvdTdt += m_inlet[i]->enthalpy_mass() * mdot_in; for (size_t n = 0; n < m_nsp; n++) { double mdot_spec = m_inlet[i]->outletSpeciesMassFlowRate(n); // flow of species into system and dilution by other species dYdt[n] += (mdot_spec - mdot_in * Y[n]) / m_mass; // In combintion with h_in*mdot_in, flow work plus thermal // energy carried with the species mcvdTdt -= m_uk[n] / mw[n] * mdot_spec; } } } ydot[0] = dmdt; ydot[1] = m_vdot; if (m_energy) { ydot[2] = mcvdTdt / (m_mass * m_thermo->cv_mass()); } else { ydot[2] = 0; } for (size_t i = 0; i < m_nv; i++) { AssertFinite(ydot[i], "IdealGasReactor::evalEqs", "ydot[" + int2str(i) + "] is not finite"); } // reset sensitivity parameters if (params) { size_t npar = m_pnum.size(); for (size_t n = 0; n < npar; n++) { double mult = m_kin->multiplier(m_pnum[n]); m_kin->setMultiplier(m_pnum[n], mult/params[n]); } size_t ploc = npar; for (size_t m = 0; m < m_nwalls; m++) { if (m_nsens_wall[m] > 0) { m_wall[m]->resetSensitivityParameters(m_lr[m]); ploc += m_nsens_wall[m]; } } } }
void IdealGasConstPressureReactor::evalEqs(doublereal time, doublereal* y, doublereal* ydot, doublereal* params) { size_t nk; m_thermo->restoreState(m_state); Kinetics* kin; size_t npar, ploc; double mult; // process sensitivity parameters if (params) { npar = m_pnum.size(); for (size_t n = 0; n < npar; n++) { mult = m_kin->multiplier(m_pnum[n]); m_kin->setMultiplier(m_pnum[n], mult*params[n]); } ploc = npar; for (size_t m = 0; m < m_nwalls; m++) { if (m_nsens_wall[m] > 0) { m_wall[m]->setSensitivityParameters(m_lr[m], params + ploc); ploc += m_nsens_wall[m]; } } } m_Q = 0.0; // compute wall terms doublereal rs0, sum, wallarea; double mcpdTdt = 0.0; // m * c_p * dT/dt double dmdt = 0.0; // dm/dt (gas phase) double* dYdt = ydot + 2; m_thermo->getPartialMolarEnthalpies(&m_hk[0]); SurfPhase* surf; size_t lr, ns, loc = m_nsp+2, surfloc; fill(m_sdot.begin(), m_sdot.end(), 0.0); for (size_t i = 0; i < m_nwalls; i++) { lr = 1 - 2*m_lr[i]; m_Q += lr*m_wall[i]->Q(time); kin = m_wall[i]->kinetics(m_lr[i]); surf = m_wall[i]->surface(m_lr[i]); if (surf && kin) { rs0 = 1.0/surf->siteDensity(); nk = surf->nSpecies(); sum = 0.0; surf->setTemperature(m_state[0]); m_wall[i]->syncCoverages(m_lr[i]); kin->getNetProductionRates(DATA_PTR(m_work)); ns = kin->surfacePhaseIndex(); surfloc = kin->kineticsSpeciesIndex(0,ns); for (size_t k = 1; k < nk; k++) { ydot[loc + k] = m_work[surfloc+k]*rs0*surf->size(k); sum -= ydot[loc + k]; } ydot[loc] = sum; loc += nk; wallarea = m_wall[i]->area(); for (size_t k = 0; k < m_nsp; k++) { m_sdot[k] += m_work[k]*wallarea; } } } const vector_fp& mw = m_thermo->molecularWeights(); const doublereal* Y = m_thermo->massFractions(); if (m_chem) { m_kin->getNetProductionRates(&m_wdot[0]); // "omega dot" } double mdot_surf = 0.0; // net mass flux from surface for (size_t k = 0; k < m_nsp; k++) { // production in gas phase and from surfaces dYdt[k] = (m_wdot[k] * m_vol + m_sdot[k]) * mw[k] / m_mass; mdot_surf += m_sdot[k] * mw[k]; } dmdt += mdot_surf; // external heat transfer mcpdTdt -= m_Q; for (size_t n = 0; n < m_nsp; n++) { // heat release from gas phase and surface reations mcpdTdt -= m_wdot[n] * m_hk[n] * m_vol; mcpdTdt -= m_sdot[n] * m_hk[n]; // dilution by net surface mass flux dYdt[n] -= Y[n] * mdot_surf / m_mass; } // add terms for open system if (m_open) { // outlets for (size_t i = 0; i < m_nOutlets; i++) { dmdt -= m_outlet[i]->massFlowRate(time); // mass flow out of system } // inlets for (size_t i = 0; i < m_nInlets; i++) { double mdot_in = m_inlet[i]->massFlowRate(time); dmdt += mdot_in; // mass flow into system mcpdTdt += m_inlet[i]->enthalpy_mass() * mdot_in; for (size_t n = 0; n < m_nsp; n++) { double mdot_spec = m_inlet[i]->outletSpeciesMassFlowRate(n); // flow of species into system and dilution by other species dYdt[n] += (mdot_spec - mdot_in * Y[n]) / m_mass; mcpdTdt -= m_hk[n] / mw[n] * mdot_spec; } } } ydot[0] = dmdt; if (m_energy) { ydot[1] = mcpdTdt / (m_mass * m_thermo->cp_mass()); } else { ydot[1] = 0.0; } // reset sensitivity parameters if (params) { npar = m_pnum.size(); for (size_t n = 0; n < npar; n++) { mult = m_kin->multiplier(m_pnum[n]); m_kin->setMultiplier(m_pnum[n], mult/params[n]); } ploc = npar; for (size_t m = 0; m < m_nwalls; m++) { if (m_nsens_wall[m] > 0) { m_wall[m]->resetSensitivityParameters(m_lr[m]); ploc += m_nsens_wall[m]; } } } }