28#ifndef OPM_BLACK_OIL_BIOEFFECTS_MODULE_HH
29#define OPM_BLACK_OIL_BIOEFFECTS_MODULE_HH
31#include <dune/common/fvector.hh>
33#include <opm/common/utility/gpuDecorators.hpp>
94template <
class TypeTag>
95class BlackOilBioeffectsModule<TypeTag, true>
109 using Toolbox = MathToolbox<Evaluation>;
113 enum { gasCompIdx = FluidSystem::gasCompIdx };
115 static constexpr unsigned microbialConcentrationIdx = Indices::microbialConcentrationIdx;
116 static constexpr unsigned oxygenConcentrationIdx = Indices::oxygenConcentrationIdx;
117 static constexpr unsigned ureaConcentrationIdx = Indices::ureaConcentrationIdx;
118 static constexpr unsigned biofilmVolumeFractionIdx = Indices::biofilmVolumeFractionIdx;
119 static constexpr unsigned calciteVolumeFractionIdx = Indices::calciteVolumeFractionIdx;
120 static constexpr unsigned contiMicrobialEqIdx = Indices::contiMicrobialEqIdx;
121 static constexpr unsigned contiOxygenEqIdx = Indices::contiOxygenEqIdx;
122 static constexpr unsigned contiUreaEqIdx = Indices::contiUreaEqIdx;
123 static constexpr unsigned contiBiofilmEqIdx = Indices::contiBiofilmEqIdx;
124 static constexpr unsigned contiCalciteEqIdx = Indices::contiCalciteEqIdx;
125 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
127 static constexpr bool enableBioeffects =
true;
128 static constexpr bool enableMICP = Indices::enableMICP;
130 static constexpr unsigned numEq = getPropValue<TypeTag, Properties::NumEq>();
144 if constexpr (enableBioeffects)
152 Simulator& simulator)
154 if constexpr (enableBioeffects)
160 if constexpr (enableBioeffects)
161 if constexpr (enableMICP)
162 return eqIdx == contiMicrobialEqIdx || eqIdx == contiOxygenEqIdx || eqIdx == contiUreaEqIdx
163 || eqIdx == contiBiofilmEqIdx || eqIdx == contiCalciteEqIdx;
165 return eqIdx == contiMicrobialEqIdx || eqIdx == contiBiofilmEqIdx;
170 static Scalar
eqWeight([[maybe_unused]]
unsigned eqIdx)
172 assert(eqApplies(eqIdx));
175 return static_cast<Scalar
>(1.0);
179 template <
class StorageType>
181 const IntensiveQuantities& intQuants)
183 using LhsEval =
typename StorageType::value_type;
184 if constexpr (enableBioeffects) {
185 const auto& fs = intQuants.fluidState();
186 LhsEval surfaceVolumeWater = Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx)) *
187 Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx)) *
188 Toolbox::template decay<LhsEval>(intQuants.porosity());
190 surfaceVolumeWater = max(surfaceVolumeWater, 1e-10);
192 const LhsEval accumulationMicrobes = surfaceVolumeWater * Toolbox::template decay<LhsEval>(intQuants.microbialConcentration());
193 storage[contiMicrobialEqIdx] += accumulationMicrobes;
195 const LhsEval accumulationBiofilm = Toolbox::template decay<LhsEval>(intQuants.biofilmVolumeFraction());
196 storage[contiBiofilmEqIdx] += accumulationBiofilm;
197 if constexpr (enableMICP) {
199 const LhsEval accumulationOxygen = surfaceVolumeWater * Toolbox::template decay<LhsEval>(intQuants.oxygenConcentration());
200 storage[contiOxygenEqIdx] += accumulationOxygen;
202 const LhsEval accumulationUrea = surfaceVolumeWater * Toolbox::template decay<LhsEval>(intQuants.ureaConcentration());
203 storage[contiUreaEqIdx] += accumulationUrea;
204 storage[contiUreaEqIdx] *= getPropValue<TypeTag, Properties::BlackOilUreaScalingFactor>();
206 const LhsEval accumulationCalcite = Toolbox::template decay<LhsEval>(intQuants.calciteVolumeFraction());
207 storage[contiCalciteEqIdx] += accumulationCalcite;
212 template <
class UpEval>
215 const Evaluation& volumeFlux,
216 const IntensiveQuantities& upFs)
218 if (phaseIdx == waterPhaseIdx) {
219 if constexpr (enableBioeffects) {
220 flux[contiMicrobialEqIdx] =
221 decay<UpEval>(upFs.microbialConcentration())
222 * decay<UpEval>(upFs.fluidState().invB(waterPhaseIdx))
224 if constexpr (enableMICP) {
225 flux[contiOxygenEqIdx] =
226 decay<UpEval>(upFs.oxygenConcentration())
227 * decay<UpEval>(upFs.fluidState().invB(waterPhaseIdx))
229 flux[contiUreaEqIdx] =
230 decay<UpEval>(upFs.ureaConcentration())
231 * decay<UpEval>(upFs.fluidState().invB(waterPhaseIdx))
241 if constexpr (enableMICP) {
242 flux[contiUreaEqIdx] *= getPropValue<TypeTag, Properties::BlackOilUreaScalingFactor>();
247 [[maybe_unused]]
const ElementContext& elemCtx,
248 [[maybe_unused]]
unsigned scvfIdx,
249 [[maybe_unused]]
unsigned timeIdx)
251 if constexpr (enableBioeffects) {
252 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
253 unsigned focusIdx = elemCtx.focusDofIndex();
254 unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
255 flux[contiMicrobialEqIdx] = 0.0;
256 if constexpr (enableMICP) {
257 flux[contiOxygenEqIdx] = 0.0;
258 flux[contiUreaEqIdx] = 0.0;
260 if (upIdx == focusIdx)
261 addBioeffectsFluxes_<Evaluation>(flux, elemCtx, scvfIdx, timeIdx);
263 addBioeffectsFluxes_<Scalar>(flux, elemCtx, scvfIdx, timeIdx);
267 template <
class UpstreamEval>
269 const ElementContext& elemCtx,
273 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
274 unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
275 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
276 const auto& volFlux = extQuants.volumeFlux(waterPhaseIdx);
277 addBioeffectsFluxes_<UpstreamEval>(flux, waterPhaseIdx, volFlux, up);
281 const Problem& problem,
282 const IntensiveQuantities& intQuants,
283 unsigned globalSpaceIdex)
285 if constexpr (enableBioeffects) {
286 const auto b = intQuants.fluidState().invB(waterPhaseIdx);
287 unsigned satnumIdx = problem.satnumRegionIndex(globalSpaceIdex);
288 Scalar rho_b = densityBiofilm(satnumIdx);
289 Scalar k_d = microbialDeathRate(satnumIdx);
290 Scalar mu = maximumGrowthRate(satnumIdx);
291 Scalar k_n = halfVelocityGrowth(satnumIdx);
292 Scalar Y = yieldGrowthCoefficient(satnumIdx);
293 Scalar k_a = microbialAttachmentRate(satnumIdx);
294 Scalar k_str = detachmentRate(satnumIdx);
295 Scalar eta = detachmentExponent(satnumIdx);
296 const auto& velocityInf = problem.model().linearizer().getVelocityInfo();
297 auto velocityInfos = velocityInf[globalSpaceIdex];
298 Scalar normVelocityCell =
299 std::accumulate(velocityInfos.begin(), velocityInfos.end(), 0.0,
300 [](
const auto acc,
const auto& info)
301 { return max(acc, std::abs(info.velocity[waterPhaseIdx])); });
302 if constexpr (enableMICP) {
303 Scalar rho_c = densityCalcite(satnumIdx);
304 Scalar k_u = halfVelocityUrea(satnumIdx);
305 Scalar mu_u = maximumUreaUtilization(satnumIdx);
306 Scalar F = oxygenConsumptionFactor(satnumIdx);
307 Scalar Y_uc = yieldUreaToCalciteCoefficient(satnumIdx);
311 Evaluation k_g = mu * intQuants.oxygenConcentration() / (k_n + intQuants.oxygenConcentration());
312 Evaluation k_c = mu_u * intQuants.ureaConcentration() / (k_u + intQuants.ureaConcentration());
313 if (intQuants.oxygenConcentration() < 0) {
314 k_g = mu * intQuants.oxygenConcentration() / k_n;
316 if (intQuants.ureaConcentration() < 0) {
317 k_c = mu_u * intQuants.ureaConcentration() / k_u;
322 source[Indices::contiMicrobialEqIdx] += intQuants.microbialConcentration() * intQuants.porosity() *
323 b * (Y * k_g - k_d - k_a) +
324 rho_b * intQuants.biofilmVolumeFraction() * k_str * pow(normVelocityCell / intQuants.porosity(), eta);
326 source[Indices::contiOxygenEqIdx] -= (intQuants.microbialConcentration() * intQuants.porosity() *
327 b + rho_b * intQuants.biofilmVolumeFraction()) * F * k_g;
329 source[Indices::contiUreaEqIdx] -= rho_b * intQuants.biofilmVolumeFraction() * k_c;
331 source[Indices::contiBiofilmEqIdx] += intQuants.biofilmVolumeFraction() * (Y * k_g - k_d -
332 k_str * pow(normVelocityCell / intQuants.porosity(), eta) - Y_uc * (rho_b / rho_c) *
333 intQuants.biofilmVolumeFraction() * k_c / (intQuants.porosity() +
334 intQuants.biofilmVolumeFraction())) + k_a * intQuants.microbialConcentration() *
335 intQuants.porosity() * b / rho_b;
337 source[Indices::contiCalciteEqIdx] += (rho_b / rho_c) * intQuants.biofilmVolumeFraction() * Y_uc * k_c;
340 source[Indices::contiUreaEqIdx] *= getPropValue<TypeTag, Properties::BlackOilUreaScalingFactor>();
343 const Scalar normVelocityCellG =
344 std::accumulate(velocityInfos.begin(), velocityInfos.end(), 0.0,
345 [](
const auto acc,
const auto& info)
346 { return max(acc, std::abs(info.velocity[1])); });
347 normVelocityCell = max(normVelocityCellG, normVelocityCell);
349 const auto& fs = intQuants.fluidState();
350 const auto& Sw = fs.saturation(waterPhaseIdx);
351 const auto& Rsw = fs.Rsw();
352 const auto& rhow = fs.density(waterPhaseIdx);
353 unsigned pvtRegionIndex = fs.pvtRegionIndex();
355 const auto& xG = RswToMassFraction(pvtRegionIndex, Rsw);
358 const Evaluation& poro = intQuants.porosity();
359 Scalar rho_gRef = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, pvtRegionIndex);
362 Evaluation k_g = mu * (xG * rhow * poro * Sw / (xG * rhow * poro * Sw + k_n));
364 k_g = mu * (xG * rhow * poro * Sw / k_n);
369 source[contiMicrobialEqIdx] += Sw * intQuants.microbialConcentration() * intQuants.porosity() * b
371 + intQuants.biofilmVolumeFraction() * rho_b * k_str
372 * pow(normVelocityCell / intQuants.porosity(), eta);
374 source[contiBiofilmEqIdx] += (k_g - k_d - k_str * pow(normVelocityCell / intQuants.porosity(), eta))
375 * intQuants.biofilmVolumeFraction()
376 + k_a * Sw * intQuants.microbialConcentration() * intQuants.porosity() * b / rho_b;
379 unsigned activeGasCompIdx = FluidSystem::canonicalToActiveCompIdx(gasCompIdx);
380 source[activeGasCompIdx] -= intQuants.biofilmVolumeFraction() * rho_b * k_g / (Y * rho_gRef);
385 static void addSource([[maybe_unused]] RateVector& source,
386 [[maybe_unused]]
const ElementContext& elemCtx,
387 [[maybe_unused]]
unsigned dofIdx,
388 [[maybe_unused]]
unsigned timeIdx)
390 if constexpr (enableMICP) {
391 const auto& problem = elemCtx.problem();
392 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, timeIdx);
393 addSource(source, problem, intQuants, dofIdx);
399 return params_.densityBiofilm_[satnumRegionIdx];
404 return params_.densityCalcite_[satnumRegionIdx];
409 return params_.detachmentRate_[satnumRegionIdx];
414 return params_.detachmentExponent_[satnumRegionIdx];
419 return params_.halfVelocityGrowth_[satnumRegionIdx];
424 return params_.halfVelocityUrea_[satnumRegionIdx];
429 return params_.maximumGrowthRate_[satnumRegionIdx];
434 return params_.maximumUreaUtilization_[satnumRegionIdx];
439 return params_.microbialAttachmentRate_[satnumRegionIdx];
444 return params_.microbialDeathRate_[satnumRegionIdx];
449 return params_.oxygenConsumptionFactor_[satnumRegionIdx];
454 return params_.yieldGrowthCoefficient_[satnumRegionIdx];
459 return params_.yieldUreaToCalciteCoefficient_[satnumRegionIdx];
464 return params_.bioDiffCoefficient_[pvtRegionIdx][compIdx];
467 static const TabulatedFunction&
permfactTable(
const ElementContext& elemCtx,
471 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
472 return params_.permfactTable_[satnumRegionIdx];
477 return params_.permfactTable_[satnumRegionIdx];
480 static const TabulatedFunction&
pcfactTable(
unsigned satnumRegionIdx)
482 return params_.pcfactTable_[satnumRegionIdx];
487 if constexpr (enableBioeffects && !enableMICP) {
488 return !params_.pcfactTable_.empty();
498 static Evaluation RswToMassFraction(
unsigned regionIdx,
const Evaluation& Rsw) {
499 Scalar rho_wRef = FluidSystem::referenceDensity(FluidSystem::waterPhaseIdx, regionIdx);
500 Scalar rho_gRef = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
502 const Evaluation rho_oG = Rsw * rho_gRef;
504 return rho_oG / (rho_wRef + rho_oG);
509template <
class TypeTag>
510BlackOilBioeffectsParams<typename BlackOilBioeffectsModule<TypeTag, true>::Scalar>
511BlackOilBioeffectsModule<TypeTag, true>::params_;
520template <
class TypeTag>
533 static constexpr unsigned microbialConcentrationIdx = Indices::microbialConcentrationIdx;
534 static constexpr unsigned oxygenConcentrationIdx = Indices::oxygenConcentrationIdx;
535 static constexpr unsigned ureaConcentrationIdx = Indices::ureaConcentrationIdx;
536 static constexpr unsigned biofilmVolumeFractionIdx = Indices::biofilmVolumeFractionIdx;
537 static constexpr unsigned calciteVolumeFractionIdx = Indices::calciteVolumeFractionIdx;
538 static constexpr bool enableMICP = Indices::enableMICP;
551 const auto linearizationType = elemCtx.linearizationType();
552 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
553 const Scalar referencePorosity_ = elemCtx.problem().referencePorosity(dofIdx, timeIdx);
554 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, dofIdx, timeIdx);
556 microbialConcentration_ = priVars.makeEvaluation(microbialConcentrationIdx, timeIdx, linearizationType);
557 biofilmVolumeFraction_ = priVars.makeEvaluation(biofilmVolumeFractionIdx, timeIdx, linearizationType);
558 biofilmMass_ = biofilmVolumeFraction_ * BioeffectsModule::densityBiofilm(satnumRegionIdx);
559 calciteVolumeFraction_ = 0.0;
560 if constexpr (enableMICP) {
561 oxygenConcentration_ = priVars.makeEvaluation(oxygenConcentrationIdx, timeIdx, linearizationType);
562 ureaConcentration_ = priVars.makeEvaluation(ureaConcentrationIdx, timeIdx, linearizationType);
563 calciteVolumeFraction_ = priVars.makeEvaluation(calciteVolumeFractionIdx, timeIdx, linearizationType);
564 calciteMass_ = calciteVolumeFraction_ * BioeffectsModule::densityCalcite(satnumRegionIdx);
566 const Evaluation poroFact = min(1.0 - (biofilmVolumeFraction_ + calciteVolumeFraction_) /
567 (referencePorosity_), 1.0);
569 const auto& permfactTable = BioeffectsModule::permfactTable(satnumRegionIdx);
570 permFactor_ = permfactTable.eval(poroFact,
true);
574 {
return microbialConcentration_; }
577 {
return oxygenConcentration_; }
580 {
return ureaConcentration_; }
583 {
return biofilmVolumeFraction_; }
586 {
return calciteVolumeFraction_; }
589 {
return biofilmMass_; }
592 {
return calciteMass_; }
595 {
return permFactor_; }
616template <
class TypeTag>
Contains the parameters required to extend the black-oil model by bioeffects.
Contains classes extending the black-oil model. \detail This file holds dummy definitions,...
Declares the properties required by the black oil model.
Provides the bioeffects specific extensive quantities to the generic black-oil module's extensive qua...
Evaluation biofilmMass_
Definition: blackoilbioeffectsmodules.hh:603
const Evaluation & calciteVolumeFraction() const
Definition: blackoilbioeffectsmodules.hh:585
const Evaluation & ureaConcentration() const
Definition: blackoilbioeffectsmodules.hh:579
Evaluation microbialConcentration_
Definition: blackoilbioeffectsmodules.hh:598
Evaluation pcFactor_
Definition: blackoilbioeffectsmodules.hh:606
Evaluation ureaConcentration_
Definition: blackoilbioeffectsmodules.hh:600
const Evaluation & oxygenConcentration() const
Definition: blackoilbioeffectsmodules.hh:576
Evaluation calciteVolumeFraction_
Definition: blackoilbioeffectsmodules.hh:602
const Evaluation & biofilmVolumeFraction() const
Definition: blackoilbioeffectsmodules.hh:582
Evaluation calciteMass_
Definition: blackoilbioeffectsmodules.hh:604
const Evaluation calciteMass() const
Definition: blackoilbioeffectsmodules.hh:591
Evaluation permFactor_
Definition: blackoilbioeffectsmodules.hh:605
Evaluation oxygenConcentration_
Definition: blackoilbioeffectsmodules.hh:599
const Evaluation & microbialConcentration() const
Definition: blackoilbioeffectsmodules.hh:573
Evaluation biofilmVolumeFraction_
Definition: blackoilbioeffectsmodules.hh:601
const Evaluation biofilmMass() const
Definition: blackoilbioeffectsmodules.hh:588
void bioeffectsPropertiesUpdate_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the intensive properties needed to handle bioeffects from the primary variables.
Definition: blackoilbioeffectsmodules.hh:547
const Evaluation & permFactor() const
Definition: blackoilbioeffectsmodules.hh:594
Provides the volumetric quantities required for the equations needed by the bioeffects extension of t...
Contains the high level supplements required to extend the black oil model by bioeffects.
Definition: blackoilbioeffectsmodules.hh:96
static const Scalar yieldUreaToCalciteCoefficient(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:457
static void setParams(BlackOilBioeffectsParams< Scalar > &¶ms)
Set parameters.
Definition: blackoilbioeffectsmodules.hh:134
static void registerParameters()
Register all run-time parameters for the black-oil bioeffects module.
Definition: blackoilbioeffectsmodules.hh:142
static const Scalar bioDiffCoefficient(unsigned pvtRegionIdx, unsigned compIdx)
Definition: blackoilbioeffectsmodules.hh:462
static const Scalar detachmentExponent(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:412
static void computeFlux(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: blackoilbioeffectsmodules.hh:246
static void addBioeffectsFluxes_(RateVector &flux, unsigned phaseIdx, const Evaluation &volumeFlux, const IntensiveQuantities &upFs)
Definition: blackoilbioeffectsmodules.hh:213
static const Scalar densityBiofilm(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:397
static Scalar eqWeight(unsigned eqIdx)
Definition: blackoilbioeffectsmodules.hh:170
static bool eqApplies(unsigned eqIdx)
Definition: blackoilbioeffectsmodules.hh:158
static void addSource(RateVector &source, const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Definition: blackoilbioeffectsmodules.hh:385
static void addSource(RateVector &source, const Problem &problem, const IntensiveQuantities &intQuants, unsigned globalSpaceIdex)
Definition: blackoilbioeffectsmodules.hh:280
static void addBioeffectsFluxes_(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: blackoilbioeffectsmodules.hh:268
static const TabulatedFunction & permfactTable(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:475
static const TabulatedFunction & pcfactTable(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:480
static void applyScaling(RateVector &flux)
Definition: blackoilbioeffectsmodules.hh:239
static const Scalar densityCalcite(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:402
static const Scalar oxygenConsumptionFactor(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:447
static OPM_HOST_DEVICE void addStorage(StorageType &storage, const IntensiveQuantities &intQuants)
Definition: blackoilbioeffectsmodules.hh:180
static const Scalar yieldGrowthCoefficient(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:452
static const TabulatedFunction & permfactTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilbioeffectsmodules.hh:467
static const Scalar maximumGrowthRate(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:427
static const Scalar microbialAttachmentRate(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:437
static bool hasPcfactTables()
Definition: blackoilbioeffectsmodules.hh:485
static void registerOutputModules(Model &model, Simulator &simulator)
Register all bioeffects specific VTK and ECL output modules.
Definition: blackoilbioeffectsmodules.hh:151
static const Scalar halfVelocityGrowth(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:417
static const Scalar maximumUreaUtilization(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:432
static const Scalar microbialDeathRate(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:442
static const Scalar halfVelocityUrea(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:422
static const Scalar detachmentRate(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:407
VTK output module for the Bioeffect model's related quantities.
Definition: vtkblackoilbioeffectsmodule.hpp:53
Definition: blackoilbioeffectsmodules.hh:45
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
Struct holding the parameters for the BlackOilBioeffectsModule class.
Definition: blackoilbioeffectsparams.hpp:42
Tabulated1DFunction< Scalar > TabulatedFunction
Definition: blackoilbioeffectsparams.hpp:46