Add options for handling Species containing undefined elements
This commit is contained in:
parent
26b6f190f3
commit
5bc4a12e2e
5 changed files with 158 additions and 12 deletions
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
/**
|
||||
* @defgroup phases Models of Phases of Matter
|
||||
*
|
||||
|
|
@ -717,7 +718,10 @@ public:
|
|||
doublereal entropy298 = ENTROPY298_UNKNOWN,
|
||||
int elem_type = CT_ELEM_TYPE_ABSPOS);
|
||||
|
||||
virtual void addSpecies(const Species& spec);
|
||||
//! Add a Species to this Phase. Returns `true` if the species was
|
||||
//! successfully added, or `false` if the species was ignored.
|
||||
//! @see ignoreUndefinedElements addUndefinedElements throwUndefinedElements
|
||||
virtual bool addSpecies(const Species& spec);
|
||||
|
||||
void addSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge = 0.0, doublereal size = 1.0);
|
||||
|
|
@ -733,6 +737,23 @@ public:
|
|||
void addUniqueSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge = 0.0,
|
||||
doublereal size = 1.0);
|
||||
|
||||
//! Set behavior when adding a species containing undefined elements to just
|
||||
//! skip the species.
|
||||
void ignoreUndefinedElements();
|
||||
|
||||
//! Set behavior when adding a species containing undefined elements to add
|
||||
//! those elements to the phase.
|
||||
void addUndefinedElements();
|
||||
|
||||
//! Set the behavior when adding a species containing undefined elements to
|
||||
//! throw an exception. This is the default behavior.
|
||||
void throwUndefinedElements();
|
||||
|
||||
struct UndefElement { enum behavior {
|
||||
error, ignore, add
|
||||
}; };
|
||||
|
||||
//!@} end group adding species and elements
|
||||
|
||||
//! Returns a bool indicating wether the object is ready for use
|
||||
|
|
@ -782,6 +803,9 @@ protected:
|
|||
|
||||
std::map<std::string, Species> m_species;
|
||||
|
||||
//! Flag determining behavior when adding species with an undefined element
|
||||
UndefElement::behavior m_undefinedElementBehavior;
|
||||
|
||||
private:
|
||||
XML_Node* m_xml; //!< XML node containing the XML info for this phase
|
||||
|
||||
|
|
|
|||
|
|
@ -1278,7 +1278,7 @@ public:
|
|||
//@{
|
||||
|
||||
using Phase::addSpecies;
|
||||
virtual void addSpecies(const Species& spec);
|
||||
virtual bool addSpecies(const Species& spec);
|
||||
|
||||
//! Store a reference pointer to the XML tree containing the species data
|
||||
//! for this phase.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ namespace Cantera
|
|||
Phase::Phase() :
|
||||
m_kk(0),
|
||||
m_ndim(3),
|
||||
m_undefinedElementBehavior(UndefElement::error),
|
||||
m_xml(new XML_Node("phase")),
|
||||
m_id("<phase>"),
|
||||
m_name(""),
|
||||
|
|
@ -35,6 +36,7 @@ Phase::Phase() :
|
|||
Phase::Phase(const Phase& right) :
|
||||
m_kk(0),
|
||||
m_ndim(3),
|
||||
m_undefinedElementBehavior(right.m_undefinedElementBehavior),
|
||||
m_xml(0),
|
||||
m_id("<phase>"),
|
||||
m_name(""),
|
||||
|
|
@ -60,6 +62,7 @@ Phase& Phase::operator=(const Phase& right)
|
|||
// Handle our own data
|
||||
m_kk = right.m_kk;
|
||||
m_ndim = right.m_ndim;
|
||||
m_undefinedElementBehavior = right.m_undefinedElementBehavior;
|
||||
m_temp = right.m_temp;
|
||||
m_dens = right.m_dens;
|
||||
m_mmw = right.m_mmw;
|
||||
|
|
@ -817,17 +820,30 @@ size_t Phase::addUniqueElementAfterFreeze(const std::string& symbol,
|
|||
return addElement(symbol, weight, atomicNumber, entropy298, elem_type);
|
||||
}
|
||||
|
||||
void Phase::addSpecies(const Species& spec) {
|
||||
bool Phase::addSpecies(const Species& spec) {
|
||||
m_species[spec.name] = spec;
|
||||
vector_fp comp(nElements());
|
||||
for (map<string, double>::const_iterator iter = spec.composition.begin();
|
||||
iter != spec.composition.end();
|
||||
iter++) {
|
||||
size_t m = elementIndex(iter->first);
|
||||
if (m == npos) {
|
||||
throw CanteraError("Phase::addSpecies",
|
||||
"Species '" + spec.name + "' contains an "
|
||||
"undefined element '" + iter->first + "'.");
|
||||
if (m == npos) { // Element doesn't exist in this phase
|
||||
switch (m_undefinedElementBehavior) {
|
||||
case UndefElement::ignore:
|
||||
return false;
|
||||
|
||||
case UndefElement::add:
|
||||
addElement(iter->first);
|
||||
comp.resize(nElements());
|
||||
m = elementIndex(iter->first);
|
||||
break;
|
||||
|
||||
case UndefElement::error:
|
||||
default:
|
||||
throw CanteraError("Phase::addSpecies",
|
||||
"Species '" + spec.name + "' contains an "
|
||||
"undefined element '" + iter->first + "'.");
|
||||
}
|
||||
}
|
||||
comp[m] = iter->second;
|
||||
}
|
||||
|
|
@ -886,6 +902,7 @@ void Phase::addSpecies(const Species& spec) {
|
|||
m_y.push_back(0.0);
|
||||
m_ym.push_back(0.0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Phase::addSpecies(const std::string& name_, const doublereal* comp,
|
||||
|
|
@ -929,6 +946,18 @@ void Phase::addUniqueSpecies(const std::string& name_, const doublereal* comp,
|
|||
addSpecies(name_, comp, charge_, size_);
|
||||
}
|
||||
|
||||
void Phase::ignoreUndefinedElements() {
|
||||
m_undefinedElementBehavior = UndefElement::ignore;
|
||||
}
|
||||
|
||||
void Phase::addUndefinedElements() {
|
||||
m_undefinedElementBehavior = UndefElement::add;
|
||||
}
|
||||
|
||||
void Phase::throwUndefinedElements() {
|
||||
m_undefinedElementBehavior = UndefElement::error;
|
||||
}
|
||||
|
||||
bool Phase::ready() const
|
||||
{
|
||||
return (m_kk > 0);
|
||||
|
|
|
|||
|
|
@ -695,10 +695,13 @@ void ThermoPhase::installSlavePhases(Cantera::XML_Node* phaseNode)
|
|||
{
|
||||
}
|
||||
|
||||
void ThermoPhase::addSpecies(const Species& spec)
|
||||
bool ThermoPhase::addSpecies(const Species& spec)
|
||||
{
|
||||
Phase::addSpecies(spec);
|
||||
m_spthermo->install_STIT(spec.thermo().duplMyselfAsSpeciesThermoInterpType());
|
||||
bool added = Phase::addSpecies(spec);
|
||||
if (added) {
|
||||
m_spthermo->install_STIT(spec.thermo().duplMyselfAsSpeciesThermoInterpType());
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
void ThermoPhase::saveSpeciesData(const size_t k, const XML_Node* const data)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "cantera/thermo/FixedChemPotSSTP.h"
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
#include "cantera/thermo/SpeciesThermoFactory.h"
|
||||
#include "cantera/thermo/speciesThermoTypes.h"
|
||||
#include "cantera/thermo/NasaPoly2.h"
|
||||
#include "cantera/thermo/IdealGasPhase.h"
|
||||
#include "cantera/base/ctml.h"
|
||||
#include "cantera/base/stringUtils.h"
|
||||
#include <fstream>
|
||||
#include "thermo_data.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
|
@ -100,4 +101,93 @@ TEST_F(ChemkinConversionTest, FailedConversion) {
|
|||
}
|
||||
#endif
|
||||
|
||||
class ConstructFromScratch : public testing::Test
|
||||
{
|
||||
public:
|
||||
ConstructFromScratch()
|
||||
: sH2O("H2O", parseCompString("H:2 O:1"),
|
||||
new NasaPoly2(0, 200, 3500, 101325, h2o_nasa_coeffs))
|
||||
, sH2("H2", parseCompString("H:2"),
|
||||
new NasaPoly2(0, 200, 3500, 101325, h2_nasa_coeffs))
|
||||
, sO2("O2", parseCompString("O:2"),
|
||||
new NasaPoly2(0, 200, 3500, 101325, o2_nasa_coeffs))
|
||||
, sOH("OH", parseCompString("H:1 O:1"),
|
||||
new NasaPoly2(0, 200, 3500, 101325, oh_nasa_coeffs))
|
||||
, sCO("CO", parseCompString("C:1 O:1"),
|
||||
new NasaPoly2(0, 200, 3500, 101325, o2_nasa_coeffs))
|
||||
, sCO2("CO2", parseCompString("C:1 O:2"),
|
||||
new NasaPoly2(0, 200, 3500, 101325, h2o_nasa_coeffs))
|
||||
{
|
||||
}
|
||||
|
||||
IdealGasPhase p;
|
||||
Species sH2O, sH2, sO2, sOH, sCO, sCO2;
|
||||
};
|
||||
|
||||
TEST_F(ConstructFromScratch, AddElements)
|
||||
{
|
||||
p.addElement("H");
|
||||
p.addElement("O");
|
||||
ASSERT_EQ((size_t) 2, p.nElements());
|
||||
ASSERT_EQ("H", p.elementName(0));
|
||||
ASSERT_EQ((size_t) 1, p.elementIndex("O"));
|
||||
}
|
||||
|
||||
TEST_F(ConstructFromScratch, AddSpeciesDefaultBehavior)
|
||||
{
|
||||
p.addElement("H");
|
||||
p.addElement("O");
|
||||
p.addSpecies(sH2O);
|
||||
p.addSpecies(sH2);
|
||||
|
||||
ASSERT_EQ((size_t) 2, p.nSpecies());
|
||||
|
||||
p.addSpecies(sO2);
|
||||
p.addSpecies(sOH);
|
||||
|
||||
ASSERT_EQ((size_t) 4, p.nSpecies());
|
||||
ASSERT_EQ("H2", p.speciesName(1));
|
||||
ASSERT_EQ(2, p.nAtoms(2, 1)); // O in O2
|
||||
ASSERT_EQ(2, p.nAtoms(0, 0)); // H in H2O
|
||||
ASSERT_THROW(p.addSpecies(sCO), CanteraError);
|
||||
}
|
||||
|
||||
TEST_F(ConstructFromScratch, ignoreUndefinedElements)
|
||||
{
|
||||
p.addElement("H");
|
||||
p.addElement("O");
|
||||
p.ignoreUndefinedElements();
|
||||
|
||||
p.addSpecies(sO2);
|
||||
p.addSpecies(sOH);
|
||||
ASSERT_EQ((size_t) 2, p.nSpecies());
|
||||
|
||||
p.addSpecies(sCO);
|
||||
p.addSpecies(sCO2);
|
||||
ASSERT_EQ((size_t) 2, p.nSpecies());
|
||||
ASSERT_EQ((size_t) 2, p.nElements());
|
||||
ASSERT_EQ(npos, p.speciesIndex("CO2"));
|
||||
}
|
||||
|
||||
TEST_F(ConstructFromScratch, addUndefinedElements)
|
||||
{
|
||||
p.addElement("H");
|
||||
p.addElement("O");
|
||||
p.addUndefinedElements();
|
||||
|
||||
p.addSpecies(sH2);
|
||||
p.addSpecies(sOH);
|
||||
ASSERT_EQ((size_t) 2, p.nSpecies());
|
||||
ASSERT_EQ((size_t) 2, p.nElements());
|
||||
|
||||
p.addSpecies(sCO);
|
||||
p.addSpecies(sCO2);
|
||||
ASSERT_EQ((size_t) 4, p.nSpecies());
|
||||
ASSERT_EQ((size_t) 3, p.nElements());
|
||||
ASSERT_EQ((size_t) 1, p.nAtoms(p.speciesIndex("CO2"), p.elementIndex("C")));
|
||||
ASSERT_EQ((size_t) 2, p.nAtoms(p.speciesIndex("CO2"), p.elementIndex("O")));
|
||||
p.setMassFractionsByName("H2:0.5, CO2:0.5");
|
||||
ASSERT_FLOAT_EQ(0.5, p.massFraction("CO2"));
|
||||
}
|
||||
|
||||
} // namespace Cantera
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue