From 6e5d45273a4b02375a676114291c08cd5524a382 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Wed, 9 Oct 2019 19:01:43 -0500 Subject: [PATCH] [Thermo] replace 'phase_id' by 'name' * 'name' corresponds to the YAML entry * rename Solution keyword 'phaseid' to 'name' (instead of 'phase_id') * rename ck2yaml argument '--id' to '--name' (instead of '--phase-id') * ensure that C++ Phase::m_id is always the same as Phase::m_name --- include/cantera/base/Solution.h | 2 -- interfaces/cython/cantera/_cantera.pxd | 2 -- interfaces/cython/cantera/base.pyx | 36 ++++++++----------- interfaces/cython/cantera/ck2yaml.py | 10 +++--- interfaces/cython/cantera/composite.py | 23 ++++++------ interfaces/cython/cantera/kinetics.pyx | 4 +-- .../cython/cantera/test/test_convert.py | 32 ++++++++--------- .../cython/cantera/test/test_reactor.py | 4 +-- interfaces/cython/cantera/test/test_thermo.py | 8 ++--- interfaces/cython/cantera/thermo.pyx | 24 ++++--------- src/base/Solution.cpp | 28 ++++++++++----- src/thermo/Phase.cpp | 17 +++------ 12 files changed, 83 insertions(+), 107 deletions(-) diff --git a/include/cantera/base/Solution.h b/include/cantera/base/Solution.h index 37141cc4d..50c8979e3 100644 --- a/include/cantera/base/Solution.h +++ b/include/cantera/base/Solution.h @@ -64,8 +64,6 @@ protected: shared_ptr m_thermo; //! ThermoPhase manager shared_ptr m_kinetics; //! Kinetics manager shared_ptr m_transport; //! Transport manager - - std::string m_name; //! name of Solution object }; } diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index 827b4acf2..02a1fb121 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -140,8 +140,6 @@ cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera": # miscellaneous string type() string report(cbool, double) except +translate_exception - string id() - void setID(string) double minTemp() except +translate_exception double maxTemp() except +translate_exception double refPressure() except +translate_exception diff --git a/interfaces/cython/cantera/base.pyx b/interfaces/cython/cantera/base.pyx index 76db56e51..3609ba25a 100644 --- a/interfaces/cython/cantera/base.pyx +++ b/interfaces/cython/cantera/base.pyx @@ -3,20 +3,18 @@ from collections import defaultdict as _defaultdict -_phase_counts = _defaultdict(int) - cdef class _SolutionBase: - def __cinit__(self, infile='', phase_id='', adjacent=(), origin=None, + def __cinit__(self, infile='', name='', adjacent=(), origin=None, source=None, yaml=None, thermo=None, species=(), kinetics=None, reactions=(), **kwargs): if 'phaseid' in kwargs: - if phase_id is not '': + if name is not '': raise AttributeError('duplicate specification of phase name') - warnings.warn("Keyword 'phase_id' replaces 'phaseid'", + warnings.warn("Keyword 'name' replaces 'phaseid'", FutureWarning) - phase_id = kwargs['phaseid'] + name = kwargs['phaseid'] if 'phases' in kwargs: if len(adjacent)>0: @@ -54,9 +52,9 @@ cdef class _SolutionBase: # Parse inputs if infile.endswith('.yml') or infile.endswith('.yaml') or yaml: - self._init_yaml(infile, phase_id, adjacent, yaml) + self._init_yaml(infile, name, adjacent, yaml) elif infile or source: - self._init_cti_xml(infile, phase_id, adjacent, source) + self._init_cti_xml(infile, name, adjacent, source) elif thermo and species: self._init_parts(thermo, species, kinetics, adjacent, reactions) else: @@ -72,23 +70,17 @@ cdef class _SolutionBase: if isinstance(self, Transport): assert self.transport is not NULL - phase_name = pystr(self.thermo.id()) + phase_name = pystr(self.base.name()) name = kwargs.get('name') if name is not None: 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[phase_name] = 0 self.name = phase_name property name: """ - The name assigned to this SolutionBase object. The default value - is based on the phase identifier in the CTI/XML/YAML input file; - a numbered suffix is added if needed to create a unique name. + The name assigned to this object. The default value corresponds + to the CTI/XML/YAML input file phase entry. """ def __get__(self): return pystr(self.base.name()) @@ -111,7 +103,7 @@ cdef class _SolutionBase: return thermo, kinetics, transport - def _init_yaml(self, infile, phase_id, adjacent, source): + def _init_yaml(self, infile, name, adjacent, source): """ Instantiate a set of new Cantera C++ objects from a YAML phase definition @@ -123,7 +115,7 @@ cdef class _SolutionBase: root = AnyMapFromYamlString(stringify(source)) phaseNode = root[stringify("phases")].getMapWhere(stringify("name"), - stringify(phase_id)) + stringify(name)) # Thermo if isinstance(self, ThermoPhase): @@ -146,7 +138,7 @@ cdef class _SolutionBase: else: self.kinetics = NULL - def _init_cti_xml(self, infile, phase_id, adjacent, source): + def _init_cti_xml(self, infile, name, adjacent, source): """ Instantiate a set of new Cantera C++ objects from a CTI or XML phase definition @@ -158,8 +150,8 @@ cdef class _SolutionBase: # Get XML data cdef XML_Node* phaseNode - if phase_id: - phaseNode = rootNode.findID(stringify(phase_id)) + if name: + phaseNode = rootNode.findID(stringify(name)) else: phaseNode = rootNode.findByName(stringify('phase')) if phaseNode is NULL: diff --git a/interfaces/cython/cantera/ck2yaml.py b/interfaces/cython/cantera/ck2yaml.py index 1ffe5a3c7..39df856bf 100644 --- a/interfaces/cython/cantera/ck2yaml.py +++ b/interfaces/cython/cantera/ck2yaml.py @@ -12,7 +12,7 @@ Usage: [--thermo=] [--transport=] [--surface=] - [--phase-id=] + [--name=] [--output=] [--permissive] [-d | --debug] @@ -32,7 +32,7 @@ specified as 'input' and the surface phase input file should be specified as 'surface'. The '--permissive' option allows certain recoverable parsing errors (e.g. -duplicate transport data) to be ignored. The '--phase-id=' option +duplicate transport data) to be ignored. The '--name=' option is used to override default phase names (i.e. 'gas'). """ @@ -2025,7 +2025,7 @@ def convert_mech(input_file, thermo_file=None, transport_file=None, surface_file def main(argv): - longOptions = ['input=', 'thermo=', 'transport=', 'surface=', 'phase-id=', + longOptions = ['input=', 'thermo=', 'transport=', 'surface=', 'name=', 'output=', 'permissive', 'help', 'debug', 'quiet', 'no-validate', 'id='] @@ -2059,9 +2059,9 @@ def main(argv): if '--id' in options: phase_name = options.get('--id', 'gas') logging.warning("\nFutureWarning: " - "option '--id=...' is superseded by '--phase-id=...'") + "option '--id=...' is superseded by '--name=...'") else: - phase_name = options.get('--phase-id', 'gas') + phase_name = options.get('--name', 'gas') if not input_file and not thermo_file: print('At least one of the arguments "--input=..." or "--thermo=..."' diff --git a/interfaces/cython/cantera/composite.py b/interfaces/cython/cantera/composite.py index 01515e671..191d1d2ea 100644 --- a/interfaces/cython/cantera/composite.py +++ b/interfaces/cython/cantera/composite.py @@ -33,19 +33,16 @@ class Solution(ThermoPhase, Kinetics, Transport): If an input file defines multiple phases, the corresponding key in the *phases* map (in YAML), *name* (in CTI), or *id* (in XML) can be used - to specify the desired phase via the ``phase_id`` keyword argument of + to specify the desired phase via the ``name`` keyword argument of the constructor:: - gas = ct.Solution('diamond.yaml', phase_id='gas') - diamond = ct.Solution('diamond.yaml', phase_id='diamond') + gas = ct.Solution('diamond.yaml', name='gas') + diamond = ct.Solution('diamond.yaml', name='diamond') - The name of the `Solution` object needs to be unique and defaults to the - *phase* specified in the input file. If another object using the same - constituting information already exists, the name is automatically appended - by a suffix. A custom name can be set via the ``name`` keyword argument of - the constructor, i.e.:: + The name of the `Solution` object defaults to the *phase* specified in the + input file. Once instatiated, a custom name can assigned via:: - gas = ct.Solution('gri30.yaml', name='my_custom_name') + gas.name = 'my_custom_name' `Solution` objects can also be constructed using `Species` and `Reaction` objects which can themselves either be imported from input files or defined @@ -54,7 +51,7 @@ class Solution(ThermoPhase, Kinetics, Transport): spec = ct.Species.listFromFile('gri30.yaml') rxns = ct.Reaction.listFromFile('gri30.yaml') gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', - species=spec, reactions=rxns) + species=spec, reactions=rxns, name='my_custom_name') where the ``thermo`` and ``kinetics`` keyword arguments are strings specifying the thermodynamic and kinetics model, respectively, and @@ -99,9 +96,9 @@ class Interface(InterfacePhase, InterfaceKinetics): in reactions need to be created and then passed in as a list in the ``adjacent`` argument to the constructor:: - gas = ct.Solution('diamond.yaml', phase_id='gas') - diamond = ct.Solution('diamond.yaml', phase_id='diamond') - diamond_surf = ct.Interface('diamond.yaml', phase_id='diamond_100', + gas = ct.Solution('diamond.yaml', name='gas') + diamond = ct.Solution('diamond.yaml', name='diamond') + diamond_surf = ct.Interface('diamond.yaml', name='diamond_100', adjacent=[gas, diamond]) """ __slots__ = ('_phase_indices',) diff --git a/interfaces/cython/cantera/kinetics.pyx b/interfaces/cython/cantera/kinetics.pyx index b16c9690a..05ddf9fdf 100644 --- a/interfaces/cython/cantera/kinetics.pyx +++ b/interfaces/cython/cantera/kinetics.pyx @@ -371,8 +371,8 @@ cdef class InterfaceKinetics(Kinetics): A kinetics manager for heterogeneous reaction mechanisms. The reactions are assumed to occur at an interface between bulk phases. """ - def __init__(self, infile='', phase_id='', adjacent=(), *args, **kwargs): - super().__init__(infile, phase_id, adjacent, *args, **kwargs) + def __init__(self, infile='', name='', adjacent=(), *args, **kwargs): + super().__init__(infile, name, adjacent, *args, **kwargs) if pystr(self.kinetics.kineticsType()) not in ("Surf", "Edge"): raise TypeError("Underlying Kinetics class is not of the correct type.") diff --git a/interfaces/cython/cantera/test/test_convert.py b/interfaces/cython/cantera/test/test_convert.py index d101ba38e..0d5c7707e 100644 --- a/interfaces/cython/cantera/test/test_convert.py +++ b/interfaces/cython/cantera/test/test_convert.py @@ -660,7 +660,7 @@ class cti2yamlTest(utilities.CanteraTest): Path(self.test_work_dir).joinpath('ptcombust.yaml')) ctiGas, yamlGas = self.checkConversion('ptcombust') ctiSurf, yamlSurf = self.checkConversion('ptcombust', ct.Interface, - phase_id='Pt_surf', ctiphases=[ctiGas], yamlphases=[yamlGas]) + name='Pt_surf', ctiphases=[ctiGas], yamlphases=[yamlGas]) self.checkKinetics(ctiGas, yamlGas, [500, 1200], [1e4, 3e5]) self.checkThermo(ctiSurf, yamlSurf, [400, 800, 1600]) @@ -670,16 +670,16 @@ class cti2yamlTest(utilities.CanteraTest): cti2yaml.convert(Path(self.cantera_data).joinpath('sofc.cti'), Path(self.test_work_dir).joinpath('sofc.yaml')) ctiGas, yamlGas = self.checkConversion('sofc') - ctiMetal, yamlMetal = self.checkConversion('sofc', phase_id='metal') - ctiOxide, yamlOxide = self.checkConversion('sofc', phase_id='oxide_bulk') + ctiMetal, yamlMetal = self.checkConversion('sofc', name='metal') + ctiOxide, yamlOxide = self.checkConversion('sofc', name='oxide_bulk') ctiMSurf, yamlMSurf = self.checkConversion('sofc', ct.Interface, - phase_id='metal_surface', ctiphases=[ctiGas, ctiMetal], + name='metal_surface', ctiphases=[ctiGas, ctiMetal], yamlphases=[yamlGas, yamlMetal]) ctiOSurf, yamlOSurf = self.checkConversion('sofc', ct.Interface, - phase_id='oxide_surface', ctiphases=[ctiGas, ctiOxide], + name='oxide_surface', ctiphases=[ctiGas, ctiOxide], yamlphases=[yamlGas, yamlOxide]) cti_tpb, yaml_tpb = self.checkConversion('sofc', ct.Interface, - phase_id='tpb', ctiphases=[ctiMetal, ctiMSurf, ctiOSurf], + name='tpb', ctiphases=[ctiMetal, ctiMSurf, ctiOSurf], yamlphases=[yamlMetal, yamlMSurf, yamlOSurf]) self.checkThermo(ctiMSurf, yamlMSurf, [900, 1000, 1100]) @@ -694,7 +694,7 @@ class cti2yamlTest(utilities.CanteraTest): Path(self.test_work_dir).joinpath('liquidvapor.yaml')) for name in ['water', 'nitrogen', 'methane', 'hydrogen', 'oxygen', 'hfc134a', 'carbondioxide', 'heptane']: - ctiPhase, yamlPhase = self.checkConversion('liquidvapor', phase_id=name) + ctiPhase, yamlPhase = self.checkConversion('liquidvapor', name=name) self.checkThermo(ctiPhase, yamlPhase, [1.3 * ctiPhase.min_temp, 0.7 * ctiPhase.max_temp]) @@ -717,10 +717,10 @@ class cti2yamlTest(utilities.CanteraTest): def test_diamond(self): cti2yaml.convert(Path(self.cantera_data).joinpath('diamond.cti'), Path(self.test_work_dir).joinpath('diamond.yaml')) - ctiGas, yamlGas = self.checkConversion('diamond', phase_id='gas') - ctiSolid, yamlSolid = self.checkConversion('diamond', phase_id='diamond') + ctiGas, yamlGas = self.checkConversion('diamond', name='gas') + ctiSolid, yamlSolid = self.checkConversion('diamond', name='diamond') ctiSurf, yamlSurf = self.checkConversion('diamond', - ct.Interface, phase_id='diamond_100', ctiphases=[ctiGas, ctiSolid], + ct.Interface, name='diamond_100', ctiphases=[ctiGas, ctiSolid], yamlphases=[yamlGas, yamlSolid]) self.checkThermo(ctiSolid, yamlSolid, [300, 500]) self.checkThermo(ctiSurf, yamlSurf, [330, 490]) @@ -730,16 +730,16 @@ class cti2yamlTest(utilities.CanteraTest): cti2yaml.convert(Path(self.cantera_data).joinpath('lithium_ion_battery.cti'), Path(self.test_work_dir).joinpath('lithium_ion_battery.yaml')) name = 'lithium_ion_battery' - ctiAnode, yamlAnode = self.checkConversion(name, phase_id='anode') - ctiCathode, yamlCathode = self.checkConversion(name, phase_id='cathode') - ctiMetal, yamlMetal = self.checkConversion(name, phase_id='electron') - ctiElyt, yamlElyt = self.checkConversion(name, phase_id='electrolyte') + ctiAnode, yamlAnode = self.checkConversion(name, name='anode') + ctiCathode, yamlCathode = self.checkConversion(name, name='cathode') + ctiMetal, yamlMetal = self.checkConversion(name, name='electron') + ctiElyt, yamlElyt = self.checkConversion(name, name='electrolyte') ctiAnodeInt, yamlAnodeInt = self.checkConversion(name, - phase_id='edge_anode_electrolyte', + name='edge_anode_electrolyte', ctiphases=[ctiAnode, ctiMetal, ctiElyt], yamlphases=[yamlAnode, yamlMetal, yamlElyt]) ctiCathodeInt, yamlCathodeInt = self.checkConversion(name, - phase_id='edge_cathode_electrolyte', + name='edge_cathode_electrolyte', ctiphases=[ctiCathode, ctiMetal, ctiElyt], yamlphases=[yamlCathode, yamlMetal, yamlElyt]) diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index c8425d990..71cc77634 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -929,9 +929,9 @@ class TestConstPressureReactor(utilities.CanteraTest): self.gas.TPX = 900, 25*ct.one_atm, 'CO:0.5, H2O:0.2' self.gas1 = ct.Solution('gri30.xml') - self.gas1.phase_id = 'gas' + self.gas1.name = 'gas' self.gas2 = ct.Solution('gri30.xml') - self.gas2.phase_id = 'gas' + self.gas2.name = 'gas' resGas = ct.Solution('gri30.xml') solid = ct.Solution('diamond.xml', 'diamond') diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index c9d947580..467c511b7 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -323,7 +323,7 @@ class TestThermoPhase(utilities.CanteraTest): self.assertIn('something', self.phase.report()) def test_phase(self): - self.assertEqual(self.phase.phase_id, 'ohmech') + self.assertEqual(self.phase.name, 'ohmech') warnings.simplefilter("always") with warnings.catch_warnings(record=True) as w: @@ -335,7 +335,7 @@ class TestThermoPhase(utilities.CanteraTest): with warnings.catch_warnings(record=True) as w: self.phase.ID = 'something' - self.assertEqual(self.phase.phase_id, 'something') + self.assertEqual(self.phase.name, 'something') self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) self.assertIn("To be removed after Cantera 2.5. ", @@ -345,7 +345,7 @@ class TestThermoPhase(utilities.CanteraTest): gas = ct.Solution('h2o2.cti', phaseid='ohmech') self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, FutureWarning)) - self.assertIn("Keyword 'phase_id' replaces 'phaseid'", + self.assertIn("Keyword 'name' replaces 'phaseid'", str(w[-1].message)) def test_badLength(self): @@ -881,7 +881,7 @@ class ImportTest(utilities.CanteraTest): Test the various ways of creating a Solution object """ def check(self, gas, phase, T, P, nSpec, nElem): - self.assertEqual(gas.phase_id, phase) + self.assertEqual(gas.name, phase) 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 7389d5a82..aa5dad5eb 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -290,36 +290,24 @@ cdef class ThermoPhase(_SolutionBase): def __call__(self, *args, **kwargs): print(self.report(*args, **kwargs)) - property phase_id: - """ - The identifier of the object. The default value corresponds to the - CTI/XML/YAML input file phase entry, and should remain unchanged. - """ - def __get__(self): - return pystr(self.thermo.id()) - def __set__(self, phase_id): - # may consider removing/deprecating, but resetting of the phase name - # is required to associate surface kinetics (with phase name being 'gas') - self.thermo.setID(stringify(phase_id)) - property ID: """ The identifier of the object. The default value corresponds to the - CTI/XML/YAML input file phase entry, and should remain unchanged. + CTI/XML/YAML input file phase entry. .. deprecated:: 2.5 To be deprecated with version 2.5, and removed thereafter. - Renamed to `phase_ID`. + Usage merged with `name`. """ def __get__(self): warnings.warn("To be removed after Cantera 2.5. " - "Use 'phase' attribute instead", DeprecationWarning) - return pystr(self.thermo.id()) + "Use 'name' attribute instead", DeprecationWarning) + return pystr(self.base.name()) def __set__(self, id_): warnings.warn("To be removed after Cantera 2.5. " - "Use 'phase' attribute instead", DeprecationWarning) - self.thermo.setID(stringify(id_)) + "Use 'name' attribute instead", DeprecationWarning) + self.base.setName(stringify(id_)) property basis: """ diff --git a/src/base/Solution.cpp b/src/base/Solution.cpp index 51099a186..85e0f1877 100644 --- a/src/base/Solution.cpp +++ b/src/base/Solution.cpp @@ -1,4 +1,7 @@ -//! @file Solution.cpp +/** + * @file Solution.cpp + * Definition file for class Solution. + */ // 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. @@ -11,16 +14,24 @@ namespace Cantera { -Solution::Solution() : - m_name("") -{} +Solution::Solution() {} std::string Solution::name() const { - return m_name; + if (m_thermo) { + return m_thermo->name(); + } else { + throw CanteraError("Solution::name()", + "Requires associated 'ThermoPhase'"); + } } -void Solution::setName(const std::string& name){ - m_name = name; +void Solution::setName(const std::string& name) { + if (m_thermo) { + m_thermo->setName(name); + } else { + throw CanteraError("Solution::setName()", + "Requires associated 'ThermoPhase'"); + } } void Solution::setThermoPhase(shared_ptr thermo) { @@ -43,4 +54,5 @@ void Solution::setTransport(shared_ptr transport) { m_transport->setRoot(shared_from_this()); } } -} + +} // namespace Cantera diff --git a/src/thermo/Phase.cpp b/src/thermo/Phase.cpp index 202f33b43..f1ef31a9a 100644 --- a/src/thermo/Phase.cpp +++ b/src/thermo/Phase.cpp @@ -9,7 +9,6 @@ #include "cantera/thermo/Phase.h" #include "cantera/base/utilities.h" #include "cantera/base/stringUtils.h" -#include "cantera/base/Solution.h" #include "cantera/base/ctml.h" #include "cantera/thermo/ThermoFactory.h" @@ -75,26 +74,18 @@ std::string Phase::id() const void Phase::setID(const std::string& id_) { m_id = id_; + m_name = id_; } std::string Phase::name() const { - auto root = m_root.lock(); - if (root) { - return root->name(); - } else { - return m_name; - } + return m_name; } void Phase::setName(const std::string& name) { - auto root = m_root.lock(); - if (root) { - root->setName(name); - } else { - m_name = name; - } + m_name = name; + m_id = name; } size_t Phase::nElements() const