예제 #1
0
bool BulkKinetics::addReaction(shared_ptr<Reaction> r)
{
    bool added = Kinetics::addReaction(r);
    if (!added) {
        return false;
    }
    double dn = 0.0;
    for (Composition::const_iterator iter = r->products.begin();
         iter != r->products.end();
         ++iter) {
        dn += iter->second;
    }
    for (Composition::const_iterator iter = r->reactants.begin();
         iter != r->reactants.end();
         ++iter) {
        dn -= iter->second;
    }

    m_dn.push_back(dn);

    if (r->reversible) {
        m_revindex.push_back(nReactions()-1);
    } else {
        m_irrev.push_back(nReactions()-1);
    }
    return true;
}
예제 #2
0
파일: chemistry0d.cpp 프로젝트: speth/ember
void InterpKinetics::update_rates_T()
{
    if (!m_ntemps) {
        rebuildInterpData(200, 250, 3000);
    }
    double Tnow = thermo().temperature();
    if (Tnow >= m_tmax) {
        rebuildInterpData(m_ntemps + 10, m_tmin, Tnow + 100.0);
    } else if (Tnow <= m_tmin) {
        rebuildInterpData(m_ntemps + 2, std::max(Tnow - 20.0, 10.0), m_tmax);
    }

    size_t n = static_cast<size_t>(floor((Tnow-m_tmin)/(m_tmax-m_tmin)*(m_ntemps-1)));
    double dT = Tnow - n * (m_tmax - m_tmin) / (m_ntemps - 1) - m_tmin;
    assert(dT >= 0 && dT <= (m_tmax - m_tmin) / (m_ntemps - 1));
    assert(n < m_ntemps);

    size_t nFall = m_falloff_low_rates.nReactions();
    vec_map(&m_rfn[0], nReactions()) = m_rfn_const.col(n) + m_rfn_slope.col(n) * dT;
    vec_map(&m_rkcn[0], nReactions()) = m_rkcn_const.col(n) + m_rkcn_slope.col(n) * dT;
    vec_map(&m_rfn_low[0], nFall) = m_rfn_low_const.col(n) + m_rfn_low_slope.col(n) * dT;
    vec_map(&m_rfn_high[0], nFall) = m_rfn_high_const.col(n) + m_rfn_high_slope.col(n) * dT;
    vec_map(&falloff_work[0], nFall) = m_falloff_work_const.col(n) + m_falloff_work_slope.col(n) * dT;

    m_logStandConc = log(thermo().standardConcentration());
    m_temp = Tnow;
    m_ROP_ok = false;
}
void BulkKinetics::addReaction(ReactionData& r)
{
    m_dn.push_back(accumulate(r.pstoich.begin(), r.pstoich.end(), 0.0) -
                   accumulate(r.rstoich.begin(), r.rstoich.end(), 0.0));

    if (r.reversible) {
        m_revindex.push_back(nReactions());
    } else {
        m_irrev.push_back(nReactions());
    }
    Kinetics::addReaction(r);
}
예제 #4
0
void AqueousKinetics::updateROP()
{
    _update_rates_T();
    _update_rates_C();

    if (m_ROP_ok) {
        return;
    }

    // copy rate coefficients into ropf
    m_ropf = m_rfn;

    // multiply by perturbation factor
    multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());

    // copy the forward rates to the reverse rates
    m_ropr = m_ropf;

    // for reverse rates computed from thermochemistry, multiply the forward
    // rates copied into m_ropr by the reciprocals of the equilibrium constants
    multiply_each(m_ropr.begin(), m_ropr.end(), m_rkcn.begin());

    // multiply ropf by concentration products
    m_reactantStoich.multiply(m_conc.data(), m_ropf.data());

    // for reversible reactions, multiply ropr by concentration products
    m_revProductStoich.multiply(m_conc.data(), m_ropr.data());

    for (size_t j = 0; j != nReactions(); ++j) {
        m_ropnet[j] = m_ropf[j] - m_ropr[j];
    }

    m_ROP_ok = true;
}
예제 #5
0
void Kinetics::getRevReactionDelta(const double* prop, double* deltaProp)
{
    fill(deltaProp, deltaProp + nReactions(), 0.0);
    // products add
    m_revProductStoich.incrementReactions(prop, deltaProp);
    // reactants subtract
    m_reactantStoich.decrementReactions(prop, deltaProp);
}
예제 #6
0
void GasKinetics::addThreeBodyReaction(ThreeBodyReaction& r)
{
    m_rates.install(nReactions()-1, r.rate);
    map<size_t, double> efficiencies;
    for (Composition::const_iterator iter = r.third_body.efficiencies.begin();
         iter != r.third_body.efficiencies.end();
         ++iter) {
        size_t k = kineticsSpeciesIndex(iter->first);
        if (k != npos) {
            efficiencies[k] = iter->second;
        } else if (!m_skipUndeclaredThirdBodies) {
            throw CanteraError("GasKinetics::addThreeBodyReaction", "Found "
                "third-body efficiency for undefined species '" + iter->first +
                "' while adding reaction '" + r.equation() + "'");
        }
    }
    m_3b_concm.install(nReactions()-1, efficiencies,
                       r.third_body.default_efficiency);
}
예제 #7
0
    void InterfaceKinetics::checkPartialEquil() {
        int i, irxn;
        vector_fp dmu(nTotalSpecies(), 0.0);
        vector_fp rmu(nReactions(), 0.0);
        vector_fp frop(nReactions(), 0.0);
        vector_fp rrop(nReactions(), 0.0);
        vector_fp netrop(nReactions(), 0.0);
        if (m_nrev > 0) {
            doublereal rt = GasConstant*thermo(0).temperature();
            cout << "T = " << thermo(0).temperature() << " " << rt << endl;
            int n, nsp, k, ik=0;
            //doublereal rt = GasConstant*thermo(0).temperature();
            //            doublereal rrt = 1.0/rt;
            int np = nPhases();
            doublereal delta;
            for (n = 0; n < np; n++) {
                thermo(n).getChemPotentials(DATA_PTR(dmu) + m_start[n]);
                nsp = thermo(n).nSpecies();
                for (k = 0; k < nsp; k++) {
                    delta = Faraday * m_phi[n] * thermo(n).charge(k);
                    //cout << thermo(n).speciesName(k) << "   " << (delta+dmu[ik])/rt << " " << dmu[ik]/rt << endl;
                    dmu[ik] += delta;
                    ik++;
                }
            }

            // compute Delta mu^ for all reversible reactions
            m_rxnstoich.getRevReactionDelta(m_ii, DATA_PTR(dmu), DATA_PTR(rmu));
            getFwdRatesOfProgress(DATA_PTR(frop));
            getRevRatesOfProgress(DATA_PTR(rrop));
            getNetRatesOfProgress(DATA_PTR(netrop));
            for (i = 0; i < m_nrev; i++) {
                irxn = m_revindex[i];
                cout << "Reaction " << reactionString(irxn) 
                     << "  " << rmu[irxn]/rt << endl;
                printf("%12.6e  %12.6e  %12.6e  %12.6e \n", 
                    frop[irxn], rrop[irxn], netrop[irxn], 
                    netrop[irxn]/(frop[irxn] + rrop[irxn]));
            }
        }
    }
