Files
cantera/interfaces/matlab_experimental/OneDim/CounterFlowDiffusionFlame.m

242 lines
8.8 KiB
Matlab

classdef CounterFlowDiffusionFlame < Sim1D
% Create a counter flow diffusion flame stack. ::
%
% >> flame = CounterFlowDiffusionFlame(left, flow, right, tp_f, tp_o, oxidizer)
%
% :param left:
% Object representing the left inlet, which must be
% created using function :mat:class:`Inlet`.
% :param flow:
% Object representing the flow, created with
% function :mat:class:`AxisymmetricFlow`.
% :param right:
% Object representing the right inlet, which must be
% created using function :mat:class:`Inlet`.
% :param tp_f:
% Object representing the fuel inlet gas, instance of class
% :mat:class:`Solution`, and an ideal gas.
% :param tp_o:
% Object representing the oxidizer inlet gas, instance of class
% :mat:class:`Solution`, and an ideal gas.
% :param oxidizer:
% String representing the oxidizer species. Most commonly O2.
% :return:
% Instance of :mat:class:`CounterFlowDiffusionFlame` object
% representing the left inlet, flow, and right inlet.
methods
function flame = CounterFlowDiffusionFlame(left, flow, right, ...
tp_f, tp_o, oxidizer)
% Constructor
%% Check input parameters
if nargin ~= 6
error('CounterFlowDiffusionFlame expects six input arguments.');
end
if ~tp_f.isIdealGas
error('Fuel gas object must represent an ideal gas mixture.');
end
if ~tp_o.isIdealGas
error('Oxidizer gas object must represent an ideal gas mixture.');
end
if ~isa(left, 'Inlet')
error('Left inlet object of wrong type.');
end
if ~isa(flow, 'Flow1D')
error('Flow object of wrong type.');
end
if ~isa(right, 'Inlet')
error('Right inlet object of wrong type.');
end
if ~ischar(oxidizer)
error('Oxidizer name must be of format character.');
end
%% Define elMoles function
function moles = elMoles(tp, element)
% Determine the elemental moles in a gas object per unit mass.
% Check input parameters
if nargin ~= 2
error('elMoles expects two input arguments.');
end
if ~tp.isIdealGas
error('Gas object must represent an ideal gas mixture.');
end
if ~ischar(element)
error('Element name must be of format character.');
end
% Calculate the moles per mass of mixture of an element within a gas
% object. The equation used is:
%
% elMoles = elMassFrac/Mel
%
% where elMassFrac is the elemental mass fraction within the gas object
% using the elementalMassFraction function; Mel is the atomic mass of
% the element.
elMassFrac = tp.elementalMassFraction(element);
eli = tp.elementIndex(element);
M = tp.atomicMasses;
Mel = M(eli);
moles = elMassFrac / Mel;
end
%% Get the density of both fuel and oxidizer streams.
% To be used in determining velocity of each stream. Also get the
% temperature of both inlet streams.
rhof = tp_f.D;
rho0 = tp_o.D;
tf = left.T;
tox = right.T;
%% Find the species index of the oxidizer.
% To be used in determining initial strain rate.
ioxidizer = tp_o.speciesIndex(oxidizer);
%% Calculate the stoichiometric mixture fraction.
% Needed for determining location of flame edges and composition.
% elMoles function used to calculate the number of moles of C, H, and O
% atoms in the fuel and oxidizer streams:
%
% elMoles = elementalMassFraction/element atomic weight.
%
% From this, the stoichiometric Air/Fuel ratio can be determined.
% 1 Mole of O needs 2 Moles of C and 0.5 Moles of H for stoichiometric
% conditions. The stoichiometric mixture fraction, Zst, is then
% calculated.
sFuel = elMoles(tp_f, 'O') - 2 * elMoles(tp_f, 'C') - ...
0.5 * elMoles(tp_f, 'H');
sOx = elMoles(tp_o, 'O') - 2 * elMoles(tp_o, 'C') - ...
0.5 * elMoles(tp_o, 'H');
phi = sFuel / sOx;
zst = 1.0 / (1.0 - phi);
%% Compute the stoichiometric mass fractions of each species.
% Use this to set the fuel gas object and calculate adiabatic flame
% temperature and equilibrium composition.
spec = tp_f.speciesNames; % Get all of the species names in gas object.
nsp = tp_f.nSpecies; % Get total number of species in gas object.
% Get the current mass fractions of both fuel and inlet streams.
yox = tp_o.Y;
yf = tp_f.Y;
ystoich_double = zeros(1, nsp); % Create empty vector for stoich mass frac.
for n = 1:nsp
% Calculate stoichiometric mass fractions.
ystoich_double(n) = zst * yf(n) + (1.0 - zst) * yox(n);
% Convert mass fraction vector to string vector.
ystoich_str{n} = num2str(ystoich_double(n));
% Convert string vector to cell with SPECIES:MASS FRACTION format.
y_stoich{n} = [spec{n}, ':', ystoich_str{n}];
end
% Initialize stoichiometric mass fraction cell with first SP:Y value.
ystoich = [y_stoich{1}];
for i = 2:nsp
% Update cell to have format similar to N2:Yst,O2:Yst,...
ystoich = [ystoich ',', y_stoich{i}];
end
% Set the fuel gas object as stoichiometric values and use equilibrate
% function to determine stoichiometric equilibrium temperature and mass
% fractions.
tp_f.TPY = {tf, tp_f.P, ystoich};
tp_f.equilibrate('HP');
teq = tp_f.T;
yeq = tp_f.Y;
%% Estimate the strain rate.
% Based on the inlet stream velocities and determine initial 'guess'
% for mixture fraction based on mass flux ratio.
zz = flow.gridPoints;
dz = zz(end) - zz(1);
mdotl = left.massFlux;
mdotr = right.massFlux;
uleft = mdotl / rhof;
uright = mdotr / rho0;
a = (abs(uleft) + abs(uright)) / dz;
diff = tp_f.mixDiffCoeffs;
f = sqrt(a / (2.0 * diff(ioxidizer)));
x0num = sqrt(uleft * mdotl) * dz;
x0den = sqrt(uleft * mdotr) + sqrt(uright * mdotr);
x0 = x0num / x0den;
%% Calculate initial values of temperature and mass fractions.
% These values to be used for energy equation solution. Method is based
% on the Burke-Schumann model.
nz = flow.nPoints;
zm = zeros(1, nz);
u = zeros(1, nz);
v = zeros(1, nz);
y = zeros(nz, nsp);
t = zeros(1, nz);
for j = 1:nz
x = zz(j);
zeta = f * (x - x0);
zmix = 0.5 * (1.0 - erf(zeta)); % Mixture fraction in flame.
zm(j) = zmix;
u(j) = a * (x0 - zz(j)); % Axial velocity.
v(j) = a; % Radial velocity.
if zmix > zst
for n = 1:nsp
y(j, n) = yeq(n) + (zmix - zst) * (yf(n) - yeq(n)) /...
(1.0 - zst);
end
t(j) = teq + (tf - teq) * (zmix - zst) / (1.0 - zst);
else
for n = 1:nsp
y(j, n) = yox(n) + zmix * (yeq(n) - yox(n)) / zst;
end
t(j) = tox + zmix * (teq - tox) / zst;
end
end
zrel = zz / dz;
%% Create the flame stack.
% Set the profile of the flame with the estimated axial velocities,
% radial velocities, temperature, and mass fractions calculated above.
flame@Sim1D({left flow right});
flame.setProfile(2, {'velocity', 'spread_rate'}, [zrel; u; v]);
flame.setProfile(2, 'T', [zrel; t]);
for n = 1:nsp
nm = tp_f.speciesName(n);
flame.setProfile(2, nm, [zrel; transpose(y(:, n))]);
end
end
end
end