[Python] Basic implementation of class Quantity
This commit is contained in:
parent
6e138d0ae4
commit
94f94dd0e6
3 changed files with 174 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
from ._cantera import *
|
||||
from ._cantera import __version__, __sundials_version__
|
||||
from .composite import *
|
||||
from .liquidvapor import *
|
||||
from .onedim import *
|
||||
from .utils import *
|
||||
|
|
|
|||
104
interfaces/cython/cantera/composite.py
Normal file
104
interfaces/cython/cantera/composite.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
from ._cantera import *
|
||||
|
||||
class Quantity(object):
|
||||
"""
|
||||
A class representing a specific quantity of a `Solution`.
|
||||
"""
|
||||
def __init__(self, phase, mass=None, moles=None, constant='UV'):
|
||||
self.state = phase.TDY
|
||||
self._phase = phase
|
||||
|
||||
if mass is not None:
|
||||
self.mass = mass
|
||||
elif moles is not None:
|
||||
self.moles = moles
|
||||
else:
|
||||
self.mass = 1.0
|
||||
|
||||
assert constant in ('TP','TV','HP','SP','SV','UV')
|
||||
self.constant = constant
|
||||
|
||||
@property
|
||||
def phase(self):
|
||||
self._phase.TDY = self.state
|
||||
return self._phase
|
||||
|
||||
@property
|
||||
def moles(self):
|
||||
return self.mass / self.phase.mean_molecular_weight
|
||||
|
||||
@moles.setter
|
||||
def moles(self, n):
|
||||
self.mass = n * self.phase.mean_molecular_weight
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
return self.mass * self.phase.volume_mass
|
||||
|
||||
@property
|
||||
def int_energy(self):
|
||||
return self.mass * self.phase.int_energy_mass
|
||||
|
||||
@property
|
||||
def enthalpy(self):
|
||||
return self.mass * self.phase.enthalpy_mass
|
||||
|
||||
@property
|
||||
def entropy(self):
|
||||
return self.mass * self.phase.entropy_mass
|
||||
|
||||
@property
|
||||
def gibbs(self):
|
||||
return self.mass * self.phase.gibbs_mass
|
||||
|
||||
def __imul__(self, other):
|
||||
self.mass *= other
|
||||
return self
|
||||
|
||||
def __mul__(self, other):
|
||||
return Quantity(self.phase, mass=self.mass * other)
|
||||
|
||||
def __rmul__(self, other):
|
||||
return Quantity(self.phase, mass=self.mass * other)
|
||||
|
||||
def __iadd__(self, other):
|
||||
assert(self.constant == other.constant)
|
||||
a1,b1 = getattr(self.phase, self.constant)
|
||||
a2,b2 = getattr(other.phase, self.constant)
|
||||
m = self.mass + other.mass
|
||||
a = (a1 * self.mass + a2 * other.mass) / m
|
||||
b = (b1 * self.mass + b2 * other.mass) / m
|
||||
self._phase.Y = (self.Y * self.mass + other.Y * other.mass) / m
|
||||
setattr(self._phase, self.constant, (a,b))
|
||||
self.state = self._phase.TDY
|
||||
self.mass = m
|
||||
return self
|
||||
|
||||
def __add__(self, other):
|
||||
newquantity = Quantity(self.phase, mass=self.mass, constant=self.constant)
|
||||
newquantity += other
|
||||
return newquantity
|
||||
|
||||
# Synonyms for total properties
|
||||
Quantity.V = Quantity.volume
|
||||
Quantity.U = Quantity.int_energy
|
||||
Quantity.H = Quantity.enthalpy
|
||||
Quantity.S = Quantity.entropy
|
||||
Quantity.G = Quantity.gibbs
|
||||
|
||||
# Add properties to act as pass-throughs for attributes of class Solution
|
||||
def _prop(attr):
|
||||
def getter(self):
|
||||
return getattr(self.phase, attr)
|
||||
|
||||
def setter(self, value):
|
||||
setattr(self.phase, attr, value)
|
||||
self.state = self._phase.TDY
|
||||
|
||||
return property(getter, setter, doc=getattr(Solution, attr).__doc__)
|
||||
|
||||
for _attr in dir(Solution):
|
||||
if _attr.startswith('_') or _attr in Quantity.__dict__:
|
||||
continue
|
||||
else:
|
||||
setattr(Quantity, _attr, _prop(_attr))
|
||||
|
|
@ -910,3 +910,72 @@ class TestSpeciesThermo(utilities.CanteraTest):
|
|||
self.assertEqual(st.max_temp, 3500)
|
||||
self.assertEqual(st.reference_pressure, 101325)
|
||||
self.assertArrayNear(self.h2o_coeffs, st.coeffs)
|
||||
|
||||
|
||||
class TestQuantity(utilities.CanteraTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.gas = ct.Solution('gri30.xml')
|
||||
|
||||
def setUp(self):
|
||||
self.gas.TPX = 300, 101325, 'O2:1.0, N2:3.76'
|
||||
|
||||
def test_mass_moles(self):
|
||||
q1 = ct.Quantity(self.gas, mass=5)
|
||||
self.assertNear(q1.mass, 5)
|
||||
self.assertNear(q1.moles, 5 / q1.mean_molecular_weight)
|
||||
|
||||
q1.mass = 7
|
||||
self.assertNear(q1.moles, 7 / q1.mean_molecular_weight)
|
||||
|
||||
q1.moles = 9
|
||||
self.assertNear(q1.moles, 9)
|
||||
self.assertNear(q1.mass, 9 * q1.mean_molecular_weight)
|
||||
|
||||
def test_extensive(self):
|
||||
q1 = ct.Quantity(self.gas, mass=5)
|
||||
self.assertNear(q1.mass, 5)
|
||||
|
||||
self.assertNear(q1.volume * q1.density, q1.mass)
|
||||
self.assertNear(q1.V * q1.density, q1.mass)
|
||||
self.assertNear(q1.int_energy, q1.moles * q1.int_energy_mole)
|
||||
self.assertNear(q1.enthalpy, q1.moles * q1.enthalpy_mole)
|
||||
self.assertNear(q1.entropy, q1.moles * q1.entropy_mole)
|
||||
self.assertNear(q1.gibbs, q1.moles * q1.gibbs_mole)
|
||||
self.assertNear(q1.int_energy, q1.U)
|
||||
self.assertNear(q1.enthalpy, q1.H)
|
||||
self.assertNear(q1.entropy, q1.S)
|
||||
self.assertNear(q1.gibbs, q1.G)
|
||||
|
||||
def test_multiply(self):
|
||||
q1 = ct.Quantity(self.gas, mass=5)
|
||||
q2 = q1 * 2.5
|
||||
self.assertNear(q1.mass * 2.5, q2.mass)
|
||||
self.assertNear(q1.moles * 2.5, q2.moles)
|
||||
self.assertNear(q1.entropy * 2.5, q2.entropy)
|
||||
self.assertArrayNear(q1.X, q2.X)
|
||||
|
||||
def test_iadd(self):
|
||||
q0 = ct.Quantity(self.gas, mass=5)
|
||||
q1 = ct.Quantity(self.gas, mass=5)
|
||||
q2 = ct.Quantity(self.gas, mass=5)
|
||||
q2.TPX = 500, 101325, 'CH4:1.0'
|
||||
|
||||
q1 += q2
|
||||
self.assertNear(q0.mass + q2.mass, q1.mass)
|
||||
# addition is at constant UV
|
||||
self.assertNear(q0.U + q2.U, q1.U)
|
||||
self.assertNear(q0.V + q2.V, q1.V)
|
||||
self.assertArrayNear(q0.X*q0.moles + q2.X*q2.moles, q1.X*q1.moles)
|
||||
|
||||
def test_add(self):
|
||||
q1 = ct.Quantity(self.gas, mass=5)
|
||||
q2 = ct.Quantity(self.gas, mass=5)
|
||||
q2.TPX = 500, 101325, 'CH4:1.0'
|
||||
|
||||
q3 = q1 + q2
|
||||
self.assertNear(q1.mass + q2.mass, q3.mass)
|
||||
# addition is at constant UV
|
||||
self.assertNear(q1.U + q2.U, q3.U)
|
||||
self.assertNear(q1.V + q2.V, q3.V)
|
||||
self.assertArrayNear(q1.X*q1.moles + q2.X*q2.moles, q3.X*q3.moles)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue