Beispiel #1
0
    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])
Beispiel #2
0
    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])
Beispiel #3
0
    def checkConversion(self, refFile, testFile):
        ref = ct.IdealGasMix(refFile)
        gas = ct.IdealGasMix(testFile)

        self.assertEqual(ref.elementNames(), gas.elementNames())
        self.assertEqual(ref.speciesNames(), gas.speciesNames())
        self.assertTrue(
            (ref.reactantStoichCoeffs() == gas.reactantStoichCoeffs()).all())

        compositionA = [[ref.nAtoms(i, j) for j in range(ref.nElements())]
                        for i in range(ref.nSpecies())]
        compositionB = [[gas.nAtoms(i, j) for j in range(gas.nElements())]
                        for i in range(gas.nSpecies())]
        self.assertEqual(compositionA, compositionB)

        return ref, gas
Beispiel #4
0
 def test_equil_complete_stoichiometric(self):
     """
     Equilibrium should correspond to complete combustion
     """
     gas = ct.importPhase('equilibrium.cti', 'complete')
     gas.set(X='CH4:1.0, O2:2.0', T=298, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=0, H2O=2, CO2=1)
Beispiel #5
0
 def test_equil_complete_stoichiometric(self):
     """
     Equilibrium should correspond to complete combustion
     """
     gas = ct.importPhase('equilibrium.cti', 'complete')
     gas.set(X='CH4:1.0, O2:2.0', T=298, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=0, H2O=2, CO2=1)
Beispiel #6
0
    def test_transport_normal(self):
        convertMech('../../data/inputs/h2o2.inp',
                    transportFile='../../data/transport/gri30_tran.dat',
                    outName='h2o2_transport_normal.cti',
                    quiet=True)

        gas = ct.IdealGasMix('h2o2_transport_normal.cti')
        gas.set(X='H2:1.0, O2:1.0', T=300, P=101325)
        self.assertAlmostEqual(gas.thermalConductivity(), 0.07663, 4)
Beispiel #7
0
 def test_equil_complete_lean(self):
     """
     Equilibrium should correspond to complete combustion (with excess O2)
     CH4 + 3 O2 -> CO2 + 2 H2O + O2
     """
     gas = ct.importPhase('equilibrium.cti', 'complete')
     gas.set(X='CH4:1.0, O2:3.0', T=298, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=1, H2O=2, CO2=1)
Beispiel #8
0
 def test_equil_complete_lean(self):
     """
     Equilibrium should correspond to complete combustion (with excess O2)
     CH4 + 3 O2 -> CO2 + 2 H2O + O2
     """
     gas = ct.importPhase('equilibrium.cti', 'complete')
     gas.set(X='CH4:1.0, O2:3.0', T=298, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=1, H2O=2, CO2=1)
Beispiel #9
0
    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])
Beispiel #10
0
    def test_transport_embedded(self):
        convertMech('../data/with-transport.inp',
                    outName='with-transport.cti',
                    quiet=True)

        gas = ct.IdealGasMix('with-transport.cti')
        gas.set(X=[0.2, 0.3, 0.5])
        D = gas.mixDiffCoeffs()
        for d in D:
            self.assertTrue(d > 0.0)
Beispiel #11
0
    def setUp(self):
        self.gas = ct.importPhase('../../data/inputs/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])
Beispiel #12
0
    def test_duplicate_species(self):
        self.assertRaises(
            ck2cti.InputParseError,
            lambda: convertMech('../data/duplicate-species.inp',
                                outName='duplicate-species.cti',
                                quiet=True))

        convertMech('../data/duplicate-species.inp',
                    outName='duplicate-species.cti',
                    quiet=True,
                    permissive=True)

        gas = ct.IdealGasMix('duplicate-species.cti')
        self.assertEqual(gas.speciesNames(), ['foo', 'bar', 'baz'])
Beispiel #13
0
    def test_unterminatedSections(self):
        self.assertRaises(
            ck2cti.InputParseError,
            lambda: convertMech('../data/unterminated-sections.inp',
                                outName='unterminated-sections.cti',
                                quiet=True))

        convertMech('../data/unterminated-sections.inp',
                    outName='unterminated-sections.cti',
                    quiet=True,
                    permissive=True)

        gas = ct.IdealGasMix('unterminated-sections.cti')
        self.assertEqual(gas.nSpecies(), 3)
        self.assertEqual(gas.nReactions(), 2)
Beispiel #14
0
    def test_pathologicalSpeciesNames(self):
        convertMech('../data/species-names.inp',
                    outName='species-names.cti',
                    quiet=True)
        gas = ct.IdealGasMix('species-names.cti')

        self.assertEqual(gas.nSpecies(), 3)
        self.assertEqual(gas.speciesName(0), '(Parens)')
        self.assertEqual(gas.speciesName(1), '@#$%^-2')
        self.assertEqual(gas.speciesName(2), '[xy2]*{.}')

        self.assertEqual(gas.nReactions(), 2)
        nu = gas.productStoichCoeffs() - gas.reactantStoichCoeffs()
        self.assertEqual(list(nu[:, 0]), [-1, -1, 2])
        self.assertEqual(list(nu[:, 1]), [-2, 3, -1])
Beispiel #15
0
    def test_duplicate_thermo(self):
        self.assertRaises(
            ck2cti.InputParseError,
            lambda: convertMech('../data/duplicate-thermo.inp',
                                outName='duplicate-thermo.cti',
                                quiet=True))

        convertMech('../data/duplicate-thermo.inp',
                    outName='duplicate-thermo.cti',
                    quiet=True,
                    permissive=True)

        gas = ct.IdealGasMix('duplicate-thermo.cti')
        self.assertTrue(gas.nSpecies(), 3)
        self.assertTrue(gas.nReactions(), 2)
Beispiel #16
0
def initializeCanteraSimulation(filepath, T, P, tf):
	"""
	Initialize a Cantera simulation at temperature `T`, pressure `P`, and solution
	termination time `tf`.
	"""
	
	# we change into the scratch folder for this because it creates xml files
	absfilepath = os.path.abspath(filepath)
	oldwd	= os.getcwd()
	try:
		os.chdir(rmg.constants.scratchDirectory)
		# load the mechanism into gas
		gas = Cantera.importPhase(absfilepath,'chem')
		# create the environment
		gasAir = Cantera.Air()
	finally:
		os.chdir(oldwd)
	
	# set the inital gas and environment conditions
	gas.set(T=T, P=P)
	gasAir.set(T=T, P=P)
	
	# create a reactor for the batch reactor
	# and a reservoir for the environment
	reactor = Cantera.Reactor.Reactor(gas, volume = 1.0)
	environment = Cantera.Reactor.Reservoir(gasAir)
	
	# Define a wall between the reactor and the environment, and
	# make it flexible, so that the pressure in the reactor is held
	# at the environment pressure, and conductive so the temperature likewise
	wall = Cantera.Reactor.Wall(reactor,environment)
	wall.set(K = 1.0e12)   # set expansion parameter. dV/dt = KA(P_1 - P_2)
	wall.set(A = 1.0)
	wall.setHeatTransferCoeff(1.0e15) # W/m2/K
	
	# put the reactor into a reactor network
	sim = Cantera.Reactor.ReactorNet([reactor]) 
	sim.setInitialTime(0.0)
	maxtime = tf
	
	return gas, gasAir, reactor, environment, wall, sim, maxtime
Beispiel #17
0
 def setUpClass(cls):
     cls.gas = ct.importPhase('../data/air-no-reactions.xml', 'air')
Beispiel #18
0
 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()
Beispiel #19
0
    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)
Beispiel #20
0
 def test_import_GRI30(self):
     gas = ct.GRI30()
     self.check(gas, 'gri30', 300, 101325, 53, 5)
Beispiel #21
0
 def setUpClass(cls):
     cls.gas = ct.importPhase('../data/air-no-reactions.xml', 'air')
Beispiel #22
0
 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)
Beispiel #23
0
    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)
Beispiel #24
0
 def test_equil_gri_lean(self):
     gas = ct.importPhase('gri30.xml')
     gas.set(X='CH4:1.0, O2:3.0', T=301, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=1, H2O=2, CO2=1)
Beispiel #25
0
 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()
Beispiel #26
0
 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)
Beispiel #27
0
	def runCantera(self, model):
		"""
		Execute a simulation of the reaction system in Cantera. The procedure:
		(1) write a CTML (Cantera) file, (2) read it into Cantera, (3) create
		the reactor in Cantera, and (4) return the simulation results.
		"""

		# Create a folder in the scratch directory for Cantera files if needed
		cantera_folder = os.path.join(settings.scratchDirectory,'cantera')
		os.path.exists(cantera_folder) or os.mkdir(cantera_folder)
		
		# Write the CTML file to scratch/cantera/ folder
		cti_file = os.path.join(cantera_folder, 'cantera_input_%03d' % len(model.core.species))
		logging.debug("Writing CTML file %s" % cti_file)
		ctml_writer.dataset(cti_file) # change name
		ctml_writer.write()

		import Cantera
		import Cantera.Reactor

		# Load the CTML file into Cantera
		logging.info("Preparing Cantera simulation %d" % len(model.core.species))
		Cantera.reset()
		gas = Cantera.importPhase('%s.xml' % cti_file, 'chem', loglevel=1)

		# Set initial concentrations
		moleFractions = numpy.zeros(len(model.core.species))
		for spec, conc in self.initialMoleFraction.iteritems():
			moleFractions[gas.speciesIndex(str(spec))] = conc
		gas.setMoleFractions(moleFractions) # it normalises it to 1

		# Set initial temperature and pressure
		gas.set(T=self.initialTemperature, P=self.initialPressure)

		# create a batch reactor
		if self.heatTransferCoeff == 1.0e100:
			reactor = Cantera.Reactor.Reactor(gas, volume=self.volume, energy='off')
		else:
			reactor = Cantera.Reactor.Reactor(gas, volume=self.volume)

		# set the inital environment conditions
		gasAir = Cantera.Air()
		gasAir.set(T=self.reservoirTemperature, P=self.reservoirPressure)

		# create a reservoir for the environment
		environment = Cantera.Reactor.Reservoir(gasAir)

		# Define a wall between the reactor and the environment, and
		# make it flexible, so that the pressure in the reactor is held
		# at the environment pressure, and conductive so the temperature likewise
		wall = Cantera.Reactor.Wall(reactor, environment)
		wall.set(K=self.expansionCoeff)
		wall.set(A=self.area)
		wall.setHeatTransferCoeff(self.heatTransferCoeff) # W/m2/K

		# put reactor in a reactor network so it can be integrated
		sim = Cantera.Reactor.ReactorNet([reactor])
		sim.setTolerances(atol=model.absoluteTolerance, rtol=model.relativeTolerance)

		#import pdb; pdb.set_trace()
		return sim, gas
Beispiel #28
0
 def test_equil_overconstrained2(self):
     gas = ct.importPhase('equilibrium.cti', 'overconstrained-2')
     gas.set(X='CH4:1.0, O2:1.0', T=301, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=1, O2=1)
Beispiel #29
0
 def test_equil_gri_lean(self):
     gas = ct.importPhase('gri30.xml')
     gas.set(X='CH4:1.0, O2:3.0', T=301, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=1, H2O=2, CO2=1)
Beispiel #30
0
 def test_equil_incomplete_lean(self):
     gas = ct.importPhase('equilibrium.cti', 'incomplete')
     gas.set(X='CH4:1.0, O2:3.0', T=301, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=1, H2O=2, CO2=1)
Beispiel #31
0
 def test_checkReactionBalance(self):
     self.assertRaises(Exception,
                       lambda: ct.IdealGasMix('../data/h2o2_unbalancedReaction.xml'))
Beispiel #32
0
"""
Unit tests for the Cantera Python module.

This script gathers all the tests defined in all of the test<foo>.py
files, runs them, and prints a report.
"""
import sys
import os
import unittest

import Cantera

Cantera.addDirectory(os.path.join(os.path.split(os.getcwd())[0], 'data'))

if __name__ == '__main__':
    print '\n* INFO: using Cantera module found at this location:'
    print '*     ', repr(Cantera.__file__), '\n'
    sys.stdout.flush()

    loader = unittest.TestLoader()
    runner = unittest.TextTestRunner(verbosity=2)
    suite = loader.loadTestsFromName('testSolution')
    suite = loader.loadTestsFromName('testKinetics')
    suite.addTests(loader.loadTestsFromName('testPureFluid'))
    suite.addTests(loader.loadTestsFromName('testEquilibrium'))
    suite.addTests(loader.loadTestsFromName('testReactors'))
    suite.addTests(loader.loadTestsFromName('testConvert'))

    results = runner.run(suite)
    sys.exit(len(results.errors) + len(results.failures))
Beispiel #33
0
 def test_equil_overconstrained2(self):
     gas = ct.importPhase('equilibrium.cti', 'overconstrained-2')
     gas.set(X='CH4:1.0, O2:1.0', T=301, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=1, O2=1)
Beispiel #34
0
 def test_equil_incomplete_lean(self):
     gas = ct.importPhase('equilibrium.cti', 'incomplete')
     gas.set(X='CH4:1.0, O2:3.0', T=301, P=100000)
     gas.equilibrate('TP', self.solver)
     self.check(gas, CH4=0, O2=1, H2O=2, CO2=1)
Beispiel #35
0
 def setUp(self):
     self.gas = ct.IdealGasMix('../data/explicit-forward-order.xml')
     self.gas.set(T=800, P=101325, X=[0.01, 0.90, 0.02, 0.03, 0.04])