[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
|
||||
// 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
|
||||
#define CT_PHASE_H
|
||||
|
|
@ -707,6 +707,10 @@ public:
|
|||
//! Return the Species object for the named species. Changes to this object
|
||||
//! do not affect the ThermoPhase object until the #modifySpecies function
|
||||
//! 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;
|
||||
|
||||
//! Return the Species object for species whose index is *k*. Changes to
|
||||
|
|
@ -747,6 +751,17 @@ public:
|
|||
//! change in state is detected
|
||||
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:
|
||||
//! Cached for saved calculations within each ThermoPhase.
|
||||
/*!
|
||||
|
|
@ -794,6 +809,14 @@ protected:
|
|||
//! Flag determining behavior when adding species with an undefined element
|
||||
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:
|
||||
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
|
||||
size_t nSpecies()
|
||||
shared_ptr[CxxSpecies] species(string) except +translate_exception
|
||||
shared_ptr[CxxSpecies] species(size_t) except +translate_exception
|
||||
size_t speciesIndex(string) except +translate_exception
|
||||
string speciesName(size_t) except +translate_exception
|
||||
double nAtoms(size_t, size_t) except +translate_exception
|
||||
void getAtoms(size_t, double*) except +translate_exception
|
||||
cbool caseSensitiveSpecies()
|
||||
void setCaseSensitiveSpecies(cbool)
|
||||
|
||||
double molecularWeight(size_t) except +translate_exception
|
||||
double meanMolecularWeight()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# 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 weakref
|
||||
|
|
@ -470,6 +470,13 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
|
||||
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):
|
||||
"""
|
||||
Return the `Species` object for species *k*, where *k* is either the
|
||||
|
|
@ -483,7 +490,8 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
|
||||
s = Species(init=False)
|
||||
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)):
|
||||
s._assign(self.thermo.species(<int>k))
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
// 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/base/utilities.h"
|
||||
|
|
@ -21,6 +21,7 @@ Phase::Phase() :
|
|||
m_kk(0),
|
||||
m_ndim(3),
|
||||
m_undefinedElementBehavior(UndefElement::add),
|
||||
m_caseSensitiveSpecies(false),
|
||||
m_xml(new XML_Node("phase")),
|
||||
m_id("<phase>"),
|
||||
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 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) {
|
||||
std::string pn;
|
||||
std::string sn = toLowerCopy(parseSpeciesName(nameStr, pn));
|
||||
std::string sn = parseSpeciesName(nameStr, pn);
|
||||
if (pn == "" || pn == m_name || pn == m_id) {
|
||||
return getValue(m_speciesIndices, sn, npos);
|
||||
} else {
|
||||
return npos;
|
||||
try {
|
||||
return m_speciesIndices.at(sn);
|
||||
} catch (std::out_of_range&) {
|
||||
if (!m_caseSensitiveSpecies) {
|
||||
return findSpeciesLower(sn);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return loc;
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
string Phase::speciesName(size_t k) const
|
||||
|
|
@ -294,10 +322,18 @@ void Phase::setMoleFractionsByName(const compositionMap& xMap)
|
|||
vector_fp mf(m_kk, 0.0);
|
||||
for (const auto& sp : xMap) {
|
||||
try {
|
||||
mf[m_speciesIndices.at(toLowerCopy(sp.first))] = sp.second;
|
||||
mf[m_speciesIndices.at(sp.first)] = sp.second;
|
||||
} catch (std::out_of_range&) {
|
||||
throw CanteraError("Phase::setMoleFractionsByName",
|
||||
"Unknown species '{}'", sp.first);
|
||||
size_t loc = npos;
|
||||
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]);
|
||||
|
|
@ -338,10 +374,18 @@ void Phase::setMassFractionsByName(const compositionMap& yMap)
|
|||
vector_fp mf(m_kk, 0.0);
|
||||
for (const auto& sp : yMap) {
|
||||
try {
|
||||
mf[m_speciesIndices.at(toLowerCopy(sp.first))] = sp.second;
|
||||
mf[m_speciesIndices.at(sp.first)] = sp.second;
|
||||
} catch (std::out_of_range&) {
|
||||
throw CanteraError("Phase::setMassFractionsByName",
|
||||
"Unknown species '{}'", sp.first);
|
||||
size_t loc = npos;
|
||||
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]);
|
||||
|
|
@ -699,7 +743,8 @@ size_t Phase::addElement(const std::string& symbol, doublereal weight,
|
|||
}
|
||||
|
||||
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",
|
||||
"Phase '{}' already contains a species named '{}'.",
|
||||
m_name, spec->name);
|
||||
|
|
@ -729,8 +774,8 @@ bool Phase::addSpecies(shared_ptr<Species> spec) {
|
|||
}
|
||||
|
||||
m_speciesNames.push_back(spec->name);
|
||||
m_species[toLowerCopy(spec->name)] = spec;
|
||||
m_speciesIndices[toLowerCopy(spec->name)] = m_kk;
|
||||
m_species[spec->name] = spec;
|
||||
m_speciesIndices[spec->name] = m_kk;
|
||||
m_speciesCharge.push_back(spec->charge);
|
||||
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 '{}'",
|
||||
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) {
|
||||
throw CanteraError("Phase::modifySpecies",
|
||||
"New composition for '{}' does not match existing composition",
|
||||
spec->name);
|
||||
}
|
||||
m_species[toLowerCopy(spec->name)] = spec;
|
||||
m_species[spec->name] = spec;
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
//! @deprecated To be removed after Cantera 2.5.
|
||||
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
|
||||
{
|
||||
return species(m_speciesNames[k]);
|
||||
return m_species.at(m_speciesNames[k]);
|
||||
}
|
||||
|
||||
void Phase::ignoreUndefinedElements() {
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ void GasTransport::setupCollisionIntegral()
|
|||
void GasTransport::getTransportData()
|
||||
{
|
||||
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 =
|
||||
dynamic_cast<GasTransportData*>(s->transport.get());
|
||||
if (!sptran) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue