From charlesreid1

No edit summary
(Fix math: replace \mbox with \text for MediaWiki math renderer compatibility (via update-page on MediaWiki MCP Server))
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
As a TA for CHEN 6153, I gave a lecture on the installation and use of Cantera.  
As a TA for CHEN 6153, I gave a lecture on the installation and use of Cantera.  


Line 72: Line 74:
What is going into our reactor?
What is going into our reactor?


<syntaxhighlight lang="matlab">
<pre>
% Import a phase to fill the reactor with
% Import a phase to fill the reactor with
% (The H2 combustion mechanism is contained in the file h2o2.cti, which comes with Cantera)
% (The H2 combustion mechanism is contained in the file h2o2.cti, which comes with Cantera)
gas = importPhase('h2o2.cti');
gas = importPhase('h2o2.cti');
</syntaxhighlight>
</pre>


What is the thermodynamic state of the material going into the reactor?
What is the thermodynamic state of the material going into the reactor?


<syntaxhighlight lang="matlab">
<pre>
% Set the gas temperature at 1500 K
% Set the gas temperature at 1500 K
% Set the pressure at 1 atm
% Set the pressure at 1 atm
% Set the composition to be 2 parts hydrogen, 1 part oxygen, and 20 parts dilute, inert Argon
% Set the composition to be 2 parts hydrogen, 1 part oxygen, and 20 parts dilute, inert Argon
set(gas, 'T',1500, 'P',oneatm, 'X','H2:2, O2:1, AR:20')
set(gas, 'T',1500, 'P',oneatm, 'X','H2:2, O2:1, AR:20')
</syntaxhighlight>
</pre>


How to create a batch reactor?  Create a Cantera Reactor object
How to create a batch reactor?  Create a Cantera Reactor object


<syntaxhighlight lang="matlab">
<pre>
% We have already set the thermodynamic state of the "gas" object
% We have already set the thermodynamic state of the "gas" object
% But if we wanted to, we could set it when we create the Reactor
% But if we wanted to, we could set it when we create the Reactor
batch = Reactor(gas);
batch = Reactor(gas);
</syntaxhighlight>
</pre>


We didn't specify the volume of the Reactor object - so how do we find it?
We didn't specify the volume of the Reactor object - so how do we find it?
Line 101: Line 103:
What information ''can'' we get about the Reactor object?
What information ''can'' we get about the Reactor object?


<syntaxhighlight lang="matlab">
<pre>
% We can use the volume() function to find the reactor's volume
% We can use the volume() function to find the reactor's volume
volume(batch)
volume(batch)
Line 111: Line 113:
% Show the functions available for Reactor objects
% Show the functions available for Reactor objects
methods Reactor
methods Reactor
</syntaxhighlight>
</pre>


The method "setInitialVolume()" looks good, so we can use it to set the initial volume of the reactor:
The method "setInitialVolume()" looks good, so we can use it to set the initial volume of the reactor:


<syntaxhighlight lang="matlab">
<pre>
setInitialVolume( batch, 10.0 );
setInitialVolume( batch, 10.0 );
</syntaxhighlight>
</pre>


Another interesting method is "massFractions()":
Another interesting method is "massFractions()":


<syntaxhighlight lang="matlab">
<pre>
% Display the mass fractions in the reactor
% Display the mass fractions in the reactor
massFractions(batch)
massFractions(batch)
</syntaxhighlight>
</pre>


This returns a 9-element vector, but it isn't clear what mass fractions are for which species.
This returns a 9-element vector, but it isn't clear what mass fractions are for which species.
Line 136: Line 138:
So use the same methodology:
So use the same methodology:


<syntaxhighlight lang="matlab">
<pre>
% Find the class type of the gas phase object
% Find the class type of the gas phase object
class(gas)
class(gas)
Line 146: Line 148:
% This list looks a little short - but we can show inherited methods like this:
% This list looks a little short - but we can show inherited methods like this:
methods Solution -full
methods Solution -full
</syntaxhighlight>
</pre>


The "speciesNames()" function looks like what we want:
The "speciesNames()" function looks like what we want:


<syntaxhighlight lang="matlab">
<pre>
speciesNames(gas)
speciesNames(gas)
</syntaxhighlight>
</pre>


This returns a 9-element vector of strings - names of species in the mechanism file 'h2o2.cti'.
This returns a 9-element vector of strings - names of species in the mechanism file 'h2o2.cti'.
Line 174: Line 176:
So first, we'll create a gas phase to fill the piston with
So first, we'll create a gas phase to fill the piston with


<source lang="matlab">
<pre>
% Create the H2-O2 gas phase
% Create the H2-O2 gas phase
gas = importPhase('h2o2.cti');
gas = importPhase('h2o2.cti');
Line 180: Line 182:
% Set the thermodynamic state of the gas
% Set the thermodynamic state of the gas
set(gas, 'T', 1500, 'P', oneatm, 'X', 'H2:2,O2:1,AR:20');
set(gas, 'T', 1500, 'P', oneatm, 'X', 'H2:2,O2:1,AR:20');
</source>
</pre>


Next, create the reservoir that represents the atmosphere, and fill it with air:
Next, create the reservoir that represents the atmosphere, and fill it with air:


<source lang="matlab">
<pre>
% Create an ideal gas mix of air
% Create an ideal gas mix of air
a = IdealGasMix('air.cti');
a = IdealGasMix('air.cti');
atmosphere = reservoir(a);
atmosphere = reservoir(a);
</source>
</pre>


A batch reactor must be created to represent the piston reactor:
A batch reactor must be created to represent the piston reactor:


<source lang="matlab">
<pre>
batch = Reactor(gas);
batch = Reactor(gas);
</source>
</pre>


The next step is to create a wall representing the piston between the reservoir and the gas. Walls in Cantera can be thought of as pistons with a certain amount of friction, or weight.
The next step is to create a wall representing the piston between the reservoir and the gas. Walls in Cantera can be thought of as pistons with a certain amount of friction, or weight.
Line 201: Line 203:


<math>
<math>
\frac{dV}{dt} = K_{\mbox{expansion}} A_{\mbox{wall}} ( P_1 - P_2 )
\frac{dV}{dt} = K_{\text{expansion}} A_{\text{wall}} ( P_1 - P_2 )
</math>
</math>


Line 210: Line 212:
The larger the <math>K</math> value, the faster the response of the wall (piston).
The larger the <math>K</math> value, the faster the response of the wall (piston).


<source lang="matlab">
<pre>
% Create a wall between the reactor and the atmosphere
% Create a wall between the reactor and the atmosphere
w = Wall;
w = Wall;
Line 218: Line 220:
% Set the expansion coefficient K
% Set the expansion coefficient K
setExpansionRateCoeff(w, 1.0e10);
setExpansionRateCoeff(w, 1.0e10);
</source>
</pre>


Remember, we can also have walls with heat transfer, so we could have heat flowing in, or flowing out, through the wall
Remember, we can also have walls with heat transfer, so we could have heat flowing in, or flowing out, through the wall
Line 226: Line 228:
Next, a reactor network can be created, in order to advance the reactor in time.
Next, a reactor network can be created, in order to advance the reactor in time.


<source lang="matlab">
<pre>
network = ReactorNet( {batch} );
network = ReactorNet( {batch} );
</source>
</pre>


== CSTR Combustor ==
== CSTR Combustor ==
Line 250: Line 252:
Create a reservoir of fuel, a reservoir of air, and a reservoir of hydrogen radicals (radicals are sure to initiate combustion reactions).
Create a reservoir of fuel, a reservoir of air, and a reservoir of hydrogen radicals (radicals are sure to initiate combustion reactions).


