[Cython] Allow setting state while holding specific properties constant
The value "None" is used to indicate the property or properties being held constant.
This commit is contained in:
parent
02112c7cde
commit
e667978655
3 changed files with 104 additions and 20 deletions
|
|
@ -276,6 +276,16 @@ Or, to set all the mass fractions to equal values::
|
|||
|
||||
>>> gas1.Y = np.ones(53)
|
||||
|
||||
When setting the state, you can control what properties are held constant by
|
||||
passing the special value `None` to the property setter. For example, to
|
||||
change the specific volume to 2.1 m^3/kg while holding entropy constant::
|
||||
|
||||
>>> gas.SV = None, 2.1
|
||||
|
||||
Or to set the mass fractions while holding temperature and pressure constant::
|
||||
|
||||
>>> gas.TPX = None, None, 'CH4:1.0, O2:0.5'
|
||||
|
||||
Working With Mechanism Files
|
||||
----------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,40 @@ class TestThermoPhase(utilities.CanteraTest):
|
|||
self.check_setters(T1 = 750.0, rho1 = 0.02,
|
||||
Y1 = [0.2, 0.1, 0.0, 0.3, 0.1, 0.0, 0.0, 0.2, 0.1])
|
||||
|
||||
def test_setters_hold_constant(self):
|
||||
props = ('T','P','s','h','u','v','X','Y')
|
||||
pairs = [('TP', 'T', 'P'), ('SP', 's', 'P'),
|
||||
('UV', 'u', 'v')]
|
||||
|
||||
self.phase.TDX = 1000, 1.5, 'H2O:0.1, O2:0.95, AR:3.0'
|
||||
values = {}
|
||||
for p in props:
|
||||
values[p] = getattr(self.phase, p)
|
||||
|
||||
for pair, first, second in pairs:
|
||||
self.phase.TDX = 500, 2.5, 'H2:0.1, O2:1.0, AR:3.0'
|
||||
first_val = getattr(self.phase, first)
|
||||
second_val = getattr(self.phase, second)
|
||||
|
||||
setattr(self.phase, pair, (values[first], None))
|
||||
self.assertNear(getattr(self.phase, first), values[first])
|
||||
self.assertNear(getattr(self.phase, second), second_val)
|
||||
|
||||
self.phase.TDX = 500, 2.5, 'H2:0.1, O2:1.0, AR:3.0'
|
||||
setattr(self.phase, pair, (None, values[second]))
|
||||
self.assertNear(getattr(self.phase, first), first_val)
|
||||
self.assertNear(getattr(self.phase, second), values[second])
|
||||
|
||||
self.phase.TDX = 500, 2.5, 'H2:0.1, O2:1.0, AR:3.0'
|
||||
setattr(self.phase, pair + 'X', (None, None, values['X']))
|
||||
self.assertNear(getattr(self.phase, first), first_val)
|
||||
self.assertNear(getattr(self.phase, second), second_val)
|
||||
|
||||
self.phase.TDX = 500, 2.5, 'H2:0.1, O2:1.0, AR:3.0'
|
||||
setattr(self.phase, pair + 'Y', (None, None, values['Y']))
|
||||
self.assertNear(getattr(self.phase, first), first_val)
|
||||
self.assertNear(getattr(self.phase, second), second_val)
|
||||
|
||||
def test_setter_errors(self):
|
||||
with self.assertRaises(Exception):
|
||||
self.phase.TD = 400
|
||||
|
|
|
|||
|
|
@ -440,7 +440,9 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.T, self.density
|
||||
def __set__(self, values):
|
||||
assert len(values) == 2
|
||||
self.thermo.setState_TR(values[0], values[1] * self._mass_factor())
|
||||
T = values[0] if values[0] is not None else self.T
|
||||
D = values[1] if values[1] is not None else self.density
|
||||
self.thermo.setState_TR(T, D * self._mass_factor())
|
||||
|
||||
property TDX:
|
||||
"""
|
||||
|
|
@ -451,8 +453,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.T, self.density, self.X
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
T = values[0] if values[0] is not None else self.T
|
||||
D = values[1] if values[1] is not None else self.density
|
||||
self.X = values[2]
|
||||
self.TD = values[:2]
|
||||
self.thermo.setState_TR(T, D * self._mass_factor())
|
||||
|
||||
property TDY:
|
||||
"""
|
||||
|
|
@ -463,8 +467,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.T, self.density, self.Y
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
T = values[0] if values[0] is not None else self.T
|
||||
D = values[1] if values[1] is not None else self.density
|
||||
self.Y = values[2]
|
||||
self.TD = values[:2]
|
||||
self.thermo.setState_TR(T, D * self._mass_factor())
|
||||
|
||||
property TP:
|
||||
"""Get/Set temperature [K] and pressure [Pa]."""
|
||||
|
|
@ -472,7 +478,9 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.T, self.P
|
||||
def __set__(self, values):
|
||||
assert len(values) == 2
|
||||
self.thermo.setState_TP(values[0], values[1])
|
||||
T = values[0] if values[0] is not None else self.T
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.thermo.setState_TP(T, P)
|
||||
|
||||
property TPX:
|
||||
"""Get/Set temperature [K], pressure [Pa], and mole fractions."""
|
||||
|
|
@ -480,8 +488,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.T, self.P, self.X
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
T = values[0] if values[0] is not None else self.T
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.X = values[2]
|
||||
self.TP = values[:2]
|
||||
self.thermo.setState_TP(T, P)
|
||||
|
||||
property TPY:
|
||||
"""Get/Set temperature [K], pressure [Pa], and mass fractions."""
|
||||
|
|
@ -489,8 +499,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.T, self.P, self.Y
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
T = values[0] if values[0] is not None else self.T
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.Y = values[2]
|
||||
self.TP = values[:2]
|
||||
self.thermo.setState_TP(T, P)
|
||||
|
||||
property UV:
|
||||
"""
|
||||
|
|
@ -501,8 +513,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.u, self.v
|
||||
def __set__(self, values):
|
||||
assert len(values) == 2
|
||||
self.thermo.setState_UV(values[0] / self._mass_factor(),
|
||||
values[1] / self._mass_factor())
|
||||
U = values[0] if values[0] is not None else self.u
|
||||
V = values[1] if values[1] is not None else self.v
|
||||
self.thermo.setState_UV(U / self._mass_factor(),
|
||||
V / self._mass_factor())
|
||||
|
||||
property UVX:
|
||||
"""
|
||||
|
|
@ -513,8 +527,11 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.u, self.v, self.X
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
U = values[0] if values[0] is not None else self.u
|
||||
V = values[1] if values[1] is not None else self.v
|
||||
self.X = values[2]
|
||||
self.UV = values[:2]
|
||||
self.thermo.setState_UV(U / self._mass_factor(),
|
||||
V / self._mass_factor())
|
||||
|
||||
property UVY:
|
||||
"""
|
||||
|
|
@ -525,8 +542,11 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.u, self.v, self.Y
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
U = values[0] if values[0] is not None else self.u
|
||||
V = values[1] if values[1] is not None else self.v
|
||||
self.Y = values[2]
|
||||
self.UV = values[:2]
|
||||
self.thermo.setState_UV(U / self._mass_factor(),
|
||||
V / self._mass_factor())
|
||||
|
||||
property HP:
|
||||
"""Get/Set enthalpy [J/kg or J/kmol] and pressure [Pa]."""
|
||||
|
|
@ -534,7 +554,9 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.h, self.P
|
||||
def __set__(self, values):
|
||||
assert len(values) == 2
|
||||
self.thermo.setState_HP(values[0] / self._mass_factor(), values[1])
|
||||
H = values[0] if values[0] is not None else self.h
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.thermo.setState_HP(H / self._mass_factor(), P)
|
||||
|
||||
property HPX:
|
||||
"""Get/Set enthalpy [J/kg or J/kmol], pressure [Pa] and mole fractions."""
|
||||
|
|
@ -542,8 +564,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.h, self.P, self.X
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
H = values[0] if values[0] is not None else self.h
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.X = values[2]
|
||||
self.HP = values[:2]
|
||||
self.thermo.setState_HP(H / self._mass_factor(), P)
|
||||
|
||||
property HPY:
|
||||
"""Get/Set enthalpy [J/kg or J/kmol], pressure [Pa] and mass fractions."""
|
||||
|
|
@ -551,8 +575,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.h, self.P, self.Y
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
H = values[0] if values[0] is not None else self.h
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.Y = values[2]
|
||||
self.HP = values[:2]
|
||||
self.thermo.setState_HP(H / self._mass_factor(), P)
|
||||
|
||||
property SP:
|
||||
"""Get/Set entropy [J/kg/K or J/kmol/K] and pressure [Pa]."""
|
||||
|
|
@ -560,7 +586,9 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.s, self.P
|
||||
def __set__(self, values):
|
||||
assert len(values) == 2
|
||||
self.thermo.setState_SP(values[0] / self._mass_factor(), values[1])
|
||||
S = values[0] if values[0] is not None else self.s
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.thermo.setState_SP(S / self._mass_factor(), P)
|
||||
|
||||
property SPX:
|
||||
"""Get/Set entropy [J/kg/K or J/kmol/K], pressure [Pa], and mole fractions."""
|
||||
|
|
@ -568,8 +596,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.s, self.P, self.X
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
S = values[0] if values[0] is not None else self.s
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.X = values[2]
|
||||
self.SP = values[:2]
|
||||
self.thermo.setState_SP(S / self._mass_factor(), P)
|
||||
|
||||
property SPY:
|
||||
"""Get/Set entropy [J/kg/K or J/kmol/K], pressure [Pa], and mass fractions."""
|
||||
|
|
@ -577,8 +607,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.s, self.P, self.Y
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
S = values[0] if values[0] is not None else self.s
|
||||
P = values[1] if values[1] is not None else self.P
|
||||
self.Y = values[2]
|
||||
self.SP = values[:2]
|
||||
self.thermo.setState_SP(S / self._mass_factor(), P)
|
||||
|
||||
property SV:
|
||||
"""
|
||||
|
|
@ -589,8 +621,10 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.s, self.v
|
||||
def __set__(self, values):
|
||||
assert len(values) == 2
|
||||
self.thermo.setState_SV(values[0] / self._mass_factor(),
|
||||
values[1] / self._mass_factor())
|
||||
S = values[0] if values[0] is not None else self.s
|
||||
V = values[1] if values[1] is not None else self.v
|
||||
self.thermo.setState_SV(S / self._mass_factor(),
|
||||
V / self._mass_factor())
|
||||
|
||||
property SVX:
|
||||
"""
|
||||
|
|
@ -601,8 +635,11 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.s, self.v, self.X
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
S = values[0] if values[0] is not None else self.s
|
||||
V = values[1] if values[1] is not None else self.v
|
||||
self.X = values[2]
|
||||
self.SV = values[:2]
|
||||
self.thermo.setState_SV(S / self._mass_factor(),
|
||||
V / self._mass_factor())
|
||||
|
||||
property SVY:
|
||||
"""
|
||||
|
|
@ -613,8 +650,11 @@ cdef class ThermoPhase(_SolutionBase):
|
|||
return self.s, self.v, self.Y
|
||||
def __set__(self, values):
|
||||
assert len(values) == 3
|
||||
S = values[0] if values[0] is not None else self.s
|
||||
V = values[1] if values[1] is not None else self.v
|
||||
self.Y = values[2]
|
||||
self.SV = values[:2]
|
||||
self.thermo.setState_SV(S / self._mass_factor(),
|
||||
V / self._mass_factor())
|
||||
|
||||
# partial molar / non-dimensional properties
|
||||
property partial_molar_enthalpies:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue