28#ifndef EWOMS_BLACK_OIL_FOAM_MODULE_HH
29#define EWOMS_BLACK_OIL_FOAM_MODULE_HH
31#include <dune/common/fvector.hh>
33#include <opm/common/ErrorMacros.hpp>
34#include <opm/common/OpmLog/OpmLog.hpp>
35#include <opm/common/utility/gpuDecorators.hpp>
37#include <opm/input/eclipse/EclipseState/Phase.hpp>
59template <class TypeTag, bool enableFoamV = getPropValue<TypeTag, Properties::EnableFoam>()>
74 using Toolbox = MathToolbox<Evaluation>;
78 static constexpr unsigned foamConcentrationIdx = Indices::foamConcentrationIdx;
79 static constexpr unsigned contiFoamEqIdx = Indices::contiFoamEqIdx;
80 static constexpr unsigned gasPhaseIdx = FluidSystem::gasPhaseIdx;
81 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
83 static constexpr unsigned enableFoam = enableFoamV;
85 static constexpr unsigned numEq = getPropValue<TypeTag, Properties::NumEq>();
87 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
108 if constexpr (enableFoam) {
109 if (Parameters::Get<Parameters::EnableVtkOutput>()) {
110 OpmLog::warning(
"VTK output requested, currently unsupported by the foam module.");
118 if constexpr (enableFoam) {
119 return pvIdx == foamConcentrationIdx;
129 return "foam_concentration";
137 return static_cast<Scalar
>(1.0);
142 if constexpr (enableFoam) {
143 return eqIdx == contiFoamEqIdx;
150 static std::string
eqName([[maybe_unused]]
unsigned eqIdx)
157 static Scalar
eqWeight([[maybe_unused]]
unsigned eqIdx)
162 return static_cast<Scalar
>(1.0);
166 template <
class StorageType>
168 const IntensiveQuantities& intQuants)
170 using LhsEval =
typename StorageType::value_type;
172 if constexpr (enableFoam) {
173 const auto& fs = intQuants.fluidState();
175 LhsEval surfaceVolume = Toolbox::template decay<LhsEval>(intQuants.porosity());
176 if (params_.transport_phase_ == Phase::WATER) {
177 surfaceVolume *= Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx)) *
178 Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx));
179 }
else if (params_.transport_phase_ == Phase::GAS) {
180 surfaceVolume *= Toolbox::template decay<LhsEval>(fs.saturation(gasPhaseIdx)) *
181 Toolbox::template decay<LhsEval>(fs.invB(gasPhaseIdx));
182 }
else if (params_.transport_phase_ == Phase::SOLVENT) {
183 if constexpr (enableSolvent) {
184 surfaceVolume *= Toolbox::template decay<LhsEval>( intQuants.solventSaturation()) *
185 Toolbox::template decay<LhsEval>(intQuants.solventInverseFormationVolumeFactor());
188 OPM_THROW(std::runtime_error,
"Transport phase is GAS/WATER/SOLVENT");
192 surfaceVolume = max(surfaceVolume, 1e-10);
195 const LhsEval freeFoam = surfaceVolume *
196 Toolbox::template decay<LhsEval>(intQuants.foamConcentration());
199 const LhsEval adsorbedFoam =
200 Toolbox::template decay<LhsEval>(1.0 - intQuants.porosity()) *
201 Toolbox::template decay<LhsEval>(intQuants.foamRockDensity()) *
202 Toolbox::template decay<LhsEval>(intQuants.foamAdsorbed());
204 const LhsEval accumulationFoam = freeFoam + adsorbedFoam;
205 storage[contiFoamEqIdx] += accumulationFoam;
210 [[maybe_unused]]
const ElementContext& elemCtx,
211 [[maybe_unused]]
unsigned scvfIdx,
212 [[maybe_unused]]
unsigned timeIdx)
214 if constexpr (enableFoam) {
215 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
216 const unsigned inIdx = extQuants.interiorIndex();
223 const unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
224 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
225 if (upIdx == inIdx) {
226 flux[contiFoamEqIdx] =
227 extQuants.volumeFlux(waterPhaseIdx) *
228 up.fluidState().invB(waterPhaseIdx) *
229 up.foamConcentration();
231 flux[contiFoamEqIdx] =
232 extQuants.volumeFlux(waterPhaseIdx) *
233 decay<Scalar>(up.fluidState().invB(waterPhaseIdx)) *
234 decay<Scalar>(up.foamConcentration());
239 const unsigned upIdx = extQuants.upstreamIndex(gasPhaseIdx);
240 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
241 if (upIdx == inIdx) {
242 flux[contiFoamEqIdx] =
243 extQuants.volumeFlux(gasPhaseIdx) *
244 up.fluidState().invB(gasPhaseIdx) *
245 up.foamConcentration();
247 flux[contiFoamEqIdx] =
248 extQuants.volumeFlux(gasPhaseIdx) *
249 decay<Scalar>(up.fluidState().invB(gasPhaseIdx)) *
250 decay<Scalar>(up.foamConcentration());
255 if constexpr (enableSolvent) {
256 const unsigned upIdx = extQuants.solventUpstreamIndex();
257 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
258 if (upIdx == inIdx) {
259 flux[contiFoamEqIdx] =
260 extQuants.solventVolumeFlux() *
261 up.solventInverseFormationVolumeFactor() *
262 up.foamConcentration();
264 flux[contiFoamEqIdx] =
265 extQuants.solventVolumeFlux() *
266 decay<Scalar>(up.solventInverseFormationVolumeFactor()) *
267 decay<Scalar>(up.foamConcentration());
270 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
274 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
287 return static_cast<Scalar
>(0.0);
290 template <
class DofEntity>
292 [[maybe_unused]] std::ostream& outstream,
293 [[maybe_unused]]
const DofEntity& dof)
295 if constexpr (enableFoam) {
296 const unsigned dofIdx = model.dofMapper().index(dof);
297 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
298 outstream << priVars[foamConcentrationIdx];
302 template <
class DofEntity>
304 [[maybe_unused]] std::istream& instream,
305 [[maybe_unused]]
const DofEntity& dof)
307 if constexpr (enableFoam) {
308 const unsigned dofIdx = model.dofMapper().index(dof);
309 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
310 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
312 instream >> priVars0[foamConcentrationIdx];
315 priVars1[foamConcentrationIdx] = priVars0[foamConcentrationIdx];
323 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
324 return params_.foamRockDensity_[satnumRegionIdx];
331 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
332 return params_.foamAllowDesorption_[satnumRegionIdx];
339 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
340 return params_.adsorbedFoamTable_[satnumRegionIdx];
347 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
348 return params_.gasMobilityMultiplierTable_[pvtnumRegionIdx];
353 const unsigned scvIdx,
354 const unsigned timeIdx)
356 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
357 return params_.foamCoefficients_[satnumRegionIdx];
361 {
return params_.transport_phase_; }
367template <
class TypeTag,
bool enableFoam>
368BlackOilFoamParams<typename BlackOilFoamModule<TypeTag, enableFoam>::Scalar>
369BlackOilFoamModule<TypeTag, enableFoam>::params_;
371template <
class TypeTag,
bool enableFoam>
381template <
class TypeTag>
396 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
398 static constexpr int foamConcentrationIdx = Indices::foamConcentrationIdx;
399 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
400 static constexpr unsigned oilPhaseIdx = FluidSystem::oilPhaseIdx;
401 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
413 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
414 foamConcentration_ = priVars.makeEvaluation(foamConcentrationIdx, timeIdx);
415 const auto& fs = asImp_().fluidState_;
418 Evaluation mobilityReductionFactor = 1.0;
419 if constexpr (
false) {
423 const auto& foamCoefficients = FoamModule::foamCoefficients(elemCtx, dofIdx, timeIdx);
425 const Scalar fm_mob = foamCoefficients.fm_mob;
427 const Scalar fm_surf = foamCoefficients.fm_surf;
428 const Scalar ep_surf = foamCoefficients.ep_surf;
430 const Scalar fm_oil = foamCoefficients.fm_oil;
431 const Scalar fl_oil = foamCoefficients.fl_oil;
432 const Scalar ep_oil = foamCoefficients.ep_oil;
434 const Scalar fm_dry = foamCoefficients.fm_dry;
435 const Scalar ep_dry = foamCoefficients.ep_dry;
437 const Scalar fm_cap = foamCoefficients.fm_cap;
438 const Scalar ep_cap = foamCoefficients.ep_cap;
440 const Evaluation C_surf = foamConcentration_;
441 const Evaluation Ca = 1e10;
442 const Evaluation S_o = fs.saturation(oilPhaseIdx);
443 const Evaluation S_w = fs.saturation(waterPhaseIdx);
445 const Evaluation F1 = pow(C_surf / fm_surf, ep_surf);
446 const Evaluation F2 = pow((fm_oil - S_o) / (fm_oil - fl_oil), ep_oil);
447 const Evaluation F3 = pow(fm_cap / Ca, ep_cap);
448 const Evaluation F7 = 0.5 + atan(ep_dry * (S_w - fm_dry)) / std::numbers::pi_v<Scalar>;
450 mobilityReductionFactor = 1. / (1. + fm_mob * F1 * F2 * F3 * F7);
455 const auto& gasMobilityMultiplier = FoamModule::gasMobilityMultiplierTable(elemCtx, dofIdx, timeIdx);
456 mobilityReductionFactor = gasMobilityMultiplier.eval(foamConcentration_,
true);
460 switch (FoamModule::transportPhase()) {
462 asImp_().mobility_[waterPhaseIdx] *= mobilityReductionFactor;
465 asImp_().mobility_[gasPhaseIdx] *= mobilityReductionFactor;
468 if constexpr (enableSolvent) {
469 asImp_().solventMobility_ *= mobilityReductionFactor;
471 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
475 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
478 foamRockDensity_ = FoamModule::foamRockDensity(elemCtx, dofIdx, timeIdx);
480 const auto& adsorbedFoamTable = FoamModule::adsorbedFoamTable(elemCtx, dofIdx, timeIdx);
481 foamAdsorbed_ = adsorbedFoamTable.eval(foamConcentration_,
true);
482 if (!FoamModule::foamAllowDesorption(elemCtx, dofIdx, timeIdx)) {
483 throw std::runtime_error(
"Foam module does not support the 'no desorption' option.");
488 {
return foamConcentration_; }
491 {
return foamRockDensity_; }
494 {
return foamAdsorbed_; }
498 {
return *
static_cast<Implementation*
>(
this); }
505template <
class TypeTag>
519 {
throw std::runtime_error(
"foamConcentration() called but foam is disabled"); }
522 {
throw std::runtime_error(
"foamRockDensity() called but foam is disabled"); }
525 {
throw std::runtime_error(
"foamAdsorbed() called but foam is disabled"); }
Contains the parameters to extend the black-oil model to include the effects of foam.
Declares the properties required by the black oil model.
Scalar foamRockDensity() const
Definition: blackoilfoammodules.hh:521
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:518
void foamPropertiesUpdate_(const ElementContext &, unsigned, unsigned)
Definition: blackoilfoammodules.hh:513
Scalar foamAdsorbed() const
Definition: blackoilfoammodules.hh:524
Evaluation foamConcentration_
Definition: blackoilfoammodules.hh:500
void foamPropertiesUpdate_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the intensive properties needed to handle polymers from the primary variables.
Definition: blackoilfoammodules.hh:409
const Evaluation & foamAdsorbed() const
Definition: blackoilfoammodules.hh:493
Scalar foamRockDensity() const
Definition: blackoilfoammodules.hh:490
Evaluation foamAdsorbed_
Definition: blackoilfoammodules.hh:502
Implementation & asImp_()
Definition: blackoilfoammodules.hh:497
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:487
Scalar foamRockDensity_
Definition: blackoilfoammodules.hh:501
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilfoammodules.hh:372
Contains the high level supplements required to extend the black oil model to include the effects of ...
Definition: blackoilfoammodules.hh:61
static bool eqApplies(unsigned eqIdx)
Definition: blackoilfoammodules.hh:140
static void registerOutputModules(Model &, Simulator &)
Register all foam specific VTK and ECL output modules.
Definition: blackoilfoammodules.hh:105
static void registerParameters()
Register all run-time parameters for the black-oil foam module.
Definition: blackoilfoammodules.hh:99
static std::string primaryVarName(unsigned pvIdx)
Definition: blackoilfoammodules.hh:126
static Scalar eqWeight(unsigned eqIdx)
Definition: blackoilfoammodules.hh:157
static void deserializeEntity(Model &model, std::istream &instream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:303
static void setParams(BlackOilFoamParams< Scalar > &¶ms)
Set parameters.
Definition: blackoilfoammodules.hh:91
static std::string eqName(unsigned eqIdx)
Definition: blackoilfoammodules.hh:150
static bool primaryVarApplies(unsigned pvIdx)
Definition: blackoilfoammodules.hh:116
static bool foamAllowDesorption(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:327
static Scalar primaryVarWeight(unsigned pvIdx)
Definition: blackoilfoammodules.hh:132
static OPM_HOST_DEVICE void addStorage(StorageType &storage, const IntensiveQuantities &intQuants)
Definition: blackoilfoammodules.hh:167
static const BlackOilFoamParams< Scalar >::FoamCoefficients & foamCoefficients(const ElementContext &elemCtx, const unsigned scvIdx, const unsigned timeIdx)
Definition: blackoilfoammodules.hh:352
static void computeFlux(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:209
static Scalar computeUpdateError(const PrimaryVariables &, const EqVector &)
Return how much a Newton-Raphson update is considered an error.
Definition: blackoilfoammodules.hh:282
static const Scalar foamRockDensity(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:319
static void serializeEntity(const Model &model, std::ostream &outstream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:291
static const TabulatedFunction & adsorbedFoamTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:335
static Phase transportPhase()
Definition: blackoilfoammodules.hh:360
static const TabulatedFunction & gasMobilityMultiplierTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:343
Declare the properties used by the infrastructure code of the finite volume discretizations.
Declare the properties used by the infrastructure code of the finite volume discretizations.
Phase
Phase indices for reservoir coupling, we currently only support black-oil phases (oil,...
Definition: ReservoirCoupling.hpp:156
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
Definition: blackoilfoamparams.hpp:60
Struct holding the parameters for the BlackoilFoamModule class.
Definition: blackoilfoamparams.hpp:44
Tabulated1DFunction< Scalar > TabulatedFunction
Definition: blackoilfoamparams.hpp:45