<source lang="matlab">
<pre>
% Create a fuel from the GRI combustion mechanism
% Create a fuel from the GRI combustion mechanism
fuel = GRI30;
fuel = GRI30;
Line 271: Line 273:
set(igniter, 'T', 300, 'P', oneatm, 'X', 'H:1.0');
set(igniter, 'T', 300, 'P', oneatm, 'X', 'H:1.0');
igniter_in = Reservoir(igniter);
igniter_in = Reservoir(igniter);
</source>
</pre>


The combustor must be initially filled with something - an inert gas is a good idea
The combustor must be initially filled with something - an inert gas is a good idea


<source lang="matlab">
<pre>
inert = GRI30;
inert = GRI30;
set(inert, 'T', 300, 'P', oneatm, 'X', 'N2:1.0');
set(inert, 'T', 300, 'P', oneatm, 'X', 'N2:1.0');
combustor = Reactor(inert);
combustor = Reactor(inert);
</source>
</pre>


The next step is to set the equivalence ratio, and set the mass flowrates accordingly.
The next step is to set the equivalence ratio, and set the mass flowrates accordingly.


<source lang="matlab">
<pre>
ER = 0.7;
ER = 0.7;


Line 294: Line 296:
% Igniter mass flowrate
% Igniter mass flowrate
igniter_mdot = 0.05;
igniter_mdot = 0.05;
</source>
</pre>


The mass flowrates could also be a Gaussian function in time, or a polynomial, e.g.
The mass flowrates could also be a Gaussian function in time, or a polynomial, e.g.


<source lang="matlab">
<pre>
igniter_mdot = Func('gaussian', 0, [1.0, 0.0, 0.1] );
igniter_mdot = Func('gaussian', 0, [1.0, 0.0, 0.1] );
igniter_mdot = Func('polynomial', 2.0, [0.0, 0.0, 0.1] );
igniter_mdot = Func('polynomial', 2.0, [0.0, 0.0, 0.1] );
</source>
</pre>


You can type "help Func" for more information.
You can type "help Func" for more information.
Line 309: Line 311:
The next step is to create the mass flow controllers entering the reactor, and the pressure exhaust valve, and finally to set up the reactor network.
The next step is to create the mass flow controllers entering the reactor, and the pressure exhaust valve, and finally to set up the reactor network.


<source lang="matlab">
<pre>
% Create the mass flowrate controllers feeding into the combustor
% Create the mass flowrate controllers feeding into the combustor
m1 = MassFlowController(oxidizer_in, combustor);
m1 = MassFlowController(oxidizer_in, combustor);
Line 326: Line 328:
% Now the reactor network can be created
% Now the reactor network can be created
network = ReactorNet( {combustor} );
network = ReactorNet( {combustor} );
</source>
</pre>
 
 




{{Cantera}}


{{Combustion}}


[[Category:Combustion Software]]
{{CanteraFlag}}

Latest revision as of 23:08, 14 June 2026


As a TA for CHEN 6153, I gave a lecture on the installation and use of Cantera.

Cantera Overview

Cantera is a code written in C++ that can be used to perform chemical kinetic and thermodynamic calculations.

The way it does this is by providing the user with a set of building blocks, and allowing the user to piece these building blocks together to form complex kinetic/thermodynamic systems or networks

Users can interface with Cantera through C++, or through the other interfaces:

  • Matlab toolbox
  • Python
  • Fortran

Visit the Cantera (software) page for a Cantera installation guide for either Mac, Linux, or Windows.


Cantera Objects

Reservoir - fixed state

  • the state of the reservoir never changes
  • used to impose fixed upstream/inlet conditions
  • chemistry is frozen - so no reactions will take place

Reactor - canonical chemical reactor

  • contains some mixture of species
  • has a set of characteristics
  • e.g. T, V, P, composition, enthalpy, density, MW, etc...

Fluids - gases or liquids

Chemical Mechanisms - external files "fed" to Cantera

  • chemical mechanisms specify two things:
    • species
    • reactions
  • all thermodynamic data for species is specified (e.g. heat capacity as a polynomial function - "NASA coefficients")
  • all thermodynamic data for chemical reactions (pre-exponential factors, activation energies, etc.)

Walls - separate reactors

  • can have heat transfer via the usual mechanisms - convection, conduction, radiation
  • can have a set heating rate (a constant, or a function of time)
  • can move - due to a pressure difference, a displacement rate expression, etc.)

Flow controllers - control flow... 3 types

Mass flow controller - maintains a fixed mass flowrate
Valves - the mass flowrate is a function of $ \Delta P $
Pressure flow controller - maintains a fixed $ P $ in the reactor (think of this as a pressure relief valve)

Matlab Examples

Batch Reactor Example

How might we combine the above Cantera objects to make a batch reactor?

e.g. where would the reactor go? Where would the flow controllers go?

Any reservoirs needed? No

Any flow controllers needed? No

What will we need? A reactor

What are we going to fill the reactor with? We also need a fluid phase, and a mechanism to go along with it (if we want reactions), or thermodynamic data to go along with it (if we want thermodynamic state changes)

Batch.jpg

We want to know what happens when the reactor is changing from state 1 to state 2

For a constant volume reactor:

What is going into our reactor?

% Import a phase to fill the reactor with
% (The H2 combustion mechanism is contained in the file h2o2.cti, which comes with Cantera)
gas = importPhase('h2o2.cti');

What is the thermodynamic state of the material going into the reactor?

% Set the gas temperature at 1500 K
% Set the pressure at 1 atm
% Set the composition to be 2 parts hydrogen, 1 part oxygen, and 20 parts dilute, inert Argon
set(gas, 'T',1500, 'P',oneatm, 'X','H2:2, O2:1, AR:20')

How to create a batch reactor? Create a Cantera Reactor object

% We have already set the thermodynamic state of the "gas" object
% But if we wanted to, we could set it when we create the Reactor
batch = Reactor(gas);

We didn't specify the volume of the Reactor object - so how do we find it?

How do we get information about the Reactor object?

What information can we get about the Reactor object?

% We can use the volume() function to find the reactor's volume
volume(batch)

% We can find the Matlab object type like this:
class(batch)
% This returns "Reactor" type

% Show the functions available for Reactor objects
methods Reactor

The method "setInitialVolume()" looks good, so we can use it to set the initial volume of the reactor:

setInitialVolume( batch, 10.0 );

Another interesting method is "massFractions()":

% Display the mass fractions in the reactor
massFractions(batch)

This returns a 9-element vector, but it isn't clear what mass fractions are for which species.

How can we figure out what species are in the reactor?

Is this a reactor property?

Or is it a gas/fluid property?

So use the same methodology:

% Find the class type of the gas phase object
class(gas)
% This returns type "Solution"

% This shows the methods available to Solution types
methods Solution 

% This list looks a little short - but we can show inherited methods like this:
methods Solution -full

The "speciesNames()" function looks like what we want:

speciesNames(gas)

This returns a 9-element vector of strings - names of species in the mechanism file 'h2o2.cti'.

Constant Pressure Reactor Example

Now for a more interesting (relevant) combustion problem:

How might we use reactors, walls, reservoirs, etc. to create a constant-pressure batch reactor?

We can create a piston-cylinder system - this would be a constant-pressure system, with combustion occurring inside the piston

Piston.jpg

The constant-pressure, constant-temperature, constant-property atmosphere is a reservoir

The piston lid is a wall

The reactants and products inside the piston are gases

So first, we'll create a gas phase to fill the piston with

% Create the H2-O2 gas phase
gas = importPhase('h2o2.cti');

% Set the thermodynamic state of the gas
set(gas, 'T', 1500, 'P', oneatm, 'X', 'H2:2,O2:1,AR:20');

Next, create the reservoir that represents the atmosphere, and fill it with air:

% Create an ideal gas mix of air
a = IdealGasMix('air.cti');
atmosphere = reservoir(a);

A batch reactor must be created to represent the piston reactor:

