mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
[MATLAB-legacy] Remove samples
This commit is contained in:
parent
e9215e6600
commit
4b4e790f5a
@ -1,53 +0,0 @@
|
||||
function [F] = PFR_solver(x,soln_vector,gas,mdot,A_in,dAdx,k)
|
||||
|
||||
% This function defines the spatial derivatives for an ideal gas plug-flow
|
||||
% reactor, where the cross-sectional area and pressure are allowed to vary,
|
||||
% axially. The model is set up by the example file 'Plug_Flow_Reactor.m',
|
||||
% which points the integrator to this function. The integrator integrates the
|
||||
% derivatives spatially, to solve the density, temperature, and species mass
|
||||
% fraction profiles as a function of distance x.
|
||||
|
||||
rho = soln_vector(1);
|
||||
T = soln_vector(2);
|
||||
Y = soln_vector(3:end);
|
||||
|
||||
if k==1
|
||||
A = A_in+k*dAdx*x;
|
||||
elseif k==-1
|
||||
A = A_in+k*dAdx*x;
|
||||
dAdx = -dAdx;
|
||||
else
|
||||
A = A_in+k*dAdx*x;
|
||||
end
|
||||
|
||||
% the gas is set to the corresponding properties during each iteration of the ode loop
|
||||
set(gas,'Temperature',T,'Density',rho,'MassFractions',Y);
|
||||
|
||||
MW_mix = meanMolecularWeight(gas);
|
||||
Ru = gasconstant();
|
||||
R = Ru/MW_mix;
|
||||
nsp = nSpecies(gas);
|
||||
vx = mdot/(rho*A);
|
||||
P = rho*R*T;
|
||||
|
||||
MW = molecularWeights(gas);
|
||||
h = enthalpies_RT(gas).*R.*T;
|
||||
w = netProdRates(gas);
|
||||
Cp = cp_mass(gas);
|
||||
%--------------------------------------------------------------------------
|
||||
%---F(1), F(2) and F(3:end) are the differential equations modelling the---
|
||||
%---density, temperature and mass fractions variations along a plug flow---
|
||||
%-------------------------reactor------------------------------------------
|
||||
%--------------------------------------------------------------------------
|
||||
F(1) = ((1-R/Cp)*((rho*vx)^2)*(1/A)*(dAdx)...
|
||||
+ rho*R*sum(MW.*w.*(h-MW_mix*Cp*T./MW))/(vx*Cp) )...
|
||||
/ (P*(1+vx^2/(Cp*T)) - rho*vx^2);
|
||||
|
||||
F(2) = (vx*vx/(rho*Cp))*F(1) + vx*vx*(1/A)*(dAdx)/Cp...
|
||||
- (1/(vx*rho*Cp))*sum(h.*w.*MW);
|
||||
|
||||
F(3:nsp+2) = w(1:nsp).*MW(1:nsp)./(rho*vx);
|
||||
|
||||
F = F';
|
||||
|
||||
end
|
@ -1,165 +0,0 @@
|
||||
% General_Plug_Flow_Reactor (PFR) - to solve PFR equations for reactors
|
||||
%
|
||||
% This code snippet is to model a constant area and varying area
|
||||
% (converging and diverging) nozzle as Plug Flow Reactor with given
|
||||
% dimensions and an incoming gas. The pressure is not assumed to be
|
||||
% constant here, as opposed to the Python Version of the
|
||||
% Plug Flow Reactor model.
|
||||
%
|
||||
% The reactor assumes that the flow follows the Ideal Gas Law.
|
||||
%
|
||||
% The governing equations used in this code can be referenced at:
|
||||
% *S.R Turns, An Introduction to Combustion - Concepts and Applications,
|
||||
% McGraw Hill Education, India, 2012, 206-210.*
|
||||
%
|
||||
% The current example is written for methane combustion, but can be readily
|
||||
% adapted for other chemistries.
|
||||
%
|
||||
% Developed by Ashwin Kumar/Dr.Joseph Meadows (mgak@vt.edu/jwm84@vt.edu) on 3-June-2020
|
||||
% Research Assistant/Assistant Professor
|
||||
% Advanced Propulsion and Power Laboratory
|
||||
% Virginia Tech
|
||||
%
|
||||
% Keywords: combustion, user-defined model, compressible flow, plotting
|
||||
|
||||
%% Clear all variables, close all figures, clear the command line:
|
||||
clear all
|
||||
close all
|
||||
clc
|
||||
|
||||
% Temperature of gas, in K
|
||||
T0 = 1473;
|
||||
% Pressure of gas, in Pa
|
||||
P0 = 4.47*101325;
|
||||
|
||||
% Equivalence Ratio
|
||||
Phi = 0.2899;
|
||||
|
||||
% Import the gas phase, read out key species indices:
|
||||
gas_calc = Solution('gri30.yaml');
|
||||
ich4 = speciesIndex(gas_calc,'CH4');
|
||||
io2 = speciesIndex(gas_calc,'O2');
|
||||
in2 = speciesIndex(gas_calc,'N2');
|
||||
nsp = nSpecies(gas_calc);
|
||||
x = zeros(nsp,1);
|
||||
|
||||
% Change the below values for different Phi values of methane Combustion
|
||||
x(ich4,1) = Phi;
|
||||
x(io2,1) = 2.0;
|
||||
x(in2,1) = 7.52;
|
||||
|
||||
% Set the initial state and then equilibrate for a given enthalpy and pressure:
|
||||
set(gas_calc,'T',T0,'P',P0,'MoleFractions',x);
|
||||
gas_calc = equilibrate(gas_calc,'HP');
|
||||
|
||||
%% Calculation of properties along the reactor length
|
||||
% The Dimensions and conditions of the reactor are given below
|
||||
|
||||
% Inlet Area, in m^2
|
||||
A_in = 0.018;
|
||||
% Exit Area, in m^2
|
||||
A_out = 0.003;
|
||||
% Length of the reactor, in m
|
||||
L = 1.284*0.0254;
|
||||
% The whole reactor is divided into n small reactors
|
||||
n = 100;
|
||||
% Mass flow rate into the reactor, in kg/s
|
||||
mdot_calc = 1.125;
|
||||
|
||||
% Flag to indicate whether the area is converging, diverging, or constant:
|
||||
% k = -1 makes the solver solve for converging area.
|
||||
% k = +1 makes the solver solve for diverging area.
|
||||
% k = 0 makes the solver solve for constant cross sectional area
|
||||
if A_in>A_out
|
||||
k = -1;
|
||||
elseif A_out>A_in
|
||||
k = 1;
|
||||
else
|
||||
k = 0;
|
||||
end
|
||||
|
||||
dAdx = abs(A_in-A_out)/L;
|
||||
% The whole length of the reactor is divided into n small lengths
|
||||
dx = L/n;
|
||||
|
||||
x_calc = 0:dx:L;
|
||||
nsp = nSpecies(gas_calc);
|
||||
|
||||
% Initialize arrays for T, Y, and rho at each location:
|
||||
T_calc = zeros(length(x_calc),1);
|
||||
Y_calc = zeros(length(x_calc),nsp);
|
||||
rho_calc = zeros(length(x_calc),1);
|
||||
|
||||
T_calc(1) = temperature(gas_calc);
|
||||
Y_calc(1,:) = massFractions(gas_calc);
|
||||
rho_calc(1) = density(gas_calc);
|
||||
|
||||
for i = 2:length(x_calc)
|
||||
|
||||
%Solver location indicator
|
||||
fprintf('Solving reactor %d of %d\n', i, length(x_calc))
|
||||
|
||||
%--------------------------------------------------------------------------
|
||||
%------The values of variables at previous location are given as initial---
|
||||
%------values to the current iteration and the limits of the current-------
|
||||
%--------------reactor and the gas entering it are being set---------------
|
||||
%--------------------------------------------------------------------------
|
||||
inlet_soln(1) = rho_calc(i-1);
|
||||
inlet_soln(2) = T_calc(i-1);
|
||||
inlet_soln(3:nsp+2) = Y_calc(i-1,:);
|
||||
limits = [x_calc(i-1),x_calc(i)];
|
||||
set(gas_calc,'T',T_calc(i-1),'Density',rho_calc(i-1),'MoleFractions',Y_calc(i-1,:));
|
||||
options = odeset('RelTol',1.e-10,'AbsTol',1e-10,'InitialStep',1e-8,'NonNegative',1);
|
||||
%--------------------------------------------------------------------------
|
||||
%--------------------------------------------------------------------------
|
||||
% These values are passed onto the ode15s solver
|
||||
[~,y] = ode15s(@PFR_solver,limits,inlet_soln,options,gas_calc,mdot_calc,A_in,dAdx,k);
|
||||
|
||||
T_calc(i) = y(end,2);
|
||||
rho_calc(i) = y(end,1);
|
||||
Y_calc(i,:) = y(end,3:nsp+2);
|
||||
end
|
||||
|
||||
A_calc = A_in+k.*x_calc*dAdx;
|
||||
vx_calc = zeros(length(x_calc),1);
|
||||
R_calc = zeros(length(x_calc),1);
|
||||
M_calc = zeros(length(x_calc),1);
|
||||
P_calc = zeros(length(x_calc),1);
|
||||
for i=1:length(x_calc)
|
||||
% The gas is set to the solved property values at each location
|
||||
set(gas_calc,'Temperature',T_calc(i),'Density',rho_calc(i),'MassFractions',Y_calc(i,:));
|
||||
% Velocity is calculated from Mass flow rate, Area and Density
|
||||
vx_calc(i) = mdot_calc./(A_calc(i)*rho_calc(i));
|
||||
% Specific Gas Constant
|
||||
R_calc(i) = gasconstant()/meanMolecularWeight(gas_calc);
|
||||
% Mach No. is calculated from local velocity and local speed of sound
|
||||
M_calc(i) = vx_calc(i)/soundspeed(gas_calc);
|
||||
% Pressure is calculated from density, temeprature and gas constant
|
||||
P_calc(i) = rho_calc(i)*R_calc(i)*T_calc(i);
|
||||
end
|
||||
|
||||
%% Plotting
|
||||
plot(x_calc,M_calc)
|
||||
xlabel('X-Position (m)')
|
||||
ylabel('Mach No')
|
||||
title('Mach No. Variation')
|
||||
figure(2)
|
||||
plot(x_calc,A_calc)
|
||||
xlabel('X-Position (m)')
|
||||
ylabel('Area (m^2)')
|
||||
title('Reactor Profile')
|
||||
figure(3)
|
||||
plot(x_calc,T_calc)
|
||||
xlabel('X-Position (m)')
|
||||
ylabel('Temperature')
|
||||
title('Temperature Variation')
|
||||
figure(4)
|
||||
plot(x_calc,rho_calc)
|
||||
xlabel('X-Position (m)')
|
||||
ylabel('Density (kg/m^3)')
|
||||
title('Density Variation')
|
||||
figure(5)
|
||||
plot(x_calc,P_calc)
|
||||
xlabel('X-Position (m)')
|
||||
ylabel('Pressure (Pa)')
|
||||
title('Pressure Variation')
|
@ -1,219 +0,0 @@
|
||||
% Catalytic combustion of a stagnation flow on a platinum surface
|
||||
%
|
||||
% This script solves a catalytic combustion problem. A stagnation flow
|
||||
% is set up, with a gas inlet 10 cm from a platinum surface at 900
|
||||
% K. The lean, premixed methane/air mixture enters at ~ 6 cm/s (0.06
|
||||
% kg/m2/s), and burns catalytically on the platinum surface. Gas-phase
|
||||
% chemistry is included too, and has some effect very near the
|
||||
% surface.
|
||||
%
|
||||
% The catalytic combustion mechanism is from Deutschmann et al., 26th
|
||||
% Symp. (Intl.) on Combustion,1996 pp. 1747-1754
|
||||
%
|
||||
% Keywords: combustion, catalysis, 1D flow, surface chemistry
|
||||
|
||||
help catcomb;
|
||||
|
||||
clear all;
|
||||
cleanup;
|
||||
|
||||
t0 = cputime; % record the starting time
|
||||
|
||||
% Parameter values are collected here to make it easier to modify
|
||||
% them
|
||||
|
||||
p = oneatm; % pressure
|
||||
tinlet = 300.0; % inlet temperature
|
||||
tsurf = 900.0; % surface temperature
|
||||
mdot = 0.06; % kg/m^2/s
|
||||
transport = 'mixture-averaged'; % transport model
|
||||
|
||||
% We will solve first for a hydrogen/air case to
|
||||
% use as the initial estimate for the methane/air case
|
||||
|
||||
% composition of the inlet premixed gas for the hydrogen/air case
|
||||
comp1 = 'H2:0.05, O2:0.21, N2:0.78, AR:0.01';
|
||||
|
||||
% composition of the inlet premixed gas for the methane/air case
|
||||
comp2 = 'CH4:0.095, O2:0.21, N2:0.78, AR:0.01';
|
||||
|
||||
% the initial grid, in meters. The inlet/surface separation is 10 cm.
|
||||
initial_grid = [0.0 0.02 0.04 0.06 0.08 0.1]; % m
|
||||
|
||||
% numerical parameters
|
||||
tol_ss = [1.0e-8 1.0e-14]; % [rtol atol] for steady-state problem
|
||||
tol_ts = [1.0e-4 1.0e-9]; % [rtol atol] for time stepping
|
||||
|
||||
loglevel = 1; % amount of diagnostic output
|
||||
% (0 to 5)
|
||||
|
||||
refine_grid = 1; % 1 to enable refinement, 0 to
|
||||
% disable
|
||||
|
||||
%%%%%%%%%%%%%%% end of parameter list %%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%%%%%%%%%%%%%%%% create the gas object %%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% This object will be used to evaluate all thermodynamic, kinetic,
|
||||
% and transport properties
|
||||
%
|
||||
% The gas phase will be taken from the definition of phase 'gas' in
|
||||
% input file 'ptcombust.yaml,' which is a stripped-down version of
|
||||
% GRI-Mech 3.0.
|
||||
gas = Solution('ptcombust.yaml','gas',transport);
|
||||
set(gas,'T',tinlet,'P',p,'X',comp1);
|
||||
|
||||
%%%%%%%%%%%%%%%% create the interface object %%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% This object will be used to evaluate all surface chemical production
|
||||
% rates. It will be created from the interface definition 'Pt_surf'
|
||||
% in input file 'ptcombust.yaml,' which implements the reaction
|
||||
% mechanism of Deutschmann et al., 1995 for catalytic combustion on
|
||||
% platinum.
|
||||
%
|
||||
surf_phase = importInterface('ptcombust.yaml','Pt_surf',gas);
|
||||
setTemperature(surf_phase, tsurf);
|
||||
|
||||
% integrate the coverage equations in time for 1 s, holding the gas
|
||||
% composition fixed to generate a good starting estimate for the
|
||||
% coverages.
|
||||
advanceCoverages(surf_phase, 1.0);
|
||||
|
||||
% The two objects we just created are independent of the problem
|
||||
% type -- they are useful in zero-D simulations, 1-D simulations,
|
||||
% etc. Now we turn to creating the objects that are specifically
|
||||
% for 1-D simulations. These will be 'stacked' together to create
|
||||
% the complete simulation.
|
||||
|
||||
%%%%%%%%%%%%%%%% create the flow object %%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The flow object is responsible for evaluating the 1D governing
|
||||
% equations for the flow. We will initialize it with the gas
|
||||
% object, and assign it the name 'flow'.
|
||||
%
|
||||
flow = AxisymmetricFlow(gas, 'flow');
|
||||
|
||||
% set some parameters for the flow
|
||||
set(flow, 'P', p, 'grid', initial_grid, 'tol', tol_ss, 'tol-time', tol_ts);
|
||||
|
||||
%%%%%%%%%%%%%%% create the inlet %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The temperature, mass flux, and composition (relative molar) may be
|
||||
% specified. This object provides the inlet boundary conditions for
|
||||
% the flow equations.
|
||||
%
|
||||
inlt = Inlet('inlet');
|
||||
|
||||
% set the inlet parameters. Start with comp1 (hydrogen/air)
|
||||
set(inlt, 'T', tinlet, 'MassFlux', mdot, 'X', comp1);
|
||||
|
||||
%%%%%%%%%%%%%% create the surface %%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% This object provides the surface boundary conditions for the flow
|
||||
% equations. By supplying object surface_phase as an argument, the
|
||||
% coverage equations for its surface species will be added to the
|
||||
% equation set, and used to compute the surface production rates of
|
||||
% the gas-phase species.
|
||||
%
|
||||
surf = Surface('surface', surf_phase);
|
||||
setTemperature(surf,tsurf);
|
||||
|
||||
%%%%%%%%%%%%% create the stack %%%%%%%%%%%%
|
||||
%
|
||||
% Once the component parts have been created, they can be assembled
|
||||
% to create the 1D simulation.
|
||||
%
|
||||
sim1D = Stack([inlt, flow, surf]);
|
||||
|
||||
% set the initial profiles.
|
||||
setProfile(sim1D, 2, {'velocity', 'spread_rate', 'T'}, ...
|
||||
[0.0 1.0 % z/zmax
|
||||
0.06 0.0 % velocity (u)
|
||||
0.0 0.0 % spread rate (V)
|
||||
tinlet tsurf]); % T
|
||||
names = speciesNames(gas);
|
||||
for k = 1:nSpecies(gas)
|
||||
y = massFraction(inlt, k);
|
||||
setProfile(sim1D, 2, names{k}, [0 1; y y]);
|
||||
end
|
||||
sim1D
|
||||
|
||||
%setTimeStep(fl, 1.0e-5, [1, 3, 6, 12]);
|
||||
%setMaxJacAge(fl, 4, 5);
|
||||
|
||||
%%%%%%%%%%%%% solution %%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% start with the energy equation on
|
||||
enableEnergy(flow);
|
||||
|
||||
% disable the surface coverage equations, and turn off all gas and
|
||||
% surface chemistry
|
||||
setCoverageEqs(surf, 'off');
|
||||
setMultiplier(surf_phase, 0.0);
|
||||
setMultiplier(gas, 0.0);
|
||||
|
||||
% solve the problem, refining the grid if needed
|
||||
solve(sim1D, 1, refine_grid);
|
||||
|
||||
% now turn on the surface coverage equations, and turn the
|
||||
% chemistry on slowly
|
||||
setCoverageEqs(surf, 'on');
|
||||
for iter=1:6
|
||||
mult = 10.0^(iter - 6);
|
||||
setMultiplier(surf_phase, mult);
|
||||
setMultiplier(gas, mult);
|
||||
solve(sim1D, 1, refine_grid);
|
||||
end
|
||||
|
||||
% At this point, we should have the solution for the hydrogen/air
|
||||
% problem. Now switch the inlet to the methane/air composition.
|
||||
set(inlt,'X',comp2);
|
||||
|
||||
% set more stringent grid refinement criteria
|
||||
setRefineCriteria(sim1D, 2, 100.0, 0.15, 0.2);
|
||||
|
||||
% solve the problem for the final time
|
||||
solve(sim1D, loglevel, refine_grid);
|
||||
|
||||
% show the solution
|
||||
sim1D
|
||||
|
||||
% save the solution
|
||||
saveSoln(sim1D,'catcomb.yaml','energy',['solution with energy equation']);
|
||||
|
||||
%%%%%%%%%% show statistics %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
writeStats(sim1D);
|
||||
elapsed = cputime - t0;
|
||||
e = sprintf('Elapsed CPU time: %10.4g',elapsed);
|
||||
disp(e);
|
||||
|
||||
%%%%%%%%%% make plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
clf;
|
||||
subplot(3,3,1);
|
||||
plotSolution(sim1D, 'flow', 'T');
|
||||
title('Temperature [K]');
|
||||
subplot(3,3,2);
|
||||
plotSolution(sim1D, 'flow', 'u');
|
||||
title('Axial Velocity [m/s]');
|
||||
subplot(3,3,3);
|
||||
plotSolution(sim1D, 'flow', 'V');
|
||||
title('Radial Velocity / Radius [1/s]');
|
||||
subplot(3,3,4);
|
||||
plotSolution(sim1D, 'flow', 'CH4');
|
||||
title('CH4 Mass Fraction');
|
||||
subplot(3,3,5);
|
||||
plotSolution(sim1D, 'flow', 'O2');
|
||||
title('O2 Mass Fraction');
|
||||
subplot(3,3,6);
|
||||
plotSolution(sim1D, 'flow', 'CO');
|
||||
title('CO Mass Fraction');
|
||||
subplot(3,3,7);
|
||||
plotSolution(sim1D, 'flow', 'CO2');
|
||||
title('CO2 Mass Fraction');
|
||||
subplot(3,3,8);
|
||||
plotSolution(sim1D, 'flow', 'H2O');
|
||||
title('H2O Mass Fraction');
|
||||
subplot(3,3,9);
|
||||
plotSolution(sim1D, 'flow', 'H2');
|
||||
title('H2 Mass Fraction');
|
@ -1,28 +0,0 @@
|
||||
function dydt = conhp(t, y, gas, mw) %#ok<INUSL>
|
||||
% CONHP ODE system for a constant-pressure, adiabatic reactor.
|
||||
%
|
||||
% Function CONHP evaluates the system of ordinary differential
|
||||
% equations for an adiabatic, constant-pressure,
|
||||
% zero-dimensional reactor. It assumes that the 'gas' object
|
||||
% represents a reacting ideal gas mixture.
|
||||
|
||||
|
||||
% Set the state of the gas, based on the current solution vector.
|
||||
setMassFractions(gas, y(2:end), 'nonorm');
|
||||
set(gas, 'T', y(1), 'P', pressure(gas));
|
||||
nsp = nSpecies(gas);
|
||||
|
||||
% energy equation
|
||||
wdot = netProdRates(gas);
|
||||
tdot = - temperature(gas) * gasconstant * enthalpies_RT(gas)' ...
|
||||
* wdot / (density(gas)*cp_mass(gas));
|
||||
|
||||
% set up column vector for dydt
|
||||
dydt = [ tdot
|
||||
zeros(nsp, 1) ];
|
||||
|
||||
% species equations
|
||||
rrho = 1.0/density(gas);
|
||||
for i = 1:nsp
|
||||
dydt(i+1) = rrho*mw(i)*wdot(i);
|
||||
end
|
@ -1,28 +0,0 @@
|
||||
function dydt = conuv(t, y, gas, mw) %#ok<INUSL>
|
||||
% CONUV ODE system for a constant-volume, adiabatic reactor.
|
||||
%
|
||||
% Function CONUV evaluates the system of ordinary differential
|
||||
% equations for an adiabatic, constant-volume,
|
||||
% zero-dimensional reactor. It assumes that the 'gas' object
|
||||
% represents a reacting ideal gas mixture.
|
||||
|
||||
|
||||
% Set the state of the gas, based on the current solution vector.
|
||||
setMassFractions(gas, y(2:end), 'nonorm');
|
||||
set(gas, 'T', y(1), 'Rho', density(gas));
|
||||
nsp = nSpecies(gas);
|
||||
|
||||
% energy equation
|
||||
wdot = netProdRates(gas);
|
||||
tdot = - temperature(gas) * gasconstant * (enthalpies_RT(gas) - ones(nsp,1))' ...
|
||||
* wdot / (density(gas)*cv_mass(gas));
|
||||
|
||||
% set up column vector for dydt
|
||||
dydt = [ tdot
|
||||
zeros(nsp, 1) ];
|
||||
|
||||
% species equations
|
||||
rrho = 1.0/density(gas);
|
||||
for i = 1:nsp
|
||||
dydt(i+1) = rrho*mw(i)*wdot(i);
|
||||
end
|
@ -1,129 +0,0 @@
|
||||
% DIFFFLAME - An opposed-flow diffusion flame.
|
||||
% This example uses the CounterFlowDiffusionFlame function to solve an
|
||||
% opposed-flow diffusion flame for Ethane in Air. This example is the same
|
||||
% as the diffusion_flame.py example without radiation.
|
||||
%
|
||||
% Keywords: combustion, 1D flow, diffusion flame, plotting
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
|
||||
runtime = cputime; % Record the starting time
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Parameter values of inlet streams
|
||||
%
|
||||
|
||||
p = oneatm; % Pressure
|
||||
tin = 300.0; % Inlet temperature
|
||||
mdot_o = 0.72; % Air mass flux, kg/m^2/s
|
||||
mdot_f = 0.24; % Fuel mass flux, kg/m^2/s
|
||||
transport = 'mixture-averaged'; % Transport model
|
||||
% NOTE: Transport model needed if mechanism file does not have transport
|
||||
% properties.
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Set-up initial grid, loglevel, tolerances. Enable/Disable grid
|
||||
% refinement.
|
||||
%
|
||||
|
||||
initial_grid = 0.02*[0.0 0.2 0.4 0.6 0.8 1.0]; % Units: m
|
||||
tol_ss = [1.0e-5 1.0e-9]; % [rtol atol] for steady-state problem
|
||||
tol_ts = [1.0e-3 1.0e-9]; % [rtol atol] for time stepping
|
||||
loglevel = 1; % Amount of diagnostic output (0 to 5)
|
||||
refine_grid = 1; % 1 to enable refinement, 0 to disable
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Create the gas objects for the fuel and oxidizer streams. These objects
|
||||
% will be used to evaluate all thermodynamic, kinetic, and transport
|
||||
% properties.
|
||||
%
|
||||
|
||||
fuel = GRI30(transport);
|
||||
ox = GRI30(transport);
|
||||
oxcomp = 'O2:0.21, N2:0.78'; % Air composition
|
||||
fuelcomp = 'C2H6:1'; % Fuel composition
|
||||
% Set each gas mixture state with the corresponding composition.
|
||||
set(fuel,'T', tin, 'P', p, 'X', fuelcomp);
|
||||
set(ox,'T',tin,'P',p,'X', oxcomp);
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Set-up the flow object. For this problem, the AxisymmetricFlow model is
|
||||
% needed. Set the state of the flow as the fuel gas object. This is
|
||||
% arbitrary and is only used to initialize the flow object. Set the grid to
|
||||
% the initial grid defined prior, same for the tolerances.
|
||||
%
|
||||
|
||||
f = AxisymmetricFlow(fuel,'flow');
|
||||
set(f, 'P', p, 'grid', initial_grid);
|
||||
set(f, 'tol', tol_ss, 'tol-time', tol_ts);
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Create the fuel and oxidizer inlet steams. Specify the temperature, mass
|
||||
% flux, and composition correspondingly.
|
||||
%
|
||||
|
||||
% Set the oxidizer inlet.
|
||||
inlet_o = Inlet('air_inlet');
|
||||
set(inlet_o, 'T', tin, 'MassFlux', mdot_o, 'X', oxcomp);
|
||||
%
|
||||
% Set the fuel inlet.
|
||||
inlet_f = Inlet('fuel_inlet');
|
||||
set(inlet_f, 'T', tin, 'MassFlux', mdot_f, 'X', fuelcomp);
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Once the inlets have been created, they can be assembled
|
||||
% to create the flame object. Function CounterFlorDiffusionFlame
|
||||
% (in Cantera/1D) sets up the initial guess for the solution using a
|
||||
% Burke-Schumann flame. The input parameters are: fuel inlet object, flow
|
||||
% object, oxidizer inlet object, fuel gas object, oxidizer gas object, and
|
||||
% the name of the oxidizer species as in character format.
|
||||
%
|
||||
|
||||
fl = CounterFlowDiffusionFlame(inlet_f, f, inlet_o, fuel, ox, 'O2');
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Solve with fixed temperature profile first. Grid refinement is turned off
|
||||
% for this process in this example. To turn grid refinement on, change 0 to
|
||||
% 1 for last input is solve function.
|
||||
%
|
||||
|
||||
solve(fl, loglevel, 0);
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Enable the energy equation. The energy equation will now be solved to
|
||||
% compute the temperature profile. We also tighten the grid refinement
|
||||
% criteria to get an accurate final solution. The explanation of the
|
||||
% setRefineCriteria function is located on cantera.org in the Matlab User's
|
||||
% Guide and can be accessed by help setRefineCriteria
|
||||
%
|
||||
|
||||
enableEnergy(f);
|
||||
setRefineCriteria(fl, 2, 200.0, 0.1, 0.2);
|
||||
solve(fl, loglevel, refine_grid);
|
||||
saveSoln(fl,'c2h6.yaml','energy',['solution with energy equation']);
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Show statistics of solution and elapsed time.
|
||||
%
|
||||
|
||||
writeStats(fl);
|
||||
elapsed = cputime - runtime;
|
||||
e = sprintf('Elapsed CPU time: %10.4g',elapsed);
|
||||
disp(e);
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Make a single plot showing temperature and mass fraction of select
|
||||
% species along axial distance from fuel inlet to air inlet.
|
||||
%
|
||||
|
||||
z = grid(fl, 'flow'); % Get grid points of flow
|
||||
spec = speciesNames(fuel); % Get species names in gas
|
||||
T = solution(fl, 'flow', 'T'); % Get temperature solution
|
||||
for i = 1:length(spec)
|
||||
% Get mass fraction of all species from solution
|
||||
y(i,:) = solution(fl, 'flow', spec{i});
|
||||
end
|
||||
j = speciesIndex(fuel, 'O2'); % Get index of O2 in gas object
|
||||
k = speciesIndex(fuel, 'H2O'); % Get index of H2O in gas object
|
||||
l = speciesIndex(fuel, 'C2H6'); % Get index of C2H6 in gas object
|
||||
m = speciesIndex(fuel, 'CO2'); % Get index of CO2 in gas object
|
||||
clf;
|
||||
yyaxis left
|
||||
plot(z,T)
|
||||
xlabel('z (m)');
|
||||
ylabel('Temperature (K)');
|
||||
yyaxis right
|
||||
plot(z,y(j,:),'r',z,y(k,:),'g',z,y(l,:),'m',z,y(m,:),'b');
|
||||
ylabel('Mass Fraction');
|
||||
legend('T','O2','H2O','C2H6','CO2');
|
@ -1,62 +0,0 @@
|
||||
function equil(g)
|
||||
% EQUIL a chemical equilibrium example.
|
||||
%
|
||||
% This example computes the adiabatic flame temperature and
|
||||
% equilibrium composition for a methane/air mixture as a function of
|
||||
% equivalence ratio.
|
||||
%
|
||||
% Keywords: combustion, equilibrium, plotting
|
||||
help equil
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('gri30.yaml');
|
||||
end
|
||||
|
||||
nsp = nSpecies(gas);
|
||||
|
||||
% find methane, nitrogen, and oxygen indices
|
||||
ich4 = speciesIndex(gas,'CH4');
|
||||
io2 = speciesIndex(gas,'O2');
|
||||
in2 = speciesIndex(gas,'N2');
|
||||
|
||||
nPhis = 50;
|
||||
phi = linspace(0.2, 2.70, nPhis);
|
||||
tad(nPhis) = 0;
|
||||
xeq(nsp,nPhis) = 0;
|
||||
|
||||
for i = 1:nPhis
|
||||
x = zeros(nsp,1);
|
||||
x(ich4,1) = phi(i);
|
||||
x(io2,1) = 2.0;
|
||||
x(in2,1) = 7.52;
|
||||
set(gas,'Temperature',300.0,'Pressure',101325.0,'MoleFractions',x);
|
||||
equilibrate(gas,'HP');
|
||||
tad(i) = temperature(gas);
|
||||
xeq(:,i) = moleFractions(gas);
|
||||
end
|
||||
|
||||
% make plots
|
||||
clf;
|
||||
subplot(1,2,1);
|
||||
plot(phi,tad);
|
||||
xlabel('Equivalence Ratio');
|
||||
ylabel('Temperature (K)');
|
||||
title('Adiabatic Flame Temperature');
|
||||
|
||||
subplot(1,2,2);
|
||||
semilogy(phi,xeq);
|
||||
axis([phi(1) phi(50) 1.0e-14 1]);
|
||||
%legend(speciesName(gas,1:nsp),1);
|
||||
j = 10;
|
||||
for k = 1:nsp
|
||||
text(phi(j),1.5*xeq(k,j),speciesName(gas,k))
|
||||
j = j + 2;
|
||||
if j > 46
|
||||
j = 10;
|
||||
end
|
||||
end
|
||||
xlabel('Equivalence Ratio');
|
||||
ylabel('Mole Fraction');
|
||||
title('Equilibrium Composition');
|
@ -1,86 +0,0 @@
|
||||
function f = flame(gas, left, flow, right)
|
||||
% FLAME - create a flame object.
|
||||
%
|
||||
% gas -- object representing the gas. This object will be used to
|
||||
% compute all required thermodynamic, kinetic, and transport
|
||||
% properties. The state of this object should be set
|
||||
% to an estimate of the gas state emerging from the
|
||||
% burner before calling StagnationFlame.
|
||||
%
|
||||
% left -- object representing the burner, which must be
|
||||
% created using function Inlet.
|
||||
%
|
||||
% flow -- object representing the flow, created with
|
||||
% function AxisymmetricFlow.
|
||||
%
|
||||
% right -- object representing the surface.
|
||||
%
|
||||
|
||||
% Check input parameters
|
||||
if nargin ~= 4
|
||||
error('wrong number of input arguments.');
|
||||
end
|
||||
|
||||
if ~isIdealGas(gas)
|
||||
error('gas object must represent an ideal gas mixture.');
|
||||
end
|
||||
if ~isInlet(left)
|
||||
error('burner object of wrong type.');
|
||||
end
|
||||
if ~isFlow(flow)
|
||||
error('flow object of wrong type.');
|
||||
end
|
||||
|
||||
flametype = 0;
|
||||
if isSurface(right)
|
||||
flametype = 1;
|
||||
elseif isInlet(right)
|
||||
flametype = 3;
|
||||
end
|
||||
|
||||
% create the container object
|
||||
f = Stack([left flow right]);
|
||||
|
||||
% set default initial profiles.
|
||||
rho0 = density(gas);
|
||||
|
||||
% find the adiabatic flame temperature and corresponding
|
||||
% equilibrium composition
|
||||
equilibrate(gas, 'HP');
|
||||
teq = temperature(gas);
|
||||
yeq = massFractions(gas);
|
||||
|
||||
z1 = 0.2;
|
||||
mdot0 = massFlux(left);
|
||||
mdot1 = massFlux(right);
|
||||
t0 = temperature(left);
|
||||
if flametype == 0
|
||||
t1 = teq;
|
||||
mdot1 = -mdot0;
|
||||
else
|
||||
t1 = temperature(right);
|
||||
end
|
||||
setProfile(f, 2, {'velocity', 'spread_rate'}, ...
|
||||
[0.0 1.0
|
||||
mdot0/rho0 -mdot1/rho0
|
||||
0.0 0.0]);
|
||||
setProfile(f, 2, 'T', [0.0 z1 1.0; t0 2000.0 t1]);
|
||||
|
||||
for n = 1:nSpecies(gas)
|
||||
nm = speciesName(gas,n);
|
||||
if strcmp(nm,'H') | strcmp(nm,'OH') | strcmp(nm,'O') | strcmp(nm,'HO2')
|
||||
yint = 1.0*yeq(n);
|
||||
else
|
||||
yint = yeq(n);
|
||||
end
|
||||
if flametype == 3
|
||||
y1 = massFraction(right, n);
|
||||
else
|
||||
y1 = yeq(n);
|
||||
end
|
||||
setProfile(f, 2, nm, [0 z1 1
|
||||
massFraction(left, n) yint y1]);
|
||||
end
|
||||
|
||||
% set minimal grid refinement criteria
|
||||
setRefineCriteria(f, 2, 10.0, 0.8, 0.8);
|
@ -1,113 +0,0 @@
|
||||
% FLAME1 - A burner-stabilized flat flame
|
||||
%
|
||||
% This script simulates a burner-stablized lean hydrogen-oxygen flame
|
||||
% at low pressure.
|
||||
%
|
||||
% Keywords: combustion, 1D flow, burner-stabilized flame, plotting
|
||||
|
||||
help flame1
|
||||
|
||||
t0 = cputime; % record the starting time
|
||||
|
||||
% parameter values
|
||||
p = 0.05*oneatm; % pressure
|
||||
tburner = 373.0; % burner temperature
|
||||
mdot = 0.06; % kg/m^2/s
|
||||
|
||||
rxnmech = 'h2o2.yaml'; % reaction mechanism file
|
||||
comp = 'H2:1.8, O2:1, AR:7'; % premixed gas composition
|
||||
|
||||
initial_grid = [0.0 0.02 0.04 0.06 0.08 0.1 ...
|
||||
0.15 0.2 0.4 0.49 0.5]; % m
|
||||
|
||||
tol_ss = [1.0e-5 1.0e-13]; % [rtol atol] for steady-state
|
||||
% problem
|
||||
tol_ts = [1.0e-4 1.0e-9]; % [rtol atol] for time stepping
|
||||
|
||||
loglevel = 1; % amount of diagnostic output (0
|
||||
% to 5)
|
||||
|
||||
refine_grid = 1; % 1 to enable refinement, 0 to
|
||||
% disable
|
||||
max_jacobian_age = [5, 10];
|
||||
|
||||
%%%%%%%%%%%%%%%% create the gas object %%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% This object will be used to evaluate all thermodynamic, kinetic,
|
||||
% and transport properties
|
||||
%
|
||||
gas = Solution(rxnmech, 'ohmech', 'mixture-averaged');
|
||||
|
||||
% set its state to that of the unburned gas at the burner
|
||||
set(gas,'T', tburner, 'P', p, 'X', comp);
|
||||
|
||||
%%%%%%%%%%%%%%%% create the flow object %%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
f = AxisymmetricFlow(gas,'flow');
|
||||
set(f, 'P', p, 'grid', initial_grid);
|
||||
set(f, 'tol', tol_ss, 'tol-time', tol_ts);
|
||||
|
||||
%%%%%%%%%%%%%%% create the burner %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The burner is an Inlet object. The temperature, mass flux,
|
||||
% and composition (relative molar) may be specified.
|
||||
%
|
||||
burner = Inlet('burner');
|
||||
set(burner, 'T', tburner, 'MassFlux', mdot, 'X', comp);
|
||||
|
||||
%%%%%%%%%%%%%% create the outlet %%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The type of flame is determined by the object that terminates
|
||||
% the domain. An Outlet object imposes zero gradient boundary
|
||||
% conditions for the temperature and mass fractions, and zero
|
||||
% radial velocity and radial pressure gradient.
|
||||
%
|
||||
s = Outlet('out');
|
||||
|
||||
%%%%%%%%%%%%% create the flame object %%%%%%%%%%%%
|
||||
%
|
||||
% Once the component parts have been created, they can be assembled
|
||||
% to create the flame object.
|
||||
%
|
||||
fl = flame(gas, burner, f, s);
|
||||
setMaxJacAge(fl, max_jacobian_age(1), max_jacobian_age(2));
|
||||
|
||||
% if the starting solution is to be read from a previously-saved
|
||||
% solution, uncomment this line and edit the file name and solution id.
|
||||
%restore(fl,'h2flame.yaml', 'energy')
|
||||
|
||||
solve(fl, loglevel, refine_grid);
|
||||
|
||||
%%%%%%%%%%%% enable the energy equation %%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The energy equation will now be solved to compute the
|
||||
% temperature profile. We also tighten the grid refinement
|
||||
% criteria to get an accurate final solution.
|
||||
%
|
||||
|
||||
enableEnergy(f);
|
||||
setRefineCriteria(fl, 2, 200.0, 0.05, 0.1);
|
||||
solve(fl, 1, 1);
|
||||
saveSoln(fl,'h2flame.yaml','energy',['solution with energy equation']);
|
||||
|
||||
%%%%%%%%%% show statistics %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
writeStats(fl);
|
||||
elapsed = cputime - t0;
|
||||
e = sprintf('Elapsed CPU time: %10.4g',elapsed);
|
||||
disp(e);
|
||||
|
||||
%%%%%%%%%% make plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
clf;
|
||||
subplot(2,2,1);
|
||||
plotSolution(fl, 'flow', 'T');
|
||||
title('Temperature [K]');
|
||||
subplot(2,2,2);
|
||||
plotSolution(fl, 'flow', 'u');
|
||||
title('Axial Velocity [m/s]');
|
||||
subplot(2,2,3);
|
||||
plotSolution(fl, 'flow', 'H2O');
|
||||
title('H2O Mass Fraction');
|
||||
subplot(2,2,4);
|
||||
plotSolution(fl, 'flow', 'O2');
|
||||
title('O2 Mass Fraction');
|
@ -1,112 +0,0 @@
|
||||
% FLAME1 - An axisymmetric stagnation-point non-premixed flame
|
||||
%
|
||||
% This script simulates a stagnation-point ethane-air flame.
|
||||
%
|
||||
% Keywords: combustion, 1D flow, strained flame, diffusion flame, plotting
|
||||
|
||||
t0 = cputime; % record the starting time
|
||||
|
||||
% parameter values
|
||||
p = oneatm; % pressure
|
||||
tin = 300.0; % inlet temperature
|
||||
mdot_o = 0.72; % air, kg/m^2/s
|
||||
mdot_f = 0.24; % fuel, kg/m^2/s
|
||||
|
||||
rxnmech = 'gri30.yaml'; % reaction mechanism file
|
||||
comp1 = 'O2:0.21, N2:0.78, AR:0.01'; % air composition
|
||||
comp2 = 'C2H6:1'; % fuel composition
|
||||
|
||||
initial_grid = 0.02*[0.0 0.2 0.4 0.6 0.8 1.0]; % m
|
||||
|
||||
tol_ss = [1.0e-5 1.0e-13]; % [rtol atol] for steady-state
|
||||
% problem
|
||||
tol_ts = [1.0e-4 1.0e-13]; % [rtol atol] for time stepping
|
||||
|
||||
loglevel = 1; % amount of diagnostic output (0
|
||||
% to 5)
|
||||
|
||||
refine_grid = 1; % 1 to enable refinement, 0 to
|
||||
% disable
|
||||
|
||||
%%%%%%%%%%%%%%%% create the gas object %%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% This object will be used to evaluate all thermodynamic, kinetic,
|
||||
% and transport properties
|
||||
%
|
||||
gas = Solution(rxnmech,'gri30','mixture-averaged');
|
||||
|
||||
% set its state to that of the fuel (arbitrary)
|
||||
set(gas,'T', tin, 'P', p, 'X', comp2);
|
||||
|
||||
%%%%%%%%%%%%%%%% create the flow object %%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
f = AxisymmetricFlow(gas,'flow');
|
||||
|
||||
set(f, 'P', p, 'grid', initial_grid);
|
||||
set(f, 'tol', tol_ss, 'tol-time', tol_ts);
|
||||
|
||||
%%%%%%%%%%%%%%% create the air inlet %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The temperature, mass flux, and composition (relative molar) may be
|
||||
% specified.
|
||||
%
|
||||
inlet_o = Inlet('air_inlet');
|
||||
set(inlet_o, 'T', tin, 'MassFlux', mdot_o, 'X', comp1);
|
||||
|
||||
%%%%%%%%%%%%%% create the fuel inlet %%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
inlet_f = Inlet('fuel_inlet');
|
||||
set(inlet_f, 'T', tin, 'MassFlux', mdot_f, 'X', comp2);
|
||||
|
||||
%%%%%%%%%%%%% create the flame object %%%%%%%%%%%%
|
||||
%
|
||||
% Once the component parts have been created, they can be assembled
|
||||
% to create the flame object.
|
||||
%
|
||||
fl = flame(gas, inlet_o, f, inlet_f);
|
||||
|
||||
% if the starting solution is to be read from a previously-saved
|
||||
% solution, uncomment this line and edit the file name and solution id.
|
||||
%restore(fl,'c2h6-flame.yaml', 'energy')
|
||||
|
||||
% solve with fixed temperature profile first
|
||||
solve(fl, loglevel, refine_grid);
|
||||
|
||||
%%%%%%%%%%%% enable the energy equation %%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% The energy equation will now be solved to compute the
|
||||
% temperature profile. We also tighten the grid refinement
|
||||
% criteria to get an accurate final solution.
|
||||
%
|
||||
|
||||
enableEnergy(f);
|
||||
setRefineCriteria(fl, 2, 200.0, 0.1, 0.1);
|
||||
solve(fl, loglevel, refine_grid);
|
||||
saveSoln(fl,'c2h6-flame.yaml','energy',['solution with energy equation']);
|
||||
|
||||
%%%%%%%%%% show statistics %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
writeStats(fl);
|
||||
elapsed = cputime - t0;
|
||||
e = sprintf('Elapsed CPU time: %10.4g',elapsed);
|
||||
disp(e);
|
||||
|
||||
%%%%%%%%%% make plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
figure(1);
|
||||
subplot(2,3,1);
|
||||
plotSolution(fl, 'flow', 'T');
|
||||
title('Temperature [K]');
|
||||
subplot(2,3,2);
|
||||
plotSolution(fl, 'flow', 'C2H6');
|
||||
title('C2H6 Mass Fraction');
|
||||
subplot(2,3,3);
|
||||
plotSolution(fl, 'flow', 'O2');
|
||||
title('O2 Mass Fraction');
|
||||
subplot(2,3,4);
|
||||
plotSolution(fl, 'flow', 'CH');
|
||||
title('CH Mass Fraction');
|
||||
subplot(2,3,5);
|
||||
plotSolution(fl, 'flow', 'V');
|
||||
title('Radial Velocity / Radius [s^-1]');
|
||||
subplot(2,3,6);
|
||||
plotSolution(fl, 'flow', 'u');
|
||||
title('Axial Velocity [m/s]');
|
@ -1,102 +0,0 @@
|
||||
function plotdata = ignite(g)
|
||||
% IGNITE Zero-dimensional kinetics: adiabatic, constant pressure.
|
||||
%
|
||||
% This example solves the same problem as 'reactor1,' but does
|
||||
% it using one of MATLAB's ODE integrators, rather than using the
|
||||
% Cantera Reactor class.
|
||||
%
|
||||
% Keywords: combustion, reactor network, ignition delay, plotting
|
||||
|
||||
help ignite
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('gri30.yaml');
|
||||
end
|
||||
|
||||
% set the initial conditions
|
||||
|
||||
set(gas,'T',1001.0,'P',oneatm,'X','H2:2,O2:1,N2:4');
|
||||
|
||||
y0 = [intEnergy_mass(gas)
|
||||
1.0/density(gas)
|
||||
massFractions(gas)];
|
||||
|
||||
time_interval = [0 0.001];
|
||||
options = odeset('RelTol',1.e-5,'AbsTol',1.e-12,'Stats','on');
|
||||
|
||||
t0 = cputime;
|
||||
out = ode15s(@reactor_ode,time_interval,y0,options,gas,@vdot,@area,@heatflux);
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
plotdata = output(out,gas);
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% the functions below may be defined arbitrarily to set the reactor
|
||||
% boundary conditions - the rate of change of volume, the heat
|
||||
% flux, and the area.
|
||||
|
||||
% Rate of change of volume. Any arbirtrary function may be implemented.
|
||||
% Input arguments:
|
||||
% t time
|
||||
% vol volume
|
||||
% gas ideal gas object
|
||||
|
||||
function v = vdot(t, vol, gas)
|
||||
%v = 0.0; %uncomment for constant volume
|
||||
v = 1.e11 * (pressure(gas) - 101325.0); % holds pressure very
|
||||
% close to 1 atm
|
||||
|
||||
% heat flux (W/m^2).
|
||||
function q = heatflux(t, gas)
|
||||
q = 0.0; % adiabatic
|
||||
|
||||
% surface area (m^2). Used only to compute heat transfer.
|
||||
function a = area(t,vol)
|
||||
a = 1.0;
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% Since the solution variables used by the 'reactor' function are
|
||||
% not necessarily those desired for output, this function is called
|
||||
% after the integration is complete to generate the desired
|
||||
% outputs.
|
||||
|
||||
function pv = output(s, gas)
|
||||
times = s.x;
|
||||
soln = s.y;
|
||||
[~,n] = size(times);
|
||||
pv = zeros(nSpecies(gas) + 4, n);
|
||||
|
||||
set(gas,'T',1001.0,'P',oneatm);
|
||||
|
||||
for j = 1:n
|
||||
ss = soln(:,j);
|
||||
y = ss(3:end);
|
||||
mass = sum(y);
|
||||
u_mass = ss(1)/mass;
|
||||
v_mass = ss(2)/mass;
|
||||
setMassFractions(gas, y);
|
||||
setState_UV(gas, [u_mass v_mass]);
|
||||
|
||||
pv(1,j) = times(j);
|
||||
pv(2,j) = temperature(gas);
|
||||
pv(3,j) = density(gas);
|
||||
pv(4,j) = pressure(gas);
|
||||
pv(5:end,j) = y;
|
||||
end
|
||||
|
||||
% plot the temperature and OH mass fractions.
|
||||
figure(1);
|
||||
plot(pv(1,:),pv(2,:));
|
||||
xlabel('time');
|
||||
ylabel('Temperature');
|
||||
title(['Final T = ' num2str(pv(2,end)) ' K']);
|
||||
|
||||
figure(2);
|
||||
ioh = speciesIndex(gas,'OH');
|
||||
plot(pv(1,:),pv(4+ioh,:));
|
||||
xlabel('time');
|
||||
ylabel('Mass Fraction');
|
||||
title('OH Mass Fraction');
|
@ -1,38 +0,0 @@
|
||||
function ignite_hp(gas)
|
||||
% IGNITE_HP Solves the same ignition problem as 'ignite', but uses function
|
||||
% conhp instead of reactor.
|
||||
%
|
||||
% Keywords: combustion, user-defined model, ignition delay, plotting
|
||||
|
||||
help ignite_hp
|
||||
|
||||
if nargin == 0
|
||||
gas = Solution('h2o2.yaml', 'ohmech', 'none');
|
||||
end
|
||||
|
||||
mw = molecularWeights(gas);
|
||||
set(gas,'T',1001.0,'P',oneatm,'X','H2:2,O2:1,N2:4');
|
||||
|
||||
y0 = [temperature(gas)
|
||||
massFractions(gas)];
|
||||
tel = [0 0.001];
|
||||
options = odeset('RelTol',1.e-5,'AbsTol',1.e-12,'Stats','on');
|
||||
t0 = cputime;
|
||||
out = ode15s(@conhp,tel,y0,options,gas,mw);
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
if nargout == 0
|
||||
% plot the temperature and OH mole fractions.
|
||||
figure(1);
|
||||
plot(out.x,out.y(1,:));
|
||||
xlabel('time');
|
||||
ylabel('Temperature');
|
||||
title(['Final T = ' num2str(out.y(1,end)) ' K']);
|
||||
|
||||
figure(2);
|
||||
ioh = speciesIndex(gas,'OH');
|
||||
plot(out.x,out.y(1+ioh,:));
|
||||
xlabel('time');
|
||||
ylabel('Mass Fraction');
|
||||
title('OH Mass Fraction');
|
||||
end
|
@ -1,38 +0,0 @@
|
||||
function ignite_uv(gas)
|
||||
% IGNITE_UV Solves the same ignition problem as 'ignite2', except
|
||||
% that function conuv is used instead of reactor.
|
||||
%
|
||||
% Keywords: combustion, user-defined model, ignition delay, plotting
|
||||
|
||||
help ignite_uv
|
||||
|
||||
if nargin == 0
|
||||
gas = Solution('h2o2.yaml', 'ohmech', 'none');
|
||||
end
|
||||
|
||||
mw = molecularWeights(gas);
|
||||
set(gas,'T',1001.0,'P',oneatm,'X','H2:2,O2:1,N2:4');
|
||||
|
||||
y0 = [temperature(gas)
|
||||
massFractions(gas)];
|
||||
tel = [0 0.001];
|
||||
options = odeset('RelTol',1.e-5,'AbsTol',1.e-12,'Stats','on');
|
||||
t0 = cputime;
|
||||
out = ode15s(@conuv,tel,y0,options,gas,mw);
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
if nargout == 0
|
||||
% plot the temperature and OH mole fractions.
|
||||
figure(1);
|
||||
plot(out.x,out.y(1,:));
|
||||
xlabel('time');
|
||||
ylabel('Temperature');
|
||||
title(['Final T = ' num2str(out.y(1,end)) ' K']);
|
||||
|
||||
figure(2);
|
||||
ioh = speciesIndex(gas,'OH');
|
||||
plot(out.x,out.y(1+ioh,:));
|
||||
xlabel('time');
|
||||
ylabel('Mass Fraction');
|
||||
title('OH Mass Fraction');
|
||||
end
|
@ -1,59 +0,0 @@
|
||||
function isentropic(g)
|
||||
% ISENTROPIC isentropic, adiabatic flow example
|
||||
%
|
||||
% In this example, the area ratio vs. Mach number curve is
|
||||
% computed for a hydrogen/nitrogen gas mixture.
|
||||
%
|
||||
% Keywords: thermodynamics, compressible flow, plotting
|
||||
|
||||
help isentropic
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('h2o2.yaml');
|
||||
end
|
||||
|
||||
% set the stagnation state
|
||||
set(gas,'T',1200.0,'P',10.0*oneatm,'X','H2:1,N2:0.1');
|
||||
s0 = entropy_mass(gas);
|
||||
h0 = enthalpy_mass(gas);
|
||||
p0 = pressure(gas);
|
||||
|
||||
mdot = 1; % arbitrary
|
||||
|
||||
mach = [];
|
||||
a = [];
|
||||
i = 1;
|
||||
amin = 1.e14;
|
||||
|
||||
% compute values for a range of pressure ratios
|
||||
for r = 0.005:0.0025:0.995
|
||||
p = p0*r;
|
||||
|
||||
% set the state using (p,s0)
|
||||
set(gas,'P',p,'S',s0);
|
||||
|
||||
h = enthalpy_mass(gas);
|
||||
rho = density(gas);
|
||||
|
||||
v2 = 2.0*(h0 - h); % h + V^2/2 = h0
|
||||
v = sqrt(v2);
|
||||
a(i) = mdot/(rho*v); % rho*v*A = constant
|
||||
|
||||
if a(i) < amin
|
||||
amin = a(i);
|
||||
end
|
||||
mach(i) = v/soundspeed(gas);
|
||||
i = i + 1;
|
||||
end
|
||||
|
||||
a = a/amin;
|
||||
|
||||
% plot results
|
||||
|
||||
clf;
|
||||
plot(mach,a);
|
||||
ylabel('Area Ratio');
|
||||
xlabel('Mach Number');
|
||||
title('Isentropic Flow: Area Ratio vs. Mach Number');
|
@ -1,136 +0,0 @@
|
||||
% This example file calculates the cell voltage of a lithium-ion battery
|
||||
% at given temperature, pressure, current, and range of state of charge (SOC).
|
||||
%
|
||||
% The thermodynamics are based on a graphite anode and a LiCoO2 cathode,
|
||||
% modeled using the 'BinarySolutionTabulatedThermo' class.
|
||||
% Further required cell parameters are the electrolyte ionic resistance, the
|
||||
% stoichiometry ranges of the active materials (electrode balancing), and the
|
||||
% surface area of the active materials.
|
||||
%
|
||||
% The functionality of this example is presented in greater detail in the
|
||||
% reference (which also describes the derivation of the
|
||||
% BinarySolutionTabulatedThermo class):
|
||||
%
|
||||
% Reference:
|
||||
% M. Mayur, S. C. DeCaluwe, B. L. Kee, W. G. Bessler, “Modeling and simulation
|
||||
% of the thermodynamics of lithium-ion battery intercalation materials in the
|
||||
% open-source software Cantera,” Electrochim. Acta 323, 134797 (2019),
|
||||
% https://doi.org/10.1016/j.electacta.2019.134797
|
||||
%
|
||||
% Keywords: surface chemistry, kinetics, electrochemistry, battery, plotting
|
||||
|
||||
% -----------------------------------------------------------------------------
|
||||
% Input
|
||||
% -----------------------------------------------------------------------------
|
||||
|
||||
% Operation parameters
|
||||
SOC = 0:0.02:1; % [-] Input state of charge (0...1) (can be a vector)
|
||||
I_app = -1; % [A] Externally-applied current, negative for discharge
|
||||
T = 293; % [K] Temperature
|
||||
P = oneatm; % [Pa] Pressure
|
||||
|
||||
% Cell properties
|
||||
inputFile = 'lithium_ion_battery.yaml'; % Cantera input file name
|
||||
R_elyt = 0.0384; % [Ohm] Electrolyte resistance
|
||||
S_ca = 1.1167; % [m^2] Cathode total active material surface area
|
||||
S_an = 0.7824; % [m^2] Anode total active material surface area
|
||||
|
||||
% Electrode balancing: The "balancing" of the electrodes relates the chemical
|
||||
% composition (lithium mole fraction in the active materials) to the macroscopic
|
||||
% cell-level state of charge.
|
||||
X_Li_an_0 = 0.01; % [-] anode Li mole fraction at SOC = 0 %
|
||||
X_Li_an_1 = 0.75; % [-] anode Li mole fraction at SOC = 100 %
|
||||
X_Li_ca_0 = 0.99; % [-] cathode Li mole fraction at SOC = 0 %
|
||||
X_Li_ca_1 = 0.49; % [-] cathode Li mole fraction at SOC = 100 %
|
||||
|
||||
% -----------------------------------------------------------------------------
|
||||
% Calculations
|
||||
% -----------------------------------------------------------------------------
|
||||
|
||||
% Calculate mole fractions from SOC
|
||||
X_Li_an = (X_Li_an_1-X_Li_an_0)*SOC+X_Li_an_0; % anode balancing
|
||||
X_Li_ca = (X_Li_ca_0-X_Li_ca_1)*(1-SOC)+X_Li_ca_1; % cathode balancing
|
||||
|
||||
% Import all Cantera phases
|
||||
anode = Solution(inputFile, 'anode');
|
||||
cathode = Solution(inputFile, 'cathode');
|
||||
elde = Solution(inputFile, 'electron');
|
||||
elyt = Solution(inputFile, 'electrolyte');
|
||||
anode_interface = Interface(inputFile, 'edge_anode_electrolyte', anode, elde, elyt);
|
||||
cathode_interface = Interface(inputFile, 'edge_cathode_electrolyte', cathode, elde, elyt);
|
||||
|
||||
% Set the temperatures and pressures of all phases
|
||||
set(anode,'T',T,'P',P);
|
||||
set(cathode,'T',T,'P',P);
|
||||
set(elde,'T',T,'P',P);
|
||||
set(elyt,'T',T,'P',P);
|
||||
set(anode_interface,'T',T,'P',P);
|
||||
set(cathode_interface,'T',T,'P',P);
|
||||
|
||||
% Calculate cell voltage, separately for each entry of the input vectors
|
||||
V_cell = zeros(length(SOC),1);
|
||||
phi_l_an = 0;
|
||||
phi_s_ca = 0;
|
||||
for i = 1:length(SOC)
|
||||
% Set anode electrode potential to 0
|
||||
phi_s_an = 0;
|
||||
|
||||
% Calculate anode electrolyte potential
|
||||
phi_l_an = fzero(@(E) anode_curr(phi_s_an,E,X_Li_an(i),anode,elde,elyt,anode_interface,S_an)-I_app, phi_l_an);
|
||||
|
||||
% Calculate cathode electrolyte potential
|
||||
phi_l_ca = phi_l_an + I_app*R_elyt;
|
||||
|
||||
% Calculate cathode electrode potential
|
||||
phi_s_ca = fzero(@(E) cathode_curr(E,phi_l_ca,X_Li_ca(i),cathode,elde,elyt,cathode_interface,S_ca)-I_app, phi_s_ca);
|
||||
|
||||
% Calculate cell voltage
|
||||
V_cell(i) = phi_s_ca - phi_s_an;
|
||||
end
|
||||
|
||||
% Let's plot the cell voltage, as a function of the state of charge:
|
||||
figure(1);
|
||||
plot(SOC*100,V_cell,'linewidth',2.5)
|
||||
ylim([2.5,4.3])
|
||||
xlabel('State of charge / %')
|
||||
ylabel('Cell voltage / V')
|
||||
set(gca,'fontsize',14)
|
||||
|
||||
|
||||
%--------------------------------------------------------------------------
|
||||
% Helper functions
|
||||
% -----------------------------------------------------------------------------
|
||||
|
||||
% This function returns the Cantera calculated anode current (in A)
|
||||
function anCurr = anode_curr(phi_s,phi_l,X_Li_an,anode,elde,elyt,anode_interface,S_an)
|
||||
% Set the active material mole fraction
|
||||
set(anode,'X',['Li[anode]:' num2str(X_Li_an) ', V[anode]:' num2str(1-X_Li_an)]);
|
||||
|
||||
% Set the electrode and electrolyte potential
|
||||
setElectricPotential(elde,phi_s);
|
||||
setElectricPotential(elyt,phi_l);
|
||||
|
||||
% Get the net reaction rate at the anode-side interface
|
||||
% Reaction according to YAML file: Li+[elyt] + V[anode] + electron <=> Li[anode]
|
||||
r = rop_net(anode_interface); % [kmol/m2/s]
|
||||
|
||||
% Calculate the current. Should be negative for cell discharge.
|
||||
anCurr = r*faradayconstant*S_an; %
|
||||
end
|
||||
|
||||
% This function returns the Cantera calculated cathode current (in A)
|
||||
function caCurr = cathode_curr(phi_s,phi_l,X_Li_ca,cathode,elde,elyt,cathode_interface,S_ca)
|
||||
% Set the active material mole fractions
|
||||
set(cathode,'X',['Li[cathode]:' num2str(X_Li_ca) ', V[cathode]:' num2str(1-X_Li_ca)]);
|
||||
|
||||
% Set the electrode and electrolyte potential
|
||||
setElectricPotential(elde,phi_s);
|
||||
setElectricPotential(elyt,phi_l);
|
||||
|
||||
% Get the net reaction rate at the cathode-side interface
|
||||
% Reaction according to YAML file: Li+[elyt] + V[cathode] + electron <=> Li[cathode]
|
||||
r = rop_net(cathode_interface); % [kmol/m2/s]
|
||||
|
||||
% Calculate the current. Should be negative for cell discharge.
|
||||
caCurr = r*faradayconstant*S_ca*(-1); %
|
||||
end
|
@ -1,106 +0,0 @@
|
||||
function periodic_cstr
|
||||
%
|
||||
% A CSTR with steady inputs but periodic interior state.
|
||||
%
|
||||
% A stoichiometric hydrogen/oxygen mixture is introduced and reacts to produce
|
||||
% water. But since water has a large efficiency as a third body in the chain
|
||||
% termination reaction
|
||||
%
|
||||
% H + O2 + M = HO2 + M
|
||||
%
|
||||
% as soon as a significant amount of water is produced the reaction
|
||||
% stops. After enough time has passed that the water is exhausted from
|
||||
% the reactor, the mixture explodes again and the process
|
||||
% repeats. This explanation can be verified by decreasing the rate for
|
||||
% reaction 7 in file 'h2o2.yaml' and re-running the example.
|
||||
%
|
||||
% Acknowledgments: The idea for this example and an estimate of the
|
||||
% conditions needed to see the oscillations came from Bob Kee,
|
||||
% Colorado School of Mines
|
||||
%
|
||||
% Keywords: combustion, reactor network, well-stirred reactor, plotting
|
||||
|
||||
help periodic_cstr
|
||||
|
||||
% create the gas mixture
|
||||
gas = Solution('h2o2.yaml');
|
||||
|
||||
% pressure = 60 Torr, T = 770 K
|
||||
p = 60.0*133.3;
|
||||
t = 770.0;
|
||||
|
||||
OneAtm = 1.01325e5;
|
||||
|
||||
set(gas,'T', 300.0, 'P', p, 'X', 'H2:2, O2:1');
|
||||
|
||||
% create an upstream reservoir that will supply the reactor. The
|
||||
% temperature, pressure, and composition of the upstream reservoir are
|
||||
% set to those of the 'gas' object at the time the reservoir is
|
||||
% created.
|
||||
upstream = Reservoir(gas);
|
||||
|
||||
% Now set the gas to the initial temperature of the reactor, and create
|
||||
% the reactor object.
|
||||
set(gas, 'T', t, 'P', p);
|
||||
cstr = IdealGasReactor(gas);
|
||||
|
||||
% Set its volume to 10 cm^3. In this problem, the reactor volume is
|
||||
% fixed, so the initial volume is the volume at all later times.
|
||||
setInitialVolume(cstr, 10.0*1.0e-6);
|
||||
|
||||
% We need to have heat loss to see the oscillations. Create a
|
||||
% reservoir to represent the environment, and initialize its
|
||||
% temperature to the reactor temperature.
|
||||
env = Reservoir(gas);
|
||||
|
||||
% Create a heat-conducting wall between the reactor and the
|
||||
% environment. Set its area, and its overall heat transfer
|
||||
% coefficient. Larger U causes the reactor to be closer to isothermal.
|
||||
% If U is too small, the gas ignites, and the temperature spikes and
|
||||
% stays high.
|
||||
w = Wall;
|
||||
install(w, cstr, env);
|
||||
setArea(w, 1.0);
|
||||
setHeatTransferCoeff(w, 0.02);
|
||||
|
||||
% Connect the upstream reservoir to the reactor with a mass flow
|
||||
% controller (constant mdot). Set the mass flow rate to 1.25 sccm.
|
||||
sccm = 1.25;
|
||||
vdot = sccm * 1.0e-6/60.0 * ((OneAtm / pressure(gas)) * ( temperature(gas) / 273.15)); % m^3/s
|
||||
mdot = density(gas) * vdot; % kg/s
|
||||
mfc = MassFlowController;
|
||||
install(mfc, upstream, cstr);
|
||||
setMassFlowRate(mfc, mdot);
|
||||
|
||||
% now create a downstream reservoir to exhaust into.
|
||||
downstream = Reservoir(gas);
|
||||
|
||||
% connect the reactor to the downstream reservoir with a valve, and
|
||||
% set the coefficient sufficiently large to keep the reactor pressure
|
||||
% close to the downstream pressure of 60 Torr.
|
||||
v = Valve;
|
||||
install(v, cstr, downstream);
|
||||
setValveCoeff(v, 1.0e-9);
|
||||
|
||||
% create the network
|
||||
network = ReactorNet({cstr});
|
||||
|
||||
% now integrate in time
|
||||
tme = 0.0;
|
||||
dt = 0.1;
|
||||
|
||||
n = 0;
|
||||
while tme < 300.0
|
||||
n = n + 1;
|
||||
tme = tme + dt;
|
||||
advance(network, tme);
|
||||
tm(n) = tme;
|
||||
y(1,n) = massFraction(cstr,'H2');
|
||||
y(2,n) = massFraction(cstr,'O2');
|
||||
y(3,n) = massFraction(cstr,'H2O');
|
||||
end
|
||||
clf
|
||||
figure(1)
|
||||
plot(tm,y)
|
||||
legend('H2','O2','H2O')
|
||||
title('Mass Fractions')
|
@ -1,76 +0,0 @@
|
||||
function prandtl1(g)
|
||||
% PRANDTL1 Prandtl number for an equilibrium H/O gas mixture.
|
||||
%
|
||||
% This example computes and plots the Prandtl number for a
|
||||
% hydrogen / oxygen mixture in chemical equilibrium for P = 1
|
||||
% atm and a range of temperatures and elemental O/(O+H) ratios.
|
||||
%
|
||||
% Keywords: equilibrium, transport, plotting
|
||||
|
||||
help prandtl1
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('h2o2.yaml', 'ohmech', 'mixture-averaged');
|
||||
end
|
||||
|
||||
pr = zeros(31,31);
|
||||
xh2 = zeros(31,31);
|
||||
visc = zeros(31,31);
|
||||
lambda = zeros(31,31);
|
||||
t = [];
|
||||
xo2 = [];
|
||||
io2 = speciesIndex(gas,'O2');
|
||||
ih2 = speciesIndex(gas,'H2');
|
||||
|
||||
minT = minTemp(gas);
|
||||
maxT = maxTemp(gas);
|
||||
dT = (maxT - minT)/30.0;
|
||||
|
||||
t0 = cputime;
|
||||
for i = 1:31
|
||||
t(i) = minT + dT*(i-1);
|
||||
for j = 1:31
|
||||
xo2(j) = 0.99*(j-1)/30.0;
|
||||
x = zeros(nSpecies(gas),1);
|
||||
x(io2) = xo2(j);
|
||||
x(ih2) = 1.0 - xo2(j);
|
||||
set(gas,'T',t(i),'P',oneatm,'X',x);
|
||||
equilibrate(gas,'TP');
|
||||
visc(i,j) = viscosity(gas);
|
||||
lambda(i,j) = thermalConductivity(gas);
|
||||
pr(i,j) = visc(i,j)*cp_mass(gas)/lambda(i,j);
|
||||
x = moleFractions(gas);
|
||||
xh2(i,j) = x(ih2);
|
||||
end
|
||||
end
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
% plot results
|
||||
|
||||
clf;
|
||||
%figure(1);
|
||||
subplot(2,2,1);
|
||||
surf(xo2,t,pr);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('Prandtl Number');
|
||||
|
||||
subplot(2,2,2);
|
||||
surf(xo2,t,xh2);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('H_2 Mole Fraction');
|
||||
|
||||
subplot(2,2,3);
|
||||
surf(xo2,t,visc);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('Viscosity');
|
||||
|
||||
subplot(2,2,4);
|
||||
surf(xo2,t,lambda);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('Thermal Conductivity');
|
@ -1,74 +0,0 @@
|
||||
function prandtl2(g)
|
||||
% PRANDTL2 Prandtl number for an equilibrium H/O gas mixture.
|
||||
%
|
||||
% This example does the same thing as prandtl1, but using
|
||||
% the multicomponent expression for the thermal conductivity.
|
||||
%
|
||||
% Keywords: transport, equilibrium, multicomponent transport, plotting
|
||||
|
||||
help prandtl2
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('h2o2.yaml', 'ohmech', 'multicomponent');
|
||||
end
|
||||
|
||||
pr = zeros(31,31);
|
||||
xh2 = zeros(31,31);
|
||||
visc = zeros(31,31);
|
||||
lambda = zeros(31,31);
|
||||
t = [];
|
||||
xo2 = [];
|
||||
io2 = speciesIndex(gas,'O2');
|
||||
ih2 = speciesIndex(gas,'H2');
|
||||
|
||||
minT = minTemp(gas);
|
||||
maxT = maxTemp(gas);
|
||||
dT = (maxT - minT)/30.0;
|
||||
|
||||
t0 = cputime;
|
||||
for i = 1:31
|
||||
t(i) = minT + dT*(i-1);
|
||||
for j = 1:31
|
||||
xo2(j) = 0.99*(j-1)/30.0;
|
||||
x = zeros(nSpecies(gas),1);
|
||||
x(io2) = xo2(j);
|
||||
x(ih2) = 1.0 - xo2(j);
|
||||
set(gas,'T',t(i),'P',oneatm,'X',x);
|
||||
equilibrate(gas,'TP');
|
||||
visc(i,j) = viscosity(gas);
|
||||
lambda(i,j) = thermalConductivity(gas);
|
||||
pr(i,j) = visc(i,j)*cp_mass(gas)/lambda(i,j);
|
||||
x = moleFractions(gas);
|
||||
xh2(i,j) = x(ih2);
|
||||
end
|
||||
end
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
% plot results
|
||||
|
||||
clf;
|
||||
subplot(2,2,1);
|
||||
surf(xo2,t,pr);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('Prandtl Number');
|
||||
|
||||
subplot(2,2,2);
|
||||
surf(xo2,t,xh2);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('H_2 Mole Fraction');
|
||||
|
||||
subplot(2,2,3);
|
||||
surf(xo2,t,visc);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('Viscosity');
|
||||
|
||||
subplot(2,2,4);
|
||||
surf(xo2,t,lambda);
|
||||
xlabel('Elemental O/(O+H)');
|
||||
ylabel('Temperature (K)');
|
||||
zlabel('Thermal Conductivity');
|
@ -1,61 +0,0 @@
|
||||
function [work, efficiency] = rankine(t1, p2, eta_pump, eta_turbine)
|
||||
%
|
||||
% This example computes the efficiency of a simple vapor power cycle.
|
||||
%
|
||||
% Keywords: thermodynamics, thermodynamic cycle, non-ideal fluid
|
||||
|
||||
help rankine
|
||||
|
||||
% create an object representing water
|
||||
w = Water;
|
||||
|
||||
% start with saturated liquid water at t1
|
||||
set(w,'T',t1,'Liquid',1.0);
|
||||
p1 = pressure(w);
|
||||
|
||||
% pump it to p2
|
||||
pump_work = pump(w, p2, eta_pump);
|
||||
h2 = enthalpy_mass(w);
|
||||
p2 = pressure(w);
|
||||
|
||||
% heat to saturated vapor
|
||||
set(w,'P',p2,'Vapor',1.0);
|
||||
h3 = enthalpy_mass(w);
|
||||
|
||||
heat_added = h3 - h2;
|
||||
|
||||
% expand adiabatically back to the initial pressure
|
||||
work = expand(w, p1, eta_turbine);
|
||||
|
||||
% compute the efficiency
|
||||
efficiency = (work - pump_work)/heat_added;
|
||||
|
||||
|
||||
function w = pump(fluid, pfinal, eta)
|
||||
% PUMP - Adiabatically pump a fluid to pressure pfinal, using a pump
|
||||
% with isentropic efficiency eta.
|
||||
%
|
||||
h0 = enthalpy_mass(fluid);
|
||||
s0 = entropy_mass(fluid);
|
||||
set(fluid, 'S', s0, 'P', pfinal);
|
||||
h1s = enthalpy_mass(fluid);
|
||||
isentropic_work = h1s - h0;
|
||||
actual_work = isentropic_work / eta;
|
||||
h1 = h0 + actual_work;
|
||||
set(fluid, 'H',h1, 'P',pfinal);
|
||||
w = actual_work;
|
||||
|
||||
|
||||
function w = expand(fluid, pfinal, eta)
|
||||
% EXPAND - Adiabatically expand a fluid to pressure pfinal, using a
|
||||
% turbine with isentropic efficiency eta.
|
||||
%
|
||||
h0 = enthalpy_mass(fluid);
|
||||
s0 = entropy_mass(fluid);
|
||||
set(fluid, 'S', s0, 'P', pfinal);
|
||||
h1s = enthalpy_mass(fluid);
|
||||
isentropic_work = h0 - h1s;
|
||||
actual_work = isentropic_work * eta;
|
||||
h1 = h0 - actual_work;
|
||||
set(fluid, 'H',h1, 'P',pfinal);
|
||||
w = actual_work;
|
@ -1,83 +0,0 @@
|
||||
function reactor1(g)
|
||||
% REACTOR1 Zero-dimensional kinetics: adiabatic, constant pressure.
|
||||
%
|
||||
% >>>> For a simpler way to carry out a constant-pressure simulation,
|
||||
% see example reactor3.m <<<<<
|
||||
%
|
||||
% This example illustrates how to use class 'Reactor' for
|
||||
% zero-dimensional kinetics simulations. Here the parameters are
|
||||
% set so that the reactor is adiabatic and very close to constant
|
||||
% pressure.
|
||||
%
|
||||
% Keywords: combustion, reactor network, ignition delay, plotting
|
||||
|
||||
help reactor1
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('h2o2.yaml', 'ohmech', 'none');
|
||||
end
|
||||
|
||||
P = oneatm;
|
||||
% set the initial conditions
|
||||
set(gas,'T',1001.0,'P',P,'X','H2:2,O2:1,N2:4');
|
||||
|
||||
% create a reactor, and insert the gas
|
||||
r = IdealGasReactor(gas);
|
||||
|
||||
% create a reservoir to represent the environment
|
||||
a = Solution('air.yaml','air','none');
|
||||
set(a,'P',P)
|
||||
env = Reservoir(a);
|
||||
|
||||
% 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.
|
||||
w = Wall;
|
||||
install(w,r,env);
|
||||
|
||||
% set expansion parameter. dV/dt = KA(P_1 - P_2)
|
||||
setExpansionRateCoeff(w, 1.0e6);
|
||||
|
||||
% set wall area
|
||||
setArea(w, 1.0);
|
||||
|
||||
% create a reactor network and insert the reactor:
|
||||
network = ReactorNet({r});
|
||||
|
||||
nSteps = 100;
|
||||
tim(nSteps) = 0;
|
||||
temp(nSteps) = 0;
|
||||
x(nSteps,3) = 0;
|
||||
t = 0.0;
|
||||
dt = 1.0e-5;
|
||||
t0 = cputime;
|
||||
for n = 1:nSteps
|
||||
t = t + dt;
|
||||
advance(network, t);
|
||||
tim(n) = time(network);
|
||||
temp(n) = temperature(r);
|
||||
x(n,1:3) = moleFraction(gas,{'OH','H','H2'});
|
||||
end
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
clf;
|
||||
subplot(2,2,1);
|
||||
plot(tim,temp);
|
||||
xlabel('Time (s)');
|
||||
ylabel('Temperature (K)');
|
||||
subplot(2,2,2)
|
||||
plot(tim,x(:,1));
|
||||
xlabel('Time (s)');
|
||||
ylabel('OH Mole Fraction (K)');
|
||||
subplot(2,2,3)
|
||||
plot(tim,x(:,2));
|
||||
xlabel('Time (s)');
|
||||
ylabel('H Mole Fraction (K)');
|
||||
subplot(2,2,4)
|
||||
plot(tim,x(:,3));
|
||||
xlabel('Time (s)');
|
||||
ylabel('H2 Mole Fraction (K)');
|
||||
clear all
|
||||
cleanup
|
@ -1,61 +0,0 @@
|
||||
function reactor2(g)
|
||||
% REACTOR2 Zero-dimensional kinetics: adiabatic, constant volume.
|
||||
%
|
||||
% This example illustrates how to use class 'Reactor' for
|
||||
% zero-dimensional kinetics simulations. Here the parameters are
|
||||
% set so that the reactor is adiabatic and constant volume.
|
||||
%
|
||||
% Keywords: combustion, reactor network, ignition delay, plotting
|
||||
|
||||
help reactor2
|
||||
|
||||
if nargin == 1
|
||||
gas = g;
|
||||
else
|
||||
gas = Solution('h2o2.yaml', 'ohmech', 'none');
|
||||
end
|
||||
|
||||
% set the initial conditions
|
||||
set(gas,'T',1001.0,'P',oneatm,'X','H2:2,O2:1,N2:4');
|
||||
|
||||
% create a reactor, and insert the gas
|
||||
r = IdealGasReactor(gas);
|
||||
|
||||
% create a reactor network and insert the reactor
|
||||
network = ReactorNet({r});
|
||||
|
||||
nSteps = 100;
|
||||
tim(nSteps) = 0;
|
||||
temp(nSteps) = 0;
|
||||
x(nSteps,3) = 0;
|
||||
t = 0;
|
||||
dt = 1.0e-5;
|
||||
t0 = cputime;
|
||||
for n = 1:100
|
||||
t = t + dt;
|
||||
advance(network, t);
|
||||
tim(n) = time(network);
|
||||
temp(n) = temperature(r);
|
||||
x(n,1:3) = moleFraction(gas,{'OH','H','H2'});
|
||||
end
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
clf;
|
||||
subplot(2,2,1);
|
||||
plot(tim,temp);
|
||||
xlabel('Time (s)');
|
||||
ylabel('Temperature (K)');
|
||||
subplot(2,2,2)
|
||||
plot(tim,x(:,1));
|
||||
xlabel('Time (s)');
|
||||
ylabel('OH Mole Fraction (K)');
|
||||
subplot(2,2,3)
|
||||
plot(tim,x(:,2));
|
||||
xlabel('Time (s)');
|
||||
ylabel('H Mole Fraction (K)');
|
||||
subplot(2,2,4)
|
||||
plot(tim,x(:,3));
|
||||
xlabel('Time (s)');
|
||||
ylabel('H2 Mole Fraction (K)');
|
||||
clear all
|
||||
cleanup
|
@ -1,50 +0,0 @@
|
||||
function dydt = reactor_ode(t,y,gas,vdot,area,heatflux)
|
||||
% REACTOR ODE system for a generic zero-dimensional reactor.
|
||||
%
|
||||
% Function REACTOR evaluates the system of ordinary differential
|
||||
% equations for a zero-dimensional reactor with arbitrary heat
|
||||
% transfer and volume change.
|
||||
%
|
||||
% Solution vector components:
|
||||
% y(1) Total internal energy U
|
||||
% y(2) Volume V
|
||||
% y(3) Mass of species 1
|
||||
% ....
|
||||
% y(2+nsp) Mass of last species
|
||||
%
|
||||
|
||||
[m,n] = size(y);
|
||||
dydt = zeros(m,n);
|
||||
|
||||
for j = 1:n
|
||||
this_y = y(:,j);
|
||||
int_energy = this_y(1);
|
||||
vol = this_y(2);
|
||||
masses = this_y(3:end);
|
||||
|
||||
% evaluate the total mass, and the specific internal energy and volume.
|
||||
total_mass = sum(masses);
|
||||
u_mass = int_energy/total_mass;
|
||||
v_mass = vol/total_mass;
|
||||
|
||||
% set the state of the gas by specifying (u,v,{Y_k})
|
||||
setMassFractions(gas,masses);
|
||||
setState_UV(gas, [u_mass v_mass]);
|
||||
p = pressure(gas);
|
||||
|
||||
% volume equation
|
||||
vdt = feval(vdot, t, vol, gas);
|
||||
|
||||
% energy equation
|
||||
a = feval(area, t, vol);
|
||||
q = feval(heatflux, t, gas);
|
||||
udt = -p * vdt + a * q;
|
||||
|
||||
% species equations
|
||||
ydt = total_mass * ydot(gas);
|
||||
|
||||
% set up column vector for dydt
|
||||
dydt(:,j) = [udt
|
||||
vdt
|
||||
ydt ];
|
||||
end
|
@ -1,99 +0,0 @@
|
||||
% SURFREACTOR Zero-dimensional reactor with surface chemistry
|
||||
%
|
||||
% This example illustrates how to use class 'Reactor' for
|
||||
% zero-dimensional simulations including both homogeneous and
|
||||
% heterogeneous chemistry.
|
||||
%
|
||||
% Keywords: catalysis, combustion, reactor network, plotting
|
||||
|
||||
help surfreactor
|
||||
|
||||
t = 870.0;
|
||||
gas = Solution('ptcombust.yaml','gas');
|
||||
|
||||
% set the initial conditions
|
||||
set(gas,'T',t,'P',oneatm,'X','CH4:0.01, O2:0.21, N2:0.78');
|
||||
|
||||
% The surface reaction mechanism describes catalytic combustion of
|
||||
% methane on platinum, and is from Deutschmann et al., 26th
|
||||
% Symp. (Intl.) on Combustion,1996, pp. 1747-1754
|
||||
surf = importInterface('ptcombust.yaml','Pt_surf', gas);
|
||||
setTemperature(surf, t);
|
||||
|
||||
nsp = nSpecies(gas);
|
||||
nSurfSp = nSpecies(surf);
|
||||
|
||||
% create a reactor, and insert the gas
|
||||
r = IdealGasReactor(gas);
|
||||
setInitialVolume(r, 1.0e-6)
|
||||
|
||||
% create a reservoir to represent the environment
|
||||
a = Solution('air.yaml','air','none');
|
||||
set(a,'T',t,'P',oneatm);
|
||||
env = Reservoir(a);
|
||||
|
||||
% 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.
|
||||
w = Wall;
|
||||
install(w,r,env);
|
||||
|
||||
A = 1e-4; % Wall area
|
||||
|
||||
% Add a reacting surface, with an area matching that of the wall
|
||||
rsurf = ReactorSurface(surf, r, A);
|
||||
|
||||
% set the wall area and heat transfer coefficient.
|
||||
setArea(w, A);
|
||||
setHeatTransferCoeff(w,1.0e1); % W/m2/K
|
||||
|
||||
% set expansion rate parameter. dV/dt = KA(P_1 - P_2)
|
||||
setExpansionRateCoeff(w, 1.0);
|
||||
|
||||
network = ReactorNet({r});
|
||||
% setTolerances(network, 1.0e-8, 1.0e-12);
|
||||
|
||||
nSteps = 100;
|
||||
p0 = pressure(r);
|
||||
names = {'CH4','CO','CO2','H2O'};
|
||||
x = zeros([nSteps 4]);
|
||||
tim = zeros(nSteps, 1);
|
||||
temp = zeros(nSteps, 1);
|
||||
pres = zeros(nSteps, 1);
|
||||
cov = zeros([nSteps nSurfSp]);
|
||||
t = 0;
|
||||
dt = 0.1;
|
||||
t0 = cputime;
|
||||
for n = 1:nSteps
|
||||
t = t + dt;
|
||||
advance(network, t);
|
||||
tim(n) = t;
|
||||
temp(n) = temperature(r);
|
||||
pres(n) = pressure(r) - p0;
|
||||
cov(n,:) = coverages(surf)';
|
||||
x(n,:) = moleFraction(gas,names);
|
||||
end
|
||||
disp(['CPU time = ' num2str(cputime - t0)]);
|
||||
|
||||
clf;
|
||||
subplot(2,2,1);
|
||||
plot(tim,temp);
|
||||
xlabel('Time (s)');
|
||||
ylabel('Temperature (K)');
|
||||
subplot(2,2,2);
|
||||
plot(tim,pres);
|
||||
axis([0 5 -0.1 0.1]);
|
||||
xlabel('Time (s)');
|
||||
ylabel('Delta Pressure (Pa)');
|
||||
subplot(2,2,3);
|
||||
semilogy(tim,cov);
|
||||
xlabel('Time (s)');
|
||||
ylabel('Coverages');
|
||||
legend(speciesNames(surf));
|
||||
subplot(2,2,4);
|
||||
plot(tim,x);
|
||||
xlabel('Time (s)');
|
||||
ylabel('Mole Fractions');
|
||||
legend(names);
|
||||
clear all
|
||||
cleanup
|
@ -1,29 +0,0 @@
|
||||
% runs selected examples without pausing
|
||||
|
||||
clear all
|
||||
close all
|
||||
cleanup
|
||||
|
||||
equil();
|
||||
isentropic();
|
||||
reactor1();
|
||||
reactor2();
|
||||
surfreactor;
|
||||
periodic_cstr;
|
||||
Plug_Flow_Reactor;
|
||||
lithium_ion_battery
|
||||
rankine(300.0, 2.0*oneatm, 0.8, 0.7);
|
||||
prandtl1();
|
||||
prandtl2();
|
||||
flame1;
|
||||
flame2;
|
||||
catcomb;
|
||||
clear all
|
||||
close all
|
||||
diffflame;
|
||||
ignite_hp;
|
||||
ignite_uv;
|
||||
|
||||
clear all
|
||||
close all
|
||||
cleanup
|
@ -1,174 +0,0 @@
|
||||
% Tutorial 1: Getting started
|
||||
%
|
||||
% Topics:
|
||||
% - creating a gas mixture
|
||||
% - setting the state
|
||||
% - cleaning up
|
||||
%
|
||||
% Keywords: tutorial
|
||||
|
||||
help tut1
|
||||
|
||||
% Start MATLAB, and at the prompt type:
|
||||
|
||||
gas1 = GRI30
|
||||
|
||||
% If you have successfully installed the Cantera toolbox, you should
|
||||
%see something like this:
|
||||
% temperature 300 K
|
||||
% pressure 101325 Pa
|
||||
% density 0.081889 kg/m^3
|
||||
% mean mol. weight 2.01588 amu
|
||||
%
|
||||
% 1 kg 1 kmol
|
||||
% ----------- ------------
|
||||
% enthalpy 26470.1 5.336e+04 J
|
||||
% internal energy -1.21088e+06 -2.441e+06 J
|
||||
% entropy 64914 1.309e+05 J/K
|
||||
% Gibbs function -1.94477e+07 -3.92e+07 J
|
||||
% heat capacity c_p 14311.8 2.885e+04 J/K
|
||||
% heat capacity c_v 10187.3 2.054e+04 J/K
|
||||
%
|
||||
% X Y Chem. Pot. / RT
|
||||
% ------------- ------------ ------------
|
||||
% H2 1 1 -15.7173
|
||||
% [ +52 minor] 0 0
|
||||
%
|
||||
% What you have just done is to create an object ("gas1") that
|
||||
% implements GRI-Mech 3.0, the 53-species, 325-reaction natural gas
|
||||
% combustion mechanism developed by Gregory P. Smith, David M. Golden,
|
||||
% Michael Frenklach, Nigel W. Moriarty, Boris Eiteneer, Mikhail
|
||||
% Goldenberg, C. Thomas Bowman, Ronald K. Hanson, Soonho Song, William
|
||||
% C. Gardiner, Jr., Vitali V. Lissianski, and Zhiwei Qin. (See
|
||||
% http://www.me.berkeley.edu/gri_mech/ for more information about
|
||||
% GRI-Mech 3.0.)
|
||||
%
|
||||
% The object created by GI30 has properties you would expect for a gas
|
||||
% mixture - it has a temperature, a pressure, species mole and mass
|
||||
% fractions, etc. As we'll soon see, it has many other properties too.
|
||||
%
|
||||
% The summary of the state of 'gas1' printed above shows that new
|
||||
% objects created by function GRI30 start out with a temperature of
|
||||
% 300 K, a pressure of 1 atm, and have a composition that consists of
|
||||
% only one species, in this case hydrogen. There is nothing special
|
||||
% about H2 - it just happens to be the first species listed in the
|
||||
% input file defining GRI-Mech 3.0 that the 'GRI30' function reads. In
|
||||
% general, the species listed first will initially have a mole
|
||||
% fraction of 1.0, and all of the others will be zero.
|
||||
|
||||
% Setting the state
|
||||
% -----------------
|
||||
|
||||
% The state of the object can be easily changed. For example,
|
||||
|
||||
setTemperature(gas1, 1200)
|
||||
|
||||
% sets the temperature to 1200 K. (Cantera always uses SI units.)
|
||||
|
||||
% Notice in the summary of properties that MATLAB prints after this
|
||||
% command is executed that the temperature has been changed as
|
||||
% requested, but the pressure has changed too. The density and
|
||||
% composition have not.
|
||||
%
|
||||
% When setting properties individually, some convention needs to be
|
||||
% adopted to specify which other properties are held constant. This is
|
||||
% because thermodynamics requires that *two* properties (not one) in
|
||||
% addition to composition information be specified to fix the
|
||||
% intensive state of a substance (or mixture).
|
||||
%
|
||||
% Cantera adopts the following convention: only one of the set
|
||||
% (temperature, density, mass fractions) is altered by setting any
|
||||
% single property. In particular:
|
||||
%
|
||||
% a) Setting the temperature is done holding density and
|
||||
% composition fixed. (The pressure changes.)
|
||||
|
||||
% b) Setting the pressure is done holding temperature and
|
||||
% composition fixed. (The density changes.)
|
||||
%
|
||||
% c) Setting the composition is done holding temperature
|
||||
% and density fixed. (The pressure changes).
|
||||
%
|
||||
|
||||
|
||||
% Setting multiple properties: the 'set' method
|
||||
% ---------------------------------------------
|
||||
|
||||
% If you want to set multiple properties at once, use the 'set'
|
||||
% method. (Note: a 'method' is just the term for a function that acts
|
||||
% on an object. In MATLAB, methods take the object as the first
|
||||
% argument.)
|
||||
|
||||
set(gas1, 'Temperature', 900.0, 'Pressure', 1.e5);
|
||||
|
||||
% This statement sets both temperature and pressure at the same
|
||||
% time. Any number of property/value pairs can be specified in a
|
||||
% call to 'set'. For example, the following sets the mole fractions
|
||||
% too:
|
||||
set(gas1, 'Temperature', 900.0, 'Pressure', 1.e5, 'MoleFractions', ...
|
||||
'CH4:1,O2:2,N2:7.52');
|
||||
|
||||
% The 'set' method also accepts abbreviated property names:
|
||||
|
||||
set(gas1,'T',900.0,'P',1.e5,'X','CH4:1,O2:2,N2:7.52')
|
||||
|
||||
% Either version results in
|
||||
%
|
||||
% temperature 900 K
|
||||
% pressure 100000 Pa
|
||||
% density 0.369279 kg/m^3
|
||||
% mean mol. weight 27.6332 amu
|
||||
%
|
||||
% 1 kg 1 kmol
|
||||
% ----------- ------------
|
||||
% enthalpy 455660 1.259e+07 J
|
||||
% internal energy 184862 5.108e+06 J
|
||||
% entropy 8529.31 2.357e+05 J/K
|
||||
% Gibbs function -7.22072e+06 -1.995e+08 J
|
||||
% heat capacity c_p 1304.4 3.604e+04 J/K
|
||||
% heat capacity c_v 1003.52 2.773e+04 J/K
|
||||
%
|
||||
% X Y Chem. Pot. / RT
|
||||
% ------------- ------------ ------------
|
||||
% O2 0.190114 0.220149 -27.9596
|
||||
% CH4 0.095057 0.0551863 -37.0813
|
||||
% N2 0.714829 0.724665 -24.935
|
||||
% [ +50 minor] 0 0
|
||||
|
||||
% Other properties may also be set using 'set', including some that
|
||||
% can't be set individually. The following property pairs may be
|
||||
% set: (Enthalpy, Pressure), (IntEnergy, Volume), (Entropy,
|
||||
% Volume), (Entropy, Pressure). In each case, the values of the
|
||||
% extensive properties must be entered *per unit mass*.
|
||||
|
||||
% Setting the enthalpy and pressure:
|
||||
set(gas1, 'Enthalpy', 2*enthalpy_mass(gas1), 'Pressure', 2*oneatm);
|
||||
|
||||
% The composition above was specified using a string. The format is a
|
||||
% comma-separated list of <species name>:<relative mole numbers>
|
||||
% pairs. The mole numbers will be normalized to produce the mole
|
||||
% fractions, and therefore they are 'relative' mole numbers. Mass
|
||||
% fractions can be set in this way too by changing 'X' to 'Y' in the
|
||||
% above statement.
|
||||
|
||||
% The composition can also be set using an array, which can be
|
||||
% either a column vector or a row vector but must have the same
|
||||
% size as the number of species. For example, to set all 53 mole
|
||||
% fractions to the same value, do this:
|
||||
|
||||
x = ones(53,1); % a column vector of 53 ones
|
||||
set(gas1, 'X', x)
|
||||
|
||||
% To set the mass fractions to equal values:
|
||||
set(gas1, 'Y', x)
|
||||
|
||||
|
||||
% This clears all Matlab objects created
|
||||
clear all
|
||||
|
||||
% and this clears all Cantera objects created
|
||||
cleanup
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% end of tutorial 1
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
@ -1,105 +0,0 @@
|
||||
% Tutorial 2: Working with input files
|
||||
%
|
||||
% Topics:
|
||||
% - using functions 'Solution' and 'importInterface'
|
||||
% - input files distributed with Cantera
|
||||
% - the Cantera search path
|
||||
% - CTML files
|
||||
% - converting from CK format
|
||||
%
|
||||
% Keywords: tutorial, input files
|
||||
|
||||
help tut2
|
||||
|
||||
t0 = cputime;
|
||||
|
||||
% In the last tutorial, we used function GRI30 to create an object
|
||||
% that models an ideal gas mixture with the species and reactions of
|
||||
% GRI-Mech 3.0. Another way to do this is shown here, with statements
|
||||
% added to measure how long this takes:
|
||||
|
||||
gas1 = Solution('gri30.yaml', 'gas', 'mixture-averaged');
|
||||
msg = sprintf('time to create gas1: %f', cputime - t0)
|
||||
|
||||
% Function 'Solution' constructs an object representing a phase of
|
||||
% matter by reading in attributes of the phase from a file, which in
|
||||
% this case is 'gri30.yaml'. This file contains a complete specification
|
||||
% of the GRI-Mech 3.0 reaction mechanism, including element data
|
||||
% (name, atomic weight), species data (name, elemental composition,
|
||||
% coefficients to compute thermodynamic and transport properties), and
|
||||
% reaction data (stoichiometry, rate coefficient parameters). The file
|
||||
% is written in a format understood by Cantera, which is described in
|
||||
% the document "Defining Phases and Interfaces."
|
||||
|
||||
% On some systems, processing long files can be a little slow. Loading
|
||||
% a file again takes much less time, because Cantera 'remembers' files
|
||||
% it has already processed and doesn't need to read them in again:
|
||||
|
||||
t0 = cputime;
|
||||
gas1b = Solution('gri30.yaml', 'gas', 'none');
|
||||
msg = sprintf('time to create gas1b: %f', cputime - t0)
|
||||
|
||||
% Since GRI-Mech is a rather small mechanism, there might not be much
|
||||
% difference in these times.
|
||||
|
||||
% YAML files distributed with Cantera
|
||||
%------------------------------------
|
||||
|
||||
% Several reaction mechanism files in this format are included in the
|
||||
% Cantera distribution, including ones that model high-temperature
|
||||
% air, a hydrogen/oxygen reaction mechanism, and a few surface
|
||||
% reaction mechanisms. Under Windows, these files may be located in
|
||||
% 'C:\Program Files\Common Files\Cantera', or in 'C:\cantera\data',
|
||||
% depending on how you installed Cantera and the options you
|
||||
% specified. On a Unix/Linux/macOS machine, they are usually kept
|
||||
% in the 'data' subdirectory within the Cantera installation
|
||||
% directory.
|
||||
|
||||
% If for some reason Cantera has difficulty finding where these files
|
||||
% are on your system, set environment variable CANTERA_DATA to the
|
||||
% directory where they are located. Alternatively, you can call function
|
||||
% adddir to add a directory to the Cantera search path:
|
||||
adddir('/usr/local/cantera/my_data_files');
|
||||
|
||||
% Cantera input files are plain text files, and can be created with
|
||||
% any text editor. See the document 'Defining Phases and Interfaces'
|
||||
% for more information.
|
||||
|
||||
|
||||
% Importing multiple phases or interfaces
|
||||
% ---------------------------------------
|
||||
|
||||
% A Cantera input file may contain more than one phase specification,
|
||||
% or may contain specifications of interfaces (surfaces). Here we
|
||||
% import definitions of two bulk phases and the interface between them
|
||||
% from file diamond.yaml:
|
||||
|
||||
gas2 = Solution('diamond.yaml', 'gas'); % a gas
|
||||
|
||||
diamond = Solution('diamond.yaml','diamond'); % bulk diamond
|
||||
|
||||
diamonnd_surf = importInterface('diamond.yaml','diamond_100',...
|
||||
gas2, diamond);
|
||||
|
||||
% Note that the bulk (that is, 3D) phases that participate in the surface
|
||||
% reactions must also be passed as arguments to importInterface.
|
||||
|
||||
% Converting CK-format files
|
||||
% --------------------------
|
||||
|
||||
% Many existing reaction mechanism files are in "CK format," by which
|
||||
% we mean the input file format developed for use with the Chemkin-II
|
||||
% software package. [See R. J. Kee, F. M. Rupley, and J. A. Miller,
|
||||
% Sandia National Laboratories Report SAND89-8009 (1989).]
|
||||
|
||||
% Cantera comes with a converter utility program 'ck2yaml' (or
|
||||
% 'ck2yaml.exe') that converts CK format into YAML format. This
|
||||
% program should be run from the command line first to convert any CK
|
||||
% files you plan to use into YAML format.
|
||||
%
|
||||
% Here's an example of how to use it:
|
||||
%
|
||||
% ck2yaml --input=mech.inp --thermo=therm.dat --transport=tran.dat --name=mymech
|
||||
|
||||
clear all
|
||||
cleanup
|
@ -1,55 +0,0 @@
|
||||
% Tutorial 3: Getting Help
|
||||
%
|
||||
% Keywords: tutorial
|
||||
|
||||
help tut3
|
||||
|
||||
% Suppose you have created a Cantera object and want to know what
|
||||
% methods are available for it, and get help on using the methods.
|
||||
|
||||
g = GRI30
|
||||
|
||||
% The first thing you need to know is the MATLAB class object g
|
||||
% belongs to. Type:
|
||||
|
||||
class(g)
|
||||
|
||||
% This tells you that g belongs to a class called 'Solution'. To find
|
||||
% the methods for this class, type
|
||||
|
||||
methods Solution
|
||||
|
||||
% This command returns only a few method names. These are the ones
|
||||
% directly defined in this class. But solution inherits many other
|
||||
% methods from base classes. To see all of its methods, type
|
||||
|
||||
methods Solution -full
|
||||
|
||||
% Now a long list is printed, along with a specification of the class
|
||||
% the method is inherited from. For example, 'setPressure' is
|
||||
% inherited from a class 'ThermoPhase'. Don't be concerned at this
|
||||
% point about what these base classes are - we'll come back to them
|
||||
% later.
|
||||
|
||||
% Now that you see what methods are available, you can type 'help
|
||||
% <method_name>' to print help text for any method. For example,
|
||||
|
||||
help setTemperature
|
||||
help setMassFractions
|
||||
help rop_net
|
||||
|
||||
% For help on how to construct objects of a given class, type 'help
|
||||
% <classname>'
|
||||
|
||||
help Solution
|
||||
|
||||
% Now that you know how to get help when you need it, you can
|
||||
% explore using the Cantera Toolbox on your own. But there are a
|
||||
% few more useful things to know, which are described in the next
|
||||
% few tutorials.
|
||||
|
||||
clear all
|
||||
cleanup
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% end of tutorial 3
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
@ -1,87 +0,0 @@
|
||||
% Tutorial 4: Chemical Equilibrium
|
||||
%
|
||||
% Topics:
|
||||
% - the equilibrate method
|
||||
% - specifying fixed TP, HP, UV, SV, or SP
|
||||
% - checking reaction rates of progress
|
||||
%
|
||||
% Keywords: tutorial, equilibrium, kinetics
|
||||
|
||||
help tut4
|
||||
|
||||
% To set a gas mixture to a state of chemical equilibrium, use the
|
||||
% 'equilibrate' method.
|
||||
%
|
||||
g = GRI30('none');
|
||||
set(g,'T',1200.0,'P',oneatm,'X','CH4:0.95,O2:2,N2:7.52')
|
||||
equilibrate(g,'TP')
|
||||
|
||||
% The above statement sets the state of object 'g' to the state of
|
||||
% chemical equilibrium holding temperature and pressure
|
||||
% fixed. Alternatively, the specific enthalpy and pressure can be held
|
||||
% fixed:
|
||||
|
||||
disp('fixed H and P:');
|
||||
set(g,'T',1200.0,'P',oneatm,'X','CH4:0.95,O2:2.0,N2:7.52');
|
||||
equilibrate(g,'HP')
|
||||
|
||||
|
||||
% Other options are
|
||||
% 'UV' fixed specific internal energy and specific volume
|
||||
% 'SV' fixed specific entropy and specific volume
|
||||
% 'SP' fixed specific entropy and pressure
|
||||
|
||||
disp('fixed U and V:');
|
||||
set(g,'T',1200.0,'P',oneatm,'X','CH4:0.95,O2:2,N2:7.52');
|
||||
equilibrate(g,'UV')
|
||||
|
||||
disp('fixed S and V:');
|
||||
set(g,'T',1200.0,'P',oneatm,'X','CH4:0.95,O2:2,N2:7.52');
|
||||
equilibrate(g,'SV')
|
||||
|
||||
disp('fixed S and P:');
|
||||
set(g,'T',1200.0,'P',oneatm,'X','CH4:0.95,O2:2,N2:7.52');
|
||||
equilibrate(g,'SP')
|
||||
|
||||
% How can you tell if 'equilibrate' has correctly found the
|
||||
% chemical equilibrium state? One way is verify that the net rates of
|
||||
% progress of all reversible reactions are zero.
|
||||
|
||||
% Here is the code to do this:
|
||||
set(g,'T',2000.0,'P',oneatm,'X','CH4:0.95,O2:2,N2:7.52');
|
||||
equilibrate(g,'TP')
|
||||
rf = rop_f(g);
|
||||
rr = rop_r(g);
|
||||
format short e;
|
||||
for i = 1:nReactions(g)
|
||||
if isReversible(g,i)
|
||||
disp([i, rf(i), rr(i), (rf(i) - rr(i))/rf(i)]);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% You might be wondering how 'equilibrate' works. (Then again, you might
|
||||
% not, in which case you can go on to the next tutorial now.) Method
|
||||
% 'equilibrate' invokes Cantera's chemical equilibrium solver, which
|
||||
% uses an element potential method. The element potential method is
|
||||
% one of a class of equivalent 'nonstoichiometric' methods that all
|
||||
% have the characteristic that the problem reduces to solving a set of
|
||||
% M nonlinear algebraic equations, where M is the number of elements
|
||||
% (not species). The so-called 'stoichiometric' methods, on the other
|
||||
% hand, (including Gibbs minimization), require solving K nonlinear
|
||||
% equations, where K is the number of species (usually K >> M). See
|
||||
% Smith and Missen, "Chemical Reaction Equilibrium Analysis" for more
|
||||
% information on the various algorithms and their characteristics.
|
||||
%
|
||||
% Cantera uses a damped Newton method to solve these equations, and
|
||||
% does a few other things to generate a good starting guess and to
|
||||
% produce a reasonably robust algorithm. If you want to know more
|
||||
% about the details, look at the on-line documented source code of
|
||||
% Cantera C++ class 'ChemEquil' at https://cantera.org.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
clear all
|
||||
cleanup
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% end of tutorial 4
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
@ -1,109 +0,0 @@
|
||||
% Tutorial 5: Reaction information and rates
|
||||
%
|
||||
% Topics:
|
||||
% - stoichiometric coefficients
|
||||
% - reaction rates of progress
|
||||
% - species production rates
|
||||
% - reaction equations
|
||||
% - equilibrium constants
|
||||
% - rate multipliers
|
||||
%
|
||||
% Keywords: tutorial, kinetics
|
||||
|
||||
help tut5
|
||||
|
||||
g = GRI30('none');
|
||||
set(g,'T',1500,'P',oneatm,'X',ones(nSpecies(g),1));
|
||||
|
||||
% Methods are provided that compute many quantities of interest for
|
||||
% kinetics. Some of these are:
|
||||
|
||||
|
||||
% 1) Stoichiometric coefficients
|
||||
|
||||
nu_r = stoich_r(g) % reactant stoichiometric coefficient mstix
|
||||
nu_p = stoich_p(g) % product stoichiometric coefficient mstix
|
||||
nu_net = stoich_net(g) % net (product - reactant) stoichiometric
|
||||
% coefficient mstix
|
||||
|
||||
% For any of these, the (k,i) matrix element is the stoichiometric
|
||||
% coefficient of species k in reaction i. Since these coefficient
|
||||
% matrices are very sparse, they are implemented as MATLAB sparse
|
||||
% matrices.
|
||||
|
||||
|
||||
% 2) Reaction rates of progress
|
||||
|
||||
% Methods rop_f, rop_r, and rop_net return column vectors containing
|
||||
% the forward, reverse, and net (forward - reverse) rates of
|
||||
% progress, respectively, for all reactions.
|
||||
|
||||
qf = rop_f(g);
|
||||
qr = rop_r(g);
|
||||
qn = rop_net(g);
|
||||
rop = [qf, qr, qn]
|
||||
|
||||
% This plots the rates of progress
|
||||
figure(1);
|
||||
bar(rop);
|
||||
legend('forward','reverse','net');
|
||||
|
||||
% 3) Species production rates
|
||||
|
||||
% Methods creationRates, destructionRates, and netProdRates return
|
||||
% column vectors containing the creation, destruction, and net
|
||||
% production (creation - destruction) rates, respectively, for all species.
|
||||
|
||||
cdot = creationRates(g);
|
||||
ddot = destructionRates(g);
|
||||
wdot = netProdRates(g);
|
||||
rates = [cdot, ddot, wdot]
|
||||
|
||||
% This plots the production rates
|
||||
figure(2);
|
||||
bar(rates);
|
||||
legend('creation','destruction','net');
|
||||
|
||||
% For comparison, the production rates may also be computed
|
||||
% directly from the rates of progress and stoichiometric
|
||||
% coefficients.
|
||||
|
||||
cdot2 = nu_p*qf + nu_r*qr;
|
||||
creation = [cdot, cdot2, cdot - cdot2]
|
||||
|
||||
ddot2 = nu_r*qf + nu_p*qr;
|
||||
destruction = [ddot, ddot2, ddot - ddot2]
|
||||
|
||||
wdot2 = nu_net * qn;
|
||||
net = [wdot, wdot2, wdot - wdot2]
|
||||
|
||||
% 4) Reaction equations
|
||||
|
||||
e8 = reactionEqn(g,8) % equation for reaction 8
|
||||
e1_10 = reactionEqn(g,1:10) % equation for rxns 1 - 10
|
||||
eqs = reactionEqn(g) % all equations
|
||||
|
||||
% 5) Equilibrium constants
|
||||
|
||||
% The equilibrium constants are computed in concentration units,
|
||||
% with concentrations in kmol/m^3.
|
||||
|
||||
kc = equil_Kc(g);
|
||||
for i = 1:nReactions(g)
|
||||
fprintf('%50s %13.5g', eqs{i}, kc(i))
|
||||
end
|
||||
|
||||
% 6) Multipliers
|
||||
|
||||
% For each reaction, a multiplier may be specified that is applied
|
||||
% to the forward rate coefficient. By default, the multiplier is
|
||||
% 1.0 for all reactions.
|
||||
|
||||
for i = 1:nReactions(g)
|
||||
setMultiplier(g, i, 2*i);
|
||||
m = multiplier(g, i);
|
||||
end
|
||||
|
||||
clear all
|
||||
cleanup
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
@ -1,73 +0,0 @@
|
||||
% Tutorial 6: Transport properties
|
||||
%
|
||||
% Topics:
|
||||
% - mixture-averaged and multicomponent models
|
||||
% - viscosity
|
||||
% - thermal conductivity
|
||||
% - binary diffusion coefficients
|
||||
% - mixture-averaged diffusion coefficients
|
||||
% - multicomponent diffusion coefficients
|
||||
% - thermal diffusion coefficients
|
||||
%
|
||||
% Keywords: tutorial, transport
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% Methods are provided to compute transport properties. By
|
||||
% default, calculation of transport properties is not enabled. If
|
||||
% transport properties are required, the transport model must be
|
||||
% specified when the gas mixture object is constructed.
|
||||
|
||||
% Currently, two models are implemented. Both are based on kinetic
|
||||
% theory expressions, and follow the approach described in Dixon-Lewis
|
||||
% (1968) and Kee, Coltrin, and Glarborg (2003). The first is a full
|
||||
% multicomponent formulation, and the second is a simplification that
|
||||
% uses expressions derived for mixtures with a small number of species
|
||||
% (1 to 3), using approximate mixture rules to average over
|
||||
% composition.
|
||||
|
||||
% To use the multicomponent model with GRI-Mech 3.0, call function
|
||||
% GRI30 as follows:
|
||||
|
||||
g1 = GRI30('multicomponent')
|
||||
|
||||
% To use the mixture-averaged model:
|
||||
|
||||
g2 = GRI30('mixture-averaged')
|
||||
|
||||
% Both models use a mixture-averaged formulation for the viscosity.
|
||||
visc = [viscosity(g1), viscosity(g2)]
|
||||
|
||||
% The thermal conductivity differs, however.
|
||||
lambda = [thermalConductivity(g1), thermalConductivity(g2)]
|
||||
|
||||
% Binary diffusion coefficients
|
||||
bdiff1 = binDiffCoeffs(g1)
|
||||
bdiff2 = binDiffCoeffs(g2)
|
||||
|
||||
% Mixture-averaged diffusion coefficients. For convenience, the
|
||||
% multicomponent model implements mixture-averaged diffusion
|
||||
% coefficients too.
|
||||
dmix2 = mixDiffCoeffs(g1)
|
||||
dmix1 = mixDiffCoeffs(g2)
|
||||
|
||||
% Multicomponent diffusion coefficients. These are only implemented
|
||||
% if the multicomponent model is used.
|
||||
dmulti = multiDiffCoeffs(g1)
|
||||
|
||||
% Thermal diffusion coefficients. These are only implemented with the
|
||||
% multicomponent model. These will be very close to zero, since
|
||||
% the composition is pure H2.
|
||||
dt = thermalDiffCoeffs(g1)
|
||||
|
||||
% Now change the composition and re-evaluate
|
||||
set(g1,'X',ones(nSpecies(g1),1));
|
||||
dt = thermalDiffCoeffs(g1)
|
||||
|
||||
% Note that there are no singularities for pure gases. This is
|
||||
% because a very small positive value is added to all mole
|
||||
% fractions for the purpose of computing transport properties.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
clear all
|
||||
cleanup
|
@ -1,35 +0,0 @@
|
||||
% Tutorial 7: Thermodynamic Properties
|
||||
%
|
||||
% Keywords: tutorial, thermodynamics
|
||||
|
||||
help tut7
|
||||
|
||||
% A variety of thermodynamic property methods are provided.
|
||||
gas = Air
|
||||
set(gas,'T',800,'P',oneatm)
|
||||
|
||||
% temperature, pressure, density
|
||||
T = temperature(gas)
|
||||
P = pressure(gas)
|
||||
rho = density(gas)
|
||||
n = molarDensity(gas)
|
||||
|
||||
% species non-dimensional properties
|
||||
hrt = enthalpies_RT(gas) % vector of h_k/RT
|
||||
|
||||
% mixture properties per mole
|
||||
hmole = enthalpy_mole(gas)
|
||||
umole = intEnergy_mole(gas)
|
||||
smole = entropy_mole(gas)
|
||||
gmole = gibbs_mole(gas)
|
||||
|
||||
% mixture properties per unit mass
|
||||
hmass = enthalpy_mass(gas)
|
||||
umass = intEnergy_mass(gas)
|
||||
smass = entropy_mass(gas)
|
||||
gmass = gibbs_mass(gas)
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
clear all
|
||||
cleanup
|
@ -4,7 +4,7 @@ function plotSolution(s, domain, component)
|
||||
% >> plotSolution(s, domain, component)
|
||||
%
|
||||
% :s:
|
||||
% Instance of class :mat:class:`Sim1D`.
|
||||
% Instance of class Matlab class `Sim1D`.
|
||||
% :domain:
|
||||
% Name of domain from which the component should be retrieved.
|
||||
% :component:
|
||||
@ -17,4 +17,4 @@ function plotSolution(s, domain, component)
|
||||
plot(z, x);
|
||||
xlabel('z (m)');
|
||||
ylabel(component);
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user