diff --git a/interfaces/matlab/toolbox/@ReactorSurface/ReactorSurface.m b/interfaces/matlab/toolbox/@ReactorSurface/ReactorSurface.m new file mode 100644 index 000000000..2e70683e9 --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/ReactorSurface.m @@ -0,0 +1,55 @@ +function x = ReactorSurface(kinetics, reactor, area) +% REACTORSURFACE ReactorSurface class constructor. +% x = ReactorSurface(kinetics, reactor, area) +% +% A surface on which heterogeneous reactions take place. The mechanism object +% (typically an instance of class :mat:func:`Interface`) must be constructed so +% that it is properly linked to the object representing the fluid in the +% reactor. The surface temperature on each side is taken to be equal to the +% temperature of the reactor. +% +% Note: all of the arguments are optional and can be activated after initial +% construction by using the various methods of the :mat:func:`ReactorSurface` +% class. +% +% :param kleft: +% Surface reaction mechanisms for the left-facing surface. This must be an +% instance of class :mat:func:`Kinetics`, or of a class derived from Kinetics, +% such as :mat:func:`Interface`. +% :param reactor: +% Instance of class :mat:func:`Reactor` to be used as the adjacent bulk +% phase. See :mat:func:`install` +% :param area: +% The area of the surface in m**2. See :mat:func:`area` and +% :mat:func:`setArea`. Defaults to 1.0 m**2 if not specified. +% :return: +% Instance of class :mat:func:`ReactorSurface` + +x.index = reactorsurfacemethods(0, 0); + +if x.index < 0 + error(geterr); +end +x.reactor = -1; +x = class(x, 'ReactorSurface'); + +if nargin >= 1 + setKinetics(x, kinetics); +end + +if nargin >= 2 + if isa(reactor, 'Reactor') + install(x, reactor); + else + warning(['"reactor" was not an instance of Reactor, ' ... + 'and was not installed.']) + end +end + +if nargin >= 3 + if isnumeric(area) + setArea(x, area); + else + warning('area was not a number and the area was not set') + end +end diff --git a/interfaces/matlab/toolbox/@ReactorSurface/area.m b/interfaces/matlab/toolbox/@ReactorSurface/area.m new file mode 100644 index 000000000..2d2ff1450 --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/area.m @@ -0,0 +1,10 @@ +function a = area(s) +% AREA Get the area of the reactor surface. +% a = area(s) +% :param s: +% Instance of class :mat:func:`ReactorSurface` +% :return: +% Area of the reactor surface in m**2 +% + +a = reactorsurfacemethods(23, reactorsurface_hndl(s)); diff --git a/interfaces/matlab/toolbox/@ReactorSurface/clear.m b/interfaces/matlab/toolbox/@ReactorSurface/clear.m new file mode 100644 index 000000000..9ffaa2f09 --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/clear.m @@ -0,0 +1,8 @@ +function clear(s) +% CLEAR Delete the C++ ReactorSurface object. +% clear(s) +% :param s: +% Instance of class :mat:func:`ReactorSurface` +% + +reactorsurfacemethods(1, reactorsurface_hndl(s)); diff --git a/interfaces/matlab/toolbox/@ReactorSurface/install.m b/interfaces/matlab/toolbox/@ReactorSurface/install.m new file mode 100644 index 000000000..8e1d4a3be --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/install.m @@ -0,0 +1,11 @@ +function install(s, reactor) +% INSTALL Install a ReactorSurface in a Reactor. +% install(s, reactor) +% :param s: +% Instance of class :mat:func:`ReactorSurface` +% :param reactor: +% Instance of class :mat:func:`Reactor` +% + +s.reactor = reactor; +reactorsurfacemethods(4, reactorsurface_hndl(s), reactor_hndl(reactor)); diff --git a/interfaces/matlab/toolbox/@ReactorSurface/private/reactorsurfacemethods.m b/interfaces/matlab/toolbox/@ReactorSurface/private/reactorsurfacemethods.m new file mode 100644 index 000000000..3050a6fff --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/private/reactorsurfacemethods.m @@ -0,0 +1,13 @@ +function v = reactorsurfacemethods(n, job, a, b, c, d) +% +if nargin == 2 + v = ctmethods(75, n, job); +elseif nargin == 3 + v = ctmethods(75, n, job, a); +elseif nargin == 4 + v = ctmethods(75, n, job, a, b); +elseif nargin == 5 + v = ctmethods(75, n, job, a, b, c); +elseif nargin == 6 + v = ctmethods(75, n, job, a, b, c, d); +end diff --git a/interfaces/matlab/toolbox/@ReactorSurface/reactorsurface_hndl.m b/interfaces/matlab/toolbox/@ReactorSurface/reactorsurface_hndl.m new file mode 100644 index 000000000..e03264040 --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/reactorsurface_hndl.m @@ -0,0 +1,11 @@ +function i = reactorsurface_hndl(s) +% REACTORSURFACE_HNDL Get the integer used to access the Cantera C++ object. +% i = reactorsurf_hndl(s) +% :param s: +% Instance of class :mat:func:`ReactorSurface` for which the handle is +% desired. +% :return: +% Integer used to access the Cantera C++ object +% + +i = s.index; diff --git a/interfaces/matlab/toolbox/@ReactorSurface/setArea.m b/interfaces/matlab/toolbox/@ReactorSurface/setArea.m new file mode 100644 index 000000000..1943754cf --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/setArea.m @@ -0,0 +1,10 @@ +function setArea(s, a) +% SETAREA Set the area of a reactor surface. +% setArea(s, a) +% :param s: +% Instance of class :mat:func:`ReactorSurface` +% :param a: +% Double area of the reactor surface. +% + +reactorsurfacemethods(5, reactorsurface_hndl(s), a); diff --git a/interfaces/matlab/toolbox/@ReactorSurface/setKinetics.m b/interfaces/matlab/toolbox/@ReactorSurface/setKinetics.m new file mode 100644 index 000000000..b765f685e --- /dev/null +++ b/interfaces/matlab/toolbox/@ReactorSurface/setKinetics.m @@ -0,0 +1,17 @@ +function setKinetics(s, kinetics) +% SETKINETICS Set the surface reaction mechanisms on a reactor surface. +% setKinetics(w, kinetics) +% :param s: +% Instance of class :mat:func:`ReactorSurface` +% :param kinetics: +% Instance of class :mat:func:`Kinetics` (or another object derived from +% Kinetics) to be used as the kinetic mechanism for this surface. Typically +% an instance of class :mat:func:`Interface`. +% + +ikin = 0; +if isa(kinetics, 'Kinetics') + ikin = kinetics_hndl(kinetics); +end + +reactorsurfacemethods(12, reactorsurface_hndl(s), ikin); diff --git a/samples/matlab/surfreactor.m b/samples/matlab/surfreactor.m index 9a306b73e..72aff020c 100644 --- a/samples/matlab/surfreactor.m +++ b/samples/matlab/surfreactor.m @@ -35,13 +35,13 @@ env = Reservoir(a); w = Wall; install(w,r,env); -% set the surface mechanism on the left side of the wall (facing -% reactor 'r' to 'surf'. No surface mechanism will be installed on -% the air side. -setKinetics(w, surf, 0); +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, 1.0e-4); +setArea(w, A); setHeatTransferCoeff(w,1.0e1); % W/m2/K % set expansion rate parameter. dV/dt = KA(P_1 - P_2) diff --git a/src/clib/ctreactor.cpp b/src/clib/ctreactor.cpp index 290023e65..6937fad79 100644 --- a/src/clib/ctreactor.cpp +++ b/src/clib/ctreactor.cpp @@ -23,11 +23,13 @@ typedef Cabinet WallCabinet; typedef Cabinet FuncCabinet; typedef Cabinet ThermoCabinet; typedef Cabinet KineticsCabinet; +typedef Cabinet ReactorSurfaceCabinet; template<> ReactorCabinet* ReactorCabinet::s_storage = 0; template<> NetworkCabinet* NetworkCabinet::s_storage = 0; template<> FlowDeviceCabinet* FlowDeviceCabinet::s_storage = 0; template<> WallCabinet* WallCabinet::s_storage = 0; +template<> ReactorSurfaceCabinet* ReactorSurfaceCabinet::s_storage = 0; extern "C" { @@ -627,6 +629,76 @@ extern "C" { } } + // ReactorSurface + + int reactorsurface_new(int type) + { + try { + return ReactorSurfaceCabinet::add(new ReactorSurface()); + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int reactorsurface_del(int i) + { + try { + ReactorSurfaceCabinet::del(i); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int reactorsurface_install(int i, int n) + { + try { + ReactorCabinet::item(n).addSurface(&ReactorSurfaceCabinet::item(i)); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int reactorsurface_setkinetics(int i, int n) + { + try { + ReactorSurfaceCabinet::item(i).setKinetics(&KineticsCabinet::item(n)); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + double reactorsurface_area(int i) + { + try { + return ReactorSurfaceCabinet::item(i).area(); + } catch (...) { + return handleAllExceptions(DERR, DERR); + } + } + + int reactorsurface_setArea(int i, double v) + { + try { + ReactorSurfaceCabinet::item(i).setArea(v); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int reactorsurface_addSensitivityReaction(int i, int rxn) + { + try { + ReactorSurfaceCabinet::item(i).addSensitivityReaction(rxn); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + int clear_reactors() { try { @@ -634,6 +706,7 @@ extern "C" { NetworkCabinet::clear(); FlowDeviceCabinet::clear(); WallCabinet::clear(); + ReactorSurfaceCabinet::clear(); return 0; } catch (...) { return handleAllExceptions(-1, ERR); diff --git a/src/clib/ctreactor.h b/src/clib/ctreactor.h index 6b466e662..e8733f21f 100644 --- a/src/clib/ctreactor.h +++ b/src/clib/ctreactor.h @@ -69,6 +69,14 @@ extern "C" { CANTERA_CAPI int wall_ready(int i); CANTERA_CAPI int wall_addSensitivityReaction(int i, int lr, int rxn); + CANTERA_CAPI int reactorsurface_new(int type); + CANTERA_CAPI int reactorsurface_del(int i); + CANTERA_CAPI int reactorsurface_install(int i, int n); + CANTERA_CAPI int reactorsurface_setkinetics(int i, int n); + CANTERA_CAPI double reactorsurface_area(int i); + CANTERA_CAPI int reactorsurface_setArea(int i, double v); + CANTERA_CAPI int reactorsurface_addSensitivityReaction(int i, int rxn); + CANTERA_CAPI int clear_reactors(); } diff --git a/src/matlab/ctmethods.cpp b/src/matlab/ctmethods.cpp index 37f43147a..8c81d5728 100644 --- a/src/matlab/ctmethods.cpp +++ b/src/matlab/ctmethods.cpp @@ -24,6 +24,7 @@ const int TRANSPORT_CLASS = 50; const int REACTOR_CLASS = 60; const int REACTORNET_CLASS = 65; const int WALL_CLASS = 70; +const int REACTORSURFACE_CLASS = 75; const int FLOWDEVICE_CLASS = 80; const int ONEDIM_CLASS = 90; const int SURF_CLASS = 100; @@ -63,6 +64,9 @@ void reactornetmethods(int nlhs, mxArray* plhs[], int nrhs, void wallmethods(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]); +void reactorsurfacemethods(int nlhs, mxArray* plhs[], int nrhs, + const mxArray* prhs[]); + void flowdevicemethods(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]); @@ -128,6 +132,9 @@ extern "C" { case WALL_CLASS: wallmethods(nlhs, plhs, nrhs, prhs); break; + case REACTORSURFACE_CLASS: + reactorsurfacemethods(nlhs, plhs, nrhs, prhs); + break; case FLOWDEVICE_CLASS: flowdevicemethods(nlhs, plhs, nrhs, prhs); break; diff --git a/src/matlab/reactorsurfacemethods.cpp b/src/matlab/reactorsurfacemethods.cpp new file mode 100644 index 000000000..b279f9f69 --- /dev/null +++ b/src/matlab/reactorsurfacemethods.cpp @@ -0,0 +1,77 @@ +/** + * @file reactorsurfacemethods.cpp + */ + +#include "clib/ctreactor.h" +#include "clib/ct.h" +#include "ctmatutils.h" + +void reactorsurfacemethods(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + int iok = 0, n; + int job = getInt(prhs[1]); + int i = getInt(prhs[2]); + double r = Undef; + double v = Undef; + if (nrhs > 3) { + v = getDouble(prhs[3]); + } + + // constructor + if (job == 0) { + n = reactorsurface_new(i); + plhs[0] = mxCreateNumericMatrix(1,1,mxDOUBLE_CLASS,mxREAL); + double* h = mxGetPr(plhs[0]); + *h = double(n); + if (n < 0) { + reportError(); + } + return; + } + + // options that do not return a value + if (job < 20) { + switch (job) { + case 1: + iok = reactorsurface_del(i); + break; + case 4: + n = getInt(prhs[3]); + iok = reactorsurface_install(i, n); + break; + case 5: + iok = reactorsurface_setArea(i, v); + break; + case 12: + n = getInt(prhs[3]); + iok = reactorsurface_setkinetics(i, n); + break; + default: + mexErrMsgTxt("unknown job parameter"); + } + plhs[0] = mxCreateNumericMatrix(1,1,mxDOUBLE_CLASS,mxREAL); + double* h = mxGetPr(plhs[0]); + *h = double(iok); + if (iok < 0) { + reportError(); + } + return; + } else if (job < 40) { + // options that return a value of type 'double' + switch (job) { + case 23: + r = reactorsurface_area(i); + break; + default: + mexErrMsgTxt("unknown job parameter"); + } + plhs[0] = mxCreateNumericMatrix(1,1,mxDOUBLE_CLASS,mxREAL); + double* h = mxGetPr(plhs[0]); + *h = r; + if (r == DERR) { + reportError(); + } + return; + } +}