[Reactor] Add componentName function to ReactorNet and Reactor classes

This commit is contained in:
Ray Speth 2016-05-09 22:29:31 -04:00
parent 3a129677df
commit 8ff82c06ce
13 changed files with 145 additions and 5 deletions

View file

@ -43,6 +43,7 @@ public:
//! the name of a homogeneous phase species, or the name of a surface //! the name of a homogeneous phase species, or the name of a surface
//! species. //! species.
virtual size_t componentIndex(const std::string& nm) const; virtual size_t componentIndex(const std::string& nm) const;
std::string componentName(size_t k);
}; };
} }

View file

@ -44,6 +44,7 @@ public:
//! "temperature", the name of a homogeneous phase species, or the name of a //! "temperature", the name of a homogeneous phase species, or the name of a
//! surface species. //! surface species.
virtual size_t componentIndex(const std::string& nm) const; virtual size_t componentIndex(const std::string& nm) const;
std::string componentName(size_t k);
protected: protected:
vector_fp m_hk; //!< Species molar enthalpies vector_fp m_hk; //!< Species molar enthalpies

View file

@ -43,6 +43,7 @@ public:
//! "volume", "temperature", the name of a homogeneous phase species, or the //! "volume", "temperature", the name of a homogeneous phase species, or the
//! name of a surface species. //! name of a surface species.
virtual size_t componentIndex(const std::string& nm) const; virtual size_t componentIndex(const std::string& nm) const;
std::string componentName(size_t k);
protected: protected:
vector_fp m_uk; //!< Species molar internal energies vector_fp m_uk; //!< Species molar internal energies

View file

@ -80,6 +80,9 @@ public:
//! Number of equations (state variables) for this reactor //! Number of equations (state variables) for this reactor
virtual size_t neq() { virtual size_t neq() {
if (!m_nv) {
initialize();
}
return m_nv; return m_nv;
} }
@ -136,6 +139,10 @@ public:
//! surface species. //! surface species.
virtual size_t componentIndex(const std::string& nm) const; virtual size_t componentIndex(const std::string& nm) const;
//! Return the name of the solution component with index *i*.
//! @see componentIndex()
virtual std::string componentName(size_t k);
protected: protected:
//! Set reaction rate multipliers based on the sensitivity variables in //! Set reaction rate multipliers based on the sensitivity variables in
//! *params*. //! *params*.

View file

@ -174,6 +174,11 @@ public:
//! reactor network. //! reactor network.
size_t globalComponentIndex(const std::string& component, size_t reactor=0); size_t globalComponentIndex(const std::string& component, size_t reactor=0);
//! Return the name of the i-th component of the global state vector. The
//! name returned includes both the name of the reactor and the specific
//! component, e.g. `'reactor1: CH4'`.
std::string componentName(size_t i) const;
//! Used by Reactor and Wall objects to register the addition of //! Used by Reactor and Wall objects to register the addition of
//! sensitivity parameters so that the ReactorNet can keep track of the //! sensitivity parameters so that the ReactorNet can keep track of the
//! order in which sensitivity parameters are added. //! order in which sensitivity parameters are added.

View file

@ -487,6 +487,7 @@ cdef extern from "cantera/zeroD/Reactor.h":
void setEnergy(int) void setEnergy(int)
cbool energyEnabled() cbool energyEnabled()
size_t componentIndex(string&) size_t componentIndex(string&)
string componentName(size_t) except +
size_t neq() size_t neq()
void getState(double*) void getState(double*)
@ -566,6 +567,7 @@ cdef extern from "cantera/zeroD/ReactorNet.h":
void setVerbose(cbool) void setVerbose(cbool)
size_t neq() size_t neq()
void getState(double*) void getState(double*)
string componentName(size_t) except +
void setSensitivityTolerances(double, double) void setSensitivityTolerances(double, double)
double rtolSensitivity() double rtolSensitivity()

View file

