mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
Merge 0ebe26fc0a
into 0720efb02d
This commit is contained in:
commit
7f38f3fc95
@ -24,6 +24,8 @@ classdef Interface < handle & ThermoPhase & Kinetics
|
||||
% Unit: kmol/m^2 for surface phases, kmol/m for edge phases.
|
||||
siteDensity
|
||||
|
||||
coverages % Surface coverages of the species on an interface.
|
||||
|
||||
end
|
||||
|
||||
properties (SetAccess = protected)
|
||||
@ -66,6 +68,10 @@ classdef Interface < handle & ThermoPhase & Kinetics
|
||||
|
||||
function delete(s)
|
||||
% Delete :mat:class:`Interface` object.
|
||||
|
||||
if isempty(s.solnID)
|
||||
return
|
||||
end
|
||||
ctFunc('soln_del', s.solnID);
|
||||
end
|
||||
|
||||
@ -82,9 +88,7 @@ classdef Interface < handle & ThermoPhase & Kinetics
|
||||
adj = Solution(id);
|
||||
end
|
||||
|
||||
function c = coverages(s)
|
||||
% Surface coverages of the species on an interface.
|
||||
|
||||
function c = get.coverages(s)
|
||||
surfID = s.tpID;
|
||||
nsp = s.nSpecies;
|
||||
xx = zeros(1, nsp);
|
||||
@ -107,10 +111,10 @@ classdef Interface < handle & ThermoPhase & Kinetics
|
||||
c = pt.Value;
|
||||
end
|
||||
|
||||
function setCoverages(s, cov, norm)
|
||||
function set.coverages(s, val)
|
||||
% Set surface coverages of the species on an interface.
|
||||
%
|
||||
% s.setCoverages(cov, norm)
|
||||
% s.coverages = {cov, norm}
|
||||
%
|
||||
% :param s:
|
||||
% Instance of class :mat:class:`Interface`
|
||||
@ -126,10 +130,18 @@ classdef Interface < handle & ThermoPhase & Kinetics
|
||||
% unphysical results, ``'nonorm'`` should be used only in rare cases, such
|
||||
% as computing partial derivatives with respect to a species coverage.
|
||||
|
||||
if nargin == 3 && strcmp(norm, 'nonorm')
|
||||
norm_flag = 0;
|
||||
else
|
||||
if iscell(val) && numel(val) >= 1 && numel(val) <= 2
|
||||
cov = val{1};
|
||||
norm_flag = 1;
|
||||
|
||||
if numel(val) == 2
|
||||
norm = val{2};
|
||||
if strcmp(norm, 'nonorm')
|
||||
norm_flag = 0;
|
||||
end
|
||||
end
|
||||
else
|
||||
error('Input must be a cell array {cov} or {cov, norm}');
|
||||
end
|
||||
|
||||
surfID = s.tpID;
|
||||
|
@ -156,7 +156,7 @@ classdef Mixture < handle
|
||||
end
|
||||
|
||||
% Create an empty mixture.
|
||||
m.mixID = calllib(ct, 'mix_new');
|
||||
m.mixID = ctFunc('mix_new');
|
||||
m.phases = phases;
|
||||
|
||||
% If phases are supplied, add them
|
||||
@ -172,8 +172,12 @@ classdef Mixture < handle
|
||||
% column contains the mole numbers of each phase.
|
||||
[np, nc] = size(phases);
|
||||
|
||||
if nc ~= 2
|
||||
error('Cell array of phases should have each phase on a new row');
|
||||
% If mole numbers are not defined, default to 1 for all phases.
|
||||
if nc == 1
|
||||
newColumn = num2cell(ones(np, 1));
|
||||
phases = [phases, newColumn];
|
||||
elseif nc < 1 || nc > 2
|
||||
error('Phases should have one or two columns');
|
||||
end
|
||||
|
||||
for n = 1:np
|
||||
@ -190,7 +194,10 @@ classdef Mixture < handle
|
||||
function delete(m)
|
||||
% Delete the :mat:class:`Mixture` object.
|
||||
|
||||
calllib(ct, 'mix_del', m.mixID);
|
||||
if isempty(m.mixID)
|
||||
return
|
||||
end
|
||||
ctFunc('mix_del', m.mixID);
|
||||
end
|
||||
|
||||
%% Mixture Utility methods
|
||||
@ -198,13 +205,13 @@ classdef Mixture < handle
|
||||
function display(m)
|
||||
% Display the state of the mixture on the terminal.
|
||||
|
||||
calllib(ct, 'mix_updatePhases', m.mixID);
|
||||
ctFunc('mix_updatePhases', m.mixID);
|
||||
[np, nc] = size(m.phases);
|
||||
|
||||
for n = 1:np
|
||||
s = [sprintf('\n******************* Phase %d', n) ...
|
||||
sprintf(' ******************************\n\n Moles: %12.6g', ...
|
||||
phaseMoles(m, n))];
|
||||
m.phaseMoles(n))];
|
||||
disp(s);
|
||||
display(m.phases{n, 1});
|
||||
end
|
||||
@ -237,54 +244,54 @@ classdef Mixture < handle
|
||||
error('Negative moles');
|
||||
end
|
||||
|
||||
calllib(ct, 'mix_addPhase', m.mixID, phase.tp_id, moles);
|
||||
ctFunc('mix_addPhase', m.mixID, phase.tpID, moles);
|
||||
|
||||
end
|
||||
|
||||
%% Mixture Get methods
|
||||
|
||||
function temperature = get.T(m)
|
||||
temperature = calllib(ct, 'mix_temperature', m.mixID);
|
||||
temperature = ctFunc('mix_temperature', m.mixID);
|
||||
end
|
||||
|
||||
function pressure = get.P(m)
|
||||
pressure = calllib(ct, 'mix_pressure', m.mixID);
|
||||
pressure = ctFunc('mix_pressure', m.mixID);
|
||||
end
|
||||
|
||||
function n = get.nAtoms(m, e)
|
||||
n = calllib(ct, 'mix_nPhases', m.mixID, k - 1, e - 1);
|
||||
n = ctFunc('mix_nPhases', m.mixID, k - 1, e - 1);
|
||||
end
|
||||
|
||||
function n = get.nElements(m)
|
||||
n = calllib(ct, 'mix_nElements', m.mixID);
|
||||
n = ctFunc('mix_nElements', m.mixID);
|
||||
end
|
||||
|
||||
function n = get.nPhases(m)
|
||||
n = calllib(ct, 'mix_nPhases', m.mixID);
|
||||
n = ctFunc('mix_nPhases', m.mixID);
|
||||
end
|
||||
|
||||
function n = get.nSpecies(m)
|
||||
n = calllib(ct, 'mix_nSpecies', m.mixID);
|
||||
n = ctFunc('mix_nSpecies', m.mixID);
|
||||
end
|
||||
|
||||
function n = get.elementIndex(m, name)
|
||||
n = calllib(ct, 'mix_elementIndex', m.mixID, name) + 1;
|
||||
n = ctFunc('mix_elementIndex', m.mixID, name) + 1;
|
||||
end
|
||||
|
||||
function n = get.speciesIndex(m, k, p)
|
||||
n = calllib(ct, 'mix_speciesIndex', m.mixID, k - 1, p - 1) + 1;
|
||||
n = ctFunc('mix_speciesIndex', m.mixID, k - 1, p - 1) + 1;
|
||||
end
|
||||
|
||||
function moles = get.elementMoles(m, e)
|
||||
|
||||
if nargin == 2
|
||||
moles = calllib(ct, 'mix_elementMoles', m.mixID, e)
|
||||
moles = ctFunc('mix_elementMoles', m.mixID, e)
|
||||
elseif nargin == 1
|
||||
nel = m.nElements;
|
||||
moles = zeros(1, nel);
|
||||
|
||||
for i = 1:nel
|
||||
moles(i) = calllib(ct, 'mix_elementMoles', m.mixID, i);
|
||||
moles(i) = ctFunc('mix_elementMoles', m.mixID, i-1);
|
||||
end
|
||||
|
||||
else error('wrong number of arguments');
|
||||
@ -295,13 +302,13 @@ classdef Mixture < handle
|
||||
function moles = get.phaseMoles(m, n)
|
||||
|
||||
if nargin == 2
|
||||
moles = calllib(ct, 'mix_phaseMoles', m.mixID, n);
|
||||
moles = ctFunc('mix_phaseMoles', m.mixID, n);
|
||||
elseif nargin == 1
|
||||
np = m.nPhases;
|
||||
moles = zeros(1, np);
|
||||
|
||||
for i = 1:np
|
||||
moles(i) = calllib(ct, 'mix_phaseMoles', m.mixID, i);
|
||||
moles(i) = ctFunc('mix_phaseMoles', m.mixID, i-1);
|
||||
end
|
||||
|
||||
else error('wrong number of arguments');
|
||||
@ -309,16 +316,16 @@ classdef Mixture < handle
|
||||
|
||||
end
|
||||
|
||||
function moles = speciesMoles(m, k)
|
||||
function moles = get.speciesMoles(m, k)
|
||||
|
||||
if nargin == 2
|
||||
moles = calllib(ct, 'mix_speciesMoles', m.mixID, k);
|
||||
moles = ctFunc('mix_speciesMoles', m.mixID, k);
|
||||
elseif nargin == 1
|
||||
nsp = m.nSpecies;
|
||||
moles = zeros(1, nsp);
|
||||
|
||||
for i = 1:nsp
|
||||
moles(i) = calllib(ct, 'mix_speciesMoles', m.mixID, i);
|
||||
moles(i) = ctFunc('mix_speciesMoles', m.mixID, i-1);
|
||||
end
|
||||
|
||||
else error('wrong number of arguments');
|
||||
@ -330,18 +337,18 @@ classdef Mixture < handle
|
||||
nsp = m.nSpecies;
|
||||
xx = zeros(1, nsp);
|
||||
ptr = libpointer('doublePtr', xx);
|
||||
calllib(ct, 'mix_getChemPotential', m.mixID, nsp, ptr);
|
||||
ctFunc('mix_getChemPotentials', m.mixID, nsp, ptr);
|
||||
mu = ptr.Value;
|
||||
end
|
||||
|
||||
%% Mixture Set methods
|
||||
|
||||
function m = set.T(m, temp)
|
||||
calllib(ct, 'mix_setTemperature', m.mixID, temp);
|
||||
ctFunc('mix_setTemperature', m.mixID, temp);
|
||||
end
|
||||
|
||||
function m = set.P(m, pressure)
|
||||
calllib(ct, 'mix_setPressure', m.mixID, pressure);
|
||||
ctFunc('mix_setPressure', m.mixID, pressure);
|
||||
end
|
||||
|
||||
function setPhaseMoles(m, n, moles)
|
||||
@ -356,7 +363,7 @@ classdef Mixture < handle
|
||||
% :param moles:
|
||||
% Number of moles to add. Units: kmol.
|
||||
|
||||
calllib(ct, 'mix_setPhaseMoles', m.mixID, n - 1, moles);
|
||||
ctFunc('mix_setPhaseMoles', m.mixID, n - 1, moles);
|
||||
end
|
||||
|
||||
function setSpeciesMoles(m, moles)
|
||||
@ -379,9 +386,9 @@ classdef Mixture < handle
|
||||
|
||||
if isa(moles, 'double')
|
||||
l = length(moles);
|
||||
calllib(ct, 'mix_setMoles', m.mixID, l, moles);
|
||||
elseif isa(moles, 'string')
|
||||
calllib(ct, 'mix_setMolesByName', m.mixID, moles);
|
||||
ctFunc('mix_setMoles', m.mixID, l, moles);
|
||||
elseif isa(moles, 'char')
|
||||
ctFunc('mix_setMolesByName', m.mixID, moles);
|
||||
else
|
||||
error('The input must be a vector or string!');
|
||||
end
|
||||
@ -454,7 +461,7 @@ classdef Mixture < handle
|
||||
XY = 'TP'
|
||||
end
|
||||
|
||||
r = calllib(ct, 'mix_equilibrate', m.mixID, XY, err, ...
|
||||
r = ctFunc('mix_equilibrate', m.mixID, XY, err, ...
|
||||
maxsteps, maxiter, loglevel);
|
||||
end
|
||||
|
||||
|
@ -86,6 +86,10 @@ classdef Solution < handle & ThermoPhase & Kinetics & Transport
|
||||
|
||||
function delete(s)
|
||||
% Delete :mat:class:`Solution` object.
|
||||
|
||||
if isempty(s.solnID)
|
||||
return
|
||||
end
|
||||
ctFunc('soln_del', s.solnID);
|
||||
end
|
||||
|
||||
|
@ -4,6 +4,10 @@ classdef Func1 < handle
|
||||
id
|
||||
end
|
||||
|
||||
properties (SetAccess = protected)
|
||||
type
|
||||
end
|
||||
|
||||
methods
|
||||
%% Func1 Class Constructor
|
||||
|
||||
@ -36,7 +40,7 @@ classdef Func1 < handle
|
||||
% * Advanced functors: ``'polynomial3'``, ``'Fourier'``, ``'Gaussian'``,
|
||||
% ``'Arrhenius'``. Use vector parameter, for example
|
||||
%
|
||||
% >> x = Func('polynomial3', [1 2 3]) % x^2 + 2x + 3
|
||||
% >> x = Func1('polynomial3', [1 2 3]) % x^2 + 2x + 3
|
||||
%
|
||||
% * Tabulation functors: ``'tabulated-linear'``,
|
||||
% ``'tabulated-previous'``. Use pair of vector parameters, for example
|
||||
@ -134,6 +138,9 @@ classdef Func1 < handle
|
||||
function delete(f)
|
||||
% Delete the :mat:class:`Func1` object.
|
||||
|
||||
if isempty(f.id)
|
||||
return
|
||||
end
|
||||
ctFunc('func_del', f.id);
|
||||
end
|
||||
|
||||
@ -179,7 +186,7 @@ classdef Func1 < handle
|
||||
r = Func1(id);
|
||||
end
|
||||
|
||||
function s = type(f)
|
||||
function s = get.type(f)
|
||||
% Return function type.
|
||||
s = ctString('func_type', f.id);
|
||||
end
|
||||
|
@ -101,6 +101,9 @@ classdef Domain1D < handle
|
||||
function delete(d)
|
||||
% Delete the :mat:class:`Domain1D` object.
|
||||
|
||||
if isempty(d.domainID)
|
||||
return
|
||||
end
|
||||
ctFunc('domain_del', d.domainID);
|
||||
end
|
||||
|
||||
|
@ -50,6 +50,9 @@ classdef Sim1D < handle
|
||||
function delete(s)
|
||||
% Delete the :mat:class:`Sim1D` object.
|
||||
|
||||
if isempty(s.stID)
|
||||
return
|
||||
end
|
||||
ctFunc('sim1D_del', s.stID);
|
||||
end
|
||||
|
||||
|
@ -83,6 +83,9 @@ classdef FlowDevice < handle
|
||||
function delete(f)
|
||||
% Delete the :mat:class:`FlowDevice` object.
|
||||
|
||||
if isempty(f.id)
|
||||
return
|
||||
end
|
||||
ctFunc('flowdev_del', f.id);
|
||||
end
|
||||
|
||||
|
@ -140,6 +140,9 @@ classdef Reactor < handle
|
||||
function delete(r)
|
||||
% Delete the :mat:class:`Reactor` object.
|
||||
|
||||
if isempty(r.id)
|
||||
return
|
||||
end
|
||||
ctFunc('reactor_del', r.id);
|
||||
end
|
||||
|
||||
|
@ -85,6 +85,9 @@ classdef ReactorNet < handle
|
||||
function delete(r)
|
||||
% Delete the :mat:class:`ReactorNet` object object.
|
||||
|
||||
if isempty(r.id)
|
||||
return
|
||||
end
|
||||
ctFunc('reactornet_del', r.id);
|
||||
end
|
||||
|
||||
|
@ -56,6 +56,9 @@ classdef ReactorSurface < handle
|
||||
function delete(s)
|
||||
% Delete the :mat:class:`ReactorSurface` object.
|
||||
|
||||
if isempty(s.surfID)
|
||||
return
|
||||
end
|
||||
ctFunc('reactorsurface_del', s.surfID);
|
||||
end
|
||||
|
||||
|
@ -127,6 +127,9 @@ classdef Wall < handle
|
||||
function delete(w)
|
||||
% Clear the :mat:class:`Wall` object.
|
||||
|
||||
if isempty(w.id)
|
||||
return
|
||||
end
|
||||
ctFunc('wall_del', w.id);
|
||||
end
|
||||
|
||||
|
22
interfaces/matlab_experimental/Utility/ImportPhases.m
Normal file
22
interfaces/matlab_experimental/Utility/ImportPhases.m
Normal file
@ -0,0 +1,22 @@
|
||||
function phases = ctImportPhases(src, phasenames)
|
||||
ctIsLoaded;
|
||||
|
||||
if nargin < 2
|
||||
error('Please specify the source file and list of phases to import');
|
||||
end
|
||||
|
||||
phases = {};
|
||||
|
||||
if ischar(phasenames)
|
||||
phases = {Solution(src, phasenames)};
|
||||
return
|
||||
elseif iscell(phasenames)
|
||||
for name = phasenames
|
||||
phases = [phases; {Solution(src, name{:})}];
|
||||
end
|
||||
else
|
||||
error (['Invalid type for phasenames, ' , ...
|
||||
'expected string or a cell array of strings']);
|
||||
end
|
||||
|
||||
end
|
@ -4,7 +4,7 @@ function output = ctString(funcName, varargin)
|
||||
|
||||
err1 = -1;
|
||||
|
||||
buflen = calllib(ctLib, funcName, varargin{:}, 0, '');
|
||||
buflen = calllib(ctLib, funcName, varargin{:}, 0, '') + 1;
|
||||
|
||||
if buflen > 0
|
||||
aa = char(ones(1, buflen));
|
||||
@ -25,7 +25,7 @@ function output = ctString(funcName, varargin)
|
||||
error('Cantera:ctError', ctGetErr);
|
||||
end
|
||||
|
||||
if iok == -err1
|
||||
if iok == err1
|
||||
error('Cantera:ctError', ctGetErr);
|
||||
end
|
||||
|
||||
|
@ -12,25 +12,22 @@ function calling from Cantera CLib.
|
||||
since it's stand-alone.
|
||||
3. For first time users, launch Matlab, then navigate to `/path/to/cantera/source/code`
|
||||
(the folder containing `interfaces` and `samples`) using "Browse for Folder".
|
||||
Note for Ubuntu users: Matlab must be launched from the terminal
|
||||
using the following command:
|
||||
`LD_PRELOAD='/usr/lib/x86_64-linux-gnu/libstdc++.so.6' matlab -softwareopengl`.
|
||||
This is because Matlab does not load the correct GLIBC++ library on start-up and
|
||||
will return an error when loading the Cantera toolbox.
|
||||
4. In the Matlab command window, run
|
||||
4. For Linux users: Matlab currently uses Intel MKL which uses 64-bit integer types
|
||||
that are incompatible with the standard 32-bit integers used by the default version
|
||||
of OpenBLAS that comes with Cantera. As such, the correct environment variables
|
||||
need to be set to launch Matlab with the correct BLAS/LAPACK libraries loaded:
|
||||
`export LD_PRELOAD=/path/to/openblas/library:/path/to/lapack/library`
|
||||
then, launch Matlab in the terminal with:
|
||||
`matlab -softwareopengl`.
|
||||
5. In the Matlab command window, run
|
||||
`addpath(genpath([pwd, '/interfaces/matlab_experimental']))` to add search path for
|
||||
the experimental toolbox.
|
||||
5. In the Matlab command window, run
|
||||
6. In the Matlab command window, run
|
||||
`cd([pwd, '/interfaces/matlab_experimental/Utility'])` to navigate to the Utility
|
||||
folder.
|
||||
6. Open the file named 'ctRoot.m', in the second line, edit `output=` to
|
||||
7. Open the file named 'ctRoot.m', in the second line, edit `output=` to
|
||||
`output='/path/to/conda/environment'`, then save the file. This sets the search path
|
||||
for the `ctLoad` command to find the shared library file for Cantera.
|
||||
7. Make sure the legacy (old) Matlab Toolbox for
|
||||
Cantera (if it's already installed) and samples files are removed from
|
||||
the Matlab search path. Having both the legacy and experimental version
|
||||
of the toolbox in the search path will lead to conflicts.
|
||||
The command to remove search path in Matlab is `rmpath`.
|
||||
8. In the Matlab command window, run `savepath` to save all search paths.
|
||||
9. To switch back to the legacy Matlab toolbox, revert the search paths.
|
||||
|
||||
|
64
test/data/invalid-inputs.yaml
Normal file
64
test/data/invalid-inputs.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
phases:
|
||||
- name: A
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: all}]
|
||||
kinetics: gas
|
||||
state: {T: 300.0, P: 1 atm, X: {O2: 0.21, N2: 0.79}}
|
||||
reactions: [A-reactions]
|
||||
- name: B
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: all}]
|
||||
kinetics: gas
|
||||
state: {T: 300.0, P: 1 atm, X: {O2: 0.21, N2: 0.79}}
|
||||
reactions: [B-reactions]
|
||||
- name: C
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: all}]
|
||||
kinetics: gas
|
||||
state: {T: 300.0, P: 1 atm, X: {O2: 0.21, N2: 0.79}}
|
||||
reactions: [C-reactions]
|
||||
- name: D
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: all}]
|
||||
kinetics: gas
|
||||
state: {T: 300.0, P: 1 atm, X: {O2: 0.21, N2: 0.79}}
|
||||
reactions: [D-reactions]
|
||||
- name: E
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: all}]
|
||||
kinetics: gas
|
||||
state: {T: 300.0, P: 1 atm, X: {O2: 0.21, N2: 0.79}}
|
||||
reactions: [E-reactions]
|
||||
- name: F
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: all}]
|
||||
kinetics: gas
|
||||
state: {T: 300.0, P: 1 atm, X: {O2: 0.21, N2: 0.79}}
|
||||
reactions: [F-reactions]
|
||||
|
||||
A-reactions:
|
||||
- equation: O + H2 <=> H + OH # Reaction 3
|
||||
rate-constant: {A: 3.87e+04 cm^6/mol^2/s, b: 2.7, Ea: 6260.0}
|
||||
|
||||
B-reactions:
|
||||
- equation: O + H2 <=> H + OH # Reaction 3
|
||||
rate-constant: {A: 3.87e+04, b: 2.7, Ea: 6260.0 m}
|
||||
|
||||
C-reactions:
|
||||
- equation: O + H2 <=> H + OH
|
||||
|
||||
D-reactions:
|
||||
- equation: 2 OH (+M) <=> H2O2 (+M)
|
||||
type: falloff
|
||||
|
||||
E-reactions:
|
||||
- equation: O + H2 <=> H + OH
|
||||
type: pressure-dependent-Arrhenius
|
||||
|
||||
F-reactions:
|
||||
- equation: O + H2 <=> H + OH
|
||||
rate-constant: {A: 3.87e+04, b: 2.7, Ea: 6260.0}
|
||||
duplicate: true
|
||||
- equation: O + H2 <=> H + OH
|
||||
rate-constant: {A: -3.87e+04, b: 2.7, Ea: 6260.0}
|
||||
duplicate: true
|
82
test/data/undeclared-tests.yaml
Normal file
82
test/data/undeclared-tests.yaml
Normal file
@ -0,0 +1,82 @@
|
||||
phases:
|
||||
- name: A
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: [H, O2, H2O, HO2]}]
|
||||
kinetics: gas
|
||||
reactions: [A-reactions]
|
||||
- name: B
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: [H, O2, H2O, HO2]}]
|
||||
kinetics: gas
|
||||
reactions: [B-reactions]
|
||||
- name: C
|
||||
thermo: ideal-gas
|
||||
species:
|
||||
- h2o2.yaml/species: [H, O2, H2O, HO2]
|
||||
kinetics: gas
|
||||
reactions:
|
||||
- h2o2.yaml/reactions: declared-species
|
||||
skip-undeclared-third-bodies: true
|
||||
- name: D
|
||||
thermo: ideal-gas
|
||||
species:
|
||||
- h2o2.yaml/species: [H, O2, HO2]
|
||||
kinetics: gas
|
||||
reactions:
|
||||
- h2o2.yaml/reactions: declared-species
|
||||
skip-undeclared-third-bodies: true
|
||||
- name: E
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: [H, O2, H2O, HO2]}]
|
||||
kinetics: gas
|
||||
reactions: [E-reactions]
|
||||
- name: F
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: [H, O2, H2O, HO2]}]
|
||||
kinetics: gas
|
||||
reactions: [F-reactions]
|
||||
- name: G
|
||||
thermo: ideal-gas
|
||||
species: [{h2o2.yaml/species: [H, O2, H2O, HO2]}]
|
||||
kinetics: gas
|
||||
reactions: [G-reactions]
|
||||
- name: gas
|
||||
thermo: ideal-gas
|
||||
species:
|
||||
- gri30.yaml/species: [H2, H, O, OH, H2O, CO2]
|
||||
- name: Pt_surf
|
||||
thermo: ideal-surface
|
||||
species:
|
||||
- ptcombust.yaml/species: [PT(S), H(S), H2O(S), OH(S), CO2(S), CH2(S)s,
|
||||
CH(S), C(S), O(S)]
|
||||
kinetics: surface
|
||||
reactions: [ptcombust.yaml/reactions: declared-species]
|
||||
site-density: 2.7063e-09
|
||||
|
||||
A-reactions:
|
||||
- equation: O + H2 <=> H + OH # Reaction 3
|
||||
rate-constant: {A: 3.87e+04, b: 2.7, Ea: 6260.0}
|
||||
|
||||
B-reactions:
|
||||
- equation: H + O2 + AR <=> HO2 + AR # Reaction 10
|
||||
rate-constant: {A: 7.0e+17, b: -0.8, Ea: 0.0}
|
||||
|
||||
E-reactions:
|
||||
- equation: H + O2 => HO2
|
||||
rate-constant: {A: 1.255943e+13, b: -2.0, Ea: 5000.0 cal/mol}
|
||||
orders:
|
||||
H2O: 0.2
|
||||
nonreactant-orders: true
|
||||
|
||||
F-reactions:
|
||||
- equation: H + O2 => HO2
|
||||
rate-constant: {A: 1.255943e+13, b: -2.0, Ea: 5000.0 cal/mol}
|
||||
orders:
|
||||
H2O: 0.2
|
||||
|
||||
G-reactions:
|
||||
- equation: H + O2 => HO2
|
||||
rate-constant: {A: 1.255943e+13, b: -2.0, Ea: 5000.0 cal/mol}
|
||||
orders:
|
||||
N2: 0.2
|
||||
nonreactant-orders: true
|
101
test/matlab_experimental/ctTestDuplicateReactions.m
Normal file
101
test/matlab_experimental/ctTestDuplicateReactions.m
Normal file
@ -0,0 +1,101 @@
|
||||
classdef ctTestDuplicateReactions < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
|
||||
function testSetUp(self)
|
||||
ctTestSetUp
|
||||
copyfile('../data/duplicate-reactions.yaml', ...
|
||||
'./duplicate-reactions.yaml');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
delete('./duplicate-reactions.yaml');
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestMethodTeardown)
|
||||
|
||||
function deleteSolution(self)
|
||||
clear self.phase;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods
|
||||
|
||||
function check(self, name)
|
||||
try
|
||||
self.phase = Solution('duplicate-reactions.yaml', name);
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'duplicate reaction');
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
|
||||
function testForwardMultiple(self)
|
||||
self.check('A');
|
||||
end
|
||||
|
||||
function testOpposite1(self)
|
||||
self.check('B');
|
||||
end
|
||||
|
||||
function testOpposite2(self)
|
||||
self.check('C');
|
||||
end
|
||||
|
||||
function testOpposite3(self)
|
||||
self.check('D');
|
||||
end
|
||||
|
||||
function testOpposite4(self)
|
||||
self.check('E');
|
||||
self.verifyEqual(self.phase.nReactions, 2);
|
||||
end
|
||||
|
||||
function testCommonEfficiencies(self)
|
||||
self.check('F');
|
||||
end
|
||||
|
||||
function testDisjointEfficiencies(self)
|
||||
self.check('G');
|
||||
self.verifyEqual(self.phase.nReactions, 2);
|
||||
end
|
||||
|
||||
function testDifferentType(self)
|
||||
self.check('H');
|
||||
self.verifyEqual(self.phase.nReactions, 2);
|
||||
end
|
||||
|
||||
function testDeclaredDupliate(self)
|
||||
self.check('I');
|
||||
self.verifyEqual(self.phase.nReactions, 2);
|
||||
end
|
||||
|
||||
function testUnmatchedDuplicate(self)
|
||||
self.check('J');
|
||||
end
|
||||
|
||||
function testNonreactingSpecies(self)
|
||||
self.check('K');
|
||||
self.verifyEqual(self.phase.nReactions, 3);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
235
test/matlab_experimental/ctTestEquilibrium.m
Normal file
235
test/matlab_experimental/ctTestEquilibrium.m
Normal file
@ -0,0 +1,235 @@
|
||||
classdef ctTestEquilibrium < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
mix
|
||||
end
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
rtol = 1e-6;
|
||||
atol = 1e-8;
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
|
||||
function testSetUp(self)
|
||||
ctTestSetUp
|
||||
copyfile('../data/equilibrium.yaml', './equilibrium.yaml');
|
||||
copyfile('../data/IdealSolidSolnPhaseExample.yaml', ...
|
||||
'./IdealSolidSolnPhaseExample.yaml');
|
||||
copyfile('../data/koh-equil-TP.csv', './koh-equil-TP.csv');
|
||||
copyfile('../data/koh-equil-HP.csv', './koh-equil-HP.csv');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
delete('./equilibrium.yaml');
|
||||
delete('./IdealSolidSolnPhaseExample.yaml');
|
||||
delete('./koh-equil-TP.csv');
|
||||
delete('./koh-equil-HP.csv');
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestMethodTeardown)
|
||||
|
||||
function deleteSolution(self)
|
||||
clear self.phase self.mix
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods
|
||||
function checkval(self, names, moles)
|
||||
ntot = sum(moles);
|
||||
xx = moles ./ ntot;
|
||||
for i = 1:length(names)
|
||||
val = self.phase.X(self.phase.speciesIndex(names{i}));
|
||||
self.verifyEqual(val, xx(i), 'AbsTol', self.atol);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
|
||||
function testEquilCompleteStoichiometric(self)
|
||||
self.phase = Solution('equilibrium.yaml', 'complete');
|
||||
self.phase.TPX = {298, 1.0e6, 'CH4:1.0, O2:2.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 0, 2, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilCompleteLean(self)
|
||||
self.phase = Solution('equilibrium.yaml', 'complete');
|
||||
self.phase.TPX = {298, 1.0e6, 'CH4:1.0, O2:3.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 1, 2, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilIncompleteStoichiometric(self)
|
||||
self.phase = Solution('equilibrium.yaml', 'incomplete');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:2.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 0, 2, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilIncompleteLean(self)
|
||||
self.phase = Solution('equilibrium.yaml', 'incomplete');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:3.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 1, 2, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilGriStoichiometric(self)
|
||||
self.phase = Solution('gri30.yaml', '', 'none');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:2.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 0, 2, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilGriLean(self)
|
||||
self.phase = Solution('gri30.yaml', '', 'none');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:3.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 1, 2, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilOverconstrained1(self)
|
||||
self.phase = Solution('equilibrium.yaml', 'overconstrained-1');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:1.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2'};
|
||||
moles = [1, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilOverconstrained2(self)
|
||||
self.phase = Solution('equilibrium.yaml', 'overconstrained-2');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:1.0'};
|
||||
self.phase.equilibrate('TP');
|
||||
|
||||
names = {'CH4', 'O2'};
|
||||
moles = [1, 1];
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilGriStoichiometricGibbs(self)
|
||||
self.phase = Solution('equilibrium.yaml', '', 'none');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:1.0'};
|
||||
self.phase.equilibrate('TP', 'gibbs');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 0, 2, 1];
|
||||
|
||||
self.assumeFail('Skipping multi-phase equilibrium test');
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testEquilGriLeanGibbs(self)
|
||||
self.phase = Solution('equilibrium.yaml', '', 'none');
|
||||
self.phase.TPX = {301, 1.0e6, 'CH4:1.0, O2:3.0'};
|
||||
self.phase.equilibrate('TP', 'gibbs');
|
||||
|
||||
names = {'CH4', 'O2', 'H2O', 'CO2'};
|
||||
moles = [0, 1, 2, 1];
|
||||
|
||||
self.assumeFail('Skipping multi-phase equilibrium test');
|
||||
self.checkval(names, moles);
|
||||
end
|
||||
|
||||
function testKOHEquilTP(self)
|
||||
phasenames = {'K_solid', 'K_liquid', ...
|
||||
'KOH_a', 'KOH_b', 'KOH_liquid', ...
|
||||
'K2O2_solid', 'K2O_solid', 'KO2_solid', ...
|
||||
'ice', 'liquid_water', 'KOH_plasma'};
|
||||
phases = ImportPhases('KOH.yaml', phasenames);
|
||||
self.mix = Mixture(phases);
|
||||
|
||||
temp = 350:300:5000;
|
||||
data = zeros(length(temp), self.mix.nSpecies + 1);
|
||||
data(:, 1) = temp;
|
||||
|
||||
for i = 1:length(temp)
|
||||
self.mix.T = temp(i);
|
||||
self.mix.P = OneAtm;
|
||||
self.mix.setSpeciesMoles('K:1.03, H2:2.12, O2:0.9');
|
||||
self.mix.equilibrate('TP');
|
||||
|
||||
data(i, 2:end) = self.mix.speciesMoles;
|
||||
end
|
||||
|
||||
refData = readmatrix('koh-equil-TP.csv');
|
||||
self.verifySize(data, size(refData), ...
|
||||
'Generated data does not match reference size');
|
||||
self.verifyEqual(data, refData, 'AbsTol', self.atol);
|
||||
end
|
||||
|
||||
function testKOHEquilHP(self)
|
||||
phasenames = {'K_solid', 'K_liquid', ...
|
||||
'KOH_a', 'KOH_b', 'KOH_liquid', ...
|
||||
'K2O2_solid', 'K2O_solid', 'KO2_solid', ...
|
||||
'ice', 'liquid_water', 'KOH_plasma'};
|
||||
phases = ImportPhases('KOH.yaml', phasenames);
|
||||
self.mix = Mixture(phases);
|
||||
|
||||
temp = 350:300:5000;
|
||||
dT = 1;
|
||||
data = zeros(length(temp), self.mix.nSpecies + 2);
|
||||
data(:, 1) = temp;
|
||||
|
||||
self.mix.P = OneAtm;
|
||||
for i = 1:length(temp)
|
||||
self.mix.setSpeciesMoles('K:1.03, H2:2.12, O2:0.9');
|
||||
self.mix.T = temp(i) - dT;
|
||||
self.mix.equilibrate('TP');
|
||||
self.mix.T = temp(i);
|
||||
self.mix.equilibrate('HP');
|
||||
|
||||
data(i, 2) = self.mix.T;
|
||||
data(i, 3:end) = self.mix.speciesMoles;
|
||||
end
|
||||
|
||||
refData = readmatrix('koh-equil-HP.csv');
|
||||
self.verifySize(data, size(refData), ...
|
||||
'Generated data does not match reference size');
|
||||
self.verifyEqual(data, refData, 'AbsTol', self.atol);
|
||||
end
|
||||
|
||||
function testIdealSolidSolnPhaseEquil(self)
|
||||
self.phase = Solution('IdealSolidSolnPhaseExample.yaml');
|
||||
self.phase.TPX = {500, OneAtm, 'C2H2-graph: 1.0'};
|
||||
self.phase.equilibrate('TP', 'element_potential');
|
||||
|
||||
self.verifyEqual(self.phase.X(self.phase.speciesIndex('C-graph')), ...
|
||||
2.0/3.0, 'AbsTol', self.atol);
|
||||
self.verifyEqual(self.phase.X(self.phase.speciesIndex('H2-solute')), ...
|
||||
1.0/3.0, 'AbsTol', self.atol);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
290
test/matlab_experimental/ctTestFunc1.m
Normal file
290
test/matlab_experimental/ctTestFunc1.m
Normal file
@ -0,0 +1,290 @@
|
||||
classdef ctTestFunc1 < matlab.unittest.TestCase
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
rtol = 1e-6;
|
||||
atol = 1e-8;
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
|
||||
function testSetUp(self)
|
||||
ctTestSetUp
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
|
||||
function testFunction(self)
|
||||
f = Func1('sin', 1);
|
||||
for i = [0, 0.1, 0.7]
|
||||
self.verifyEqual(f(i), sin(i), 'AbsTol', self.atol);
|
||||
end
|
||||
|
||||
clear f
|
||||
end
|
||||
|
||||
function testLambda(self)
|
||||
f1 = Func1('sin', 1);
|
||||
f2 = Func1('pow', 0.5);
|
||||
f = Func1('product', f1, f2);
|
||||
|
||||
for i = [0.1, 0.7, 4.5]
|
||||
self.verifyEqual(f(i), sin(i)*sqrt(i), 'AbsTol', self.atol);
|
||||
end
|
||||
|
||||
clear f1 f2 f
|
||||
end
|
||||
|
||||
function testConstant(self)
|
||||
f = Func1('constant', 5);
|
||||
|
||||
for i = [0.1, 0.7, 4.5]
|
||||
self.verifyEqual(f(i), 5, 'AbsTol', self.atol);
|
||||
end
|
||||
|
||||
clear f
|
||||
end
|
||||
|
||||
function testSimple(self)
|
||||
functors = {'sin', 'cos', 'exp', 'log'};
|
||||
coeff = 2.34;
|
||||
|
||||
for name = functors
|
||||
f = Func1(name{:}, coeff);
|
||||
self.verifySubstring(f.write, name{:});
|
||||
self.verifyEqual(f.type, name{:});
|
||||
for val = [0.1, 1, 10]
|
||||
self.verifyEqual(f(val), feval(name{:}, coeff*val), ...
|
||||
'AbsTol', self.atol);
|
||||
end
|
||||
clear f
|
||||
end
|
||||
end
|
||||
|
||||
function testCompound(self)
|
||||
f0 = 3.1415;
|
||||
f1 = Func1('pow', 2);
|
||||
f2 = Func1('sin');
|
||||
val = [0.1, 1, 10];
|
||||
functors = containers.Map(...
|
||||
{'sum', 'diff', 'product', 'ratio'}, ...
|
||||
{@(x, y) x + y, @(x, y) x - y, @(x, y) x * y, @(x, y) x / y});
|
||||
|
||||
for k = keys(functors)
|
||||
func = Func1(k{:}, f1, f2);
|
||||
f = functors(k{:});
|
||||
self.verifyFalse(contains(func.write, k{:}));
|
||||
self.verifyEqual(k{:}, func.type);
|
||||
for v = val
|
||||
x1 = func(v);
|
||||
x2 = f(f1(v), f2(v));
|
||||
self.verifyEqual(x1, x2, 'absTol', self.atol);
|
||||
end
|
||||
clear func
|
||||
end
|
||||
|
||||
f3 = Func1('sum', f0, f1);
|
||||
f4 = Func1('sum', f2, f0);
|
||||
for v = val
|
||||
self.verifyEqual(f3(v), f0 + f1(v), 'absTol', self.atol);
|
||||
self.verifyEqual(f4(v), f0 + f2(v), 'absTol', self.atol);
|
||||
end
|
||||
|
||||
try
|
||||
f5 = Func1('sum', f0, f0);
|
||||
catch ME
|
||||
self.verifySubstring(ME.message, 'Invalid arguments');
|
||||
end
|
||||
|
||||
try
|
||||
f6 = Func1('sum', 'spam', 'eggs');
|
||||
catch ME
|
||||
self.verifySubstring(ME.message, 'Invalid arguments');
|
||||
end
|
||||
|
||||
clear f1 f2 f3 f4
|
||||
end
|
||||
|
||||
function testNewSum(self)
|
||||
f1 = Func1('sin', 3);
|
||||
|
||||
f2 = f1 + 0;
|
||||
self.verifyEqual(f2.type, 'sin');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3), 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = 0 + f1;
|
||||
self.verifyEqual(f2.type, 'sin');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3), 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 + Func1('constant', 1);
|
||||
self.verifyEqual(f2.type, 'plus-constant');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3) + 1, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 + f1;
|
||||
self.verifyEqual(f2.type, 'times-constant');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3) * 2, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
clear f1
|
||||
end
|
||||
|
||||
function testNewDiff(self)
|
||||
f1 = Func1('sin', 3);
|
||||
|
||||
f2 = f1 - 0;
|
||||
self.verifyEqual(f2.type, 'sin');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3), 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = 0 - f1;
|
||||
self.verifyEqual(f2.type, 'times-constant');
|
||||
self.verifyEqual(f2(0.5), -sin(0.5 * 3), 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 - Func1('constant', 1);
|
||||
self.verifyEqual(f2.type, 'plus-constant');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3) - 1, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 - f1;
|
||||
self.verifyEqual(f2.type, 'constant');
|
||||
self.verifyEqual(f2(0.5), 0, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
clear f1
|
||||
end
|
||||
|
||||
function testNewProd(self)
|
||||
f1 = Func1('sin', 3);
|
||||
|
||||
f2 = f1 * Func1('constant', 1);
|
||||
self.verifyEqual(f2.type, 'sin');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3), 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 * 2;
|
||||
self.verifyEqual(f2.type, 'times-constant');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3) * 2, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 * 0;
|
||||
self.verifyEqual(f2.type, 'constant');
|
||||
self.verifyEqual(f2(0.5), 0, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
clear f1
|
||||
end
|
||||
|
||||
function testNewRatio(self)
|
||||
f1 = Func1('sin', 3);
|
||||
|
||||
f2 = f1 / Func1('constant', 1);
|
||||
self.verifyEqual(f2.type, 'sin');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3), 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = 0 / f1;
|
||||
self.verifyEqual(f2.type, 'constant');
|
||||
self.verifyEqual(f2(0.5), 0, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
f2 = f1 / 2;
|
||||
self.verifyEqual(f2.type, 'times-constant');
|
||||
self.verifyEqual(f2(0.5), sin(0.5 * 3) / 2, 'absTol', self.atol);
|
||||
clear f2
|
||||
|
||||
try
|
||||
f2 = f1 / 0;
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'Division by zero');
|
||||
clear f2
|
||||
end
|
||||
|
||||
clear f1
|
||||
end
|
||||
|
||||
function testModified(self)
|
||||
f1 = Func1('sin');
|
||||
const = 2.34;
|
||||
val = [0.1, 1, 10];
|
||||
functors = containers.Map(...
|
||||
{'plus-constant', 'times-constant'}, ...
|
||||
{@(x, y) x + y, @(x, y) x * y});
|
||||
|
||||
for k = keys(functors)
|
||||
func = Func1(k{:}, f1, const);
|
||||
f = functors(k{:});
|
||||
self.verifyFalse(contains(func.write, k{:}));
|
||||
self.verifyEqual(k{:}, func.type);
|
||||
for v = val
|
||||
x1 = func(v);
|
||||
x2 = f(f1(v), const);
|
||||
self.verifyEqual(x1, x2, 'absTol', self.atol);
|
||||
end
|
||||
clear func
|
||||
|
||||
try
|
||||
func = Func1(k{:}, const, f1);
|
||||
catch ME
|
||||
self.verifySubstring(ME.message, 'Invalid arguments');
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function testTabulated(self)
|
||||
t = [0, 1, 2];
|
||||
fval = [2, 1, 0];
|
||||
v1 = [-0.5, 0, 0.5, 1.0, 1.5, 2, 2.5];
|
||||
v2 = [2.0, 2.0, 1.5, 1.0, 0.5, 0.0, 0.0];
|
||||
v3 = [2.0, 2.0, 2.0, 2.0, 1.0, 0.0, 0.0];
|
||||
|
||||
func1 = Func1('tabulated-linear', t, fval);
|
||||
self.verifyEqual(func1.type, 'tabulated-linear');
|
||||
for i = length(v1)
|
||||
self.verifyEqual(func1(v1(i)), v2(i), 'absTol', self.atol);
|
||||
end
|
||||
|
||||
func2 = Func1('tabulated-previous', t, fval);
|
||||
self.verifyEqual(func2.type, 'tabulated-previous');
|
||||
for i = length(v1)
|
||||
self.verifyEqual(func2(v1(i)), v3(i), 'absTol', self.atol);
|
||||
end
|
||||
|
||||
try
|
||||
func3 = Func1('tabulated-linear', 0:2, 0:3);
|
||||
catch ME
|
||||
self.verifySubstring(ME.message, 'even number of entries');
|
||||
end
|
||||
|
||||
try
|
||||
func3 = Func1('tabulated-linear', [], []);
|
||||
catch ME
|
||||
self.verifySubstring(ME.message, 'at least 4 entries');
|
||||
end
|
||||
|
||||
try
|
||||
func3 = Func1('tabulated-linear', [0, 1, 0.5, 2], [2, 1, 1, 0]);
|
||||
catch ME
|
||||
self.verifySubstring(ME.message, 'monotonically');
|
||||
end
|
||||
|
||||
clear func1 func2
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
97
test/matlab_experimental/ctTestInvalidInputs.m
Normal file
97
test/matlab_experimental/ctTestInvalidInputs.m
Normal file
@ -0,0 +1,97 @@
|
||||
classdef ctTestInvalidInputs < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
end
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
inputfile = 'invalid-inputs.yaml';
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
|
||||
function testSetUp(self)
|
||||
copyfile('../data/invalid-inputs.yaml', ...
|
||||
'./invalid-inputs.yaml');
|
||||
ctTestSetUp
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
delete('./invalid-inputs.yaml');
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestMethodTeardown)
|
||||
|
||||
function deleteSolution(self)
|
||||
clear self.phase;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
|
||||
function testFailingConvert1(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'A');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'UnitSystem::convert');
|
||||
end
|
||||
end
|
||||
|
||||
function testFailingConvert2(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'B');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'UnitSystem::convertActivationEnergy');
|
||||
end
|
||||
end
|
||||
|
||||
function testFailingUnconfigured1(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'C');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'ArrheniusBase::validate');
|
||||
end
|
||||
end
|
||||
|
||||
function testFailingUnconfigured2(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'D');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'FalloffRate::validate');
|
||||
end
|
||||
end
|
||||
|
||||
function testFailingUnconfigured3(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'E');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'PlogRate::validate');
|
||||
end
|
||||
end
|
||||
|
||||
function testFailingInvalidDuplicate(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'F');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'ArrheniusBase::check');
|
||||
self.verifySubstring(ME.message, 'negative pre-exponential factor');
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -2,6 +2,9 @@ classdef ctTestKinetics < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
end
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
rtol = 1e-6;
|
||||
atol = 1e-8;
|
||||
end
|
||||
@ -10,6 +13,12 @@ classdef ctTestKinetics < matlab.unittest.TestCase
|
||||
|
||||
function testSetUp(self)
|
||||
ctTestSetUp
|
||||
copyfile('../data/air-no-reactions.yaml', ...
|
||||
'./air-no-reactions.yaml');
|
||||
copyfile('../data/chemically-activated-reaction.yaml', ...
|
||||
'./chemically-activated-reaction.yaml');
|
||||
copyfile('../data/addReactions_err_test.yaml', ...
|
||||
'./addReactions_err_test.yaml');
|
||||
end
|
||||
|
||||
end
|
||||
@ -17,6 +26,9 @@ classdef ctTestKinetics < matlab.unittest.TestCase
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
delete('./air-no-reactions.yaml');
|
||||
delete('./chemically-activated-reaction.yaml');
|
||||
delete('./addReactions_err_test.yaml');
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
@ -150,6 +162,113 @@ classdef ctTestKinetics < matlab.unittest.TestCase
|
||||
|
||||
end
|
||||
|
||||
function testRatesOfProgress(self)
|
||||
forROP = self.phase.forwardRatesOfProgress;
|
||||
revROP = self.phase.reverseRatesOfProgress;
|
||||
netROP = self.phase.netRatesOfProgress;
|
||||
|
||||
l = length(netROP);
|
||||
tol = ones(1, l) .* self.atol;
|
||||
|
||||
self.verifyEqual(l, self.phase.nReactions);
|
||||
self.verifyEqual(forROP - revROP, netROP, 'AbsTol', tol);
|
||||
end
|
||||
|
||||
function testRateConstants(self)
|
||||
kf = self.phase.forwardRateConstants;
|
||||
kr = self.phase.reverseRateConstants;
|
||||
Keq = self.phase.equilibriumConstants;
|
||||
|
||||
l = length(kf);
|
||||
self.verifyEqual(l, self.phase.nReactions);
|
||||
|
||||
ix = find(kr ~= 0);
|
||||
tol = ones(1, l) .* self.rtol;
|
||||
self.verifyEqual(kf(ix) ./ kr(ix), Keq(ix), 'RelTol', tol);
|
||||
end
|
||||
|
||||
function testSpeciesRates(self)
|
||||
nu_p = self.phase.productStoichCoeffs;
|
||||
nu_r = self.phase.reactantStoichCoeffs;
|
||||
forROP = self.phase.forwardRatesOfProgress;
|
||||
revROP = self.phase.reverseRatesOfProgress;
|
||||
cr = full(sum(nu_p .* forROP, 2) + sum(nu_r .* revROP, 2))';
|
||||
de = full(sum(nu_r .* forROP, 2) + sum(nu_p .* revROP, 2))';
|
||||
|
||||
l = length(self.phase.nSpecies);
|
||||
tol = ones(1, l) .* self.rtol;
|
||||
|
||||
self.verifyEqual(self.phase.creationRates, cr, 'RelTol', tol);
|
||||
self.verifyEqual(self.phase.destructionRates, de, 'RelTol', tol);
|
||||
self.verifyEqual(self.phase.netProdRates, cr - de, 'RelTol', tol);
|
||||
end
|
||||
|
||||
function testReactionDeltas(self)
|
||||
H = self.phase.deltaEnthalpy;
|
||||
S = self.phase.deltaEntropy;
|
||||
G = self.phase.deltaGibbs;
|
||||
Hs = self.phase.deltaStandardEnthalpy;
|
||||
Ss = self.phase.deltaStandardEntropy;
|
||||
Gs = self.phase.deltaStandardGibbs;
|
||||
T = self.phase.T;
|
||||
|
||||
l = length(H);
|
||||
tol = ones(1, l) .* self.rtol;
|
||||
|
||||
self.verifyEqual(H - S .* T, G, 'RelTol', tol);
|
||||
self.verifyEqual(Hs - Ss .* T, Gs, 'RelTol', tol);
|
||||
end
|
||||
|
||||
function testEmptyKinetics(self)
|
||||
try
|
||||
gas = Solution('air-no-reactions.yaml');
|
||||
arr = zeros(1, gas.nSpecies);
|
||||
tol = ones(1, gas.nSpecies) .* self.atol;
|
||||
|
||||
self.verifyEqual(gas.nReactions, 0);
|
||||
self.verifyEqual(gas.creationRates, arr, 'AbsTol', tol);
|
||||
self.verifyEqual(gas.destructionRates, arr, 'AbsTol', tol);
|
||||
self.verifyEqual(gas.netProdRates, arr, 'AbsTol', tol);
|
||||
|
||||
clear gas
|
||||
|
||||
catch ME
|
||||
clear gas
|
||||
rethrow(ME);
|
||||
end
|
||||
end
|
||||
|
||||
function testChemicallyActivated(self)
|
||||
try
|
||||
gas = Solution('chemically-activated-reaction.yaml');
|
||||
|
||||
P = [2026.5, 202650.0, 10132500.0];
|
||||
Rf = [2.851022e-04, 2.775924e+00, 2.481792e+03];
|
||||
xx = [0.01, 0.01, 0.04, 0.10, 0.84];
|
||||
|
||||
for i = 1:length(P)
|
||||
gas.TPX = {900.0, P(i), xx};
|
||||
self.verifyEqual(gas.forwardRatesOfProgress(1), Rf(i), 'RelTol', 2.0e-05);
|
||||
end
|
||||
|
||||
clear gas
|
||||
|
||||
catch ME
|
||||
clear gas
|
||||
rethrow(ME);
|
||||
end
|
||||
end
|
||||
|
||||
function testPdepError(self)
|
||||
try
|
||||
gas = Solution('addReactions_err_test.yaml');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'Invalid rate coefficient');
|
||||
clear gas
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
174
test/matlab_experimental/ctTestKineticsRepeatability.m
Normal file
174
test/matlab_experimental/ctTestKineticsRepeatability.m
Normal file
@ -0,0 +1,174 @@
|
||||
classdef ctTestKineticsRepeatability < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
X0
|
||||
X1
|
||||
end
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
T0 = 1200;
|
||||
T1 = 1300;
|
||||
rho0 = 2.4;
|
||||
rho1 = 3.1;
|
||||
P0 = 1.4e+05;
|
||||
P1 = 3.7e+06;
|
||||
rtol = 1e-6;
|
||||
atol = 1e-8;
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
|
||||
function testSetUp(self)
|
||||
ctTestSetUp
|
||||
copyfile('../data/pdep-test.yaml', ...
|
||||
'./pdep-test.yaml');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
delete('./pdep-test.yaml');
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestMethodTeardown)
|
||||
|
||||
function deleteSolution(self)
|
||||
clear self.phase;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods
|
||||
|
||||
function setup_phase(self, mech)
|
||||
clear self.phase
|
||||
self.phase = Solution(mech);
|
||||
self.X0 = 1 + sin(1:self.phase.nSpecies);
|
||||
self.X1 = 1 + sin(2:self.phase.nSpecies + 1);
|
||||
end
|
||||
|
||||
function checkRatesX(self, mech)
|
||||
self.setup_phase(mech);
|
||||
|
||||
self.phase.TDX = {self.T0, self.rho0, self.X0};
|
||||
w1 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TDX = {self.T1, self.rho1, self.X1};
|
||||
w2 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TDX = {self.T0, self.rho0, self.X1};
|
||||
w3 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TDX = {self.T0, self.rho0, self.X0};
|
||||
w4 = self.phase.netProdRates;
|
||||
|
||||
self.verifyEqual(w1, w4, 'RelTol', self.rtol);
|
||||
end
|
||||
|
||||
function checkRatesT1(self, mech)
|
||||
self.setup_phase(mech);
|
||||
|
||||
self.phase.TDX = {self.T0, self.rho0, self.X0};
|
||||
w1 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TDX = {self.T1, self.rho1, self.X1};
|
||||
w2 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TDX = {self.T1, self.rho0, self.X0};
|
||||
w3 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TDX = {self.T0, self.rho0, self.X0};
|
||||
w4 = self.phase.netProdRates;
|
||||
|
||||
self.verifyEqual(w1, w4, 'RelTol', self.rtol);
|
||||
end
|
||||
|
||||
function checkRatesT2(self, mech)
|
||||
self.setup_phase(mech);
|
||||
|
||||
self.phase.TPX = {self.T0, self.P0, self.X0};
|
||||
w1 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TPX = {self.T1, self.P1, self.X1};
|
||||
w2 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TPX = {self.T1, self.P0, self.X0};
|
||||
w3 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TPX = {self.T0, self.P0, self.X0};
|
||||
w4 = self.phase.netProdRates;
|
||||
|
||||
self.verifyEqual(w1, w4, 'RelTol', self.rtol);
|
||||
end
|
||||
|
||||
function checkRatesP(self, mech)
|
||||
self.setup_phase(mech);
|
||||
|
||||
self.phase.TPX = {self.T0, self.P0, self.X0};
|
||||
w1 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TPX = {self.T1, self.P1, self.X1};
|
||||
w2 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TPX = {self.T0, self.P1, self.X0};
|
||||
w3 = self.phase.netProdRates;
|
||||
|
||||
self.phase.TPX = {self.T0, self.P0, self.X0};
|
||||
w4 = self.phase.netProdRates;
|
||||
|
||||
self.verifyEqual(w1, w4, 'RelTol', self.rtol);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
|
||||
function testGRI30X(self)
|
||||
self.checkRatesX('gri30.yaml');
|
||||
end
|
||||
|
||||
function testGRI30T(self)
|
||||
self.checkRatesT1('gri30.yaml');
|
||||
self.checkRatesT2('gri30.yaml');
|
||||
end
|
||||
|
||||
function testGRI30P(self)
|
||||
self.checkRatesP('gri30.yaml');
|
||||
end
|
||||
|
||||
function testH2O2X(self)
|
||||
self.checkRatesX('h2o2.yaml');
|
||||
end
|
||||
|
||||
function testH2O2T(self)
|
||||
self.checkRatesT1('h2o2.yaml');
|
||||
self.checkRatesT2('h2o2.yaml');
|
||||
end
|
||||
|
||||
function testH2O2P(self)
|
||||
self.checkRatesP('h2o2.yaml');
|
||||
end
|
||||
|
||||
function testPdepX(self)
|
||||
self.checkRatesX('pdep-test.yaml');
|
||||
end
|
||||
|
||||
function testPdepT(self)
|
||||
self.checkRatesT1('pdep-test.yaml');
|
||||
self.checkRatesT2('pdep-test.yaml');
|
||||
end
|
||||
|
||||
function testPdepP(self)
|
||||
self.checkRatesP('pdep-test.yaml');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -21,3 +21,4 @@ cantera_root = getenv('CANTERA_ROOT');
|
||||
% Add the Cantera toolbox to the Matlab path
|
||||
addpath(genpath([cantera_root, '/interfaces/matlab_experimental']));
|
||||
addpath(genpath([cantera_root, '/test/matlab_experimental']));
|
||||
addpath(genpath([cantera_root, '/test/data']));
|
||||
|
@ -2,6 +2,9 @@ classdef ctTestThermo < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
end
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
rtol = 1e-6;
|
||||
atol = 1e-8;
|
||||
end
|
||||
|
110
test/matlab_experimental/ctTestUndeclared.m
Normal file
110
test/matlab_experimental/ctTestUndeclared.m
Normal file
@ -0,0 +1,110 @@
|
||||
classdef ctTestUndeclared < matlab.unittest.TestCase
|
||||
|
||||
properties
|
||||
phase
|
||||
end
|
||||
|
||||
properties (SetAccess = immutable)
|
||||
inputfile = 'undeclared-tests.yaml';
|
||||
end
|
||||
|
||||
methods (TestClassSetup)
|
||||
|
||||
function testSetUp(self)
|
||||
copyfile('../data/undeclared-tests.yaml', ...
|
||||
'./undeclared-tests.yaml');
|
||||
ctTestSetUp
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestClassTeardown)
|
||||
|
||||
function testTearDown(self)
|
||||
delete('./undeclared-tests.yaml');
|
||||
ctCleanUp
|
||||
ctTestTearDown
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (TestMethodTeardown)
|
||||
|
||||
function deleteSolution(self)
|
||||
clear self.phase;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Test)
|
||||
|
||||
function testRaiseUndeclaredSpecies(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'A');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'contains undeclared species');
|
||||
end
|
||||
end
|
||||
|
||||
function testRaiseUndeclaredThirdBodies(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'B');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'three-body reaction with undeclared');
|
||||
end
|
||||
end
|
||||
|
||||
function testSkipUndeclaredThirdBodies1(self)
|
||||
self.phase = Solution(self.inputfile, 'C');
|
||||
self.verifyEqual(self.phase.nReactions, 3);
|
||||
end
|
||||
|
||||
function testSkipUndeclaredThirdBodies2(self)
|
||||
self.phase = Solution(self.inputfile, 'D');
|
||||
rxns = self.phase.reactionEquations;
|
||||
self.verifyTrue(ismember('H + O2 + M <=> HO2 + M', rxns));
|
||||
end
|
||||
|
||||
function testSkipUndeclaredOrders(self)
|
||||
self.phase = Solution(self.inputfile, 'E');
|
||||
self.verifyEqual(self.phase.nReactions, 1);
|
||||
end
|
||||
|
||||
function testRaiseNonreactantOrders(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'F');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'Reaction order specified');
|
||||
end
|
||||
end
|
||||
|
||||
function testRaiseUndeclaredOrders(self)
|
||||
try
|
||||
self.phase = Solution(self.inputfile, 'G');
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
self.verifySubstring(ME.message, 'reaction orders for undeclared');
|
||||
end
|
||||
end
|
||||
|
||||
function testSkipUndeclaredSurfSpecies(self)
|
||||
try
|
||||
gas = Solution(self.inputfile, 'gas');
|
||||
surf = Interface(self.inputfile, 'Pt_surf', gas);
|
||||
self.verifyEqual(surf.nReactions, 14);
|
||||
|
||||
clear gas
|
||||
clear surf
|
||||
|
||||
catch ME
|
||||
self.verifySubstring(ME.identifier, 'Cantera:ctError');
|
||||
clear gas
|
||||
clear surf
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user