void Reactor::updateState(doublereal* y) { // The components of y are [0] the total mass, [1] the total volume, // [2] the total internal energy, [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); if (m_energy) { // Use a damped Newton's method to determine the mixture temperature. // Tight tolerances are required both for Jacobian evaluation and for // sensitivity analysis to work correctly. doublereal U = y[2]; doublereal T = temperature(); double dT = 100; double dUprev = 1e10; double dU = 1e10; int i = 0; double damp = 1.0; while (abs(dT / T) > 10 * DBL_EPSILON) { dUprev = dU; m_thermo->setState_TR(T, m_mass / m_vol); double dUdT = m_thermo->cv_mass() * m_mass; dU = m_thermo->intEnergy_mass() * m_mass - U; dT = dU / dUdT; // Reduce the damping coefficient if the magnitude of the error // isn't decreasing if (std::abs(dU) < std::abs(dUprev)) { damp = 1.0; } else { damp *= 0.8; } dT = std::min(dT, 0.5 * T) * damp; T -= dT; i++; if (i > 100) { throw CanteraError("Reactor::updateState", "no convergence\nU/m = {}\nT = {}\nrho = {}\n", U / m_mass, T, m_mass / m_vol); } } } else { m_thermo->setDensity(m_mass/m_vol); } updateSurfaceState(y + m_nsp + 3); // 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 IdealGasReactor::updateState(doublereal* y) { // 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); updateSurfaceState(y + m_nsp + 3); // 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 ConstPressureReactor::updateState(doublereal* y) { // The components of y are [0] the total mass, [1] the total enthalpy, // [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); if (m_energy) { m_thermo->setState_HP(y[1]/m_mass, m_pressure, 1.0e-4); } else { m_thermo->setPressure(m_pressure); } m_vol = m_mass / m_thermo->density(); updateSurfaceState(y + m_nsp + 2); // save parameters needed by other connected reactors m_enthalpy = m_thermo->enthalpy_mass(); m_intEnergy = m_thermo->intEnergy_mass(); m_thermo->saveState(m_state); }