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> 94 template <
class TypeTag>
95 class BlackOilBioeffectsModule<TypeTag, true>
109 using Toolbox = MathToolbox<Evaluation>;
111 using TabulatedFunction =
typename BlackOilBioeffectsParams<Scalar>::TabulatedFunction;
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)
158 static bool eqApplies(
unsigned eqIdx)
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>
180 OPM_HOST_DEVICE
static void addStorage(StorageType& storage,
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>
213 static void addBioeffectsFluxes_(RateVector& flux,
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))
239 static void applyScaling(RateVector& flux)
241 if constexpr (enableMICP) {
242 flux[contiUreaEqIdx] *= getPropValue<TypeTag, Properties::BlackOilUreaScalingFactor>();
246 static void computeFlux([[maybe_unused]] RateVector& flux,
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>
268 static void addBioeffectsFluxes_(RateVector& flux,
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);
280 static void addSource(RateVector& source,
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);
397 static const Scalar densityBiofilm(
unsigned satnumRegionIdx)
399 return params_.densityBiofilm_[satnumRegionIdx];
402 static const Scalar densityCalcite(
unsigned satnumRegionIdx)
404 return params_.densityCalcite_[satnumRegionIdx];
407 static const Scalar detachmentRate(
unsigned satnumRegionIdx)
409 return params_.detachmentRate_[satnumRegionIdx];
412 static const Scalar detachmentExponent(
unsigned satnumRegionIdx)
414 return params_.detachmentExponent_[satnumRegionIdx];
417 static const Scalar halfVelocityGrowth(
unsigned satnumRegionIdx)
419 return params_.halfVelocityGrowth_[satnumRegionIdx];
422 static const Scalar halfVelocityUrea(
unsigned satnumRegionIdx)
424 return params_.halfVelocityUrea_[satnumRegionIdx];
427 static const Scalar maximumGrowthRate(
unsigned satnumRegionIdx)
429 return params_.maximumGrowthRate_[satnumRegionIdx];
432 static const Scalar maximumUreaUtilization(
unsigned satnumRegionIdx)
434 return params_.maximumUreaUtilization_[satnumRegionIdx];
437 static const Scalar microbialAttachmentRate(
unsigned satnumRegionIdx)
439 return params_.microbialAttachmentRate_[satnumRegionIdx];
442 static const Scalar microbialDeathRate(
unsigned satnumRegionIdx)
444 return params_.microbialDeathRate_[satnumRegionIdx];
447 static const Scalar oxygenConsumptionFactor(
unsigned satnumRegionIdx)
449 return params_.oxygenConsumptionFactor_[satnumRegionIdx];
452 static const Scalar yieldGrowthCoefficient(
unsigned satnumRegionIdx)
454 return params_.yieldGrowthCoefficient_[satnumRegionIdx];
457 static const Scalar yieldUreaToCalciteCoefficient(
unsigned satnumRegionIdx)
459 return params_.yieldUreaToCalciteCoefficient_[satnumRegionIdx];
462 static const Scalar bioDiffCoefficient(
unsigned pvtRegionIdx,
unsigned compIdx)
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];
475 static const TabulatedFunction& permfactTable(
unsigned satnumRegionIdx)
477 return params_.permfactTable_[satnumRegionIdx];
480 static const TabulatedFunction& pcfactTable(
unsigned satnumRegionIdx)
482 return params_.pcfactTable_[satnumRegionIdx];
485 static bool hasPcfactTables()
487 if constexpr (enableBioeffects && !enableMICP) {
488 return !params_.pcfactTable_.empty();
496 static BlackOilBioeffectsParams<Scalar> params_;
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);
509 template <
class TypeTag>
510 BlackOilBioeffectsParams<typename BlackOilBioeffectsModule<TypeTag, true>::Scalar>
511 BlackOilBioeffectsModule<TypeTag, true>::params_;
520 template <
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);
573 const Evaluation& microbialConcentration()
const 574 {
return microbialConcentration_; }
576 const Evaluation& oxygenConcentration()
const 577 {
return oxygenConcentration_; }
579 const Evaluation& ureaConcentration()
const 580 {
return ureaConcentration_; }
582 const Evaluation& biofilmVolumeFraction()
const 583 {
return biofilmVolumeFraction_; }
585 const Evaluation& calciteVolumeFraction()
const 586 {
return calciteVolumeFraction_; }
588 const Evaluation biofilmMass()
const 589 {
return biofilmMass_; }
591 const Evaluation calciteMass()
const 592 {
return calciteMass_; }
594 const Evaluation& permFactor()
const 595 {
return permFactor_; }
598 Evaluation microbialConcentration_;
599 Evaluation oxygenConcentration_;
600 Evaluation ureaConcentration_;
601 Evaluation biofilmVolumeFraction_;
602 Evaluation calciteVolumeFraction_;
603 Evaluation biofilmMass_;
604 Evaluation calciteMass_;
605 Evaluation permFactor_;
606 Evaluation pcFactor_;
616 template <
class TypeTag>
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
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:41
static void setParams(BlackOilBioeffectsParams< Scalar > &¶ms)
Set parameters.
Definition: blackoilbioeffectsmodules.hh:134
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
Contains classes extending the black-oil model.
Declares the properties required by the black oil model.
Provides the bioeffects specific extensive quantities to the generic black-oil module's extensive qua...
VTK output module for the Bioeffect model's related quantities.
Definition: vtkblackoilbioeffectsmodule.hpp:52
Contains the parameters required to extend the black-oil model by bioeffects.
Contains the high level supplements required to extend the black oil model by bioeffects.
Definition: blackoilbioeffectsmodules.hh:95
static void registerParameters()
Register all run-time parameters for the multi-phase VTK output module.
Definition: vtkblackoilbioeffectsmodule.hpp:85
static void registerParameters()
Register all run-time parameters for the black-oil bioeffects module.
Definition: blackoilbioeffectsmodules.hh:142
Provides the volumetric quantities required for the equations needed by the bioeffects extension of t...
static void registerOutputModules(Model &model, Simulator &simulator)
Register all bioeffects specific VTK and ECL output modules.
Definition: blackoilbioeffectsmodules.hh:151
VTK output module for the Bioeffect model's related quantities.