예제 #8
0
 /**
  * Finish adding reactions and prepare for use. This function
  * must be called after all reactions are entered into the mechanism
  * and before the mechanism is used to calculate reaction rates.
  *
  * Here, we resize work arrays based on the number of reactions,
  * since we don't know this number up to now.
  */
 void InterfaceKinetics::finalize() {
     m_rwork.resize(nReactions());
     int ks = reactionPhaseIndex();
     if (ks < 0) throw CanteraError("InterfaceKinetics::finalize",
          "no surface phase is present.");
     m_surf = (SurfPhase*)&thermo(ks);
     if (m_surf->nDim() != 2) 
         throw CanteraError("InterfaceKinetics::finalize",
             "expected interface dimension = 2, but got dimension = "
             +int2str(m_surf->nDim()));
     m_finalized = true;
 }
예제 #9
0
void BulkKinetics::getRevRateConstants(doublereal* krev, bool doIrreversible)
{
    /*
     * go get the forward rate constants. -> note, we don't
     * really care about speed or redundancy in these
     * informational routines.
     */
    getFwdRateConstants(krev);

    if (doIrreversible) {
        getEquilibriumConstants(&m_ropnet[0]);
        for (size_t i = 0; i < nReactions(); i++) {
            krev[i] /= m_ropnet[i];
        }
    } else {
        // m_rkcn[] is zero for irreversible reactions
        for (size_t i = 0; i < nReactions(); i++) {
            krev[i] *= m_rkcn[i];
        }
    }
}
예제 #10
0
void GasKinetics::updateROP()
{
    update_rates_C();
    update_rates_T();

    if (m_ROP_ok) {
        return;
    }

    // copy rate coefficients into ropf
    copy(m_rfn.begin(), m_rfn.end(), m_ropf.begin());

    // multiply ropf by enhanced 3b conc for all 3b rxns
    if (!concm_3b_values.empty()) {
        m_3b_concm.multiply(&m_ropf[0], &concm_3b_values[0]);
    }

    if (m_nfall) {
        processFalloffReactions();
    }

    // multiply by perturbation factor
    multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());

    // copy the forward rates to the reverse rates
    copy(m_ropf.begin(), m_ropf.end(), m_ropr.begin());

    // for reverse rates computed from thermochemistry, multiply the forward
    // rates copied into m_ropr by the reciprocals of the equilibrium constants
    multiply_each(m_ropr.begin(), m_ropr.end(), m_rkcn.begin());

    // multiply ropf by concentration products
    m_reactantStoich.multiply(&m_conc[0], &m_ropf[0]);

    // for reversible reactions, multiply ropr by concentration products
    m_revProductStoich.multiply(&m_conc[0], &m_ropr[0]);

    for (size_t j = 0; j != nReactions(); ++j) {
        m_ropnet[j] = m_ropf[j] - m_ropr[j];
    }

    for (size_t i = 0; i < m_rfn.size(); i++) {
        AssertFinite(m_rfn[i], "GasKinetics::updateROP",
                     "m_rfn[" + int2str(i) + "] is not finite.");
        AssertFinite(m_ropf[i], "GasKinetics::updateROP",
                     "m_ropf[" + int2str(i) + "] is not finite.");
        AssertFinite(m_ropr[i], "GasKinetics::updateROP",
                     "m_ropr[" + int2str(i) + "] is not finite.");
    }

    m_ROP_ok = true;
}
예제 #11
0
  /**
   * Compute the forward rate constants.
   */
  void InterfaceKinetics::getFwdRateConstants(doublereal* kfwd) {

    updateROP();

    const vector_fp& rf = m_kdata->m_rfn;

    // copy rate coefficients into kfwd
    copy(rf.begin(), rf.end(), kfwd);

    // multiply by perturbation factor
    multiply_each(kfwd, kfwd + nReactions(), m_perturb.begin());
           
  }
