[Cython] Move reactor tests from old Python module to Cython module

This commit is contained in:
Ray Speth 2013-12-09 01:34:46 +00:00
parent 59564659b3
commit 57f1506d0b
3 changed files with 167 additions and 194 deletions

View file

@ -1,6 +1,8 @@
import math
import re
import numpy as np
from .utilities import unittest
import re
import cantera as ct
from . import utilities
@ -1067,3 +1069,166 @@ class TestReactorSensitivities(utilities.CanteraTest):
for a,b in [(0,1),(2,3),(4,5),(6,7)]:
for i,j in enumerate((4,2,1,3,0)):
self.assertArrayNear(S[a][:,i], S[b][:,j], 1e-2, 1e-3)
class CombustorTestImplementation(object):
"""
These tests are based on the sample:
interfaces/cython/cantera/examples/reactors/combustor.py
with some simplifications so that they run faster and produce more
consistent output.
"""
referenceFile = '../data/CombustorTest-integrateWithAdvance.csv'
def setUp(self):
self.gas = ct.Solution('h2o2.xml')
# create a reservoir for the fuel inlet, and set to pure methane.
self.gas.TPX = 300.0, ct.one_atm, 'H2:1.0'
fuel_in = ct.Reservoir(self.gas)
fuel_mw = self.gas.mean_molecular_weight
# Oxidizer inlet
self.gas.TPX = 300.0, ct.one_atm, 'O2:1.0, AR:3.0'
oxidizer_in = ct.Reservoir(self.gas)
oxidizer_mw = self.gas.mean_molecular_weight
# to ignite the fuel/air mixture, we'll introduce a pulse of radicals.
# The steady-state behavior is independent of how we do this, so we'll
# just use a stream of pure atomic hydrogen.
self.gas.TPX = 300.0, ct.one_atm, 'H:1.0'
self.igniter = ct.Reservoir(self.gas)
# create the combustor, and fill it in initially with a diluent
self.gas.TPX = 300.0, ct.one_atm, 'AR:1.0'
self.combustor = ct.IdealGasReactor(self.gas, volume=1.0)
# create a reservoir for the exhaust
self.exhaust = ct.Reservoir(self.gas)
# compute fuel and air mass flow rates
factor = 0.1
oxidizer_mdot = 4 * factor*oxidizer_mw
fuel_mdot = factor*fuel_mw
# The igniter will use a time-dependent igniter mass flow rate.
def igniter_mdot(t, t0=0.1, fwhm=0.05, amplitude=0.1):
return amplitude * math.exp(-(t-t0)**2 * 4 * math.log(2) / fwhm**2)
# create and install the mass flow controllers. Controllers
# m1 and m2 provide constant mass flow rates, and m3 provides
# a short Gaussian pulse only to ignite the mixture
m1 = ct.MassFlowController(fuel_in, self.combustor, mdot=fuel_mdot)
m2 = ct.MassFlowController(oxidizer_in, self.combustor, mdot=oxidizer_mdot)
m3 = ct.MassFlowController(self.igniter, self.combustor, mdot=igniter_mdot)
# put a valve on the exhaust line to regulate the pressure
self.v = ct.Valve(self.combustor, self.exhaust, K=1.0)
# the simulation only contains one reactor
self.sim = ct.ReactorNet([self.combustor])
def test_integrateWithStep(self):
tnow = 0.0
tfinal = 0.25
self.data = []
while tnow < tfinal:
tnow = self.sim.step(tfinal)
self.data.append([tnow, self.combustor.T] +
list(self.combustor.thermo.X))
self.assertTrue(tnow >= tfinal)
bad = utilities.compareProfiles(self.referenceFile, self.data,
rtol=1e-3, atol=1e-9)
self.assertFalse(bad, bad)
def test_integrateWithAdvance(self, saveReference=False):
self.data = []
for t in np.linspace(0, 0.25, 101)[1:]:
self.sim.advance(t)
self.data.append([t, self.combustor.T] +
list(self.combustor.thermo.X))
if saveReference:
np.savetxt(self.referenceFile, np.array(self.data), '%11.6e', ', ')
else:
bad = utilities.compareProfiles(self.referenceFile, self.data,
rtol=1e-6, atol=1e-12)
self.assertFalse(bad, bad)
class WallTestImplementation(object):
"""
These tests are based on the sample:
interfaces/cython/cantera/examples/reactors/reactor2.py
with some simplifications so that they run faster and produce more
consistent output.
"""
referenceFile = '../data/WallTest-integrateWithAdvance.csv'
def setUp(self):
# reservoir to represent the environment
self.gas0 = ct.Solution('air.xml')
self.gas0.TP = 300, ct.one_atm
self.env = ct.Reservoir(self.gas0)
# reactor to represent the side filled with Argon
self.gas1 = ct.Solution('air.xml')
self.gas1.TPX = 1000.0, 30*ct.one_atm, 'AR:1.0'
self.r1 = ct.Reactor(self.gas1)
# reactor to represent the combustible mixture
self.gas2 = ct.Solution('h2o2.xml')
self.gas2.TPX = 500.0, 1.5*ct.one_atm, 'H2:0.5, O2:1.0, AR:10.0'
self.r2 = ct.Reactor(self.gas2)
# Wall between the two reactors
self.w1 = ct.Wall(self.r2, self.r1, A=1.0, K=2e-4, U=400.0)
# Wall to represent heat loss to the environment
self.w2 = ct.Wall(self.r2, self.env, A=1.0, U=2000.0)
# Create the reactor network
self.sim = ct.ReactorNet([self.r1, self.r2])
def test_integrateWithStep(self):
tnow = 0.0
tfinal = 0.01
self.data = []
while tnow < tfinal:
tnow = self.sim.step(tfinal)
self.data.append([tnow,
self.r1.T, self.r2.T,
self.r1.thermo.P, self.r2.thermo.P,
self.r1.volume, self.r2.volume])
self.assertTrue(tnow >= tfinal)
bad = utilities.compareProfiles(self.referenceFile, self.data,
rtol=1e-3, atol=1e-8)
self.assertFalse(bad, bad)
def test_integrateWithAdvance(self, saveReference=False):
self.data = []
for t in np.linspace(0, 0.01, 200)[1:]:
self.sim.advance(t)
self.data.append([t,
self.r1.T, self.r2.T,
self.r1.thermo.P, self.r2.thermo.P,
self.r1.volume, self.r2.volume])
if saveReference:
np.savetxt(self.referenceFile, np.array(self.data), '%11.6e', ', ')
else:
bad = utilities.compareProfiles(self.referenceFile, self.data,
rtol=2e-5, atol=1e-9)
self.assertFalse(bad, bad)
# Keep the implementations separate from the unittest-derived class
# so that they can be run independently to generate the reference data files.
class CombustorTest(CombustorTestImplementation, unittest.TestCase): pass
class WallTest(WallTestImplementation, unittest.TestCase): pass

