Added option to ignore third-body efficiencies for undeclared species

To enable this option, in the phase definition, add
'skip_undeclared_third_bodies' to the list passed as the 'options'
argument.
This commit is contained in:
Ray Speth 2012-05-18 22:41:58 +00:00
parent df40d898b0
commit 754faa3b13
4 changed files with 75 additions and 44 deletions

View file

@ -252,17 +252,20 @@ The options field is used to indicate how certain conditions should be handled
when importing the phase definition. The options field may be assigned a string
or a sequence of strings from the table below.
============================== ================
Option String Meaning
============================== ================
``'no_validation'`` Turn off all validation. Use when the definition
has been previously validated to speed up importing
the definition into an application. Use with caution!
``'skip_undeclared_elements'`` When importing species, skip any containing undeclared
elements, rather than flagging them as an error.
``'skip_undeclared_species'`` When importing reactions, skip any containing undeclared
species, rather than flagging them as an error.
============================== ================
================================== ================
Option String Meaning
================================== ================
``'no_validation'`` Turn off all validation. Use when the definition
has been previously validated to speed up importing
the definition into an application. Use with caution!
``'skip_undeclared_elements'`` When importing species, skip any containing undeclared
elements, rather than flagging them as an error.
``'skip_undeclared_species'`` When importing reactions, skip any containing undeclared
species, rather than flagging them as an error.
``'skip_undeclared_third_bodies'`` When importing reactions with third body efficiencies,
ignore any efficiencies for undeclared species, rather
than flagging them as an error.
================================== ================
Using the ``options`` field, it is possible to extract a sub-mechanism from a large
reaction mechanism, as follows::

View file

@ -27,6 +27,14 @@ class Kinetics;
class SpeciesThermoFactory;
class XML_Node;
//! Rules for parsing and installing reactions
struct ReactionRules
{
ReactionRules();
bool skipUndeclaredSpecies;
bool skipUndeclaredThirdBodies;
bool allowNegativeA;
};
//!This function returns a ratio if two reactions are duplicates of
//!one another, and 0.0 otherwise.
@ -85,17 +93,15 @@ void checkRxnElementBalance(Kinetics& kin,
* Length is number of reactants or products.
* stoich = stoichiometric coefficient of the reactant or product
* Length is number of reactants or products.
* order = Order of the reactant and product in the reaction
* rate expression
* @param rule If we fail to find a species, we will throw an error
* if rule != 1. If rule = 1, we simply return false,
* allowing the calling routine to skip this reaction
* and continue.
* order = Order of the reactant and product in the reaction rate expression
* @param rules If rules.skipUndeclaredSpecies is set and we fail to find a
* species we simply return false, allowing the calling routine to skip
* this reaction and continue. Otherwise, we will throw an error.
*/
bool getReagents(const XML_Node& rxn, Kinetics& kin, int rp,
std::string default_phase,
std::vector<size_t>& spnum, vector_fp& stoich,
vector_fp& order, int rule);
vector_fp& order, const ReactionRules& rule);
//! Read the rate coefficient data from the XML file.
/*!
@ -113,8 +119,8 @@ bool getReagents(const XML_Node& rxn, Kinetics& kin, int rp,
*
* @ingroup kineticsmgr
*/
void getRateCoefficient(const XML_Node& kf, Kinetics& kin,
ReactionData& rdata, int negA);
void getRateCoefficient(const XML_Node& kf, Kinetics& kin, ReactionData& rdata,
const ReactionRules& rules);
//! Create a new ThermoPhase object and initializes it according to the XML tree database.

View file

@ -1621,10 +1621,16 @@ class phase:
datasrc = r[0]
ra = p.addChild('reactionArray')
ra['datasrc'] = datasrc+'#reaction_data'
rk = None
if 'skip_undeclared_species' in self._options:
rk = ra.addChild('skip')
rk['species'] = 'undeclared'
if 'skip_undeclared_third_bodies' in self._options:
if not rk:
rk = ra.addChild('skip')
rk['third_bodies'] = 'undeclared'
rtoks = r[1].split()
if rtoks[0] != 'all':
i = ra.addChild('include')

