[Thermo] add flag that makes species names case sensitive
* store species information with case sensitive names * retain lookup for non-case sensitive species names, e.g. Phase::speciesIndex * implement flag that enforces case sensitive species names as a member variable of Phase * add exception handling for species that are not uniquely defined unless case sensitive (e.g. Cs and CS in nasa.cti if cs is specified and case sensitivity is not enforced) * deprecate Phase::species(std::string&)
This commit is contained in:
parent
e0fe5eed59
commit
2231141e32
5 changed files with 107 additions and 26 deletions
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
// This file is part of Cantera. See License.txt in the top-level directory or
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
// at https://cantera.org/license.txt for license and copyright information.
|
||||||
|
|
||||||
#ifndef CT_PHASE_H
|
#ifndef CT_PHASE_H
|
||||||
#define CT_PHASE_H
|
#define CT_PHASE_H
|
||||||
|
|
@ -707,6 +707,10 @@ public:
|
||||||
//! Return the Species object for the named species. Changes to this object
|
//! Return the Species object for the named species. Changes to this object
|
||||||
//! do not affect the ThermoPhase object until the #modifySpecies function
|
//! do not affect the ThermoPhase object until the #modifySpecies function
|
||||||
//! is called.
|
//! is called.
|
||||||
|
/*!
|
||||||
|
* @deprecated To be removed after Cantera 2.5. Replaceable with
|
||||||
|
* Phase::species(size_t) via Phase::speciesIndex(std::string&).
|
||||||
|
*/
|
||||||
shared_ptr<Species> species(const std::string& name) const;
|
shared_ptr<Species> species(const std::string& name) const;
|
||||||
|
|
||||||
//! Return the Species object for species whose index is *k*. Changes to
|
//! Return the Species object for species whose index is *k*. Changes to
|
||||||
|
|
@ -747,6 +751,17 @@ public:
|
||||||
//! change in state is detected
|
//! change in state is detected
|
||||||
virtual void invalidateCache();
|
virtual void invalidateCache();
|
||||||
|
|
||||||
|
//! Returns `true` if case sensitive species names are enforced
|
||||||
|
bool caseSensitiveSpecies() const {
|
||||||
|
return m_caseSensitiveSpecies;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Set flag that determines whether case sensitive species are enforced
|
||||||
|
//! in look-up operations, e.g. speciesIndex
|
||||||
|
void setCaseSensitiveSpecies(bool cflag = true) {
|
||||||
|
m_caseSensitiveSpecies = cflag;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Cached for saved calculations within each ThermoPhase.
|
//! Cached for saved calculations within each ThermoPhase.
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -794,6 +809,14 @@ protected:
|
||||||
//! Flag determining behavior when adding species with an undefined element
|
//! Flag determining behavior when adding species with an undefined element
|
||||||
UndefElement::behavior m_undefinedElementBehavior;
|
UndefElement::behavior m_undefinedElementBehavior;
|
||||||
|
|
||||||
|
//! Find lowercase species name in m_speciesIndices when case sensitive
|
||||||
|
//! species names are not enforced. Raise exception if lowercase name
|
||||||
|
//! is not unique.
|
||||||
|
size_t findSpeciesLower(const std::string& nameStr) const;
|
||||||
|
|
||||||
|
//! Flag determining whether case sensitive species names are enforced
|
||||||
|
bool m_caseSensitiveSpecies;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XML_Node* m_xml; //!< XML node containing the XML info for this phase
|
XML_Node* m_xml; //!< XML node containing the XML info for this phase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,12 +165,13 @@ cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera":
|
||||||
|
|
||||||
# species properties
|
# species properties
|
||||||
size_t nSpecies()
|
size_t nSpecies()
|
||||||
shared_ptr[CxxSpecies] species(string) except +translate_exception
|
|
||||||
shared_ptr[CxxSpecies] species(size_t) except +translate_exception
|
shared_ptr[CxxSpecies] species(size_t) except +translate_exception
|
||||||
size_t speciesIndex(string) except +translate_exception
|
size_t speciesIndex(string) except +translate_exception
|
||||||
string speciesName(size_t) except +translate_exception
|
string speciesName(size_t) except +translate_exception
|
||||||
double nAtoms(size_t, size_t) except +translate_exception
|
double nAtoms(size_t, size_t) except +translate_exception
|
||||||
void getAtoms(size_t, double*) except +translate_exception
|
void getAtoms(size_t, double*) except +translate_exception
|
||||||
|
cbool caseSensitiveSpecies()
|
||||||
|
void setCaseSensitiveSpecies(cbool)
|
||||||
|
|
||||||
double molecularWeight(size_t) except +translate_exception
|
double molecularWeight(size_t) except +translate_exception
|
||||||
double meanMolecularWeight()
|
double meanMolecularWeight()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# This file is part of Cantera. See License.txt in the top-level directory or
|
# This file is part of Cantera. See License.txt in the top-level directory or
|
||||||
# at http://www.cantera.org/license.txt for license and copyright information.
|
# at https://cantera.org/license.txt for license and copyright information.
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
import weakref
|
import weakref
|
||||||
|
|
@ -470,6 +470,13 @@ cdef class ThermoPhase(_SolutionBase):
|
||||||
|
|
||||||
return index
|
return index
|
||||||
|
|
||||||
|
property case_sensitive_species_names:
|
||||||
|
"""Enforce case-sensitivity for look up of species names"""
|
||||||
|
def __get__(self):
|
||||||
|
return self.thermo.caseSensitiveSpecies()
|
||||||
|
def __set__(self, val):
|
||||||
|
self.thermo.setCaseSensitiveSpecies(bool(val))
|
||||||
|
|
||||||
def species(self, k=None):
|
def species(self, k=None):
|
||||||
"""
|
"""
|
||||||
Return the `Species` object for species *k*, where *k* is either the
|
Return the `Species` object for species *k*, where *k* is either the
|
||||||
|
|
@ -483,7 +490,8 @@ cdef class ThermoPhase(_SolutionBase):
|
||||||
|
|
||||||
s = Species(init=False)
|
s = Species(init=False)
|
||||||
if isinstance(k, (str, bytes)):
|
if isinstance(k, (str, bytes)):
|
||||||
s._assign(self.thermo.species(stringify(k)))
|
kk = self.thermo.speciesIndex(stringify(k))
|
||||||
|
s._assign(self.thermo.species(<int>kk))
|
||||||
elif isinstance(k, (int, float)):
|
elif isinstance(k, (int, float)):
|
||||||
s._assign(self.thermo.species(<int>k))
|
s._assign(self.thermo.species(<int>k))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
// This file is part of Cantera. See License.txt in the top-level directory or
|
||||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
// at https://cantera.org/license.txt for license and copyright information.
|
||||||
|
|
||||||
#include "cantera/thermo/Phase.h"
|
#include "cantera/thermo/Phase.h"
|
||||||
#include "cantera/base/utilities.h"
|
#include "cantera/base/utilities.h"
|
||||||
|
|
@ -21,6 +21,7 @@ Phase::Phase() :
|
||||||
m_kk(0),
|
m_kk(0),
|
||||||
m_ndim(3),
|
m_ndim(3),
|
||||||
m_undefinedElementBehavior(UndefElement::add),
|
m_undefinedElementBehavior(UndefElement::add),
|
||||||
|
m_caseSensitiveSpecies(false),
|
||||||
m_xml(new XML_Node("phase")),
|
m_xml(new XML_Node("phase")),
|
||||||
m_id("<phase>"),
|
m_id("<phase>"),
|
||||||
m_temp(0.001),
|
m_temp(0.001),
|
||||||
|
|
@ -172,20 +173,47 @@ void Phase::getAtoms(size_t k, double* atomArray) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Phase::findSpeciesLower(const std::string& name) const
|
||||||
|
{
|
||||||
|
size_t loc = npos;
|
||||||
|
std::string nLower = toLowerCopy(name);
|
||||||
|
for (const auto& k : m_speciesIndices) {
|
||||||
|
if (toLowerCopy(k.first) == nLower) {
|
||||||
|
if (loc == npos) {
|
||||||
|
loc = k.second;
|
||||||
|
} else {
|
||||||
|
throw CanteraError("Phase::findSpeciesLower",
|
||||||
|
"Lowercase species name '{}' is not unique", nLower);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
size_t Phase::speciesIndex(const std::string& nameStr) const
|
size_t Phase::speciesIndex(const std::string& nameStr) const
|
||||||
{
|
{
|
||||||
size_t loc = getValue(m_speciesIndices, toLowerCopy(nameStr), npos);
|
size_t loc = npos;
|
||||||
|
try {
|
||||||
|
return m_speciesIndices.at(nameStr);
|
||||||
|
} catch (std::out_of_range&) {
|
||||||
|
if (!m_caseSensitiveSpecies) {
|
||||||
|
loc = findSpeciesLower(nameStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (loc == npos && nameStr.find(':') != npos) {
|
if (loc == npos && nameStr.find(':') != npos) {
|
||||||
std::string pn;
|
std::string pn;
|
||||||
std::string sn = toLowerCopy(parseSpeciesName(nameStr, pn));
|
std::string sn = parseSpeciesName(nameStr, pn);
|
||||||
if (pn == "" || pn == m_name || pn == m_id) {
|
if (pn == "" || pn == m_name || pn == m_id) {
|
||||||
return getValue(m_speciesIndices, sn, npos);
|
try {
|
||||||
} else {
|
return m_speciesIndices.at(sn);
|
||||||
return npos;
|
} catch (std::out_of_range&) {
|
||||||
|
if (!m_caseSensitiveSpecies) {
|
||||||
|
return findSpeciesLower(sn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return loc;
|
|
||||||
}
|
}
|
||||||
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
string Phase::speciesName(size_t k) const
|
string Phase::speciesName(size_t k) const
|
||||||
|
|
@ -294,10 +322,18 @@ void Phase::setMoleFractionsByName(const compositionMap& xMap)
|
||||||
vector_fp mf(m_kk, 0.0);
|
vector_fp mf(m_kk, 0.0);
|
||||||
for (const auto& sp : xMap) {
|
for (const auto& sp : xMap) {
|
||||||
try {
|
try {
|
||||||
mf[m_speciesIndices.at(toLowerCopy(sp.first))] = sp.second;
|
mf[m_speciesIndices.at(sp.first)] = sp.second;
|
||||||
} catch (std::out_of_range&) {
|
} catch (std::out_of_range&) {
|
||||||
throw CanteraError("Phase::setMoleFractionsByName",
|
size_t loc = npos;
|
||||||
"Unknown species '{}'", sp.first);
|
if (!m_caseSensitiveSpecies) {
|
||||||
|
loc = findSpeciesLower(sp.first);
|
||||||
|
}
|
||||||
|
if (loc == npos) {
|
||||||
|
throw CanteraError("Phase::setMoleFractionsByName",
|
||||||
|
"Unknown species '{}'", sp.first);
|
||||||
|
} else {
|
||||||
|
mf[loc] = sp.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setMoleFractions(&mf[0]);
|
setMoleFractions(&mf[0]);
|
||||||
|
|
@ -338,10 +374,18 @@ void Phase::setMassFractionsByName(const compositionMap& yMap)
|
||||||
vector_fp mf(m_kk, 0.0);
|
vector_fp mf(m_kk, 0.0);
|
||||||
for (const auto& sp : yMap) {
|
for (const auto& sp : yMap) {
|
||||||
try {
|
try {
|
||||||
mf[m_speciesIndices.at(toLowerCopy(sp.first))] = sp.second;
|
mf[m_speciesIndices.at(sp.first)] = sp.second;
|
||||||
} catch (std::out_of_range&) {
|
} catch (std::out_of_range&) {
|
||||||
throw CanteraError("Phase::setMassFractionsByName",
|
size_t loc = npos;
|
||||||
"Unknown species '{}'", sp.first);
|
if (!m_caseSensitiveSpecies) {
|
||||||
|
loc = findSpeciesLower(sp.first);
|
||||||
|
}
|
||||||
|
if (loc == npos) {
|
||||||
|
throw CanteraError("Phase::setMassFractionsByName",
|
||||||
|
"Unknown species '{}'", sp.first);
|
||||||
|
} else {
|
||||||
|
mf[loc] = sp.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setMassFractions(&mf[0]);
|
setMassFractions(&mf[0]);
|
||||||
|
|
@ -699,7 +743,8 @@ size_t Phase::addElement(const std::string& symbol, doublereal weight,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Phase::addSpecies(shared_ptr<Species> spec) {
|
bool Phase::addSpecies(shared_ptr<Species> spec) {
|
||||||
if (m_species.find(toLowerCopy(spec->name)) != m_species.end()) {
|
// species names are case sensitive
|
||||||
|
if (m_species.find(spec->name) != m_species.end()) {
|
||||||
throw CanteraError("Phase::addSpecies",
|
throw CanteraError("Phase::addSpecies",
|
||||||
"Phase '{}' already contains a species named '{}'.",
|
"Phase '{}' already contains a species named '{}'.",
|
||||||
m_name, spec->name);
|
m_name, spec->name);
|
||||||
|
|
@ -729,8 +774,8 @@ bool Phase::addSpecies(shared_ptr<Species> spec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
m_speciesNames.push_back(spec->name);
|
m_speciesNames.push_back(spec->name);
|
||||||
m_species[toLowerCopy(spec->name)] = spec;
|
m_species[spec->name] = spec;
|
||||||
m_speciesIndices[toLowerCopy(spec->name)] = m_kk;
|
m_speciesIndices[spec->name] = m_kk;
|
||||||
m_speciesCharge.push_back(spec->charge);
|
m_speciesCharge.push_back(spec->charge);
|
||||||
size_t ne = nElements();
|
size_t ne = nElements();
|
||||||
|
|
||||||
|
|
@ -794,24 +839,28 @@ void Phase::modifySpecies(size_t k, shared_ptr<Species> spec)
|
||||||
"New species name '{}' does not match existing name '{}'",
|
"New species name '{}' does not match existing name '{}'",
|
||||||
spec->name, speciesName(k));
|
spec->name, speciesName(k));
|
||||||
}
|
}
|
||||||
const shared_ptr<Species>& old = m_species[toLowerCopy(spec->name)];
|
const shared_ptr<Species>& old = m_species[spec->name];
|
||||||
if (spec->composition != old->composition) {
|
if (spec->composition != old->composition) {
|
||||||
throw CanteraError("Phase::modifySpecies",
|
throw CanteraError("Phase::modifySpecies",
|
||||||
"New composition for '{}' does not match existing composition",
|
"New composition for '{}' does not match existing composition",
|
||||||
spec->name);
|
spec->name);
|
||||||
}
|
}
|
||||||
m_species[toLowerCopy(spec->name)] = spec;
|
m_species[spec->name] = spec;
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! @deprecated To be removed after Cantera 2.5.
|
||||||
shared_ptr<Species> Phase::species(const std::string& name) const
|
shared_ptr<Species> Phase::species(const std::string& name) const
|
||||||
{
|
{
|
||||||
return m_species.at(toLowerCopy(name));
|
warn_deprecated("Phase::species(std::string&)",
|
||||||
|
"To be removed after Cantera 2.5. "
|
||||||
|
"Use Phase::species(size_t) instead.");
|
||||||
|
return m_species.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<Species> Phase::species(size_t k) const
|
shared_ptr<Species> Phase::species(size_t k) const
|
||||||
{
|
{
|
||||||
return species(m_speciesNames[k]);
|
return m_species.at(m_speciesNames[k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Phase::ignoreUndefinedElements() {
|
void Phase::ignoreUndefinedElements() {
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,7 @@ void GasTransport::setupCollisionIntegral()
|
||||||
void GasTransport::getTransportData()
|
void GasTransport::getTransportData()
|
||||||
{
|
{
|
||||||
for (size_t k = 0; k < m_thermo->nSpecies(); k++) {
|
for (size_t k = 0; k < m_thermo->nSpecies(); k++) {
|
||||||
shared_ptr<Species> s = m_thermo->species(m_thermo->speciesName(k));
|
shared_ptr<Species> s = m_thermo->species(k);
|
||||||
const GasTransportData* sptran =
|
const GasTransportData* sptran =
|
||||||
dynamic_cast<GasTransportData*>(s->transport.get());
|
dynamic_cast<GasTransportData*>(s->transport.get());
|
||||||
if (!sptran) {
|
if (!sptran) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue