Skip to content

Commit eb36c56

Browse files
Build jacobian structure defined for walls and flow devices
1 parent d2985a2 commit eb36c56

File tree

13 files changed

+375
-1
lines changed

13 files changed

+375
-1
lines changed

include/cantera/zeroD/FlowDevice.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "cantera/base/ct_defs.h"
1010
#include "cantera/base/global.h"
1111
#include "cantera/base/ctexceptions.h"
12+
#include "cantera/numerics/eigen_sparse.h"
1213

1314
namespace Cantera
1415
{
@@ -114,7 +115,47 @@ class FlowDevice
114115
m_time = time;
115116
}
116117

118+
/*! Build the Jacobian terms specific to the flow device for the given connected reactor.
119+
* @param r a pointer to the calling reactor
120+
* @param jacVector a vector of triplets to be added to the jacobian for the reactor
121+
* @warning This function is an experimental part of the %Cantera API and may be changed
122+
* or removed without notice.
123+
* @since New in %Cantera 3.0.
124+
*/
125+
virtual void buildReactorJacobian(ReactorBase* r, vector<Eigen::Triplet<double>>& jacVector) {
126+
throw NotImplementedError(type() + "::buildReactorJacobian");
127+
}
128+
129+
/*! Build the Jacobian terms specific to the flow device for the network. These terms
130+
* will be adjusted to the networks indexing system outside of the reactor.
131+
* @param jacVector a vector of triplets to be added to the jacobian for the reactor
132+
* @warning This function is an experimental part of the %Cantera API and may be changed
133+
* or removed without notice.
134+
* @since New in %Cantera 3.0.
135+
*/
136+
virtual void buildNetworkJacobian(vector<Eigen::Triplet<double>>& jacVector) {
137+
throw NotImplementedError(type() + "::buildNetworkJacobian");
138+
}
139+
140+
/*! Specify the jacobian terms have been calculated and should not be recalculated.
141+
* @warning This function is an experimental part of the %Cantera API and may be changed
142+
* or removed without notice.
143+
* @since New in %Cantera 3.0.
144+
*/
145+
void jacobianCalculated() { m_jac_calculated = true; };
146+
147+
/*! Specify that jacobian terms have not been calculated and should be recalculated.
148+
* @warning This function is an experimental part of the %Cantera API and may be changed
149+
* or removed without notice.
150+
* @since New in %Cantera 3.0.
151+
*/
152+
void jacobianNotCalculated() { m_jac_calculated = false; };
153+
117154
protected:
155+
//! a variable to switch on and off so calculations are not doubled by the calling
156+
//! reactor or network
157+
bool m_jac_calculated = false;
158+
118159
double m_mdot = Undef;
119160

120161
//! Function set by setPressureFunction; used by updateMassFlowRate

include/cantera/zeroD/IdealGasMoleReactor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ class IdealGasMoleReactor : public MoleReactor
4545

4646
bool preconditionerSupported() const override {return true;};
4747

48+
double moleDerivative(size_t index) override;
49+
50+
double moleRadiationDerivative(size_t index) override;
51+
52+
size_t speciesOffset() const override { return m_sidx; };
53+
4854
protected:
4955
vector<double> m_uk; //!< Species molar internal energies
5056
};

include/cantera/zeroD/MoleReactor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define CT_MOLEREACTOR_H
88

99
#include "Reactor.h"
10+
#include "cantera/zeroD/Wall.h"
1011

1112
namespace Cantera
1213
{
@@ -38,6 +39,8 @@ class MoleReactor : public Reactor
3839

3940
string componentName(size_t k) override;
4041

42+
size_t energyIndex() const override { return m_eidx; };
43+
4144
protected:
4245
//! For each surface in the reactor, update vector of triplets with all relevant
4346
//! surface jacobian derivatives of species with respect to species
@@ -60,6 +63,9 @@ class MoleReactor : public Reactor
6063

6164
//! const value for the species start index
6265
const size_t m_sidx = 2;
66+
67+
//! index of state variable associated with energy
68+
const size_t m_eidx = 0;
6369
};
6470

6571
}

include/cantera/zeroD/Reactor.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,27 @@ class Reactor : public ReactorBase
232232
throw NotImplementedError(type() + "::buildJacobian");
233233
}
234234

235-
// virtual void jacobian()
235+
//! Calculate the Jacobian of a Reactor specialization for wall contributions.
236+
//! @param jacVector vector where jacobian triplets are added
237+
//! @warning Depending on the particular implementation, this may return an
238+
//! approximate Jacobian intended only for use in forming a preconditioner for
239+
//! iterative solvers.
240+
//! @ingroup derivGroup
241+
//!
242+
//! @warning This method is an experimental part of the %Cantera
243+
//! API and may be changed or removed without notice.
244+
virtual void buildWallJacobian(vector<Eigen::Triplet<double>>& jacVector);
245+
246+
//! Calculate flow contributions to the Jacobian of a Reactor specialization.
247+
//! @param jac_vector vector where jacobian triplets are added
248+
//! @warning Depending on the particular implementation, this may return an
249+
//! approximate Jacobian intended only for use in forming a preconditioner for
250+
//! iterative solvers.
251+
//! @ingroup derivGroup
252+
//!
253+
//! @warning This method is an experimental part of the %Cantera
254+
//! API and may be changed or removed without notice.
255+
virtual void buildFlowJacobian(vector<Eigen::Triplet<double>>& jacVector);
236256

237257
//! Calculate the reactor-specific Jacobian using a finite difference method.
238258
//!
@@ -325,6 +345,10 @@ class Reactor : public ReactorBase
325345

326346
//! Vector of triplets representing the jacobian
327347
vector<Eigen::Triplet<double>> m_jac_trips;
348+
//! Boolean to skip walls in jacobian
349+
bool m_jac_skip_walls = false;
350+
//! Boolean to skip flow devices in jacobian
351+
bool m_jac_skip_flow_devices = false;
328352
};
329353
}
330354

include/cantera/zeroD/ReactorBase.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,46 @@ class ReactorBase
248248
//! Set the ReactorNet that this reactor belongs to.
249249
void setNetwork(ReactorNet* net);
250250

251+
/*! Calculate the derivative of T with respect to the ith species in the heat
252+
* transfer equation based on the reactor specific equation of state.
253+
* will be adjusted to the networks indexing system outside of the reactor.
254+
* @param index index of the species the derivative is with respect too
255+
* @warning This function is an experimental part of the %Cantera API and may be changed
256+
* or removed without notice.
257+
* @since New in %Cantera 3.0.
258+
*/
259+
virtual double moleDerivative(size_t index) {
260+
throw NotImplementedError("Reactor::moleDerivative");
261+
}
262+
263+
/*! Calculate the derivative of T with respect to the ith species in the heat
264+
* transfer radiation equation based on the reactor specific equation of state.
265+
* will be adjusted to the networks indexing system outside of the reactor.
266+
* @param index index of the species the derivative is with respect too
267+
* @warning This function is an experimental part of the %Cantera API and may be changed
268+
* or removed without notice.
269+
* @since New in %Cantera 3.0.
270+
*/
271+
virtual double moleRadiationDerivative(size_t index) {
272+
throw NotImplementedError("Reactor::moleRadiationDerivative");
273+
}
274+
275+
//! Return the index associated with energy of the system
276+
virtual size_t energyIndex() const { return m_eidx; };
277+
278+
//! Return the offset between species and state variables
279+
virtual size_t speciesOffset() const { return m_sidx; };
280+
251281
protected:
252282
//! Number of homogeneous species in the mixture
253283
size_t m_nsp = 0;
254284

285+
//! species offset in the state vector
286+
const size_t m_sidx = 3;
287+
288+
//! index of state variable associated with energy
289+
const size_t m_eidx = 1;
290+
255291
ThermoPhase* m_thermo = nullptr;
256292
double m_vol = 1.0; //!< Current volume of the reactor [m^3]
257293
double m_enthalpy = 0.0; //!< Current specific enthalpy of the reactor [J/kg]