예제 #12
0
 /**
  * Update the rates of progress of the reactions in the reaciton
  * mechanism. This routine operates on internal data.
  */
 void InterfaceKinetics::getRevRateConstants(doublereal* krev, bool doIrreversible) {
     getFwdRateConstants(krev);
     if (doIrreversible) {
         doublereal *tmpKc = DATA_PTR(m_kdata->m_ropnet);
         getEquilibriumConstants(tmpKc);
         for (int i = 0; i < m_ii; i++) {
             krev[i] /=  tmpKc[i];
         }
     }
     else {
         const vector_fp& rkc = m_kdata->m_rkcn;
         multiply_each(krev, krev + nReactions(), rkc.begin());
     }
 }
예제 #13
0
void BulkKinetics::finalize()
{
    m_finalized = true;

    // Guarantee that these arrays can be converted to double* even in the
    // special case where there are no reactions defined.
    if (!nReactions()) {
        m_perturb.resize(1, 1.0);
        m_ropf.resize(1, 0.0);
        m_ropr.resize(1, 0.0);
        m_ropnet.resize(1, 0.0);
        m_rkcn.resize(1, 0.0);
    }
}
예제 #14
0
void GasKinetics::addFalloffReaction(FalloffReaction& r)
{
    // install high and low rate coeff calculators
    // and extend the high and low rate coeff value vectors
    m_falloff_high_rates.install(m_nfall, r.high_rate);
    m_rfn_high.push_back(0.0);
    m_falloff_low_rates.install(m_nfall, r.low_rate);
    m_rfn_low.push_back(0.0);

    // add this reaction number to the list of falloff reactions
    m_fallindx.push_back(nReactions()-1);
    m_rfallindx[nReactions()-1] = m_nfall;

    // install the enhanced third-body concentration calculator
    map<size_t, double> efficiencies;
    for (Composition::const_iterator iter = r.third_body.efficiencies.begin();
         iter != r.third_body.efficiencies.end();
         ++iter) {
        size_t k = kineticsSpeciesIndex(iter->first);
        if (k != npos) {
            efficiencies[k] = iter->second;
        } else if (!m_skipUndeclaredThirdBodies) {
            throw CanteraError("GasKinetics::addTFalloffReaction", "Found "
                "third-body efficiency for undefined species '" + iter->first +
                "' while adding reaction '" + r.equation() + "'");
        }
    }
    m_falloff_concm.install(m_nfall, efficiencies,
                            r.third_body.default_efficiency);

    // install the falloff function calculator for this reaction
    m_falloffn.install(m_nfall, r.reaction_type, r.falloff);

    // increment the falloff reaction counter
    ++m_nfall;
}
예제 #15
0
void AqueousKinetics::getFwdRateConstants(doublereal* kfwd)
{
    _update_rates_T();
    _update_rates_C();

    // copy rate coefficients into ropf
    m_ropf = m_rfn;

    // multiply by perturbation factor
    multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());

    for (size_t i = 0; i < nReactions(); i++) {
        kfwd[i] = m_ropf[i];
    }
}
예제 #16
0
void GasKinetics::getEquilibriumConstants(doublereal* kc)
{
    update_rates_T();
    thermo().getStandardChemPotentials(&m_grt[0]);
    fill(m_rkcn.begin(), m_rkcn.end(), 0.0);

    // compute Delta G^0 for all reactions
    getReactionDelta(&m_grt[0], &m_rkcn[0]);

    doublereal rrt = 1.0/(GasConstant * thermo().temperature());
    for (size_t i = 0; i < nReactions(); i++) {
        kc[i] = exp(-m_rkcn[i]*rrt + m_dn[i]*m_logStandConc);
    }

    // force an update of T-dependent properties, so that m_rkcn will
    // be updated before it is used next.
    m_temp = 0.0;
}
예제 #17
0
  /**
   * Update the equilibrium constants in molar units for all
   * reversible reactions. Irreversible reactions have their 
   * equilibrium constant set to zero.
   * For reactions involving charged species the equilibrium 
   * constant is adjusted according to the electrostatis potential.
   */
  void InterfaceKinetics::updateKc() {
    int i, irxn;

    vector_fp& m_rkc = m_kdata->m_rkcn;
    fill(m_rkc.begin(), m_rkc.end(), 0.0);

    //static vector_fp mu(nTotalSpecies());
    if (m_nrev > 0) {

      /*
       * Get the vector of electrochemical potentials and store it in m_mu0
       */
      int n, nsp, k, ik = 0;
      doublereal rt = GasConstant*thermo(0).temperature();
      doublereal rrt = 1.0 / rt;
      int np = nPhases();
      for (n = 0; n < np; n++) {
	thermo(n).getStandardChemPotentials(DATA_PTR(m_mu0) + m_start[n]);
	nsp = thermo(n).nSpecies();
	for (k = 0; k < nsp; k++) {
	  m_mu0[ik] -= rt * thermo(n).logStandardConc(k);
	  m_mu0[ik] += Faraday * m_phi[n] * thermo(n).charge(k);
	  ik++;
	}
      }

      // compute Delta mu^0 for all reversible reactions
      m_rxnstoich.getRevReactionDelta(m_ii, DATA_PTR(m_mu0), 
				      DATA_PTR(m_rkc));

      for (i = 0; i < m_nrev; i++) {
	irxn = m_revindex[i];
	if (irxn < 0 || irxn >= nReactions()) {
	  throw CanteraError("InterfaceKinetics",
			     "illegal value: irxn = "+int2str(irxn));
	}
	m_rkc[irxn] = exp(m_rkc[irxn]*rrt);
      }
      for (i = 0; i != m_nirrev; ++i) {
	m_rkc[ m_irrev[i] ] = 0.0;
      }
    }
  }
