From 70a728c8f7611268683774c09ff7e6f7b5a93103 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Mon, 9 Dec 2013 01:34:25 +0000 Subject: [PATCH] [Cython] Move thermo tests from old Python module to Cython module --- interfaces/cython/cantera/test/test_thermo.py | 102 ++++++++++- test/python/runTests.py | 3 +- test/python/testSolution.py | 159 ------------------ 3 files changed, 98 insertions(+), 166 deletions(-) delete mode 100644 test/python/testSolution.py diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index 5cd24fb6e..173e867f5 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -8,6 +8,9 @@ class TestThermoPhase(utilities.CanteraTest): def setUp(self): self.phase = ct.Solution('h2o2.xml') + def teste_phases(self): + self.assertEqual(self.phase.n_phases, 1) + def test_species(self): self.assertEqual(self.phase.n_species, 9) for i,name in enumerate(self.phase.species_names): @@ -23,14 +26,30 @@ class TestThermoPhase(utilities.CanteraTest): self.assertEqual(i, self.phase.element_index(i)) def test_n_atoms(self): - self.assertEqual(self.phase.n_atoms('H2', 'H'), 2) - self.assertEqual(self.phase.n_atoms('H2O2', 'H'), 2) - self.assertEqual(self.phase.n_atoms('HO2', 'H'), 1) - self.assertEqual(self.phase.n_atoms('AR', 'H'), 0) + data = [(1, 'O', 'O'), (2, 'O', 'O2'), (1, 'H', 'OH'), + (2, 'H', 'H2O'), (2, 'O', 'H2O2'), (1, 'Ar', 'AR'), + (0, 'O', 'H'), (0, 'H', 'AR'), (0, 'Ar', 'HO2')] + for (n, elem, species) in data: + self.assertEqual(self.phase.n_atoms(species, elem), n) + mElem = self.phase.element_index(elem) + kSpec = self.phase.species_index(species) + self.assertEqual(self.phase.n_atoms(kSpec, mElem), n) self.assertRaises(ValueError, lambda: self.phase.n_atoms('C', 'H2')) self.assertRaises(ValueError, lambda: self.phase.n_atoms('H', 'CH4')) + def test_weights(self): + atomic_weights = self.phase.atomic_weights + molecular_weights = self.phase.molecular_weights + self.assertEqual(self.phase.n_elements, len(atomic_weights)) + self.assertEqual(self.phase.n_species, len(molecular_weights)) + + for i,mw in enumerate(molecular_weights): + test_weight = 0.0 + for j,aw in enumerate(atomic_weights): + test_weight += aw * self.phase.n_atoms(i,j) + self.assertAlmostEqual(test_weight, mw) + def test_setComposition(self): X = np.zeros(self.phase.n_species) X[2] = 1.0 @@ -102,7 +121,6 @@ class TestThermoPhase(utilities.CanteraTest): self.assertEqual(self.phase.cv_mole, self.phase.cv) self.assertEqual(self.phase.cp_mole, self.phase.cp) - def check_setters(self, T1, rho1, Y1): T0, rho0, Y0 = self.phase.TDY self.phase.TDY = T1, rho1, Y1 @@ -293,6 +311,7 @@ class TestThermoPhase(utilities.CanteraTest): class TestThermo(utilities.CanteraTest): def setUp(self): self.gas = ct.ThermoPhase('h2o2.xml') + self.gas.TPX = 450, 2e5, 'H2:1.0, O2:0.4, AR:3, H2O:0.1' def test_setSV_lowT(self): """ @@ -352,6 +371,44 @@ class TestThermo(utilities.CanteraTest): self.assertNear(self.gas.P, p1) self.assertTrue(self.gas.T > self.gas.max_temp) + def test_volume(self): + """ This phase should follow the ideal gas law """ + g = self.gas + self.assertAlmostEqual(g.P, g.density_mole * ct.gas_constant * g.T) + + self.assertAlmostEqual( + g.P / g.density, + ct.gas_constant / g.mean_molecular_weight * g.T) + + self.assertAlmostEqual(g.density, 1.0 / g.volume_mass) + + def test_energy(self): + g = self.gas + mmw = g.mean_molecular_weight + self.assertAlmostEqual(g.enthalpy_mass, g.enthalpy_mole / mmw) + self.assertAlmostEqual(g.int_energy_mass, g.int_energy_mole / mmw) + self.assertAlmostEqual(g.gibbs_mass, g.gibbs_mole / mmw) + self.assertAlmostEqual(g.entropy_mass, g.entropy_mole / mmw) + + self.assertAlmostEqual(g.cv_mass, g.cv_mole / mmw) + self.assertAlmostEqual(g.cp_mass, g.cp_mole / mmw) + self.assertAlmostEqual(g.cv_mole + ct.gas_constant, g.cp_mole) + + def test_nondimensional(self): + g = self.gas + R = ct.gas_constant + + self.assertAlmostEqual(np.dot(g.standard_cp_R, g.X), + g.cp_mole / R) + self.assertAlmostEqual(np.dot(g.standard_enthalpies_RT, g.X), + g.enthalpy_mole / (R*g.T)) + + Smix_R = - np.dot(g.X, np.log(g.X+1e-20)) + self.assertAlmostEqual(np.dot(g.standard_entropies_R, g.X) + Smix_R, + g.entropy_mole / R) + self.assertAlmostEqual(np.dot(g.standard_gibbs_RT, g.X) - Smix_R, + g.gibbs_mole / (R*g.T)) + class TestInterfacePhase(utilities.CanteraTest): def setUp(self): @@ -363,3 +420,38 @@ class TestInterfacePhase(utilities.CanteraTest): def test_properties(self): self.interface.site_density = 100 self.assertNear(self.interface.site_density, 100) + + +class ImportTest(utilities.CanteraTest): + """ + Test the various ways of creating a Solution object + """ + def check(self, gas, name, T, P, nSpec, nElem): + self.assertEqual(gas.name, name) + self.assertAlmostEqual(gas.T, T) + self.assertAlmostEqual(gas.P, P) + self.assertEqual(gas.n_species, nSpec) + self.assertEqual(gas.n_elements, nElem) + + def test_import_phase_cti(self): + gas1 = ct.Solution('../data/air-no-reactions.cti', 'air') + self.check(gas1, 'air', 300, 101325, 8, 3) + + gas2 = ct.Solution('../data/air-no-reactions.cti', 'notair') + self.check(gas2, 'notair', 900, 5*101325, 7, 2) + + def test_import_phase_cti2(self): + # This should import the first phase, i.e. 'air' + gas = ct.Solution('../data/air-no-reactions.cti') + self.check(gas, 'air', 300, 101325, 8, 3) + + def test_import_phase_xml(self): + gas1 = ct.Solution('../data/air-no-reactions.xml', 'air') + self.check(gas1, 'air', 300, 101325, 8, 3) + + gas2 = ct.Solution('../data/air-no-reactions.xml', 'notair') + self.check(gas2, 'notair', 900, 5*101325, 7, 2) + + def test_checkReactionBalance(self): + self.assertRaises(Exception, + lambda: ct.Solution('../data/h2o2_unbalancedReaction.xml')) diff --git a/test/python/runTests.py b/test/python/runTests.py index 3c31b09a8..700135071 100644 --- a/test/python/runTests.py +++ b/test/python/runTests.py @@ -21,8 +21,7 @@ if __name__ == '__main__': loader = unittest.TestLoader() runner = unittest.TextTestRunner(verbosity=2) - suite = loader.loadTestsFromName('testSolution') - suite.addTests(loader.loadTestsFromName('testKinetics')) + suite = loader.loadTestsFromName('testKinetics') suite.addTests(loader.loadTestsFromName('testPureFluid')) suite.addTests(loader.loadTestsFromName('testEquilibrium')) suite.addTests(loader.loadTestsFromName('testReactors')) diff --git a/test/python/testSolution.py b/test/python/testSolution.py deleted file mode 100644 index bd6f07287..000000000 --- a/test/python/testSolution.py +++ /dev/null @@ -1,159 +0,0 @@ -import unittest - -import numpy as np - -import Cantera as ct - -class ImportTest(unittest.TestCase): - """ - Test the various ways of creating a Solution object - """ - def check(self, gas, name, T, P, nSpec, nElem): - self.assertEqual(gas.name(), name) - self.assertAlmostEqual(gas.temperature(), T) - self.assertAlmostEqual(gas.pressure(), P) - self.assertEqual(gas.nSpecies(), nSpec) - self.assertEqual(gas.nElements(), nElem) - - def test_importPhase_cti(self): - gas1 = ct.importPhase('../data/air-no-reactions.cti', 'air') - self.check(gas1, 'air', 300, 101325, 8, 3) - - gas2 = ct.importPhase('../data/air-no-reactions.cti', 'notair') - self.check(gas2, 'notair', 900, 5*101325, 7, 2) - - def test_importPhase_cti2(self): - # This should import the first phase, i.e. 'air' - gas = ct.importPhase('../data/air-no-reactions.cti') - self.check(gas, 'air', 300, 101325, 8, 3) - - def test_importPhase_xml(self): - gas1 = ct.importPhase('../data/air-no-reactions.xml', 'air') - self.check(gas1, 'air', 300, 101325, 8, 3) - - gas2 = ct.importPhase('../data/air-no-reactions.xml', 'notair') - self.check(gas2, 'notair', 900, 5*101325, 7, 2) - - def test_import_GRI30(self): - gas = ct.GRI30() - self.check(gas, 'gri30', 300, 101325, 53, 5) - - def test_checkReactionBalance(self): - self.assertRaises(Exception, - lambda: ct.IdealGasMix('../data/h2o2_unbalancedReaction.xml')) - - -class BasicTest(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.gas = ct.importPhase('../data/air-no-reactions.xml', 'air') - - def setUp(self): - # Workaround for Python 2.6 unittest, which does not call setUpClass - try: - self.gas - except AttributeError: - self.setUpClass() - - - def test_counts(self): - self.assertEqual(self.gas.nElements(), 3) - self.assertEqual(self.gas.nSpecies(), 8) - self.assertEqual(self.gas.nPhases(), 1) - - def test_elements(self): - self.assertEqual(self.gas.nElements(), len(self.gas.elementNames())) - for i,name in enumerate(self.gas.elementNames()): - self.assertEqual(self.gas.elementName(i), name) - self.assertEqual(self.gas.elementIndex(name), i) - - def test_species(self): - self.assertEqual(self.gas.nSpecies(), len(self.gas.speciesNames())) - for i,name in enumerate(self.gas.speciesNames()): - self.assertEqual(self.gas.speciesName(i), name) - self.assertEqual(self.gas.speciesIndex(name), i) - - def test_nAtoms(self): - data = [(1, 'O', 'O'), (2, 'O', 'O2'), (1, 'N', 'NO'), - (1, 'O', 'NO'), (1, 'N', 'NO2'), (2, 'O', 'NO2'), - (0, 'O', 'N2'), (0, 'Ar', 'N2O')] - for (n, elem, species) in data: - self.assertEqual(self.gas.nAtoms(species, elem), n) - mElem = self.gas.elementIndex(elem) - kSpec = self.gas.speciesIndex(species) - self.assertEqual(self.gas.nAtoms(kSpec, mElem), n) - - def test_weights(self): - atomic_weights = self.gas.atomicWeights() - molecular_weights = self.gas.molecularWeights() - self.assertEqual(self.gas.nElements(), len(atomic_weights)) - self.assertEqual(self.gas.nSpecies(), len(molecular_weights)) - - for i,mw in enumerate(molecular_weights): - test_weight = 0.0 - for j,aw in enumerate(atomic_weights): - test_weight += aw * self.gas.nAtoms(i,j) - self.assertAlmostEqual(test_weight, mw) - - -class ThermoTest(unittest.TestCase): - """ - Test the thermodynamic property accessor functions of a Solution - """ - @classmethod - def setUpClass(cls): - cls.gas = ct.importPhase('../data/air-no-reactions.xml', 'air') - cls.T0 = cls.gas.temperature() - cls.P0 = cls.gas.pressure() - cls.X0 = cls.gas.moleFractions() - - def setUp(self): - # Workaround for Python 2.6 unittest, which does not call setUpClass - try: - self.gas - except AttributeError: - self.setUpClass() - - self.gas.set(T=self.T0, P=self.P0, X=self.X0) - - def test_volume(self): - # This class should follow the ideal gas law - g = self.gas - self.assertAlmostEqual( - g.pressure(), - g.molarDensity() * ct.GasConstant * g.temperature()) - - self.assertAlmostEqual( - g.pressure() / g.density(), - ct.GasConstant / g.meanMolecularWeight() * g.temperature()) - - self.assertAlmostEqual(g.density(), 1.0 / g.volume_mass()) - - def test_energy(self): - g = self.gas - mmw = g.meanMolecularWeight() - self.assertAlmostEqual(g.enthalpy_mass(), g.enthalpy_mole() / mmw) - self.assertAlmostEqual(g.intEnergy_mass(), g.intEnergy_mole() / mmw) - self.assertAlmostEqual(g.gibbs_mass(), g.gibbs_mole() / mmw) - self.assertAlmostEqual(g.entropy_mass(), g.entropy_mole() / mmw) - - self.assertAlmostEqual(g.cv_mass(), g.cv_mole() / mmw) - self.assertAlmostEqual(g.cp_mass(), g.cp_mole() / mmw) - self.assertAlmostEqual(g.cv_mole() + ct.GasConstant, g.cp_mole()) - - def test_nondimensional(self): - g = self.gas - T = g.temperature() - R = ct.GasConstant - X = g.moleFractions() - - self.assertAlmostEqual(np.dot(g.cp_R(), X), - g.cp_mole() / R) - self.assertAlmostEqual(np.dot(g.enthalpies_RT(), X), - g.enthalpy_mole() / (R*T)) - - Smix_R = - np.dot(X, np.log(X+1e-20)) - self.assertAlmostEqual(np.dot(g.entropies_R(), X) + Smix_R, - g.entropy_mole() / R) - self.assertAlmostEqual(np.dot(g.gibbs_RT(), X) - Smix_R, - g.gibbs_mole() / (R*T))