@ -233,9 +233,9 @@ cdef class Reactor(ReactorBase):
""" """
Returns the index of the component named *name* in the system. This Returns the index of the component named *name* in the system. This
determines the (relative) index of the component in the vector of determines the (relative) index of the component in the vector of
sensitivity coefficients. *name* is either a species name or the name sensitivity coefficients. *name* is either a species name or the name of
of a reactor state variable, e.g. 'U', 'T', depending on the reactor's a reactor state variable, e.g. 'int_energy', 'temperature', depending on
equations. the reactor's equations.
""" """
k = self.reactor.componentIndex(stringify(name)) k = self.reactor.componentIndex(stringify(name))
@ -243,6 +243,14 @@ cdef class Reactor(ReactorBase):
raise IndexError('No such component: {!r}'.format(name)) raise IndexError('No such component: {!r}'.format(name))
return k return k
def component_name(self, int i):
"""
Returns the name of the component with index *i* within the array of
variables returned by `get_state`. This is the inverse of
`component_index`.
"""
return pystr(self.reactor.componentName(i))
property n_vars: property n_vars:
""" """
The number of state variables in the reactor. The number of state variables in the reactor.
@ -276,8 +284,9 @@ cdef class Reactor(ReactorBase):
- 1 - enthalpy or temperature - 1 - enthalpy or temperature
- 2+ - mass fractions of the species - 2+ - mass fractions of the species
You can use the function `component_index` to determine the location You can use the function `component_index` to determine the location of
of a specific component a specific component from its name, or `component_name` to determine the
name from the index.
""" """
if not self.n_vars: if not self.n_vars:
raise Exception('Reactor empty or network not initialized.') raise Exception('Reactor empty or network not initialized.')
@ -908,6 +917,14 @@ cdef class ReactorNet:
def __set__(self, pybool v): def __set__(self, pybool v):
self.net.setVerbose(v) self.net.setVerbose(v)
def component_name(self, int i):
"""
Return the name of the i-th component of the global state vector. The
name returned includes both the name of the reactor and the specific
component, e.g. `'reactor1: CH4'`.
"""
return pystr(self.net.componentName(i))
def sensitivity(self, component, int p, int r=0): def sensitivity(self, component, int p, int r=0):
""" """
Returns the sensitivity of the solution variable *component* in Returns the sensitivity of the solution variable *component* in

View file

@ -83,6 +83,16 @@ class TestReactor(utilities.CanteraTest):
for i, name in enumerate(self.gas1.species_names): for i, name in enumerate(self.gas1.species_names):
self.assertEqual(i + N0, self.r1.component_index(name)) self.assertEqual(i + N0, self.r1.component_index(name))
def test_component_names(self):
self.make_reactors(n_reactors=2)
N = self.net.n_vars // 2
for i in range(N):
self.assertEqual(self.r1.component_index(self.r1.component_name(i)), i)
self.assertEqual(self.net.component_name(i),
'{}: {}'.format(self.r1.name, self.r1.component_name(i)))
self.assertEqual(self.net.component_name(N+i),
'{}: {}'.format(self.r2.name, self.r2.component_name(i)))
def test_disjoint(self): def test_disjoint(self):
T1, P1 = 300, 101325 T1, P1 = 300, 101325
T2, P2 = 500, 300000 T2, P2 = 500, 300000
@ -757,6 +767,13 @@ class TestConstPressureReactor(utilities.CanteraTest):
for i, name in enumerate(iface.species_names): for i, name in enumerate(iface.species_names):
self.assertEqual(i + N1, r.component_index(name)) self.assertEqual(i + N1, r.component_index(name))
def test_component_names(self):
self.create_reactors(add_surf=True)
for i in range(self.net1.n_vars):
self.assertEqual(self.r1.component_index(self.r1.component_name(i)), i)
self.assertEqual(self.net1.component_name(i),
'{}: {}'.format(self.r1.name, self.r1.component_name(i)))
def integrate(self, surf=False): def integrate(self, surf=False):
for t in np.arange(0.5, 50, 1.0): for t in np.arange(0.5, 50, 1.0):
self.net1.advance(t) self.net1.advance(t)