예제 #18
0
void AqueousKinetics::getEquilibriumConstants(doublereal* kc)
{
    _update_rates_T();

    thermo().getStandardChemPotentials(m_grt.data());
    fill(m_rkcn.begin(), m_rkcn.end(), 0.0);
    for (size_t k = 0; k < thermo().nSpecies(); k++) {
        doublereal logStandConc_k = thermo().logStandardConc(k);
        m_grt[k] -= GasConstant * m_temp * logStandConc_k;
    }

    // compute Delta G^0 for all reactions
    getReactionDelta(m_grt.data(), m_rkcn.data());

    doublereal rrt = 1.0 / thermo().RT();
    for (size_t i = 0; i < nReactions(); i++) {
        kc[i] = exp(-m_rkcn[i]*rrt);
    }

    // force an update of T-dependent properties, so that m_rkcn will
    // be updated before it is used next.
    m_temp = 0.0;
}
예제 #19
0
  /**
   * Finish adding reactions and prepare for use. This function
   * must be called after all reactions are entered into the mechanism
   * and before the mechanism is used to calculate reaction rates.
   *
   * Here, we resize work arrays based on the number of reactions,
   * since we don't know this number up to now.
   */
  void InterfaceKinetics::finalize() {
    Kinetics::finalize();
    m_rwork.resize(nReactions());
    int ks = reactionPhaseIndex();
    if (ks < 0) throw CanteraError("InterfaceKinetics::finalize",
				   "no surface phase is present.");
    m_surf = (SurfPhase*)&thermo(ks);
    if (m_surf->nDim() != 2) 
      throw CanteraError("InterfaceKinetics::finalize",
			 "expected interface dimension = 2, but got dimension = "
			 +int2str(m_surf->nDim()));



    m_StandardConc.resize(m_nTotalSpecies, 0.0);
    m_deltaG0.resize(m_ii, 0.0);
    m_ProdStanConcReac.resize(m_ii, 0.0);

    if (m_thermo.size() != m_phaseExists.size()) {
      throw CanteraError("InterfaceKinetics::finalize", "internal error");
    }

    m_finalized = true;
  }
