9 using namespace Cantera;
14 ReactorNet::ReactorNet() : Cantera::
FuncEval(), m_nr(0), m_nreactors(0),
15 m_integ(0), m_time(0.0), m_init(false),
16 m_nv(0), m_rtol(1.0e-9), m_rtolsens(1.0e-4),
17 m_atols(1.0e-15), m_atolsens(1.0e-4),
19 m_verbose(false), m_ntotpar(0)
24 m_integ = newIntegrator(
"CVODE");
30 m_integ->setProblemType(DENSE + NOJAC);
34 ReactorNet::~ReactorNet()
36 for (
size_t n = 0; n < m_nr; n++) {
44 deleteIntegrator(m_integ);
47 void ReactorNet::initialize(doublereal t0)
55 writelog(
"Initializing reactor network.\n");
59 "no reactors in network!");
60 for (n = 0; n < m_nr; n++) {
61 if (m_r[n]->type() >= ReactorType) {
62 m_r[n]->initialize(t0);
64 m_reactors.push_back(r);
67 m_nparams.push_back(r->nSensParams());
68 m_ntotpar += r->nSensParams();
73 sprintf(buf,
"Reactor %s: %s variables.\n",
76 sprintf(buf,
" %s sensitivity params.\n",
77 int2str(r->nSensParams()).c_str());
80 if (m_r[n]->type() == FlowReactorType && m_nr > 1) {
82 "FlowReactors must be used alone.");
87 m_connect.resize(m_nr*m_nr,0);
88 m_ydot.resize(m_nv,0.0);
89 size_t i, j, nin, nout, nw;
91 for (i = 0; i < m_nr; i++) {
93 for (j = 0; j < m_nr; j++) {
99 for (n = 0; n < nin; n++) {
100 if (&rj->inlet(n).
out() == r) {
104 nout = rj->nOutlets();
105 for (n = 0; n < nout; n++) {
106 if (&rj->outlet(n).
in() == r) {
111 for (n = 0; n < nw; n++) {
112 if (&rj->wall(n).left() == rj
113 && &rj->wall(n).right() == r) {
115 }
else if (&rj->wall(n).left() == r
116 && &rj->wall(n).right() == rj) {
124 m_atol.resize(neq());
125 fill(m_atol.begin(), m_atol.end(), m_atols);
126 m_integ->setTolerances(m_rtol, neq(),
DATA_PTR(m_atol));
127 m_integ->setSensitivityTolerances(m_rtolsens, m_atolsens);
128 m_integ->setMaxStepSize(m_maxstep);
130 sprintf(buf,
"Number of equations: %s\n",
int2str(neq()).c_str());
132 sprintf(buf,
"Maximum time step: %14.6g\n", m_maxstep);
135 m_integ->initialize(t0, *
this);
139 void ReactorNet::advance(doublereal time)
142 if (m_maxstep < 0.0) {
143 m_maxstep = time - m_time;
147 m_integ->integrate(time);
149 updateState(m_integ->solution());
152 double ReactorNet::step(doublereal time)
155 if (m_maxstep < 0.0) {
156 m_maxstep = time - m_time;
160 m_time = m_integ->step(time);
161 updateState(m_integ->solution());
166 void ReactorNet::addReactor(
ReactorBase* r,
bool iown)
168 if (r->type() >= ReactorType) {
170 m_iown.push_back(iown);
173 writelog(
"Adding reactor "+r->name()+
"\n");
177 writelog(
"Not adding reactor "+r->name()+
178 ", since type = "+
int2str(r->type())+
"\n");
200 void ReactorNet::eval(doublereal t, doublereal* y,
201 doublereal* ydot, doublereal* p)
210 for (n = 0; n < m_nreactors; n++) {
211 m_reactors[n]->evalEqs(t, y + start,
212 ydot + start, p + pstart);
214 pstart += m_nparams[n];
217 std::cerr << err.
what() << std::endl;
218 error(
"Terminating execution.");
224 void ReactorNet::evalJacobian(doublereal t, doublereal* y,
225 doublereal* ydot, doublereal* p,
Array2D* j)
227 doublereal ysave, dy;
235 for (
size_t n = 0; n < m_nv; n++) {
239 dy = m_atol[n] + fabs(ysave)*m_rtol;
247 for (
size_t m = 0; m < m_nv; m++) {
248 jac(m,n) = (m_ydot[m] - ydot[m])/dy;
253 std::cerr << err.
what() << std::endl;
254 error(
"Terminating execution.");
258 void ReactorNet::updateState(doublereal* y)
261 for (
size_t n = 0; n < m_nreactors; n++) {
262 m_reactors[n]->updateState(y + start);
267 void ReactorNet::getInitialConditions(doublereal t0,
268 size_t leny, doublereal* y)
271 for (
size_t n = 0; n < m_nreactors; n++) {
272 m_reactors[n]->getInitialConditions(t0, m_size[n], y + start);
277 size_t ReactorNet::globalComponentIndex(
string species,
size_t reactor)
281 for (n = 0; n < reactor; n++) {
284 return start + m_reactors[n]->componentIndex(species);