View file

@ -4,6 +4,7 @@
#include "cantera/zeroD/ConstPressureReactor.h" #include "cantera/zeroD/ConstPressureReactor.h"
#include "cantera/zeroD/FlowDevice.h" #include "cantera/zeroD/FlowDevice.h"
#include "cantera/zeroD/Wall.h"
using namespace std; using namespace std;
@ -149,4 +150,33 @@ size_t ConstPressureReactor::componentIndex(const string& nm) const
} }
} }
std::string ConstPressureReactor::componentName(size_t k) {
if (k == 0) {
return "mass";
} else if (k == 1) {
return "enthalpy";
} else if (k >= 2 && k < neq()) {
k -= 2;
if (k < m_thermo->nSpecies()) {
return m_thermo->speciesName(k);
} else {
k -= m_thermo->nSpecies();
}
for (size_t m = 0; m < m_wall.size(); m++) {
Wall& w = *m_wall[m];
if (w.kinetics(m_lr[m])) {
size_t kp = w.kinetics(m_lr[m])->reactionPhaseIndex();
ThermoPhase& th = w.kinetics(m_lr[m])->thermo(kp);
if (k < th.nSpecies()) {
return th.speciesName(k);
} else {
k -= th.nSpecies();
}
}
}
}
throw CanteraError("ConstPressureReactor::componentName",
"Index is out of bounds.");
}
} }

View file

@ -161,4 +161,12 @@ size_t IdealGasConstPressureReactor::componentIndex(const string& nm) const
} }
} }
std::string IdealGasConstPressureReactor::componentName(size_t k) {
if (k == 1) {
return "temperature";
} else {
return ConstPressureReactor::componentName(k);
}
}
} }

View file

@ -176,4 +176,13 @@ size_t IdealGasReactor::componentIndex(const string& nm) const
} }
} }
std::string IdealGasReactor::componentName(size_t k) {
if (k == 2) {
return "temperature";
} else {
return Reactor::componentName(k);
}
}
} }

View file

@ -398,6 +398,36 @@ size_t Reactor::componentIndex(const string& nm) const
} }
} }
std::string Reactor::componentName(size_t k) {
if (k == 0) {
return "mass";
} else if (k == 1) {
return "volume";
} else if (k == 2) {
return "int_energy";
} else if (k >= 3 && k < neq()) {
k -= 3;
if (k < m_thermo->nSpecies()) {
return m_thermo->speciesName(k);
} else {
k -= m_thermo->nSpecies();
}
for (size_t m = 0; m < m_wall.size(); m++) {
Wall& w = *m_wall[m];
if (w.kinetics(m_lr[m])) {
size_t kp = w.kinetics(m_lr[m])->reactionPhaseIndex();
ThermoPhase& th = w.kinetics(m_lr[m])->thermo(kp);
if (k < th.nSpecies()) {
return th.speciesName(k);
} else {
k -= th.nSpecies();
}
}
}
}
throw CanteraError("Reactor::componentName", "Index is out of bounds.");
}
void Reactor::applySensitivity(double* params) void Reactor::applySensitivity(double* params)
{ {
if (!params) { if (!params) {

View file

@ -242,6 +242,18 @@ size_t ReactorNet::globalComponentIndex(const string& component, size_t reactor)
return m_start[reactor] + m_reactors[reactor]->componentIndex(component); return m_start[reactor] + m_reactors[reactor]->componentIndex(component);
} }
std::string ReactorNet::componentName(size_t i) const
{
for (auto r : m_reactors) {
if (i < r->neq()) {
return r->name() + ": " + r->componentName(i);
} else {
i -= r->neq();
}
}
throw CanteraError("ReactorNet::componentName", "Index out of bounds");
}
size_t ReactorNet::registerSensitivityParameter( size_t ReactorNet::registerSensitivityParameter(
const std::string& name, double value, double scale) const std::string& name, double value, double scale)
{ {