示例#1
0
/**
 * This routine will look up a species number based on the input
 * std::string nm. The lookup of species will occur in the specified
 * phase of the object, or all phases if ph is "<any>".
 *
 *  return
 *   - If a match is found, the position in the species list is returned.
 *   - If no match is found, the value npos (-1) is returned.
 *
 * @param nm   Input string name of the species
 * @param ph   Input string name of the phase.
 */
size_t Kinetics::kineticsSpeciesIndex(const std::string& nm,
                                      const std::string& ph) const
{
    if (ph == "<any>") {
        return kineticsSpeciesIndex(nm);
    }

    for (size_t n = 0; n < m_thermo.size(); n++) {
        string id = thermo(n).id();
        if (ph == id) {
            size_t k = thermo(n).speciesIndex(nm);
            if (k == npos) {
                return npos;
            }
            return k + m_start[n];
        }
    }
    return npos;
}
示例#2
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);
}
示例#3
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;
}
示例#4
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;
}
示例#5
0
std::pair<size_t, size_t> Kinetics::checkDuplicates(bool throw_err) const
{
    //! Map of (key indicating participating species) to reaction numbers
    std::map<size_t, std::vector<size_t> > participants;
    std::vector<std::map<int, double> > net_stoich;

    for (size_t i = 0; i < m_reactions.size(); i++) {
        // Get data about this reaction
        unsigned long int key = 0;
        Reaction& R = *m_reactions[i];
        net_stoich.emplace_back();
        std::map<int, double>& net = net_stoich.back();
        for (const auto& sp : R.reactants) {
            int k = static_cast<int>(kineticsSpeciesIndex(sp.first));
            key += k*(k+1);
            net[-1 -k] -= sp.second;
        }
        for (const auto& sp : R.products) {
            int k = static_cast<int>(kineticsSpeciesIndex(sp.first));
            key += k*(k+1);
            net[1+k] += sp.second;
        }

        // Compare this reaction to others with similar participants
        vector<size_t>& related = participants[key];
        for (size_t m = 0; m < related.size(); m++) {
            Reaction& other = *m_reactions[related[m]];
            if (R.reaction_type != other.reaction_type) {
                continue; // different reaction types
            } else if (R.duplicate && other.duplicate) {
                continue; // marked duplicates
            }
            doublereal c = checkDuplicateStoich(net_stoich[i], net_stoich[m]);
            if (c == 0) {
                continue; // stoichiometries differ (not by a multiple)
            } else if (c < 0.0 && !R.reversible && !other.reversible) {
                continue; // irreversible reactions in opposite directions
            } else if (R.reaction_type == FALLOFF_RXN ||
                       R.reaction_type == CHEMACT_RXN) {
                ThirdBody& tb1 = dynamic_cast<FalloffReaction&>(R).third_body;
                ThirdBody& tb2 = dynamic_cast<FalloffReaction&>(other).third_body;
                bool thirdBodyOk = true;
                for (size_t k = 0; k < nTotalSpecies(); k++) {
                    string s = kineticsSpeciesName(k);
                    if (tb1.efficiency(s) * tb2.efficiency(s) != 0.0) {
                        // non-zero third body efficiencies for species `s` in
                        // both reactions
                        thirdBodyOk = false;
                        break;
                    }
                }
                if (thirdBodyOk) {
                    continue; // No overlap in third body efficiencies
                }
            } else if (R.reaction_type == THREE_BODY_RXN) {
                ThirdBody& tb1 = dynamic_cast<ThreeBodyReaction&>(R).third_body;
                ThirdBody& tb2 = dynamic_cast<ThreeBodyReaction&>(other).third_body;
                bool thirdBodyOk = true;
                for (size_t k = 0; k < nTotalSpecies(); k++) {
                    string s = kineticsSpeciesName(k);
                    if (tb1.efficiency(s) * tb2.efficiency(s) != 0.0) {
                        // non-zero third body efficiencies for species `s` in
                        // both reactions
                        thirdBodyOk = false;
                        break;
                    }
                }
                if (thirdBodyOk) {
                    continue; // No overlap in third body efficiencies
                }
            }
            if (throw_err) {
                throw CanteraError("installReaction",
                        "Undeclared duplicate reactions detected:\n"
                        "Reaction {}: {}\nReaction {}: {}\n",
                        i+1, other.equation(), m+1, R.equation());
            } else {
                return {i,m};
            }
        }
        participants[key].push_back(i);
    }
    return {npos, npos};
}