diff --git a/include/cantera/thermo/Phase.h b/include/cantera/thermo/Phase.h index 9f9c1d7ea..37ab5d5de 100644 --- a/include/cantera/thermo/Phase.h +++ b/include/cantera/thermo/Phase.h @@ -707,10 +707,6 @@ 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(const std::string& name) const; //! Return the Species object for species whose index is *k*. Changes to @@ -809,15 +805,15 @@ 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: + //! Find lowercase species name in m_speciesIndices when case sensitive + //! species names are not enforced and a user specifies a non-canonical + //! species name. Raise exception if lowercase name is not unique. + size_t findSpeciesLower(const std::string& nameStr) const; + XML_Node* m_xml; //!< XML node containing the XML info for this phase //! ID of the phase. This is the value of the ID attribute of the XML diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index eb46af930..d2fddd4fb 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -123,7 +123,7 @@ class TestThermoPhase(utilities.CanteraTest): self.assertEqual(list(X[0,:,0]), list(Y)) def test_setCompositionString(self): - self.phase.X = 'H2:1.0, O2:1.0' + self.phase.X = 'h2:1.0, o2:1.0' X = self.phase.X self.assertNear(X[0], 0.5) self.assertNear(X[3], 0.5) @@ -161,7 +161,7 @@ class TestThermoPhase(utilities.CanteraTest): self.assertNear(Y[3], 0.75) def test_getCompositionDict(self): - self.phase.X = 'OH:1e-9, O2:0.4, AR:0.6' + self.phase.X = 'oh:1e-9, O2:0.4, AR:0.6' self.assertEqual(len(self.phase.mole_fraction_dict(1e-7)), 2) self.assertEqual(len(self.phase.mole_fraction_dict()), 3) @@ -202,7 +202,7 @@ class TestThermoPhase(utilities.CanteraTest): self.phase.Y = {'H2':1.0, 'O2':'xx'} def test_setCompositionSlice(self): - self.phase['H2', 'O2'].X = 0.1, 0.9 + self.phase['h2', 'o2'].X = 0.1, 0.9 X = self.phase.X self.assertNear(X[0], 0.1) self.assertNear(X[3], 0.9) @@ -1257,7 +1257,7 @@ class TestMisc(utilities.CanteraTest): gas = ct.Solution('h2o2.xml') self.assertFalse(gas.case_sensitive_species_names) self.assertTrue(gas.species_index('h2') == 0) - + gas.case_sensitive_species_names = True self.assertTrue(gas.case_sensitive_species_names) with self.assertRaises(ValueError): diff --git a/src/thermo/Phase.cpp b/src/thermo/Phase.cpp index ffe01fe10..62fe85cd9 100644 --- a/src/thermo/Phase.cpp +++ b/src/thermo/Phase.cpp @@ -183,7 +183,9 @@ size_t Phase::findSpeciesLower(const std::string& name) const loc = k.second; } else { throw CanteraError("Phase::findSpeciesLower", - "Lowercase species name '{}' is not unique", nLower); + "Lowercase species name '{}' is not unique. " + "Set Phase::caseSensitiveSpecies to true to " + "enforce case sensitive species names", nLower); } } } @@ -193,23 +195,23 @@ size_t Phase::findSpeciesLower(const std::string& name) const size_t Phase::speciesIndex(const std::string& nameStr) const { size_t loc = npos; - try { - return m_speciesIndices.at(nameStr); - } catch (std::out_of_range&) { - if (!m_caseSensitiveSpecies) { - loc = findSpeciesLower(nameStr); - } + std::map::const_iterator it; + + it = m_speciesIndices.find(nameStr); + if (it != m_speciesIndices.end()) { + return it->second; + } else if (!m_caseSensitiveSpecies) { + loc = findSpeciesLower(nameStr); } if (loc == npos && nameStr.find(':') != npos) { std::string pn; std::string sn = parseSpeciesName(nameStr, pn); if (pn == "" || pn == m_name || pn == m_id) { - try { - return m_speciesIndices.at(sn); - } catch (std::out_of_range&) { - if (!m_caseSensitiveSpecies) { - return findSpeciesLower(sn); - } + it = m_speciesIndices.find(nameStr); + if (it != m_speciesIndices.end()) { + return it->second; + } else if (!m_caseSensitiveSpecies) { + return findSpeciesLower(sn); } } } @@ -320,20 +322,14 @@ void Phase::setMoleFractions_NoNorm(const doublereal* const x) void Phase::setMoleFractionsByName(const compositionMap& xMap) { vector_fp mf(m_kk, 0.0); + for (const auto& sp : xMap) { - try { - mf[m_speciesIndices.at(sp.first)] = sp.second; - } catch (std::out_of_range&) { - 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; - } + size_t loc = speciesIndex(sp.first); + if (loc != npos) { + mf[loc] = sp.second; + } else { + throw CanteraError("Phase::setMoleFractionsByName", + "Unknown species '{}'", sp.first); } } setMoleFractions(&mf[0]); @@ -743,7 +739,6 @@ size_t Phase::addElement(const std::string& symbol, doublereal weight, } bool Phase::addSpecies(shared_ptr spec) { - // species names are case sensitive if (m_species.find(spec->name) != m_species.end()) { throw CanteraError("Phase::addSpecies", "Phase '{}' already contains a species named '{}'.", @@ -849,13 +844,35 @@ void Phase::modifySpecies(size_t k, shared_ptr spec) invalidateCache(); } -//! @deprecated To be removed after Cantera 2.5. shared_ptr Phase::species(const std::string& name) const { - warn_deprecated("Phase::species(std::string&)", - "To be removed after Cantera 2.5. " - "Use Phase::species(size_t) instead."); - return m_species.at(name); + std::map >::const_iterator it; + + it = m_species.find(name); + if (it != m_species.end()) { + return it->second; + } else if (!m_caseSensitiveSpecies) { + std::string nLower = toLowerCopy(name); + bool found = false; + shared_ptr sp; + for (const auto& k : m_species) { + if (toLowerCopy(k.first) == nLower) { + if (!found) { + found = true; + sp = k.second; + } else { + throw CanteraError("Phase::species", + "Lowercase species name '{}' is not unique. " + "Set Phase::caseSensitiveSpecies to true to " + "enforce case sensitive species names", nLower); + } + } + } + return sp; + } else { + throw CanteraError("Phase::setMassFractionsByName", + "Unknown species '{}'", name); + } } shared_ptr Phase::species(size_t k) const diff --git a/src/thermo/RedlichKwongMFTP.cpp b/src/thermo/RedlichKwongMFTP.cpp index e389fe6f8..d79fc3334 100644 --- a/src/thermo/RedlichKwongMFTP.cpp +++ b/src/thermo/RedlichKwongMFTP.cpp @@ -710,8 +710,6 @@ vector RedlichKwongMFTP::getCoeff(const std::string& iName) // based on crit properties T_c and P_c: for (size_t isp = 0; isp < nDatabase; isp++) { XML_Node& acNodeDoc = doc->child(isp); - // not enforcing case sensitive species names as this is external - // to CTI or YAML input files std::string iNameLower = toLowerCopy(iName); std::string dbName = toLowerCopy(acNodeDoc.attrib("name")); diff --git a/test/thermo/ThermoPhase_Test.cpp b/test/thermo/ThermoPhase_Test.cpp index ad60e781e..21a64c86f 100644 --- a/test/thermo/ThermoPhase_Test.cpp +++ b/test/thermo/ThermoPhase_Test.cpp @@ -40,7 +40,7 @@ TEST_F(TestThermoMethods, getMoleFractionsByName) EXPECT_DOUBLE_EQ(X["H2"], 0.3); EXPECT_DOUBLE_EQ(X["AR"], 0.5); - thermo->setMoleFractionsByName("OH:1e-9, O2:0.2, H2:0.3, AR:0.5"); + thermo->setMoleFractionsByName("OH:1e-9, O2:0.2, h2:0.3, AR:0.5"); X = thermo->getMoleFractionsByName(); EXPECT_EQ(X.size(), (size_t) 4); diff --git a/test/thermo/phaseConstructors.cpp b/test/thermo/phaseConstructors.cpp index 2deea16eb..f9808be6e 100644 --- a/test/thermo/phaseConstructors.cpp +++ b/test/thermo/phaseConstructors.cpp @@ -299,7 +299,7 @@ TEST_F(ConstructFromScratch, addUndefinedElements) 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"))); + ASSERT_EQ((size_t) 2, p.nAtoms(p.speciesIndex("co2"), p.elementIndex("O"))); p.setMassFractionsByName("H2:0.5, CO2:0.5"); ASSERT_DOUBLE_EQ(0.5, p.massFraction("CO2")); }