Skip to content

Commit

Permalink
[Python] Add unit handling to AnyMap
Browse files Browse the repository at this point in the history
  • Loading branch information
speth authored and ischoegl committed Apr 18, 2023
1 parent c2863ce commit 6c45457
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
26 changes: 26 additions & 0 deletions interfaces/cython/cantera/_utils.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,26 @@ cdef class AnyMap(dict):
def default_units(self):
return self.unitsystem.defaults()

@property
def units(self):
"""Get the `UnitSystem` applicable to this `AnyMap`."""
return self.unitsystem

def convert(self, str key, dest):
"""
Convert the value corresponding to the specified *key* to the units defined by
*dest*. *dest* may be a string or a `Units` object.
"""
return self.unitsystem.convert_to(self[key], dest)

def convert_activation_energy(self, key, dest):
"""
Convert the value corresponding to the specified *key* to the units defined by
*dest*. *dest* may be a string or a `Units` object defining units that are
interpretable as an activation energy.
"""
return self.unitsystem.convert_activation_energy_to(self[key], dest)


cdef anyvalue_to_python(string name, CxxAnyValue& v):
cdef CxxAnyMap a
Expand Down Expand Up @@ -240,6 +260,7 @@ cdef CxxAnyMap py_to_anymap(data, cbool hyphenize=False) except *:

for k, v in data.items():
m[stringify(k)] = python_to_anyvalue(v, k)
m.applyUnits()
return m

cdef get_types(item):
Expand Down Expand Up @@ -446,3 +467,8 @@ def _py_to_any_to_py(dd):
cdef string name = stringify("test")
cdef CxxAnyValue vv = python_to_anyvalue(dd)
return anyvalue_to_python(name, vv), pystr(vv.type_str())

def _py_to_anymap_to_py(pp):
# used for internal testing purposes only
cdef CxxAnyMap m = py_to_anymap(pp)
return anymap_to_py(m)
34 changes: 33 additions & 1 deletion test/python/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import cantera as ct
from . import utilities

from cantera._utils import _py_to_any_to_py
from cantera._utils import _py_to_any_to_py, _py_to_anymap_to_py


class TestUnitSystem(utilities.CanteraTest):
Expand Down Expand Up @@ -239,3 +239,35 @@ def test_unconvertible(self):

def test_unconvertible2(self):
self.check_raises([3+4j, 1-2j], ct.CanteraError, "Unable to convert")


class TestAnyMap(utilities.CanteraTest):
@classmethod
def setup_class(cls):
data = {
"units": {"length": "mm", "energy": "kJ"},
"group1": {
"a": 5000,
"b": "12 MJ",
"c": "8000 K",
"d": [16, "10 cm^2"]
},
"group2": {
"units": {"mass": "g"},
"x": 1300
}
}
cls.data = _py_to_anymap_to_py(data)

def test_units_simple(self):
assert self.data['group1'].convert('a', 'm') == 5.0
assert self.data['group1'].convert('b', 'J') == 12e6
assert self.data['group1'].convert('d', 'm^2') == [16e-6, 10e-4]

def test_units_activation_energy(self):
assert self.data['group1'].convert_activation_energy('a', 'J/kmol') == 5e6
assert (self.data['group1'].convert_activation_energy('c', 'J/kmol')
== pytest.approx(8000 * ct.gas_constant))

def test_units_nested(self):
assert self.data['group2'].convert('x', 'J/kg') == 1300 * 1e6

0 comments on commit 6c45457

Please sign in to comment.