|
32 | 32 | #include <functional>
|
33 | 33 | #include <bitset>
|
34 | 34 | #include <Eigen/Dense>
|
| 35 | +#include <Eigen/Sparse> |
35 | 36 |
|
36 | 37 | #include<iostream>
|
37 | 38 |
|
@@ -372,6 +373,7 @@ bool CSTRModel::configure(IParameterProvider& paramProvider)
|
372 | 373 | if (_qsReactionBulk != nullptr)
|
373 | 374 | {
|
374 | 375 | _dynReactionBulk->fillConservedMoietiesBulk(_MconvMoityBulk, _QsCompBulk); // fill conserved moities matrix
|
| 376 | + |
375 | 377 | int nMoitiesBulk = _MconvMoityBulk.rows();
|
376 | 378 | if (nMoitiesBulk != 0)
|
377 | 379 | {
|
@@ -1655,6 +1657,110 @@ void CSTRModel::applyConservedMoitiesBulk(double t, unsigned int secIdx, const C
|
1655 | 1657 |
|
1656 | 1658 | }
|
1657 | 1659 |
|
| 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 | + |
1658 | 1764 | template <typename StateType, typename ResidualType, typename ParamType, bool wantJac>
|
1659 | 1765 | int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* const y, double const* const yDot, ResidualType* const res, LinearBufferAllocator tlmAlloc)
|
1660 | 1766 | {
|
@@ -1749,7 +1855,8 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons
|
1749 | 1855 |
|
1750 | 1856 | if (_hasQuasiStationaryReactionBulk)
|
1751 | 1857 | {
|
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 | + |
1753 | 1860 | }
|
1754 | 1861 | }
|
1755 | 1862 | // Bound states
|
|
0 commit comments