From 6a4367e30a94050e25e87aecb2e414a984b2377a Mon Sep 17 00:00:00 2001 From: "a.berger" Date: Wed, 15 Jan 2025 15:24:36 +0100 Subject: [PATCH] Restart implementation --- src/libcadet/model/ReactionModel.hpp | 19 ++- src/libcadet/model/StirredTankModel.cpp | 110 ++++++++++-- src/libcadet/model/StirredTankModel.hpp | 7 + .../reaction/CrystallizationReaction.cpp | 5 +- src/libcadet/model/reaction/DummyReaction.cpp | 6 + .../model/reaction/MassActionLawReaction.cpp | 158 ++++++++++++++++++ .../reaction/MichaelisMentenReaction.cpp | 3 + .../model/reaction/ReactionModelBase.cpp | 1 + .../model/reaction/ReactionModelBase.hpp | 12 +- 9 files changed, 303 insertions(+), 18 deletions(-) diff --git a/src/libcadet/model/ReactionModel.hpp b/src/libcadet/model/ReactionModel.hpp index 0b2ab8397..861ea1589 100644 --- a/src/libcadet/model/ReactionModel.hpp +++ b/src/libcadet/model/ReactionModel.hpp @@ -213,6 +213,10 @@ class IDynamicReactionModel virtual int residualLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, double* res, double factor, LinearBufferAllocator workSpace) const = 0; + virtual int quasiStationaryFlux(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, + active* fluxes, std::vector& mapQSReac, LinearBufferAllocator workSpace) const = 0; + + /** * @brief Adds the analytical Jacobian of the reaction terms for one liquid phase cell * @details Adds the Jacobian of the dynamic reaction terms for the given liquid phase @@ -237,9 +241,15 @@ class IDynamicReactionModel virtual void analyticJacobianLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, double factor, linalg::BandMatrix::RowIterator jac, LinearBufferAllocator workSpace) const = 0; virtual void analyticJacobianLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, double factor, linalg::DenseBandedRowIterator jac, LinearBufferAllocator workSpace) const = 0; virtual void analyticJacobianLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, double factor, linalg::BandedSparseRowIterator jac, LinearBufferAllocator workSpace) const = 0; - #ifdef ENABLE_DG + + + virtual void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector& QSReaction, std::vector& _QsCompBulk) = 0; + + +#ifdef ENABLE_DG virtual void analyticJacobianLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, double factor, linalg::BandedEigenSparseRowIterator jac, LinearBufferAllocator workSpace) const = 0; - #endif + +#endif /** * @brief Evaluates the residual for one combined phase cell @@ -314,6 +324,11 @@ class IDynamicReactionModel * @return Number of reactions */ virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT = 0; + + /** + * @brief Returns wheather liquid reactions are in quasi-stationary state + * @return boolean + */ protected: }; diff --git a/src/libcadet/model/StirredTankModel.cpp b/src/libcadet/model/StirredTankModel.cpp index 671a59de1..15229e0b3 100644 --- a/src/libcadet/model/StirredTankModel.cpp +++ b/src/libcadet/model/StirredTankModel.cpp @@ -31,6 +31,10 @@ #include #include +#include + +#include + namespace cadet { @@ -76,7 +80,8 @@ CSTRModel::~CSTRModel() CADET_NOEXCEPT delete[] _strideBound; delete[] _offsetParType; - delete _dynReactionBulk; + delete[] _dynReactionBulk; + //delete[] _temp; -> Jan warum funktioniert das nicht? } unsigned int CSTRModel::numDofs() const CADET_NOEXCEPT @@ -235,6 +240,26 @@ bool CSTRModel::configureModelDiscretization(IParameterProvider& paramProvider, if (_dynReactionBulk->usesParamProviderInDiscretizationConfig()) paramProvider.popScope(); + + if (true) //paramProvider.exists("QUASI_STATIONARY_REACTION_BULK") + { + //_qsReacBulk = paramProvider.getIntArray("QUASI_STATIONARY_REACTION_BULK"); + _qsReacBulk = {1}; + _nQsReacBulk = _qsReacBulk.size(); + //_temp = new active[_nComp]; + + _nMoitiesBulk = (_nComp + _totalBound) - _nQsReacBulk; + _MconvMoityBulk = Eigen::MatrixXd::Zero(_nMoitiesBulk, _nComp); // matrix for conserved moities + } + else + { + _QsCompBulk.clear(); + _qsReacBulk.clear(); + _nMoitiesBulk = 0; + _nQsReacBulk = 0; + _MconvMoityBulk = Eigen::MatrixXd::Zero(0, 0); + + } } _dynReaction = std::vector(_nParType, nullptr); @@ -356,6 +381,12 @@ bool CSTRModel::configure(IParameterProvider& paramProvider) paramProvider.pushScope("reaction_bulk"); dynReactionConfSuccess = _dynReactionBulk->configure(paramProvider, _unitOpIdx, ParTypeIndep); paramProvider.popScope(); + + if (true) //paramProvider.exists("QUASI_STATIONARY_REACTION_BULK") + { + _dynReactionBulk->fillConservedMoietiesBulk(_MconvMoityBulk, _qsReacBulk, _QsCompBulk); // fill conserved moities matrix + int a = 0; + } } for (unsigned int type = 0; type < _nParType; ++type) @@ -422,9 +453,7 @@ unsigned int CSTRModel::threadLocalMemorySize() const CADET_NOEXCEPT return lms.bufferSize(); } -void CSTRModel::setSectionTimes(double const* secTimes, bool const* secContinuity, unsigned int nSections) -{ -} +void CSTRModel::setSectionTimes(double const* secTimes, bool const* secContinuity, unsigned int nSections){} void CSTRModel::useAnalyticJacobian(const bool analyticJac) { @@ -1247,7 +1276,7 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons const ParamType flowIn = static_cast(_flowRateIn); const ParamType flowOut = static_cast(_flowRateOut); - + // Inlet DOF for (unsigned int i = 0; i < _nComp; ++i) { @@ -1256,7 +1285,7 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons // Concentrations: \dot{V^l} * c + V^l * \dot{c} + V^s * sum_j sum_m \dot{q}_{j,m}] = c_in * F_in - c * F_out const ParamType vsolid = static_cast(_constSolidVolume); - ResidualType* const resC = res + _nComp; + ResidualType* resC = res + _nComp; for (unsigned int i = 0; i < _nComp; ++i) { resC[i] = 0.0; @@ -1312,14 +1341,73 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons // Reactions in liquid phase const ColumnPosition colPos{0.0, 0.0, 0.0}; - if (_dynReactionBulk && (_dynReactionBulk->numReactionsLiquid() > 0)) + if (_dynReactionBulk && (_nQsReacBulk > 0)) { - LinearBufferAllocator subAlloc = tlmAlloc.manageRemainingMemory(); - BufferedArray flux = subAlloc.array(_nComp); + LinearBufferAllocator subAlloc = tlmAlloc.manageRemainingMemory(); // todo nachgucken ob das wirklich so geht + BufferedArray flux = subAlloc.array(_nComp); std::fill_n(static_cast(flux), _nComp, 0.0); + + BufferedArray qsflux = subAlloc.array(_nQsReacBulk); + std::fill_n(static_cast(qsflux), _nQsReacBulk, 0.0); + + BufferedArray temp = subAlloc.array(_nComp); + std::fill_n(static_cast(temp), _nComp, 0.0); + _dynReactionBulk->residualLiquidAdd(t, secIdx, colPos, c, static_cast(flux), -1.0, subAlloc); + _dynReactionBulk->quasiStationaryFlux(t, secIdx, colPos, c, static_cast(qsflux), _qsReacBulk, subAlloc); + + + + Eigen::Map> resCMoities(static_cast(temp), _nComp); + resCMoities.setZero(); + + Eigen::Map> mapResC(resC, _nComp); + std::vector visitedQSComp(_nComp, 0); + int MoityIdx = 0; + + for (unsigned int state = 0; state < (_nComp - _nQsReacBulk); ++state) + { + if (_QsCompBulk[state] == 1) + { + ResidualType dotProduct = 0.0; + for (unsigned int i; i < _MconvMoityBulk.cols(); i++) // hier Optimierung durch Vermeidung von 0 Zeilen in MconvMoityBulk + { + dotProduct += static_cast(_MconvMoityBulk(MoityIdx, i)) * (mapResC[i]); + + if (wantJac) + _jac.native(i, state) = vDotTimeFactor + static_cast(flowOut); // dF_{ci}/dcj = v_liquidDot + F_out + } + resCMoities[state] = dotProduct; + + + MoityIdx++; + } + else if (_QsCompBulk[state] == 0) + { + resCMoities[state] += v * flux[state]; // hier sicher stellen, was in flux steht entweder res + flux oder nur flux + + if (wantJac) + _jac.native(state, _nComp + _totalBound) += static_cast(flux[state]); dF/dvliquid = flux + int a = 0; // add function that adds the jacobian for one state or change analyticJacobianLiquidAdd + } + } + + int state = (_nComp - _nQsReacBulk); + for (unsigned int qsreac = 0; qsreac < _nQsReacBulk; ++qsreac) + { + resCMoities[state++] = v * qsflux[qsreac]; + + if(wantJac) + int a = 0; // add function that adds the jacobian for single reactions -> maybe der klammer + } + + mapResC = resCMoities; + + } + else + { for (unsigned int comp = 0; comp < _nComp; ++comp) resC[comp] += v * flux[comp]; @@ -1331,7 +1419,7 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons _dynReactionBulk->analyticJacobianLiquidAdd(t, secIdx, colPos, reinterpret_cast(c), -static_cast(v), _jac.row(0), subAlloc); } } - + // Bound states for (unsigned int type = 0; type < _nParType; ++type) { @@ -1401,7 +1489,6 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons } } } - if (wantJac) { // Assemble Jacobian: Reaction @@ -1440,7 +1527,6 @@ int CSTRModel::residualImpl(double t, unsigned int secIdx, StateType const* cons // Volume: \dot{V} = F_{in} - F_{out} - F_{filter} res[2 * _nComp + _totalBound] = vDot - flowIn + flowOut + static_cast(_curFlowRateFilter); - return 0; } diff --git a/src/libcadet/model/StirredTankModel.hpp b/src/libcadet/model/StirredTankModel.hpp index dc720b997..0fe5578ae 100644 --- a/src/libcadet/model/StirredTankModel.hpp +++ b/src/libcadet/model/StirredTankModel.hpp @@ -171,6 +171,13 @@ class CSTRModel : public UnitOperationBase IDynamicReactionModel* _dynReactionBulk; //!< Dynamic reactions in the bulk volume + // active* _temp; + Eigen::MatrixXd _MconvMoityBulk; //!< Matrix with conservation of moieties in the bulk volume + std::vector _qsReacBulk; //!< Indices of components that are not conserved in the bulk volume + std::vector _QsCompBulk; + unsigned int _nQsReacBulk; + unsigned int _nMoitiesBulk; + class Exporter : public ISolutionExporter { public: diff --git a/src/libcadet/model/reaction/CrystallizationReaction.cpp b/src/libcadet/model/reaction/CrystallizationReaction.cpp index 77eea953b..d9eadf942 100644 --- a/src/libcadet/model/reaction/CrystallizationReaction.cpp +++ b/src/libcadet/model/reaction/CrystallizationReaction.cpp @@ -197,7 +197,10 @@ namespace cadet virtual bool requiresConfiguration() const CADET_NOEXCEPT { return true; } virtual bool usesParamProviderInDiscretizationConfig() const CADET_NOEXCEPT { return false; } - + void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector& QSReaction, std::vector& QSComponent) { } + bool hasQuasiStationaryReactionsLiquid() { return false; } + virtual int quasiStationaryFlux(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, + active* fluxes, std::vector& mapQSReac, LinearBufferAllocator workSpace) const { return 0; } virtual bool configure(IParameterProvider& paramProvider, UnitOpIdx unitOpIdx, ParticleTypeIdx parTypeIdx) { readScalarParameterOrArray(_bins, paramProvider, "CRY_BINS", 1); diff --git a/src/libcadet/model/reaction/DummyReaction.cpp b/src/libcadet/model/reaction/DummyReaction.cpp index 4b2581ede..1ac3786d1 100644 --- a/src/libcadet/model/reaction/DummyReaction.cpp +++ b/src/libcadet/model/reaction/DummyReaction.cpp @@ -99,6 +99,12 @@ class DummyDynamicReaction : public IDynamicReactionModel virtual unsigned int numReactionsLiquid() const CADET_NOEXCEPT { return 0; } virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT { return 0; } + + void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector& QSReaction, std::vector& QSComponent) {} + bool hasQuasiStationaryReactionsLiquid() { return false;} + + virtual int quasiStationaryFlux(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, + active* fluxes, std::vector& mapQSReac, LinearBufferAllocator workSpace) const {return 0;} protected: }; diff --git a/src/libcadet/model/reaction/MassActionLawReaction.cpp b/src/libcadet/model/reaction/MassActionLawReaction.cpp index 2c11bff5d..498d6f3bd 100644 --- a/src/libcadet/model/reaction/MassActionLawReaction.cpp +++ b/src/libcadet/model/reaction/MassActionLawReaction.cpp @@ -25,7 +25,9 @@ #include #include #include +#include +using namespace Eigen; /* { "name": "MassActionLawParamHandler", @@ -312,11 +314,17 @@ class MassActionLawReactionBase : public DynamicReactionModelBase virtual void setExternalFunctions(IExternalFunction** extFuns, unsigned int size) { _paramHandler.setExternalFunctions(extFuns, size); } virtual bool dependsOnTime() const CADET_NOEXCEPT { return ParamHandler_t::dependsOnTime(); } virtual bool requiresWorkspace() const CADET_NOEXCEPT { return true; } + bool hasQuasiStationaryReactionsLiquid() { return true; } + virtual bool hasDynamicReactions() const CADET_NOEXCEPT { return true; } + virtual int const* reactionQuasiStationarity() const CADET_NOEXCEPT { return _reactionQuasistationarity.data(); } + virtual unsigned int workspaceSize(unsigned int nComp, unsigned int totalNumBoundStates, unsigned int const* nBoundStates) const CADET_NOEXCEPT { return _paramHandler.cacheSize(maxNumReactions(), nComp, totalNumBoundStates) + std::max(maxNumReactions() * sizeof(active), 2 * (_nComp + totalNumBoundStates) * sizeof(double)); } + + virtual bool configureModelDiscretization(IParameterProvider& paramProvider, unsigned int nComp, unsigned int const* nBound, unsigned int const* boundOffset) { DynamicReactionModelBase::configureModelDiscretization(paramProvider, nComp, nBound, boundOffset); @@ -371,6 +379,93 @@ class MassActionLawReactionBase : public DynamicReactionModelBase return true; } + + //void fillConservedMoietiesBulk(Eigen::MatrixXd M, std::vectorQSReaction, std::vectorQSComponent) { + // ConservedMoietiesLiquid(M, QSReaction,QSComponent); + //} + /* + * @brief Calculates the conserved moieties based on the stoichiometric matrix and reaction quasistationarity. + * @param S The stoichiometric matrix. + * @param _reactionQuasistationarity The reaction quasistationarity vector. + * @return The conserved moieties matrix. + */ + virtual void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector& mapQSReac, std::vector& _QsCompBulk) + { + + //1. get stoichmetic matrix with only reaction in quasi stationary + // S dim -> ncomp x nreac + + int nQS = std::count(mapQSReac.begin(), mapQSReac.end(), 1); + // Count the number of entries with value 1 in _reactionQuasistationarity + + + Eigen::MatrixXd QSS(_stoichiometryBulk.rows(), nQS); + int rowIndex = 0; + + // Fülle die Spalten basierend auf _reactionQuasistationarity + for (int i = 0; i < _stoichiometryBulk.columns(); ++i) + { + const double* rowData = reinterpret_cast(_stoichiometryBulk.data() + i * _stoichiometryBulk.columns()); + Eigen::Map Srow(rowData, _stoichiometryBulk.columns()); + QSS.row(rowIndex++) = Srow; + } + + //Remove zero rows from QSS + int nQScomp = 0; // Number of quasi stationary active components + for (int i = 0; i < QSS.rows(); ++i) + { + if (QSS.row(i).norm() < 1e-10) { + _QsCompBulk.push_back(0); + } + else + { + _QsCompBulk.push_back(1); + nQScomp++; + } + } + // Redimensioniere QSS und kopiere nur die nicht-null Zeilen + if (_nComp - nQScomp < 0.0 ) // if kinetic components exists we can resize QSS + { + Eigen::MatrixXd QSSCompressed(nQScomp, QSS.cols()); + for (std::size_t i = 0; i < _QsCompBulk.size(); ++i) + { + if (_QsCompBulk[i] == 1) + { + QSSCompressed.row(i) = QSS.row(_QsCompBulk[i]); + } + } + QSS.swap(QSSCompressed); // Swap the compressed matrix back into QSS + } + + //3. Test if the matrix is full rank + int rang = QSS.fullPivLu().rank(); + if (rang != nQS) + { + throw std::runtime_error("The matrix is not full rank"); + } + + //3. Calculate the null space of the matrix + Eigen::MatrixXd leftZeroSpace = QSS.transpose().fullPivLu().kernel().transpose(); + + if (_nComp - nQScomp < 1e-10) // if there are no kinetic components we can return the zero matrix + { + M = leftZeroSpace; + } + else // add zero rows for each component that is not in the quasi stationary + { + for (std::size_t i = 0; i < _QsCompBulk.size(); ++i) + { + if (_QsCompBulk[i] == 0) + { + leftZeroSpace.conservativeResize(NoChange, leftZeroSpace.cols() + 1); + leftZeroSpace.rightCols(leftZeroSpace.cols() - i - 1) = leftZeroSpace.middleCols(i, leftZeroSpace.cols() - i - 1); + leftZeroSpace.col(i).setZero(); + } + } + M = leftZeroSpace; + } + + } virtual unsigned int numReactionsLiquid() const CADET_NOEXCEPT { return _stoichiometryBulk.columns(); } virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT { return _stoichiometryLiquid.columns() + _stoichiometrySolid.columns(); } @@ -396,6 +491,8 @@ class MassActionLawReactionBase : public DynamicReactionModelBase linalg::ActiveDenseMatrix _expSolidFwdLiquid; linalg::ActiveDenseMatrix _expSolidBwdLiquid; + std::vector _reactionQuasistationarity; + inline int maxNumReactions() const CADET_NOEXCEPT { return std::max(std::max(_stoichiometryBulk.columns(), _stoichiometryLiquid.columns()), _stoichiometrySolid.columns()); } virtual bool configureImpl(IParameterProvider& paramProvider, UnitOpIdx unitOpIdx, ParticleTypeIdx parTypeIdx) @@ -549,6 +646,67 @@ class MassActionLawReactionBase : public DynamicReactionModelBase return true; } + int singleFlux(int r, active const* y, typename DoubleActivePromoter::type flow, typename ParamHandler_t::ParamsHandle const p) + { + typedef typename DoubleActivePromoter::type flux_t; + + flux_t fwd = rateConstantOrZero(static_cast::type>(p->kFwdBulk[r]), r, _expBulkFwd, _nComp); + for (int c = 0; c < _nComp; ++c) + { + if (_expBulkFwd.native(c, r) != 0.0) + { + if (static_cast(y[c]) > 0.0) + fwd *= pow(static_cast::type>(y[c]), + static_cast::type>(_expBulkFwd.native(c, r))); + else + { + fwd *= 0.0; + break; + } + } + } + + flux_t bwd = rateConstantOrZero(static_cast::type>(p->kBwdBulk[r]), r, _expBulkBwd, _nComp); + for (int c = 0; c < _nComp; ++c) + { + if (_expBulkBwd.native(c, r) != 0.0) + { + if (static_cast(y[c]) > 0.0) + bwd *= pow(static_cast::type>(y[c]), + static_cast::type>(_expBulkBwd.native(c, r))); + else + { + bwd *= 0.0; + break; + } + } + } + + flow = fwd - bwd; + return 0; + } + + + virtual int quasiStationaryFlux(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, + active* fluxes, std::vector& mapQSReac, LinearBufferAllocator workSpace) const + { + typedef typename DoubleActivePromoter::type flux_t; + typename ParamHandler_t::ParamsHandle const p = _paramHandler.update(t, secIdx, colPos, _nComp, _nBoundStates, workSpace); + + flux_t flow; + + for (int r = 0; r < _stoichiometryBulk.columns(); ++r) + { + if (mapQSReac[r] == 1) + { + //flow.clear() + singleFlux(r, y, flow, p); + fluxes[r] = flow; + } + return 0; + } + } + template int residualLiquidImpl(double t, unsigned int secIdx, const ColumnPosition& colPos, StateType const* y, ResidualType* res, const FactorType& factor, LinearBufferAllocator workSpace) const diff --git a/src/libcadet/model/reaction/MichaelisMentenReaction.cpp b/src/libcadet/model/reaction/MichaelisMentenReaction.cpp index ee1f209b8..aad1ef500 100644 --- a/src/libcadet/model/reaction/MichaelisMentenReaction.cpp +++ b/src/libcadet/model/reaction/MichaelisMentenReaction.cpp @@ -152,6 +152,9 @@ class MichaelisMentenReactionBase : public DynamicReactionModelBase virtual unsigned int numReactionsLiquid() const CADET_NOEXCEPT { return _stoichiometryBulk.columns(); } virtual unsigned int numReactionsCombined() const CADET_NOEXCEPT { return 0; } + void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector& QSReaction, std::vector& QSComponent) {} + virtual int quasiStationaryFlux(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, + active* fluxes, std::vector& mapQSReac, LinearBufferAllocator workSpace) const { return 0; } CADET_DYNAMICREACTIONMODEL_BOILERPLATE diff --git a/src/libcadet/model/reaction/ReactionModelBase.cpp b/src/libcadet/model/reaction/ReactionModelBase.cpp index 71e59ca5f..e3d8f9979 100644 --- a/src/libcadet/model/reaction/ReactionModelBase.cpp +++ b/src/libcadet/model/reaction/ReactionModelBase.cpp @@ -87,6 +87,7 @@ bool DynamicReactionModelBase::setParameter(const ParameterId& pId, bool value) return false; } + active* DynamicReactionModelBase::getParameter(const ParameterId& pId) { auto paramHandle = _parameters.find(pId); diff --git a/src/libcadet/model/reaction/ReactionModelBase.hpp b/src/libcadet/model/reaction/ReactionModelBase.hpp index fe4f50724..83b54266c 100644 --- a/src/libcadet/model/reaction/ReactionModelBase.hpp +++ b/src/libcadet/model/reaction/ReactionModelBase.hpp @@ -19,8 +19,8 @@ #define LIBCADET_REACTIONMODELBASE_HPP_ #include "model/ReactionModel.hpp" +#include "linalg/ActiveDenseMatrix.hpp" #include "ParamIdUtil.hpp" - #include namespace cadet @@ -56,13 +56,18 @@ class DynamicReactionModelBase : public IDynamicReactionModel virtual active* getParameter(const ParameterId& pId); - virtual void setExternalFunctions(IExternalFunction** extFuns, unsigned int size) { } + virtual void setExternalFunctions(IExternalFunction** extFuns, unsigned int size) { }; + virtual void fillConservedMoietiesBulk(Eigen::MatrixXd& M, std::vector& QSReaction, std::vector& _QsCompBulk) = 0; + virtual int quasiStationaryFlux(double t, unsigned int secIdx, const ColumnPosition& colPos, double const* y, + active* fluxes, std::vector& mapQSReac, LinearBufferAllocator workSpace) const = 0; + protected: int _nComp; //!< Number of components unsigned int const* _nBoundStates; //!< Array with number of bound states for each component unsigned int const* _boundOffset; //!< Array with offsets to the first bound state of each component int _nTotalBoundStates; + std::unordered_map _parameters; //!< Map used to translate ParameterIds to actual variables @@ -91,7 +96,7 @@ class DynamicReactionModelBase : public IDynamicReactionModel * The implementation is inserted inline in the class declaration. */ #ifdef ENABLE_DG -#define CADET_DYNAMICREACTIONMODEL_BOILERPLATE \ +#define CADET_DYNAMICREACTIONMODEL_BOILERPLATE \ virtual int residualLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, active const* y, \ active* res, const active& factor, LinearBufferAllocator workSpace) const \ { \ @@ -181,6 +186,7 @@ class DynamicReactionModelBase : public IDynamicReactionModel { \ jacobianCombinedImpl(t, secIdx, colPos, yLiquid, ySolid, factor, jacLiquid, jacSolid, workSpace); \ } + #else #define CADET_DYNAMICREACTIONMODEL_BOILERPLATE \ virtual int residualLiquidAdd(double t, unsigned int secIdx, const ColumnPosition& colPos, active const* y, \