[Python] Add ability to instantiate objects from YAML files
This commit is contained in:
parent
8a0eed3be5
commit
59b0f64e26
3 changed files with 84 additions and 3 deletions
|
|
@ -5,6 +5,7 @@
|
|||
from libcpp.vector cimport vector
|
||||
from libcpp.string cimport string
|
||||
from libcpp.map cimport map as stdmap
|
||||
from libcpp.unordered_map cimport unordered_map
|
||||
from libcpp.pair cimport pair
|
||||
from libcpp cimport bool as cbool
|
||||
from cpython cimport bool as pybool
|
||||
|
|
@ -43,6 +44,21 @@ cdef extern from "cantera/base/xml.h" namespace "Cantera":
|
|||
XML_Node* findID(string)
|
||||
int nChildren()
|
||||
|
||||
cdef extern from "cantera/base/AnyMap.h" namespace "Cantera":
|
||||
cdef cppclass CxxAnyValue "Cantera::AnyValue"
|
||||
|
||||
cdef cppclass CxxAnyMap "Cantera::AnyMap":
|
||||
CxxAnyMap()
|
||||
CxxAnyValue& operator[](string) except +translate_exception
|
||||
string keys_str()
|
||||
|
||||
cdef cppclass CxxAnyValue "Cantera::AnyValue":
|
||||
CxxAnyValue()
|
||||
unordered_map[string, CxxAnyMap*] asMap(string) except +translate_exception
|
||||
|
||||
CxxAnyMap AnyMapFromYamlFile "Cantera::AnyMap::fromYamlFile" (string) except +translate_exception
|
||||
CxxAnyMap AnyMapFromYamlString "Cantera::AnyMap::fromYamlString" (string) except +translate_exception
|
||||
|
||||
cdef extern from "cantera/base/stringUtils.h" namespace "Cantera":
|
||||
cdef Composition parseCompString(string) except +translate_exception
|
||||
|
||||
|
|
@ -610,10 +626,12 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera":
|
|||
cdef extern from "cantera/thermo/ThermoFactory.h" namespace "Cantera":
|
||||
cdef CxxThermoPhase* newPhase(string, string) except +translate_exception
|
||||
cdef CxxThermoPhase* newPhase(XML_Node&) except +translate_exception
|
||||
cdef shared_ptr[CxxThermoPhase] newPhase(CxxAnyMap&, CxxAnyMap&) except +translate_exception
|
||||
cdef CxxThermoPhase* newThermoPhase(string) except +translate_exception
|
||||
|
||||
cdef extern from "cantera/kinetics/KineticsFactory.h" namespace "Cantera":
|
||||
cdef CxxKinetics* newKineticsMgr(XML_Node&, vector[CxxThermoPhase*]) except +translate_exception
|
||||
cdef shared_ptr[CxxKinetics] newKinetics(vector[CxxThermoPhase*], CxxAnyMap&, CxxAnyMap&) except +translate_exception
|
||||
cdef CxxKinetics* CxxNewKinetics "Cantera::newKineticsMgr" (string) except +translate_exception
|
||||
|
||||
cdef extern from "cantera/transport/TransportFactory.h" namespace "Cantera":
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
cdef class _SolutionBase:
|
||||
def __cinit__(self, infile='', phaseid='', phases=(), origin=None,
|
||||
source=None, thermo=None, species=(), kinetics=None,
|
||||
reactions=(), **kwargs):
|
||||
source=None, yaml=None, thermo=None, species=(),
|
||||
kinetics=None, reactions=(), **kwargs):
|
||||
# Shallow copy of an existing Solution (for slicing support)
|
||||
cdef _SolutionBase other
|
||||
if origin is not None:
|
||||
|
|
@ -21,7 +21,9 @@ cdef class _SolutionBase:
|
|||
self._selected_species = other._selected_species.copy()
|
||||
return
|
||||
|
||||
if infile or source:
|
||||
if infile.endswith('.yml') or infile.endswith('.yaml') or yaml:
|
||||
self._init_yaml(infile, phaseid, phases, yaml)
|
||||
elif infile or source:
|
||||
self._init_cti_xml(infile, phaseid, phases, source)
|
||||
elif thermo and species:
|
||||
self._init_parts(thermo, species, kinetics, phases, reactions)
|
||||
|
|
@ -37,6 +39,55 @@ cdef class _SolutionBase:
|
|||
if isinstance(self, Transport):
|
||||
assert self.transport is not NULL
|
||||
|
||||
def _init_yaml(self, infile, phaseid, phases, source):
|
||||
"""
|
||||
Instantiate a set of new Cantera C++ objects from a YAML
|
||||
phase definition
|
||||
"""
|
||||
cdef CxxAnyMap root
|
||||
if infile:
|
||||
root = AnyMapFromYamlFile(stringify(infile))
|
||||
elif source:
|
||||
root = AnyMapFromYamlString(stringify(source))
|
||||
|
||||
phaseNodes = root[stringify("phases")].asMap(stringify("name"))
|
||||
phaseNames = []
|
||||
for item in phaseNodes:
|
||||
phaseNames.append(pystr(item.first))
|
||||
|
||||
if not phaseNames:
|
||||
raise ValueError("YAML document doesn't contain any phase definitions")
|
||||
|
||||
if phaseid:
|
||||
if phaseid in phaseNames:
|
||||
phaseNode = phaseNodes[stringify(phaseid)]
|
||||
else:
|
||||
raise ValueError("YAML document doesn't contain"
|
||||
" a phase named '{}'".format(phaseid))
|
||||
else:
|
||||
phaseNode = phaseNodes[stringify(phaseNames[0])]
|
||||
|
||||
# Thermo
|
||||
if isinstance(self, ThermoPhase):
|
||||
self._thermo = newPhase(deref(phaseNode), root)
|
||||
self.thermo = self._thermo.get()
|
||||
else:
|
||||
self.thermo = NULL
|
||||
|
||||
# Kinetics
|
||||
cdef vector[CxxThermoPhase*] v
|
||||
cdef _SolutionBase phase
|
||||
|
||||
if isinstance(self, Kinetics):
|
||||
v.push_back(self.thermo)
|
||||
for phase in phases:
|
||||
# adjacent bulk phases for a surface phase
|
||||
v.push_back(phase.thermo)
|
||||
self._kinetics = newKinetics(v, deref(phaseNode), root)
|
||||
self.kinetics = self._kinetics.get()
|
||||
else:
|
||||
self.kinetics = NULL
|
||||
|
||||
def _init_cti_xml(self, infile, phaseid, phases, source):
|
||||
"""
|
||||
Instantiate a set of new Cantera C++ objects from a CTI or XML
|
||||
|
|
|
|||
|
|
@ -919,6 +919,18 @@ ideal_gas(name='spam', elements='O H',
|
|||
with self.assertRaisesRegex(ct.CanteraError, 'reaction is unbalanced'):
|
||||
ct.Solution('h2o2_unbalancedReaction.xml')
|
||||
|
||||
def test_yaml_ideal_gas_simple(self):
|
||||
gas = ct.ThermoPhase('ideal-gas.yaml', 'simple')
|
||||
self.check(gas, 'simple', 500, 10 * ct.one_atm, 3, 2)
|
||||
|
||||
def test_yaml_ideal_gas_remote_species(self):
|
||||
gas = ct.ThermoPhase('ideal-gas.yaml', 'species-remote')
|
||||
self.check(gas, 'species-remote', 300, ct.one_atm, 4, 2)
|
||||
|
||||
def test_yaml_duplicate(self):
|
||||
with self.assertRaisesRegex(ct.CanteraError, 'duplicate'):
|
||||
gas = ct.ThermoPhase('ideal-gas.yaml', 'duplicate-species')
|
||||
|
||||
|
||||
class TestSpecies(utilities.CanteraTest):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue