Skip to content

Commit 8fdee6b

Browse files
committed
New caclulation version with eigen stare matrix multiplication instead of iteration
simple example works without consistent initalisation fix conserved moities calculation
1 parent 85df024 commit 8fdee6b

File tree

8 files changed

+265
-41
lines changed

8 files changed

+265
-41
lines changed

src/libcadet/model/ReactionModel.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ class IDynamicReactionModel
265265
* @param [in,out] QsCompBulk Vector to be filled with the components involved in qs reactions
266266
*/
267267
virtual void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector<int>& QsCompBulk) {}
268+
virtual void fillConservedMoietiesBulk2(Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>& M, std::vector<int>& QsCompBulk) {}
269+
virtual void fillConservedMoietiesBulk2(Eigen::Matrix<active, Eigen::Dynamic, Eigen::Dynamic>& M, std::vector<int>& QsCompBulk) {}
270+
268271

269272
/**
270273
* @brief Returns whether this dynamic reaction model has quasi-stationary reactions
@@ -358,9 +361,10 @@ class IDynamicReactionModel
358361
virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT = 0;
359362

360363
/**
361-
* @brief Returns wheather liquid reactions are in quasi-stationary state
362-
* @return boolean
364+
* @brief Returns the number of reactions in quasi stationary state
365+
* @return Number of reactions
363366
*/
367+
virtual unsigned int numReactionQuasiStationary() const CADET_NOEXCEPT = 0;
364368

365369
protected:
366370
};

src/libcadet/model/StirredTankModel.cpp

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <functional>
3333
#include <bitset>
3434
#include <Eigen/Dense>
35+
#include <Eigen/Sparse>
3536

3637
#include<iostream>
3738

@@ -372,6 +373,7 @@ bool CSTRModel::configure(IParameterProvider& paramProvider)
372373
if (_qsReactionBulk != nullptr)
373374
{
374375
_dynReactionBulk->fillConservedMoietiesBulk(_MconvMoityBulk, _QsCompBulk); // fill conserved moities matrix
376+
375377
int nMoitiesBulk = _MconvMoityBulk.rows();
376378
if (nMoitiesBulk != 0)
377379
{
@@ -1655,6 +1657,110 @@ void CSTRModel::applyConservedMoitiesBulk(double t, unsigned int secIdx, const C
16551657

16561658
}
16571659

1660+
template <typename StateType, typename ResidualType, typename ParamType, bool wantJac>
1661+
void CSTRModel::applyConservedMoitiesBulk2(double t, unsigned int secIdx, const ColumnPosition& colPos, StateType const* const c, double const* const yDot, ResidualType* const resC, LinearBufferAllocator tlmAlloc)
1662+
{
1663+
// prepare memory
1664+
LinearBufferAllocator subAlloc = tlmAlloc.manageRemainingMemory();
1665+
1666+
// create map to residual vector of concentrations
1667+
Eigen::Map<Eigen::Vector<ResidualType, Eigen::Dynamic>> mapResC(resC, _nComp);
1668+
1669+
// calculate flux for quasi stationary reactions
1670+
BufferedArray<ResidualType> temp2 = subAlloc.array<ResidualType>(_nComp);
1671+
Eigen::Map<Eigen::Vector<ResidualType, Eigen::Dynamic>> qsFlux(static_cast<ResidualType*>(temp2), _dynReactionBulk->numReactionsLiquid());
1672+
qsFlux.setZero();
1673+
1674+
_dynReactionBulk->computeQuasiStationaryReactionFlux(t, secIdx, colPos, c, qsFlux, _qsReactionBulk, subAlloc);
1675+
1676+
// calculate conserved moities
1677+
Eigen::Matrix<ResidualType, Eigen::Dynamic, Eigen::Dynamic> M(_nComp, _nComp);
1678+
_dynReactionBulk->fillConservedMoietiesBulk2(M, _QsCompBulk); // fill conserved moities matrix (alternative method)
1679+
1680+
1681+
// buffer memory for transformed residual
1682+
BufferedArray<ResidualType> temp = subAlloc.array<ResidualType>(_nComp);
1683+
Eigen::Map<Eigen::Vector<ResidualType, Eigen::Dynamic>> resCWithMoities(static_cast<ResidualType*>(temp), _nComp);
1684+
resCWithMoities.setZero();
1685+
1686+
1687+
// multiply conserved moities matrix with residual
1688+
resCWithMoities = M * mapResC;
1689+
1690+
// add quasi stationary reaction to residium
1691+
const int nQsReac = _dynReactionBulk->numReactionQuasiStationary();
1692+
int state = M.rows() - 1 ;
1693+
for (int qsReac = 0; qsReac < nQsReac; qsReac++)
1694+
{
1695+
if (state < _nComp)
1696+
{
1697+
resCWithMoities[state] = qsFlux[qsReac];
1698+
state++;
1699+
}
1700+
else
1701+
throw InvalidParameterException(
1702+
"Residual implementation with conserved moities: Too many quasi stationary reactions detected. "
1703+
"Please check the implementation of the model."
1704+
);
1705+
}
1706+
1707+
mapResC = resCWithMoities;
1708+
1709+
// multiply conserved moities matrix with jacobian
1710+
if (wantJac)
1711+
{
1712+
// transform _jac into Eigen sparse matrix
1713+
Eigen::SparseMatrix<double> jacSparse(_nComp, _nComp);
1714+
1715+
// Copy data from original Jacobian
1716+
for (int k = 0; k < _jac.stride(); ++k) {
1717+
for (typename Eigen::SparseMatrix<double>::InnerIterator it(jacSparse, k); it; ++it) {
1718+
it.valueRef() = _jac.native(it.row(), it.col());
1719+
}
1720+
}
1721+
1722+
// apply conserved moities to jacobian
1723+
Eigen::SparseMatrix<double> jacSparseMoities(_nComp, _nComp);
1724+
1725+
Eigen::SparseMatrix<double> sparseMoieties(_nComp, _nComp);
1726+
sparseMoieties.reserve(M.nonZeros());
1727+
for (int i = 0; i < M.rows(); ++i) {
1728+
for (int j = 0; j < M.cols(); ++j) {
1729+
if (std::abs(static_cast<double>(M(i, j))) > 1e-15) { // Only insert non-zero elements
1730+
sparseMoieties.insert(i, j) = static_cast<double>(M(i, j));
1731+
}
1732+
}
1733+
}
1734+
sparseMoieties.makeCompressed();
1735+
1736+
jacSparseMoities = sparseMoieties * jacSparse;
1737+
1738+
// Copy transformed Jacobian back
1739+
for (int k = 0; k < jacSparseMoities.outerSize(); ++k) {
1740+
for (typename Eigen::SparseMatrix<double>::InnerIterator it(jacSparseMoities, k); it; ++it) {
1741+
_jac.native(it.row(), it.col()) = it.value();
1742+
}
1743+
}
1744+
1745+
int state = M.rows() - 1;
1746+
for(int qsReac = 0; qsReac < nQsReac; ++qsReac) // todo this in a function
1747+
{
1748+
if (state < _nComp)
1749+
{
1750+
_dynReactionBulk->analyticJacobianQuasiStationaryReaction(t, secIdx, colPos, reinterpret_cast<double const*>(c), state, qsReac, _jac.row(state), subAlloc);
1751+
state++;
1752+
}
1753+
else
1754+
throw InvalidParameterException(
1755+
"Jacobian implementation with conserved moities: Too many quasi stationary reactions detected. "
1756+
"Please check the implementation of the model."
1757+
);
1758+
}
1759+
}
1760+
}
1761+
1762+
1763+
16581764
template <typename StateType, typename ResidualType, typename ParamType, bool wantJac>
16591765
int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* const y, double const* const yDot, ResidualType* const res, LinearBufferAllocator tlmAlloc)
16601766
{
@@ -1749,7 +1855,8 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons
17491855

17501856
if (_hasQuasiStationaryReactionBulk)
17511857
{
1752-
applyConservedMoitiesBulk<StateType, ResidualType, ParamType, wantJac>(t, secIdx, colPos, c, yDot, resC, subAlloc);
1858+
applyConservedMoitiesBulk2<StateType, ResidualType, ParamType, wantJac>(t, secIdx, colPos, c, yDot, resC, subAlloc);
1859+
17531860
}
17541861
}
17551862
// Bound states

src/libcadet/model/StirredTankModel.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class CSTRModel : public UnitOperationBase
8181

8282
template <typename StateType, typename ResidualType, typename ParamType, bool wantJac>
8383
void applyConservedMoitiesBulk(double t, unsigned int secIdx, const ColumnPosition& colPos, StateType const* const y, double const* const yDot, ResidualType* const resC, LinearBufferAllocator tlmAlloc);
84+
template <typename StateType, typename ResidualType, typename ParamType, bool wantJac>
85+
void applyConservedMoitiesBulk2(double t, unsigned int secIdx, const ColumnPosition& colPos, StateType const* const y, double const* const yDot, ResidualType* const resC, LinearBufferAllocator tlmAlloc);
86+
8487
virtual int jacobian(const SimulationTime& simTime, const ConstSimulationState& simState, double* const res, const AdJacobianParams& adJac, util::ThreadLocalStorage& threadLocalMem);
8588
virtual int residualWithJacobian(const SimulationTime& simTime, const ConstSimulationState& simState, double* const res, const AdJacobianParams& adJac, util::ThreadLocalStorage& threadLocalMem);
8689
virtual int residualSensFwdAdOnly(const SimulationTime& simTime, const ConstSimulationState& simState, active* const adRes, util::ThreadLocalStorage& threadLocalMem);

src/libcadet/model/reaction/CrystallizationReaction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ namespace cadet
346346

347347
virtual unsigned int numReactionsLiquid() const CADET_NOEXCEPT { return 1; }
348348
virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT { return 1; }
349+
virtual unsigned int numReactionQuasiStationary() const CADET_NOEXCEPT { return 0; }
350+
template <typename ResidualType>
351+
void fillConservedMoietiesBulk21(Eigen::Matrix<ResidualType, Eigen::Dynamic, Eigen::Dynamic>& M, std::vector<int>& QsCompBulk) {}
349352

350353
CADET_DYNAMICREACTIONMODEL_BOILERPLATE
351354

src/libcadet/model/reaction/DummyReaction.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ class DummyDynamicReaction : public IDynamicReactionModel
128128

129129
virtual unsigned int numReactionsLiquid() const CADET_NOEXCEPT { return 0; }
130130
virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT { return 0; }
131-
131+
virtual unsigned int numReactionQuasiStationary() const CADET_NOEXCEPT { return 0; }
132+
template <typename ResidualType>
133+
void fillConservedMoietiesBulk21(Eigen::Matrix<ResidualType, Eigen::Dynamic, Eigen::Dynamic>& M, std::vector<int>& QsCompBulk) {}
132134
protected:
133135
};
134136

0 commit comments

Comments
 (0)