View file

@ -21,8 +21,7 @@ if __name__ == '__main__':
loader = unittest.TestLoader()
runner = unittest.TextTestRunner(verbosity=2)
suite = loader.loadTestsFromName('testReactors')
suite.addTests(loader.loadTestsFromName('testConvert'))
suite = loader.loadTestsFromName('testConvert')
results = runner.run(suite)
sys.exit(len(results.errors) + len(results.failures))

View file

@ -1,191 +0,0 @@
import unittest
import pprint
import numpy as np
import Cantera as ct
from Cantera import Reactor as reactors
from Cantera.Func import Gaussian
import utilities
class CombustorTestImplementation(object):
"""
These tests are based on the sample:
python/reactors/combustor_sim/combustor.py
with some simplifications so that they run faster and produce more
consistent output.
"""
referenceFile = '../data/CombustorTest-integrateWithAdvance.csv'
def setUp(self):
self.gas = ct.importPhase('h2o2.cti')
# create a reservoir for the fuel inlet, and set to pure methane.
self.gas.set(T=300.0, P=ct.OneAtm, X='H2:1.0')
fuel_in = reactors.Reservoir(self.gas)
fuel_mw = self.gas.meanMolarMass()
# Oxidizer inlet
self.gas.set(T=300.0, P=ct.OneAtm, X='O2:1.0, AR:3.0')
oxidizer_in = reactors.Reservoir(self.gas)
oxidizer_mw = self.gas.meanMolarMass()
# to ignite the fuel/air mixture, we'll introduce a pulse of radicals.
# The steady-state behavior is independent of how we do this, so we'll
# just use a stream of pure atomic hydrogen.
self.gas.set(T=300.0, P=ct.OneAtm, X='H:1.0')
self.igniter = reactors.Reservoir(self.gas)
# create the combustor, and fill it in initially with a diluent
self.gas.set(T=300.0, P=ct.OneAtm, X='AR:1.0')
self.combustor = reactors.Reactor(contents=self.gas, volume=1.0)
# create a reservoir for the exhaust
self.exhaust = reactors.Reservoir(self.gas)
# compute fuel and air mass flow rates
factor = 0.1
oxidizer_mdot = 4 * factor*oxidizer_mw
fuel_mdot = factor*fuel_mw
# create and install the mass flow controllers. Controllers
# m1 and m2 provide constant mass flow rates, and m3 provides
# a short Gaussian pulse only to ignite the mixture
m1 = reactors.MassFlowController(upstream=fuel_in,
downstream=self.combustor,
mdot=fuel_mdot)
m2 = reactors.MassFlowController(upstream=oxidizer_in,
downstream=self.combustor,
mdot=oxidizer_mdot)
# The igniter will use a Gaussian 'functor' object to specify the
# time-dependent igniter mass flow rate.
igniter_mdot = Gaussian(t0=0.1, FWHM=0.05, A=0.1)
m3 = reactors.MassFlowController(upstream=self.igniter,
downstream=self.combustor,
mdot=igniter_mdot)
# put a valve on the exhaust line to regulate the pressure
self.v = reactors.Valve(upstream=self.combustor,
downstream=self.exhaust, Kv=1.0)
# the simulation only contains one reactor
self.sim = reactors.ReactorNet([self.combustor])
#self.sim.setTolerances(1e-8, 1e-12)
def test_integrateWithStep(self):
tnow = 0.0
tfinal = 0.25
self.data = []
while tnow < tfinal:
tnow = self.sim.step(tfinal)
self.data.append([tnow, self.combustor.temperature()] +
list(self.combustor.moleFractions()))
self.assertTrue(tnow >= tfinal)
bad = utilities.compareTimeSeries(self.referenceFile, self.data,
rtol=1e-3, atol=1e-9)
self.assertFalse(bad, bad)
def test_integrateWithAdvance(self, saveReference=False):
times = np.linspace(0, 0.25, 101)
self.data = []
for t in times[1:]:
self.sim.advance(t)
self.data.append([t, self.combustor.temperature()] +
list(self.combustor.moleFractions()))
if saveReference:
np.savetxt(self.referenceFile, np.array(self.data), '%11.6e', ', ')
else:
bad = utilities.compareTimeSeries(self.referenceFile, self.data,
rtol=1e-6, atol=1e-12)
self.assertFalse(bad, bad)
class WallTestImplementation(object):
"""
These tests are based on the sample:
python/reactors/reactor2_sim/reactor2.py
with some simplifications so that they run faster and produce more
consistent output.
"""
referenceFile = '../data/WallTest-integrateWithAdvance.csv'
def setUp(self):
# reservoir to represent the environment
self.gas0 = ct.importPhase('air.cti')
self.gas0.set(T=300, P=ct.OneAtm)
self.env = reactors.Reservoir(self.gas0)
# reactor to represent the side filled with Argon
self.gas1 = ct.importPhase('air.cti')
self.gas1.set(T=1000.0, P=30*ct.OneAtm, X='AR:1.0')
self.r1 = reactors.Reactor(self.gas1)
# reactor to represent the combustible mixture
self.gas2 = ct.importPhase('h2o2.cti')
self.gas2.set(T=500.0, P=1.5*ct.OneAtm, X='H2:0.5, O2:1.0, AR:10.0')
self.r2 = reactors.Reactor(self.gas2)
# Wall between the two reactors
self.w1 = reactors.Wall(self.r2, self.r1)
self.w1.set(area=1.0, K=2e-4, U=400.0)
# Wall to represent heat loss to the environment
self.w2 = reactors.Wall(self.r2, self.env)
self.w2.set(area=1.0, U=2000.0)
# Create the reactor network
self.sim = reactors.ReactorNet([self.r1, self.r2])
def test_integrateWithStep(self):
tnow = 0.0
tfinal = 0.01
self.data = []
while tnow < tfinal:
tnow = self.sim.step(tfinal)
self.data.append([tnow,
self.r1.temperature(),
self.r2.temperature(),
self.r1.pressure(),
self.r2.pressure(),
self.r1.volume(),
self.r2.volume()])
self.assertTrue(tnow >= tfinal)
bad = utilities.compareTimeSeries(self.referenceFile, self.data,
rtol=1e-3, atol=1e-8)
self.assertFalse(bad, bad)
def test_integrateWithAdvance(self, saveReference=False):
times = np.linspace(0, 0.01, 200)
self.data = []
for t in times[1:]:
self.sim.advance(t)
self.data.append([t,
self.r1.temperature(),
self.r2.temperature(),
self.r1.pressure(),
self.r2.pressure(),
self.r1.volume(),
self.r2.volume()])
if saveReference:
np.savetxt(self.referenceFile, np.array(self.data), '%11.6e', ', ')
else:
bad = utilities.compareTimeSeries(self.referenceFile, self.data,
rtol=2e-5, atol=1e-9)
self.assertFalse(bad, bad)
# Keep the implementations separate from the unittest-derived class
# so that they can be run independently to generate the reference data files.
class CombustorTest(CombustorTestImplementation, unittest.TestCase): pass
class WallTest(WallTestImplementation, unittest.TestCase): pass