diff --git a/include/cantera/thermo/Phase.h b/include/cantera/thermo/Phase.h index d6f3a678121..a6427b108ab 100644 --- a/include/cantera/thermo/Phase.h +++ b/include/cantera/thermo/Phase.h @@ -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 @@ -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 @@ -747,6 +749,11 @@ class Phase //! change in state is detected virtual void invalidateCache(); + //! 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. /*! @@ -848,6 +855,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 2b21ce6e1d4..a1b6da7a69d 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 e9c25a7b563..84a6241e92f 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -941,8 +941,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 4bb8dcb57ff..7a271593895 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 42f882bb404..b96107ee1f3 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 ca315513a46..45b8c4b4d04 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -15,9 +15,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' @@ -308,18 +308,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) @@ -854,7 +850,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 2513ac27502..c21bdc59a65 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -284,16 +284,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. @@ -303,7 +293,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 880bdfae9b1..6f2e78732c3 100644 --- a/src/thermo/Phase.cpp +++ b/src/thermo/Phase.cpp @@ -4,12 +4,13 @@ */ // 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" #include "cantera/base/stringUtils.h" #include "cantera/base/ctml.h" +#include "cantera/base/Base.h" #include "cantera/thermo/ThermoFactory.h" using namespace std; @@ -77,12 +78,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 0f634757997..ce36b7b1bb1 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__"]; }