예제 #20
0
void GasKinetics::getFwdRateConstants(doublereal* kfwd)
{
    update_rates_C();
    update_rates_T();

    // copy rate coefficients into ropf
    copy(m_rfn.begin(), m_rfn.end(), m_ropf.begin());

    // multiply ropf by enhanced 3b conc for all 3b rxns
    if (!concm_3b_values.empty()) {
        m_3b_concm.multiply(&m_ropf[0], &concm_3b_values[0]);
    }

    if (m_nfall) {
        processFalloffReactions();
    }

    // multiply by perturbation factor
    multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());

    for (size_t i = 0; i < nReactions(); i++) {
        kfwd[i] = m_ropf[i];
    }
}
예제 #21
0
파일: chemistry0d.cpp 프로젝트: speth/ember
void InterpKinetics::rebuildInterpData(size_t nTemps, double Tmin, double Tmax)
{
    m_ntemps = nTemps;
    m_tmin = Tmin;
    m_tmax = Tmax;

    m_rfn_const = dmatrix::Zero(nReactions(), m_ntemps);
    m_rfn_slope = dmatrix::Zero(nReactions(), m_ntemps);

    m_rkcn_const = dmatrix::Zero(nReactions(), m_ntemps);
    m_rkcn_slope = dmatrix::Zero(nReactions(), m_ntemps);

    size_t nFall = m_falloff_low_rates.nReactions();
    m_rfn_low_const = dmatrix::Zero(nFall, m_ntemps);
    m_rfn_low_slope = dmatrix::Zero(nFall, m_ntemps);
    m_rfn_high_const = dmatrix::Zero(nFall, m_ntemps);
    m_rfn_high_slope = dmatrix::Zero(nFall, m_ntemps);
    m_falloff_work_const = dmatrix::Zero(nFall, m_ntemps);
    m_falloff_work_slope = dmatrix::Zero(nFall, m_ntemps);

    double T_save = thermo().temperature();
    double rho_save = thermo().density();
    for (size_t n = 0; n < m_ntemps; n++) {
        thermo().setState_TR(Tmin + ((double) n)/(m_ntemps - 1) * (Tmax - Tmin),
                             rho_save);
        GasKinetics::update_rates_T();
        m_rfn_const.col(n) = vec_map(&m_rfn[0], nReactions());
        m_rkcn_const.col(n) = vec_map(&m_rkcn[0], nReactions());
        m_rfn_low_const.col(n) = vec_map(&m_rfn_low[0], nFall);
        m_rfn_high_const.col(n) = vec_map(&m_rfn_high[0], nFall);
        m_falloff_work_const.col(n) = vec_map(&falloff_work[0], nFall);
    }

    double dT = (Tmax - Tmin) / (m_ntemps - 1);
    for (size_t n = 0; n < m_ntemps - 1; n++) {
        m_rfn_slope.col(n) = (m_rfn_const.col(n+1) - m_rfn_const.col(n)) / dT;
        m_rkcn_slope.col(n) = (m_rkcn_const.col(n+1) - m_rkcn_const.col(n)) / dT;
        m_rfn_low_slope.col(n) = (m_rfn_low_const.col(n+1) - m_rfn_low_const.col(n)) / dT;
        m_rfn_high_slope.col(n) = (m_rfn_high_const.col(n+1) - m_rfn_high_const.col(n)) / dT;
        m_falloff_work_slope.col(n) = (m_falloff_work_const.col(n+1) - m_falloff_work_const.col(n)) / dT;
    }
    thermo().setState_TR(T_save, rho_save);
}
예제 #22
0
void GasKinetics::addPlogReaction(PlogReaction& r)
{
    m_plog_rates.install(nReactions()-1, r.rate);
}
예제 #23
0
void GasKinetics::addChebyshevReaction(ChebyshevReaction& r)
{
    m_cheb_rates.install(nReactions()-1, r.rate);
}
예제 #24
0
void BulkKinetics::addElementaryReaction(ElementaryReaction& r)
{
    m_rates.install(nReactions()-1, r.rate);
}
예제 #25
0
void Kinetics::checkReactionIndex(size_t i) const
{
    if (i >= nReactions()) {
        throw IndexError("checkReactionIndex", "reactions", i, nReactions()-1);
    }
}
예제 #26
0
bool Kinetics::addReaction(shared_ptr<Reaction> r)
{
    r->validate();
    if (m_kk == 0) {
        init();
    }
    resizeSpecies();

    // If reaction orders are specified, then this reaction does not follow
    // mass-action kinetics, and is not an elementary reaction. So check that it
    // is not reversible, since computing the reverse rate from thermochemistry
    // only works for elementary reactions.
    if (r->reversible && !r->orders.empty()) {
        throw CanteraError("Kinetics::addReaction", "Reaction orders may only "
            "be given for irreversible reactions");
    }

    // Check for undeclared species
    for (const auto& sp : r->reactants) {
        if (kineticsSpeciesIndex(sp.first) == npos) {
            if (m_skipUndeclaredSpecies) {
                return false;
            } else {
                throw CanteraError("Kinetics::addReaction", "Reaction '" +
                    r->equation() + "' contains the undeclared species '" +
                    sp.first + "'");
            }
        }
    }
    for (const auto& sp : r->products) {
        if (kineticsSpeciesIndex(sp.first) == npos) {
            if (m_skipUndeclaredSpecies) {
                return false;
            } else {
                throw CanteraError("Kinetics::addReaction", "Reaction '" +
                    r->equation() + "' contains the undeclared species '" +
                    sp.first + "'");
            }
        }
    }

    checkReactionBalance(*r);
    size_t irxn = nReactions(); // index of the new reaction

    // indices of reactant and product species within this Kinetics object
    std::vector<size_t> rk, pk;

    // Reactant and product stoichiometric coefficients, such that rstoich[i] is
    // the coefficient for species rk[i]
    vector_fp rstoich, pstoich;

    for (const auto& sp : r->reactants) {
        size_t k = kineticsSpeciesIndex(sp.first);
        rk.push_back(k);
        rstoich.push_back(sp.second);
    }

    for (const auto& sp : r->products) {
        size_t k = kineticsSpeciesIndex(sp.first);
        pk.push_back(k);
        pstoich.push_back(sp.second);
    }

    // The default order for each reactant is its stoichiometric coefficient,
    // which can be overridden by entries in the Reaction.orders map. rorder[i]
    // is the order for species rk[i].
    vector_fp rorder = rstoich;
    for (const auto& sp : r->orders) {
        size_t k = kineticsSpeciesIndex(sp.first);
        // Find the index of species k within rk
        auto rloc = std::find(rk.begin(), rk.end(), k);
        if (rloc != rk.end()) {
            rorder[rloc - rk.begin()] = sp.second;
        } else {
            // If the reaction order involves a non-reactant species, add an
            // extra term to the reactants with zero stoichiometry so that the
            // stoichiometry manager can be used to compute the global forward
            // reaction rate.
            rk.push_back(k);
            rstoich.push_back(0.0);
            rorder.push_back(sp.second);
        }
    }

    m_reactantStoich.add(irxn, rk, rorder, rstoich);
    // product orders = product stoichiometric coefficients
    if (r->reversible) {
        m_revProductStoich.add(irxn, pk, pstoich, pstoich);
    } else {
        m_irrevProductStoich.add(irxn, pk, pstoich, pstoich);
    }

    m_reactions.push_back(r);
    m_rfn.push_back(0.0);
    m_rkcn.push_back(0.0);
    m_ropf.push_back(0.0);
    m_ropr.push_back(0.0);
    m_ropnet.push_back(0.0);
    m_perturb.push_back(1.0);
    return true;
}
void BulkKinetics::addElementaryReaction(ReactionData& r)
{
    m_rates.install(nReactions(), r);
}
예제 #28
0
void Kinetics::checkReactionArraySize(size_t ii) const
{
    if (nReactions() > ii) {
        throw ArraySizeError("checkReactionArraySize", ii, nReactions());
    }
}