2121#include " model/BindingModel.hpp"
2222#include " model/ReactionModel.hpp"
2323#include " model/parts/BindingCellKernel.hpp"
24+ #include " model/ParameterDependence.hpp"
2425#include " SimulationTypes.hpp"
2526#include " linalg/DenseMatrix.hpp"
2627#include " linalg/BandMatrix.hpp"
@@ -63,7 +64,7 @@ int schurComplementMultiplierLRMPores(void* userData, double const* x, double* z
6364
6465template <typename ConvDispOperator>
6566LumpedRateModelWithPores<ConvDispOperator>::LumpedRateModelWithPores(UnitOpIdx unitOpIdx) : UnitOperationBase(unitOpIdx),
66- _dynReactionBulk (nullptr ), _jacP(0 ), _jacPdisc(0 ), _jacPF(0 ), _jacFP(0 ), _jacInlet(), _analyticJac(true ),
67+ _dynReactionBulk (nullptr ), _filmDiffDep( nullptr ), _jacP(0 ), _jacPdisc(0 ), _jacPF(0 ), _jacFP(0 ), _jacInlet(), _analyticJac(true ),
6768 _jacobianAdDirs(0 ), _factorizeJacobian(false ), _tempState(nullptr ), _initC(0 ), _initCp(0 ), _initQ(0 ),
6869 _initState(0 ), _initStateDot(0 )
6970{
@@ -75,6 +76,7 @@ LumpedRateModelWithPores<ConvDispOperator>::~LumpedRateModelWithPores() CADET_NO
7576 delete[] _tempState;
7677
7778 delete _dynReactionBulk;
79+ delete _filmDiffDep;
7880
7981 delete[] _disc.parTypeOffset ;
8082 delete[] _disc.nBound ;
@@ -263,6 +265,18 @@ bool LumpedRateModelWithPores<ConvDispOperator>::configureModelDiscretization(IP
263265
264266 const bool transportSuccess = _convDispOp.configureModelDiscretization (paramProvider, helper, _disc.nComp , _disc.nCol );
265267
268+ if (paramProvider.exists (" FILM_DIFFUSION_DEP" ))
269+ {
270+ const std::string paramDepName = paramProvider.getString (" FILM_DIFFUSION_DEP" );
271+ _filmDiffDep = helper.createParameterParameterDependence (paramDepName);
272+ if (!_filmDiffDep)
273+ throw InvalidParameterException (" Unknown parameter dependence " + paramDepName + " in FILM_DIFFUSION_DEP" );
274+
275+ _filmDiffDep->configureModelDiscretization (paramProvider);
276+ }
277+ else
278+ _filmDiffDep = helper.createParameterParameterDependence (" CONSTANT_ONE" );
279+
266280 // Allocate memory
267281 Indexer idxr (_disc);
268282
@@ -402,6 +416,12 @@ bool LumpedRateModelWithPores<ConvDispOperator>::configure(IParameterProvider& p
402416
403417 const bool transportSuccess = _convDispOp.configure (_unitOpIdx, paramProvider, _parameters);
404418
419+ if (_filmDiffDep)
420+ {
421+ if (!_filmDiffDep->configure (paramProvider, _unitOpIdx, ParTypeIndep, BoundStateIndep, " FILM_DIFFUSION_DEP" ))
422+ throw InvalidParameterException (" Failed to configure film diffusion parameter dependency (FILM_DIFFUSION_DEP)" );
423+ }
424+
405425 // Read geometry parameters
406426 _colPorosity = paramProvider.getDouble (" COL_POROSITY" );
407427 _singleParRadius = readAndRegisterMultiplexTypeParam (paramProvider, _parameters, _parRadius, " PAR_RADIUS" , _disc.nParType , _unitOpIdx);
@@ -964,7 +984,7 @@ template <typename ConvDispOperator>
964984template <typename StateType, typename ResidualType, typename ParamType, bool wantJac>
965985int LumpedRateModelWithPores<ConvDispOperator>::residualBulk(double t, unsigned int secIdx, StateType const * yBase, double const * yDotBase, ResidualType* resBase, util::ThreadLocalStorage& threadLocalMem)
966986{
967- _convDispOp.residual (t, secIdx, yBase, yDotBase, resBase, wantJac, typename ParamSens<ParamType>::enabled ());
987+ _convDispOp.residual (* this , t, secIdx, yBase, yDotBase, resBase, wantJac, typename ParamSens<ParamType>::enabled ());
968988 if (!_dynReactionBulk || (_dynReactionBulk->numReactionsLiquid () == 0 ))
969989 return 0 ;
970990
@@ -1068,7 +1088,12 @@ int LumpedRateModelWithPores<ConvDispOperator>::residualFlux(double t, unsigned
10681088 {
10691089 const unsigned int colCell = i / _disc.nComp ;
10701090 const unsigned int comp = i % _disc.nComp ;
1071- resCol[i] += jacCF_val * static_cast <ParamType>(filmDiff[comp]) * static_cast <ParamType>(_parTypeVolFrac[type + _disc.nParType * colCell]) * yFluxType[i];
1091+
1092+ const double relPos = _convDispOp.relativeCoordinate (colCell);
1093+ const active curVelocity = _convDispOp.currentVelocity (relPos);
1094+ const active modifier = _filmDiffDep->getValue (*this , ColumnPosition{relPos, 0.0 , 0.0 }, comp, ParTypeIndep, BoundStateIndep, curVelocity);
1095+
1096+ resCol[i] += jacCF_val * static_cast <ParamType>(filmDiff[comp]) * static_cast <ParamType>(modifier) * static_cast <ParamType>(_parTypeVolFrac[type + _disc.nParType * colCell]) * yFluxType[i];
10721097 }
10731098
10741099 // J_{f,0} block, adds bulk volume state c_i to flux equation
@@ -1084,10 +1109,15 @@ int LumpedRateModelWithPores<ConvDispOperator>::residualFlux(double t, unsigned
10841109 // J_{p,f} block, adds flux to particle / bead volume equations
10851110 for (unsigned int pblk = 0 ; pblk < _disc.nCol ; ++pblk)
10861111 {
1112+ const double relPos = _convDispOp.relativeCoordinate (pblk);
1113+ const active curVelocity = _convDispOp.currentVelocity (relPos);
1114+
10871115 for (unsigned int comp = 0 ; comp < _disc.nComp ; ++comp)
10881116 {
1117+ const active modifier = _filmDiffDep->getValue (*this , ColumnPosition{relPos, 0.0 , 0.0 }, comp, ParTypeIndep, BoundStateIndep, curVelocity);
1118+
10891119 const unsigned int eq = pblk * idxr.strideColCell () + comp * idxr.strideColComp ();
1090- resParType[pblk * idxr.strideParBlock (type) + comp] += jacPF_val / static_cast <ParamType>(poreAccFactor[comp]) * static_cast <ParamType>(filmDiff[comp]) * yFluxType[eq];
1120+ resParType[pblk * idxr.strideParBlock (type) + comp] += jacPF_val / static_cast <ParamType>(poreAccFactor[comp]) * static_cast <ParamType>(filmDiff[comp]) * static_cast <ParamType>(modifier) * yFluxType[eq];
10911121 }
10921122 }
10931123
@@ -1148,8 +1178,12 @@ void LumpedRateModelWithPores<ConvDispOperator>::assembleOffdiagJac(double t, un
11481178 const unsigned int colCell = eq / _disc.nComp ;
11491179 const unsigned int comp = eq % _disc.nComp ;
11501180
1181+ const double relPos = _convDispOp.relativeCoordinate (colCell);
1182+ const double curVelocity = static_cast <double >(_convDispOp.currentVelocity (relPos));
1183+ const double modifier = _filmDiffDep->getValue (*this , ColumnPosition{relPos, 0.0 , 0.0 }, comp, ParTypeIndep, BoundStateIndep, curVelocity);
1184+
11511185 // Main diagonal corresponds to j_{f,i} (flux) state variable
1152- _jacCF.addElement (eq, eq + typeOffset, jacCF_val * static_cast <double >(filmDiff[comp]) * static_cast <double >(_parTypeVolFrac[type + _disc.nParType * colCell]));
1186+ _jacCF.addElement (eq, eq + typeOffset, jacCF_val * static_cast <double >(filmDiff[comp]) * modifier * static_cast <double >(_parTypeVolFrac[type + _disc.nParType * colCell]));
11531187 }
11541188
11551189 // J_{f,0} block, adds bulk volume state c_i to flux equation
@@ -1161,11 +1195,16 @@ void LumpedRateModelWithPores<ConvDispOperator>::assembleOffdiagJac(double t, un
11611195 // J_{p,f} block, implements bead boundary condition in outer bead shell equation
11621196 for (unsigned int pblk = 0 ; pblk < _disc.nCol ; ++pblk)
11631197 {
1198+ const double relPos = _convDispOp.relativeCoordinate (pblk);
1199+ const double curVelocity = static_cast <double >(_convDispOp.currentVelocity (relPos));
1200+
11641201 for (unsigned int comp = 0 ; comp < _disc.nComp ; ++comp)
11651202 {
11661203 const unsigned int eq = typeOffset + pblk * idxr.strideColCell () + comp * idxr.strideColComp ();
11671204 const unsigned int col = pblk * idxr.strideParBlock (type) + comp;
1168- _jacPF[type].addElement (col, eq, jacPF_val / static_cast <double >(poreAccFactor[comp]) * static_cast <double >(filmDiff[comp]));
1205+
1206+ const double modifier = _filmDiffDep->getValue (*this , ColumnPosition{relPos, 0.0 , 0.0 }, comp, ParTypeIndep, BoundStateIndep, curVelocity);
1207+ _jacPF[type].addElement (col, eq, jacPF_val / static_cast <double >(poreAccFactor[comp]) * static_cast <double >(filmDiff[comp]) * modifier);
11691208 }
11701209 }
11711210
@@ -1468,6 +1507,15 @@ bool LumpedRateModelWithPores<ConvDispOperator>::setParameter(const ParameterId&
14681507
14691508 if (_convDispOp.setParameter (pId, value))
14701509 return true ;
1510+
1511+ if (_filmDiffDep)
1512+ {
1513+ if (_filmDiffDep->hasParameter (pId))
1514+ {
1515+ _filmDiffDep->setParameter (pId, value);
1516+ return true ;
1517+ }
1518+ }
14711519 }
14721520
14731521 return UnitOperationBase::setParameter (pId, value);
@@ -1509,6 +1557,16 @@ void LumpedRateModelWithPores<ConvDispOperator>::setSensitiveParameterValue(cons
15091557
15101558 if (_convDispOp.setSensitiveParameterValue (_sensParams, pId, value))
15111559 return ;
1560+
1561+ if (_filmDiffDep)
1562+ {
1563+ active* const param = _filmDiffDep->getParameter (pId);
1564+ if (param)
1565+ {
1566+ param->setValue (value);
1567+ return ;
1568+ }
1569+ }
15121570 }
15131571
15141572 UnitOperationBase::setSensitiveParameterValue (pId, value);
@@ -1575,6 +1633,17 @@ bool LumpedRateModelWithPores<ConvDispOperator>::setSensitiveParameter(const Par
15751633 LOG (Debug) << " Found parameter " << pId << " : Dir " << adDirection << " is set to " << adValue;
15761634 return true ;
15771635 }
1636+
1637+ if (_filmDiffDep)
1638+ {
1639+ active* const param = _filmDiffDep->getParameter (pId);
1640+ if (param)
1641+ {
1642+ LOG (Debug) << " Found parameter " << pId << " : Dir " << adDirection << " is set to " << adValue;
1643+ param->setADValue (adDirection, adValue);
1644+ return true ;
1645+ }
1646+ }
15781647 }
15791648
15801649 return UnitOperationBase::setSensitiveParameter (pId, adDirection, adValue);
0 commit comments