include/cantera/zeroD/ReactorNet.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,20 @@ class ReactorNet : public FuncEval
236236
//! reactor network.
237237
size_t globalComponentIndex(const string& component, size_t reactor=0);
238238

239+
//! Return the index corresponding to the start of the reactor specific state
240+
//! vector in the reactor with index *reactor* in the global state vector for the
241+
//! reactor network.
242+
size_t globalStartIndex(Reactor* curr_reactor) {
243+
for (size_t i = 0; i < m_reactors.size(); i++) {
244+
if (curr_reactor == m_reactors[i]) {
245+
return m_start[i];
246+
}
247+
}
248+
throw CanteraError("ReactorNet::globalStartIndex: ",
249+
curr_reactor->name(), " not found in network.");
250+
return npos;
251+
}
252+
239253
//! Return the name of the i-th component of the global state vector. The
240254
//! name returned includes both the name of the reactor and the specific
241255
//! component, for example `'reactor1: CH4'`.
@@ -396,6 +410,10 @@ class ReactorNet : public FuncEval
396410
//! "left hand side" of each governing equation
397411
vector<double> m_LHS;
398412
vector<double> m_RHS;
413+
414+
//! derivative settings
415+
bool m_jac_skip_walls = false;
416+
bool m_jac_skip_flow_devices = false;
399417
};
400418
}
401419

include/cantera/zeroD/Wall.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "cantera/base/ctexceptions.h"
1010
#include "cantera/zeroD/ReactorBase.h"
11+
#include "cantera/numerics/eigen_sparse.h"
1112

1213
namespace Cantera
1314
{
@@ -115,6 +116,42 @@ class WallBase
115116
m_time = time;
116117
}
117118

119+
/*! Build the Jacobian terms specific to the flow device for the given connected reactor.
120+
* @param r a pointer to the calling reactor
121+
* @param jacVector a vector of triplets to be added to the jacobian for the reactor
122+
* @warning This function is an experimental part of the %Cantera API and may be changed
123+
* or removed without notice.
124+
* @since New in %Cantera 3.0.
125+
*/
126+
virtual void buildReactorJacobian(ReactorBase* r, vector<Eigen::Triplet<double>>& jacVector) {
127+
throw NotImplementedError("WallBase::buildReactorJacobian");
128+
}
129+
130+
/*! Build the Jacobian terms specific to the flow device for the network. These terms
131+
* will be adjusted to the networks indexing system outside of the reactor.
132+
* @param jacVector a vector of triplets to be added to the jacobian for the reactor
133+
* @warning This function is an experimental part of the %Cantera API and may be changed
134+
* or removed without notice.
135+
* @since New in %Cantera 3.0.
136+
*/
137+
virtual void buildNetworkJacobian(vector<Eigen::Triplet<double>>& jacVector) {
138+
throw NotImplementedError("WallBase::buildNetworkJacobian");
139+
}
140+
141+
/*! Specify the jacobian terms have been calculated and should not be recalculated.
142+
* @warning This function is an experimental part of the %Cantera API and may be changed
143+
* or removed without notice.
144+
* @since New in %Cantera 3.0.
145+
*/
146+
void jacobianCalculated() { m_jac_calculated = true; };
147+
148+
/*! Specify that jacobian terms have not been calculated and should be recalculated.
149+
* @warning This function is an experimental part of the %Cantera API and may be changed
150+
* or removed without notice.
151+
* @since New in %Cantera 3.0.
152+
*/
153+
void jacobianNotCalculated() { m_jac_calculated = false; };
154+
118155
protected:
119156
ReactorBase* m_left = nullptr;
120157
ReactorBase* m_right = nullptr;
@@ -123,6 +160,10 @@ class WallBase
123160
double m_time = 0.0;
124161

