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/OpmLog/OpmLog.hpp>
34#include <opm/common/utility/gpuDecorators.hpp>
36#include <opm/input/eclipse/EclipseState/Phase.hpp>
58template <class TypeTag, bool enableFoamV = getPropValue<TypeTag, Properties::EnableFoam>()>
73 using Toolbox = MathToolbox<Evaluation>;
77 static constexpr unsigned foamConcentrationIdx = Indices::foamConcentrationIdx;
78 static constexpr unsigned contiFoamEqIdx = Indices::contiFoamEqIdx;
79 static constexpr unsigned gasPhaseIdx = FluidSystem::gasPhaseIdx;
80 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
82 static constexpr unsigned enableFoam = enableFoamV;
84 static constexpr unsigned numEq = getPropValue<TypeTag, Properties::NumEq>();
86 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
107 if constexpr (enableFoam) {
108 if (Parameters::Get<Parameters::EnableVtkOutput>()) {
109 OpmLog::warning(
"VTK output requested, currently unsupported by the foam module.");
117 if constexpr (enableFoam) {
118 return pvIdx == foamConcentrationIdx;
128 return "foam_concentration";
136 return static_cast<Scalar
>(1.0);
141 if constexpr (enableFoam) {
142 return eqIdx == contiFoamEqIdx;
149 static std::string
eqName([[maybe_unused]]
unsigned eqIdx)
156 static Scalar
eqWeight([[maybe_unused]]
unsigned eqIdx)
161 return static_cast<Scalar
>(1.0);
165 template <
class StorageType>
167 const IntensiveQuantities& intQuants)
169 using LhsEval =
typename StorageType::value_type;
171 if constexpr (enableFoam) {
172 const auto& fs = intQuants.fluidState();
174 LhsEval surfaceVolume = Toolbox::template decay<LhsEval>(intQuants.porosity());
175 if (params_.transport_phase_ == Phase::WATER) {
176 surfaceVolume *= Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx)) *
177 Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx));
178 }
else if (params_.transport_phase_ == Phase::GAS) {
179 surfaceVolume *= Toolbox::template decay<LhsEval>(fs.saturation(gasPhaseIdx)) *
180 Toolbox::template decay<LhsEval>(fs.invB(gasPhaseIdx));
181 }
else if (params_.transport_phase_ == Phase::SOLVENT) {
182 if constexpr (enableSolvent) {
183 surfaceVolume *= Toolbox::template decay<LhsEval>( intQuants.solventSaturation()) *
184 Toolbox::template decay<LhsEval>(intQuants.solventInverseFormationVolumeFactor());
187 throw std::runtime_error(
"Transport phase is GAS/WATER/SOLVENT");
191 surfaceVolume = max(surfaceVolume, 1e-10);
194 const LhsEval freeFoam = surfaceVolume *
195 Toolbox::template decay<LhsEval>(intQuants.foamConcentration());
198 const LhsEval adsorbedFoam =
199 Toolbox::template decay<LhsEval>(1.0 - intQuants.porosity()) *
200 Toolbox::template decay<LhsEval>(intQuants.foamRockDensity()) *
201 Toolbox::template decay<LhsEval>(intQuants.foamAdsorbed());
203 const LhsEval accumulationFoam = freeFoam + adsorbedFoam;
204 storage[contiFoamEqIdx] += accumulationFoam;
209 [[maybe_unused]]
const ElementContext& elemCtx,
210 [[maybe_unused]]
unsigned scvfIdx,
211 [[maybe_unused]]
unsigned timeIdx)
213 if constexpr (enableFoam) {
214 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
215 const unsigned inIdx = extQuants.interiorIndex();
222 const unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
223 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
224 if (upIdx == inIdx) {
225 flux[contiFoamEqIdx] =
226 extQuants.volumeFlux(waterPhaseIdx) *
227 up.fluidState().invB(waterPhaseIdx) *
228 up.foamConcentration();
230 flux[contiFoamEqIdx] =
231 extQuants.volumeFlux(waterPhaseIdx) *
232 decay<Scalar>(up.fluidState().invB(waterPhaseIdx)) *
233 decay<Scalar>(up.foamConcentration());
238 const unsigned upIdx = extQuants.upstreamIndex(gasPhaseIdx);
239 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
240 if (upIdx == inIdx) {
241 flux[contiFoamEqIdx] =
242 extQuants.volumeFlux(gasPhaseIdx) *
243 up.fluidState().invB(gasPhaseIdx) *
244 up.foamConcentration();
246 flux[contiFoamEqIdx] =
247 extQuants.volumeFlux(gasPhaseIdx) *
248 decay<Scalar>(up.fluidState().invB(gasPhaseIdx)) *
249 decay<Scalar>(up.foamConcentration());
254 if constexpr (enableSolvent) {
255 const unsigned upIdx = extQuants.solventUpstreamIndex();
256 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
257 if (upIdx == inIdx) {
258 flux[contiFoamEqIdx] =
259 extQuants.solventVolumeFlux() *
260 up.solventInverseFormationVolumeFactor() *
261 up.foamConcentration();
263 flux[contiFoamEqIdx] =
264 extQuants.solventVolumeFlux() *
265 decay<Scalar>(up.solventInverseFormationVolumeFactor()) *
266 decay<Scalar>(up.foamConcentration());
269 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
273 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
286 return static_cast<Scalar
>(0.0);
289 template <
class DofEntity>
291 [[maybe_unused]] std::ostream& outstream,
292 [[maybe_unused]]
const DofEntity& dof)
294 if constexpr (enableFoam) {
295 const unsigned dofIdx = model.dofMapper().index(dof);
296 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
297 outstream << priVars[foamConcentrationIdx];
301 template <
class DofEntity>
303 [[maybe_unused]] std::istream& instream,
304 [[maybe_unused]]
const DofEntity& dof)
306 if constexpr (enableFoam) {
307 const unsigned dofIdx = model.dofMapper().index(dof);
308 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
309 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
311 instream >> priVars0[foamConcentrationIdx];
314 priVars1[foamConcentrationIdx] = priVars0[foamConcentrationIdx];
322 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
323 return params_.foamRockDensity_[satnumRegionIdx];
330 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
331 return params_.foamAllowDesorption_[satnumRegionIdx];
338 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
339 return params_.adsorbedFoamTable_[satnumRegionIdx];
346 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
347 return params_.gasMobilityMultiplierTable_[pvtnumRegionIdx];
352 const unsigned scvIdx,
353 const unsigned timeIdx)
355 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
356 return params_.foamCoefficients_[satnumRegionIdx];
360 {
return params_.transport_phase_; }
366template <
class TypeTag,
bool enableFoam>
367BlackOilFoamParams<typename BlackOilFoamModule<TypeTag, enableFoam>::Scalar>
368BlackOilFoamModule<TypeTag, enableFoam>::params_;
370template <
class TypeTag,
bool enableFoam>
380template <
class TypeTag>
395 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
397 static constexpr int foamConcentrationIdx = Indices::foamConcentrationIdx;
398 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
399 static constexpr unsigned oilPhaseIdx = FluidSystem::oilPhaseIdx;
400 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
412 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
413 foamConcentration_ = priVars.makeEvaluation(foamConcentrationIdx, timeIdx);
414 const auto& fs = asImp_().fluidState_;
417 Evaluation mobilityReductionFactor = 1.0;
418 if constexpr (
false) {
422 const auto& foamCoefficients = FoamModule::foamCoefficients(elemCtx, dofIdx, timeIdx);
424 const Scalar fm_mob = foamCoefficients.fm_mob;
426 const Scalar fm_surf = foamCoefficients.fm_surf;
427 const Scalar ep_surf = foamCoefficients.ep_surf;
429 const Scalar fm_oil = foamCoefficients.fm_oil;
430 const Scalar fl_oil = foamCoefficients.fl_oil;
431 const Scalar ep_oil = foamCoefficients.ep_oil;
433 const Scalar fm_dry = foamCoefficients.fm_dry;
434 const Scalar ep_dry = foamCoefficients.ep_dry;
436 const Scalar fm_cap = foamCoefficients.fm_cap;
437 const Scalar ep_cap = foamCoefficients.ep_cap;
439 const Evaluation C_surf = foamConcentration_;
440 const Evaluation Ca = 1e10;
441 const Evaluation S_o = fs.saturation(oilPhaseIdx);
442 const Evaluation S_w = fs.saturation(waterPhaseIdx);
444 const Evaluation F1 = pow(C_surf / fm_surf, ep_surf);
445 const Evaluation F2 = pow((fm_oil - S_o) / (fm_oil - fl_oil), ep_oil);
446 const Evaluation F3 = pow(fm_cap / Ca, ep_cap);
447 const Evaluation F7 = 0.5 + atan(ep_dry * (S_w - fm_dry)) / std::numbers::pi_v<Scalar>;
449 mobilityReductionFactor = 1. / (1. + fm_mob * F1 * F2 * F3 * F7);
454 const auto& gasMobilityMultiplier = FoamModule::gasMobilityMultiplierTable(elemCtx, dofIdx, timeIdx);
455 mobilityReductionFactor = gasMobilityMultiplier.eval(foamConcentration_,
true);
459 switch (FoamModule::transportPhase()) {
461 asImp_().mobility_[waterPhaseIdx] *= mobilityReductionFactor;
464 asImp_().mobility_[gasPhaseIdx] *= mobilityReductionFactor;
467 if constexpr (enableSolvent) {
468 asImp_().solventMobility_ *= mobilityReductionFactor;
470 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
474 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
477 foamRockDensity_ = FoamModule::foamRockDensity(elemCtx, dofIdx, timeIdx);
479 const auto& adsorbedFoamTable = FoamModule::adsorbedFoamTable(elemCtx, dofIdx, timeIdx);
480 foamAdsorbed_ = adsorbedFoamTable.eval(foamConcentration_,
true);
481 if (!FoamModule::foamAllowDesorption(elemCtx, dofIdx, timeIdx)) {
482 throw std::runtime_error(
"Foam module does not support the 'no desorption' option.");
487 {
return foamConcentration_; }
490 {
return foamRockDensity_; }
493 {
return foamAdsorbed_; }
497 {
return *
static_cast<Implementation*
>(
this); }
504template <
class TypeTag>
518 {
throw std::runtime_error(
"foamConcentration() called but foam is disabled"); }
521 {
throw std::runtime_error(
"foamRockDensity() called but foam is disabled"); }
524 {
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:520
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:517
void foamPropertiesUpdate_(const ElementContext &, unsigned, unsigned)
Definition: blackoilfoammodules.hh:512
Scalar foamAdsorbed() const
Definition: blackoilfoammodules.hh:523
Evaluation foamConcentration_
Definition: blackoilfoammodules.hh:499
void foamPropertiesUpdate_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the intensive properties needed to handle polymers from the primary variables.
Definition: blackoilfoammodules.hh:408
const Evaluation & foamAdsorbed() const
Definition: blackoilfoammodules.hh:492
Scalar foamRockDensity() const
Definition: blackoilfoammodules.hh:489
Evaluation foamAdsorbed_
Definition: blackoilfoammodules.hh:501
Implementation & asImp_()
Definition: blackoilfoammodules.hh:496
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:486
Scalar foamRockDensity_
Definition: blackoilfoammodules.hh:500
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilfoammodules.hh:371
Contains the high level supplements required to extend the black oil model to include the effects of ...
Definition: blackoilfoammodules.hh:60
static bool eqApplies(unsigned eqIdx)
Definition: blackoilfoammodules.hh:139
static void registerOutputModules(Model &, Simulator &)
Register all foam specific VTK and ECL output modules.
Definition: blackoilfoammodules.hh:104
static void registerParameters()
Register all run-time parameters for the black-oil foam module.
Definition: blackoilfoammodules.hh:98
static std::string primaryVarName(unsigned pvIdx)
Definition: blackoilfoammodules.hh:125
static Scalar eqWeight(unsigned eqIdx)
Definition: blackoilfoammodules.hh:156
static void deserializeEntity(Model &model, std::istream &instream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:302
static void setParams(BlackOilFoamParams< Scalar > &¶ms)
Set parameters.
Definition: blackoilfoammodules.hh:90
static std::string eqName(unsigned eqIdx)
Definition: blackoilfoammodules.hh:149
static bool primaryVarApplies(unsigned pvIdx)
Definition: blackoilfoammodules.hh:115
static bool foamAllowDesorption(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:326
static Scalar primaryVarWeight(unsigned pvIdx)
Definition: blackoilfoammodules.hh:131
static OPM_HOST_DEVICE void addStorage(StorageType &storage, const IntensiveQuantities &intQuants)
Definition: blackoilfoammodules.hh:166
static const BlackOilFoamParams< Scalar >::FoamCoefficients & foamCoefficients(const ElementContext &elemCtx, const unsigned scvIdx, const unsigned timeIdx)
Definition: blackoilfoammodules.hh:351
static void computeFlux(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:208
static Scalar computeUpdateError(const PrimaryVariables &, const EqVector &)
Return how much a Newton-Raphson update is considered an error.
Definition: blackoilfoammodules.hh:281
static const Scalar foamRockDensity(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:318
static void serializeEntity(const Model &model, std::ostream &outstream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:290
static const TabulatedFunction & adsorbedFoamTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:334
static Phase transportPhase()
Definition: blackoilfoammodules.hh:359
static const TabulatedFunction & gasMobilityMultiplierTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:342
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