batch = Reactor(gas);

The next step is to create a wall representing the piston between the reservoir and the gas. Walls in Cantera can be thought of as pistons with a certain amount of friction, or weight.

The wall expansion parameter is defined as:

$ \frac{dV}{dt} = K_{\text{expansion}} A_{\text{wall}} ( P_1 - P_2 ) $

What happens when $ K=0 $?

What happens when $ K=\infty $?

The larger the $ K $ value, the faster the response of the wall (piston).

% Create a wall between the reactor and the atmosphere
w = Wall;
install(w, batch, atmosphere);
setArea(w,1.0);

% Set the expansion coefficient K
setExpansionRateCoeff(w, 1.0e10);

Remember, we can also have walls with heat transfer, so we could have heat flowing in, or flowing out, through the wall

By default, the wall is adiabatic

Next, a reactor network can be created, in order to advance the reactor in time.

network = ReactorNet( {batch} );

CSTR Combustor

This example is for a continuously-fired combustor.

The reactor is a combustor with a fuel and oxidizer reservoir, as well as a reservoir of igniter to initiate combustion.

There is also a reservoir for the exhaust.

Cstr.jpg

So we will need some reservoirs, a reactor...

What else? Flow controllers

We want to run the CSTR with various fuel/oxidizer ratios, and see how it affects the concentrations, temperatures, etc.

We might want to vary residence time, too - see the extent of combustion as a function of residence time

Create a reservoir of fuel, a reservoir of air, and a reservoir of hydrogen radicals (radicals are sure to initiate combustion reactions).

% Create a fuel from the GRI combustion mechanism
fuel = GRI30;
set(fuel, 'T', 300, 'P', oneatm, 'X', 'C3H8:1.0');
fuel_mw = meanMolecularWeight(fuel);

% Create the fuel reservoir
fuel_in = Reservoir(fuel);

% Create the oxidizer
oxidizer = Air();
set(oxidizer, 'T', 300, 'P', oneatm);
oxidizer_mw = meanMolecularWeight(oxidizer);

% Create the oxidizer reservoir
oxidizer_in = Reservoir(oxidizer);

% Create the igniter reservoir
igniter = GRI30;
set(igniter, 'T', 300, 'P', oneatm, 'X', 'H:1.0');
igniter_in = Reservoir(igniter);

The combustor must be initially filled with something - an inert gas is a good idea

inert = GRI30;
set(inert, 'T', 300, 'P', oneatm, 'X', 'N2:1.0');
combustor = Reactor(inert);

The next step is to set the equivalence ratio, and set the mass flowrates accordingly.

ER = 0.7;

% Fuel mass flowrate
fuel_mdot = fuel_mw*ER;

% Oxidizer mass flowrate
oxidizer_mdot = (1/ER)*(1/.21)*oxidizer_mw;

% Igniter mass flowrate
igniter_mdot = 0.05;

The mass flowrates could also be a Gaussian function in time, or a polynomial, e.g.

igniter_mdot = Func('gaussian', 0, [1.0, 0.0, 0.1] );
igniter_mdot = Func('polynomial', 2.0, [0.0, 0.0, 0.1] );

You can type "help Func" for more information.

(However, this does not seem to be working...)

The next step is to create the mass flow controllers entering the reactor, and the pressure exhaust valve, and finally to set up the reactor network.

% Create the mass flowrate controllers feeding into the combustor
m1 = MassFlowController(oxidizer_in, combustor);
setMassFlowRate(m1, oxidizer_mdot);

m2 = MassFlowController(fuel_in, combustor);
setMassFlowRate(m2, fuel_mdot);

m3 = MassFlowController(igniter_in, combustor);
setMassFlowrate(m3, igniter_mdot);

% And create an exhaust valve regulating the pressure in the combustor
exhaust_valve = Valve(combustor,exhaust);
setValveCoeff(exhaust_valve,1.0);

% Now the reactor network can be created
network = ReactorNet( {combustor} );