From c4211a65b24d83f3559fa092139abbee0c3825b2 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Fri, 16 Aug 2019 16:39:12 -0500 Subject: [PATCH] [Base] remove redundant unique_name attribute * Resolve conflation of gas.ID and gas.name in unit tests * Also fixes #691 --- include/cantera/thermo/Phase.h | 10 ++++++++++ include/cantera/thermo/ThermoPhase.h | 12 +---------- interfaces/cython/cantera/_cantera.pxd | 2 +- interfaces/cython/cantera/base.pyx | 20 ++++++++++++------- .../cython/cantera/test/test_mixture.py | 5 +++-- interfaces/cython/cantera/test/test_thermo.py | 12 ++++------- interfaces/cython/cantera/thermo.pyx | 11 ---------- src/thermo/Phase.cpp | 15 ++++++++++++-- src/thermo/ThermoFactory.cpp | 1 + 9 files changed, 46 insertions(+), 42 deletions(-) diff --git a/include/cantera/thermo/Phase.h b/include/cantera/thermo/Phase.h index a82e69d784..289b3faba5 100644 --- a/include/cantera/thermo/Phase.h +++ b/include/cantera/thermo/Phase.h @@ -29,6 +29,8 @@ namespace Cantera * support thermodynamic calculations (see \ref thermoprops). */ +class SolutionBase; + //! Class Phase is the base class for phases of matter, managing the species and //! elements in a phase, as well as the independent variables of temperature, //! mass density, species mass/mole fraction, and other generalized forces and @@ -758,6 +760,11 @@ class Phase m_caseSensitiveSpecies = cflag; } + //! Set root SolutionBase holding all phase information + virtual void setRoot(std::shared_ptr root) { + m_root = root; + } + protected: //! Cached for saved calculations within each ThermoPhase. /*! @@ -870,6 +877,9 @@ class Phase //! Entropy at 298.15 K and 1 bar of stable state pure elements (J kmol-1) vector_fp m_entropy298; + + //! reference to SolutionBase + std::weak_ptr m_root; }; } diff --git a/include/cantera/thermo/ThermoPhase.h b/include/cantera/thermo/ThermoPhase.h index 2b21ce6e1d..a1b6da7a69 100644 --- a/include/cantera/thermo/ThermoPhase.h +++ b/include/cantera/thermo/ThermoPhase.h @@ -6,7 +6,7 @@ */ // This file is part of Cantera. See License.txt in the top-level directory or -// at https://cantera.org/license.txt for license and copyright information. +// at http://www.cantera.org/license.txt for license and copyright information. #ifndef CT_THERMOPHASE_H #define CT_THERMOPHASE_H @@ -40,8 +40,6 @@ const int cSS_CONVENTION_VPSS = 1; const int cSS_CONVENTION_SLAVE = 2; //@} -class SolutionBase; - //! Base class for a phase with thermodynamic properties. /*! * Class ThermoPhase is the base class for the family of classes that represent @@ -1618,11 +1616,6 @@ class ThermoPhase : public Phase //@} - //! Set root SolutionBase holding all phase information - virtual void setRoot(std::shared_ptr root) { - m_root = root; - } - protected: //! Fills `names` and `data` with the column names and species thermo //! properties to be included in the output of the reportCSV method. @@ -1667,9 +1660,6 @@ class ThermoPhase : public Phase //! last value of the temperature processed by reference state mutable doublereal m_tlast; - - //! reference to SolutionBase - std::weak_ptr m_root; }; //! typedef for the ThermoPhase class diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index ff576b20ef..fa93cc36e4 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -943,8 +943,8 @@ cdef class GasTransportData: cdef _assign(self, shared_ptr[CxxTransportData] other) cdef class _SolutionBase: - cdef CxxSolutionBase* base cdef shared_ptr[CxxSolutionBase] _base + cdef CxxSolutionBase* base cdef shared_ptr[CxxThermoPhase] _thermo cdef CxxThermoPhase* thermo cdef shared_ptr[CxxKinetics] _kinetics diff --git a/interfaces/cython/cantera/base.pyx b/interfaces/cython/cantera/base.pyx index 4bb8dcb57f..7a27159389 100644 --- a/interfaces/cython/cantera/base.pyx +++ b/interfaces/cython/cantera/base.pyx @@ -60,22 +60,28 @@ cdef class _SolutionBase: else: raise ValueError('Missing required keyword `base_type`.') - phasename = pystr(self.thermo.name()) + phase_name = pystr(self.thermo.id()) name = kwargs.get('name', None) if name is not None: - self.unique_name = name + self.name = name + elif phase_name in _phase_counts: + _phase_counts[phase_name] += 1 + n = _phase_counts[phase_name] + self.name = '{0}_{1}'.format(phase_name, n) else: - _phase_counts[phasename] += 1 - n = _phase_counts[phasename] - self.unique_name = '{0}_{1}'.format(phasename, n) + _phase_counts[phase_name] = 0 + self.name = phase_name property type: """The type of the SolutionBase object.""" def __get__(self): return pystr(self.base.type()) - property unique_name: - """The unique name of the SolutionBase object.""" + property name: + """ + The name assigned to this SolutionBase object. The default is + taken from the CTI/XML/YAML input file. + """ def __get__(self): return pystr(self.base.name()) diff --git a/interfaces/cython/cantera/test/test_mixture.py b/interfaces/cython/cantera/test/test_mixture.py index 42f882bb40..b96107ee1f 100644 --- a/interfaces/cython/cantera/test/test_mixture.py +++ b/interfaces/cython/cantera/test/test_mixture.py @@ -112,10 +112,11 @@ def test_charge(self): def test_phase_moles(self): M = self.mix.phase_moles() + name = self.phase2.name self.assertEqual(M[0], self.mix.phase_moles(0)) - self.assertEqual(M[1], self.mix.phase_moles('air')) + self.assertEqual(M[1], self.mix.phase_moles(name)) - self.mix.set_phase_moles('air', 4) + self.mix.set_phase_moles(name, 4) self.assertEqual(self.mix.phase_moles(1), 4) def test_species_moles(self): diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index 73ae716669..3c319ab5d7 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -16,9 +16,9 @@ def setUp(self): def test_cpp_attributes(self): self.assertTrue(isinstance(self.phase.type, str)) self.assertTrue(self.phase.type=='Solution') - self.assertTrue(isinstance(self.phase.unique_name, str)) - self.phase.unique_name = 'spam' - self.assertTrue(self.phase.unique_name=='spam') + self.assertTrue(isinstance(self.phase.name, str)) + self.phase.name = 'spam' + self.assertTrue(self.phase.name=='spam') with self.assertRaises(AttributeError): self.phase.type = 'eggs' @@ -309,18 +309,14 @@ def test_default_report(self): self.assertNotIn(name, report) def test_name(self): - self.assertEqual(self.phase.name, 'ohmech') - self.phase.name = 'something' self.assertEqual(self.phase.name, 'something') self.assertIn('something', self.phase.report()) def test_ID(self): self.assertEqual(self.phase.ID, 'ohmech') - self.phase.ID = 'something' self.assertEqual(self.phase.ID, 'something') - self.assertEqual(self.phase.name, 'ohmech') def test_badLength(self): X = np.zeros(5) @@ -855,7 +851,7 @@ class ImportTest(utilities.CanteraTest): Test the various ways of creating a Solution object """ def check(self, gas, name, T, P, nSpec, nElem): - self.assertEqual(gas.name, name) + self.assertEqual(gas.ID, name) self.assertNear(gas.T, T) self.assertNear(gas.P, P) self.assertEqual(gas.n_species, nSpec) diff --git a/interfaces/cython/cantera/thermo.pyx b/interfaces/cython/cantera/thermo.pyx index b61b3d6247..a3f0b1cf67 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -285,16 +285,6 @@ cdef class ThermoPhase(_SolutionBase): def __call__(self, *args, **kwargs): print(self.report(*args, **kwargs)) - property name: - """ - The name assigned to this phase. The default is taken from the CTI/XML - input file. - """ - def __get__(self): - return pystr(self.thermo.name()) - def __set__(self, name): - self.thermo.setName(stringify(name)) - property ID: """ The ID of the phase. The default is taken from the CTI/XML input file. @@ -304,7 +294,6 @@ cdef class ThermoPhase(_SolutionBase): def __set__(self, id_): self.thermo.setID(stringify(id_)) - property basis: """ Determines whether intensive thermodynamic properties are treated on a diff --git a/src/thermo/Phase.cpp b/src/thermo/Phase.cpp index 85798d5ec8..fc21d66ead 100644 --- a/src/thermo/Phase.cpp +++ b/src/thermo/Phase.cpp @@ -10,6 +10,7 @@ #include "cantera/base/utilities.h" #include "cantera/base/stringUtils.h" #include "cantera/base/ctml.h" +#include "cantera/base/Base.h" #include "cantera/thermo/ThermoFactory.h" using namespace std; @@ -78,12 +79,22 @@ void Phase::setID(const std::string& id_) std::string Phase::name() const { - return m_name; + if (m_root.expired()) { + return m_name; + } else { + auto root = m_root.lock(); + return root->name(); + } } void Phase::setName(const std::string& nm) { - m_name = nm; + if (m_root.expired()) { + m_name = nm; + } else { + auto root = m_root.lock(); + root->setName(nm); + } } size_t Phase::nElements() const diff --git a/src/thermo/ThermoFactory.cpp b/src/thermo/ThermoFactory.cpp index 387b47ccbe..239c4af6a3 100644 --- a/src/thermo/ThermoFactory.cpp +++ b/src/thermo/ThermoFactory.cpp @@ -448,6 +448,7 @@ void addSpecies(ThermoPhase& thermo, const AnyValue& names, const AnyValue& spec void setupPhase(ThermoPhase& thermo, AnyMap& phaseNode, const AnyMap& rootNode) { thermo.setName(phaseNode["name"].asString()); + thermo.setID(phaseNode["name"].asString()); if (rootNode.hasKey("__file__")) { phaseNode["__file__"] = rootNode["__file__"]; }