125162
double m_area = 1.0;
163+
164+
//! a variable to switch on and off so calculations are not doubled by the calling
165+
//! reactor or network
166+
bool m_jac_calculated = false;
126167
};
127168

128169
//! Represents a wall between between two ReactorBase objects.
@@ -255,6 +296,10 @@ class Wall : public WallBase
255296
return m_k;
256297
}
257298

299+
virtual void buildReactorJacobian(ReactorBase* r, vector<Eigen::Triplet<double>>& jacVector) override;
300+
301+
virtual void buildNetworkJacobian(vector<Eigen::Triplet<double>>& jacVector) override;
302+
258303
protected:
259304

260305
//! expansion rate coefficient

interfaces/cython/cantera/reactor.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera":
202202
void setPreconditioner(shared_ptr[CxxPreconditionerBase] preconditioner)
203203
void setDerivativeSettings(CxxAnyMap&)
204204
CxxAnyMap solverStats() except +translate_exception
205+
CxxSparseMatrix jacobian() except +translate_exception
206+
CxxSparseMatrix finiteDifferenceJacobian() except +translate_exception
205207

206208
cdef extern from "cantera/zeroD/ReactorDelegator.h" namespace "Cantera":
207209
cdef cppclass CxxReactorAccessor "Cantera::ReactorAccessor":

interfaces/cython/cantera/reactor.pyx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,3 +1797,29 @@ cdef class ReactorNet:
17971797
"""
17981798
def __set__(self, settings):
17991799
self.net.setDerivativeSettings(py_to_anymap(settings))
1800+
1801+
property jacobian:
1802+
"""
1803+
Get the system Jacobian or an approximation thereof.
1804+
1805+
**Warning**: Depending on the particular implementation, this may return an
1806+
approximate Jacobian intended only for use in forming a preconditioner for
1807+
iterative solvers, excluding terms that would generate a fully-dense Jacobian.
1808+
1809+
**Warning**: This method is an experimental part of the Cantera API and may be
1810+
changed or removed without notice.
1811+
"""
1812+
def __get__(self):
1813+
return get_from_sparse(self.net.jacobian(), self.n_vars, self.n_vars)
1814+
1815+
property finite_difference_jacobian:
1816+
"""
1817+
Get the system Jacobian, calculated using a finite difference method.
1818+
1819+
**Warning:** this property is an experimental part of the Cantera API and
1820+
may be changed or removed without notice.
1821+
"""
1822+
def __get__(self):
1823+
return get_from_sparse(self.net.finiteDifferenceJacobian(),
1824+
self.n_vars, self.n_vars)
1825+

src/zeroD/IdealGasMoleReactor.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,31 @@ void IdealGasMoleReactor::buildJacobian(vector<Eigen::Triplet<double>>& jacVecto
244244
(specificHeat[j] * qdot - NCv * uk_dnkdnj_sums[j]) * denom);
245245
}
246246
}
247+
248+
// build wall jacobian
249+
buildWallJacobian(jacVector);
250+
251+
// build flow jacobian
252+
buildFlowJacobian(jacVector);
253+
}
254+
255+
double IdealGasMoleReactor::moleDerivative(size_t index)
256+
{
257+
// derivative of temperature transformed by ideal gas law
258+
vector<double> moles(m_nsp);
259+
getMoles(moles.data());
260+
double dTdni = pressure() * m_vol / GasConstant / std::accumulate(moles.begin(), moles.end(), 0);
261+
return dTdni;
262+
}
263+
264+
double IdealGasMoleReactor::moleRadiationDerivative(size_t index)
265+
{
266+
// derivative of temperature transformed by ideal gas law
267+
vector<double> moles(m_nsp);
268+
getMoles(moles.data());
269+
double dT4dni = std::pow(pressure() * m_vol / GasConstant, 4);
270+
dT4dni *= std::pow(1 / std::accumulate(moles.begin(), moles.end(), 0), 5);
271+
return dT4dni;
247272
}
248273

249274
}

0 commit comments

Comments
 (0)