[Kinetics] Check for unmatched duplicate reactions

Reactions which are marked as duplicates but have no matching reactions are
considered errors.

Fixes #389
This commit is contained in:
Ray Speth 2017-01-23 14:34:18 -05:00
parent 7979a2b52a
commit 0fd2f7c4d0
3 changed files with 28 additions and 4 deletions

View file

@ -651,6 +651,9 @@ class TestDuplicateReactions(utilities.CanteraTest):
gas = ct.Solution(self.infile, 'I')
self.assertEqual(gas.n_reactions, 2)
def test_unmatched_duplicate(self):
self.check('J')
class TestReaction(utilities.CanteraTest):
@classmethod

View file

@ -12,6 +12,7 @@
#include "cantera/kinetics/Kinetics.h"
#include "cantera/kinetics/Reaction.h"
#include "cantera/base/stringUtils.h"
#include <unordered_set>
using namespace std;
@ -156,6 +157,12 @@ 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;
std::unordered_set<size_t> unmatched_duplicates;
for (size_t i = 0; i < m_reactions.size(); i++) {
if (m_reactions[i]->duplicate) {
unmatched_duplicates.insert(i);
}
}
for (size_t i = 0; i < m_reactions.size(); i++) {
// Get data about this reaction
@ -178,10 +185,13 @@ std::pair<size_t, size_t> Kinetics::checkDuplicates(bool throw_err) const
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) {
if (R.duplicate && other.duplicate) {
// marked duplicates
unmatched_duplicates.erase(i);
unmatched_duplicates.erase(related[m]);
continue;
} else 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) {
@ -223,7 +233,7 @@ std::pair<size_t, size_t> Kinetics::checkDuplicates(bool throw_err) const
}
}
if (throw_err) {
throw CanteraError("installReaction",
throw CanteraError("Kinetics::checkDuplicates",
"Undeclared duplicate reactions detected:\n"
"Reaction {}: {}\nReaction {}: {}\n",
i+1, other.equation(), m+1, R.equation());
@ -233,6 +243,16 @@ std::pair<size_t, size_t> Kinetics::checkDuplicates(bool throw_err) const
}
participants[key].push_back(i);
}
if (unmatched_duplicates.size()) {
size_t i = *unmatched_duplicates.begin();
if (throw_err) {
throw CanteraError("Kinetics::checkDuplicates",
"No duplicate found for declared duplicate reaction number {}"
" ({})", i, m_reactions[i]->equation());
} else {
return {i, i};
}
}
return {npos, npos};
}

View file

@ -16,6 +16,7 @@ make_gas('F', 'F-*')
make_gas('G', 'G-*')
make_gas('H', 'H-*')
make_gas('I', 'I-*')
make_gas('J', ['C-1', 'F-1', 'I-1']) # unmatched duplicate
kf = [1e10, 0, 100]