View file

@ -40,6 +40,13 @@ using namespace std;
namespace Cantera
{
ReactionRules::ReactionRules() :
skipUndeclaredSpecies(false),
skipUndeclaredThirdBodies(false),
allowNegativeA(false)
{
}
//! these are all used to check for duplicate reactions
class rxninfo
{
@ -67,7 +74,7 @@ public:
std::map<std::vector<char>, std::vector<size_t> > m_participants;
bool installReaction(int i, const XML_Node& r, Kinetics& kin,
std::string default_phase, int rule,
std::string default_phase, ReactionRules& rule,
bool validate_rxn) ;
};
@ -162,14 +169,15 @@ void checkRxnElementBalance(Kinetics& kin,
* Length is number of reactants or products.
* order = Order of the reactant and product in the reaction
* rate expression
* rule = If we fail to find a species, we will throw an error
* rules = If we fail to find a species, we will throw an error
* if rule != 1. If rule = 1, we simply return false,
* allowing the calling routine to skip this reaction
* and continue.
*/
bool getReagents(const XML_Node& rxn, Kinetics& kin, int rp,
std::string default_phase, std::vector<size_t>& spnum,
vector_fp& stoich, vector_fp& order, int rule)
vector_fp& stoich, vector_fp& order,
const ReactionRules& rules)
{
string rptype;
@ -211,7 +219,7 @@ bool getReagents(const XML_Node& rxn, Kinetics& kin, int rp,
*/
size_t isp = kin.kineticsSpeciesIndex(sp);
if (isp == npos) {
if (rule == 1) {
if (rules.skipUndeclaredSpecies) {
return false;
} else {
throw CanteraError("getReagents",
@ -464,7 +472,8 @@ static void getFalloff(const XML_Node& f, ReactionData& rdata)
* reaction mechanism is homogeneous, so that all species belong
* to phase(0) of 'kin'.
*/
static void getEfficiencies(const XML_Node& eff, Kinetics& kin, ReactionData& rdata)
static void getEfficiencies(const XML_Node& eff, Kinetics& kin,
ReactionData& rdata, const ReactionRules& rules)
{
// set the default collision efficiency
rdata.default_3b_eff = fpValue(eff["default"]);
@ -476,12 +485,13 @@ static void getEfficiencies(const XML_Node& eff, Kinetics& kin, ReactionData& rd
for (size_t n = 0; n < key.size(); n++) { // ; bb != ee; ++bb) {
nm = key[n];// bb->first;
size_t k = kin.kineticsSpeciesIndex(nm, phse);
if (k == npos) {
if (k != npos) {
rdata.thirdBodyEfficiencies[k] = fpValue(val[n]); // bb->second;
} else if (!rules.skipUndeclaredThirdBodies) {
throw CanteraError("getEfficiencies", "Encountered third-body "
"efficiency for undefined species \"" + nm + "\"\n"
"while adding reaction " + int2str(rdata.number+1) + ".");
}
rdata.thirdBodyEfficiencies[k] = fpValue(val[n]); // bb->second;
}
}
@ -494,7 +504,7 @@ static void getEfficiencies(const XML_Node& eff, Kinetics& kin, ReactionData& rd
* @param kf Reference to the XML Node named rateCoeff
*/
void getRateCoefficient(const XML_Node& kf, Kinetics& kin,
ReactionData& rdata, int negA)
ReactionData& rdata, const ReactionRules& rules)
{
if (rdata.reactionType == PLOG_RXN) {
rdata.rateCoeffType = PLOG_REACTION_RATECOEFF_TYPE;
@ -560,7 +570,7 @@ void getRateCoefficient(const XML_Node& kf, Kinetics& kin,
kin.thermo(kin.surfacePhaseIndex()), rdata);
}
if (coeff[0] <= 0.0 && negA == 0) {
if (coeff[0] <= 0.0 && !rules.allowNegativeA) {
throw CanteraError("getRateCoefficient",
"negative or zero A coefficient for reaction "+int2str(rdata.number));
}
@ -572,7 +582,7 @@ void getRateCoefficient(const XML_Node& kf, Kinetics& kin,
} else if (nm == "falloff") {
getFalloff(c, rdata);
} else if (nm == "efficiencies") {
getEfficiencies(c, kin, rdata);
getEfficiencies(c, kin, rdata, rules);
} else if (nm == "electrochem") {
rdata.beta = fpValue(c["beta"]);
}
@ -666,7 +676,7 @@ next:
* @ingroup kineticsmgr
*/
bool rxninfo::installReaction(int iRxn, const XML_Node& r, Kinetics& kin,
string default_phase, int rule,
string default_phase, ReactionRules& rules,
bool validate_rxn)
{
// Check to see that we are in fact at a reaction node
@ -687,7 +697,7 @@ bool rxninfo::installReaction(int iRxn, const XML_Node& r, Kinetics& kin,
// Check to see if the reaction rate constant can be negative. It's an
// error if a negative rate constant is found and this is not set.
int negA = (r.hasAttrib("negative_A")) ? 1 : 0;
rules.allowNegativeA = (r.hasAttrib("negative_A")) ? 1 : 0;
// Use the contents of the "equation" child element as the reaction's
// string representation. Post-process to convert "[" and "]" characters
@ -705,11 +715,11 @@ bool rxninfo::installReaction(int iRxn, const XML_Node& r, Kinetics& kin,
// get the reactants
bool ok = getReagents(r, kin, 1, default_phase, rdata.reactants,
rdata.rstoich, rdata.rorder, rule);
rdata.rstoich, rdata.rorder, rules);
// Get the products. We store the id of products in rdata.products
ok = ok && getReagents(r, kin, -1, default_phase, rdata.products,
rdata.pstoich, rdata.porder, rule);
rdata.pstoich, rdata.porder, rules);
// if there was a problem getting either the reactants or the products,
// then abort.
@ -845,7 +855,7 @@ bool rxninfo::installReaction(int iRxn, const XML_Node& r, Kinetics& kin,
// Read the rate coefficient data from the XML file. Trigger an
// exception for negative A unless specifically authorized.
getRateCoefficient(r.child("rateCoeff"), kin, rdata, negA);
getRateCoefficient(r.child("rateCoeff"), kin, rdata, rules);
// Check to see that the elements balance in the reaction.
// Throw an error if they don't
@ -909,20 +919,26 @@ bool installReactionArrays(const XML_Node& p, Kinetics& kin,
*/
const XML_Node* rdata = get_XML_Node(rxns["datasrc"], &rxns.root());
/*
* If the reactionArray element has a child element named
* "skip", and if the attribute of skip called "species" has
* a value of "undeclared", we will set rxnrule = 1.
* rxnrule is passed to the routine that parses each individual
* reaction. I believe what this means is that the parser will
* skip all reactions containing an undefined species without
* throwing an error condition.
* If the reactionArray element has a child element named "skip", and
* if the attribute of skip called "species" has a value of "undeclared",
* we will set rxnrule.skipUndeclaredSpecies to 'true'. rxnrule is
* passed to the routine that parses each individual reaction so that
* the parser will skip all reactions containing an undefined species
* without throwing an error.
*
* Similarly, an attribute named "third_bodies" with the value of
* "undeclared" will skip undeclared third body efficiencies (while
* retaining the reaction and any other efficiencies).
*/
int rxnrule = 0;
ReactionRules rxnrule;
if (rxns.hasChild("skip")) {
const XML_Node& sk = rxns.child("skip");
string sskip = sk["species"];
if (sskip == "undeclared") {
rxnrule = 1;
rxnrule.skipUndeclaredSpecies = true;
}
if (sk["third_bodies"] == "undeclared") {
rxnrule.skipUndeclaredThirdBodies = true;
}
}
int i, nrxns = 0;