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>
56template <
class TypeTag,
bool enableFoamV>
64template <
class TypeTag>
79 using Toolbox = MathToolbox<Evaluation>;
83 static constexpr unsigned foamConcentrationIdx = Indices::foamConcentrationIdx;
84 static constexpr unsigned contiFoamEqIdx = Indices::contiFoamEqIdx;
85 static constexpr unsigned gasPhaseIdx = FluidSystem::gasPhaseIdx;
86 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
88 static constexpr bool enableFoam =
true;
90 static constexpr unsigned numEq = getPropValue<TypeTag, Properties::NumEq>();
92 static constexpr bool enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>();
113 if (Parameters::Get<Parameters::EnableVtkOutput>()) {
114 OpmLog::warning(
"VTK output requested, currently unsupported by the foam module.");
121 return pvIdx == foamConcentrationIdx;
126 assert(primaryVarApplies(pvIdx));
127 return "foam_concentration";
132 assert(primaryVarApplies(pvIdx));
135 return static_cast<Scalar
>(1.0);
140 return eqIdx == contiFoamEqIdx;
143 static std::string
eqName([[maybe_unused]]
unsigned eqIdx)
145 assert(eqApplies(eqIdx));
150 static Scalar
eqWeight([[maybe_unused]]
unsigned eqIdx)
152 assert(eqApplies(eqIdx));
155 return static_cast<Scalar
>(1.0);
159 template <
class StorageType>
161 const IntensiveQuantities& intQuants)
163 using LhsEval =
typename StorageType::value_type;
165 const auto& fs = intQuants.fluidState();
167 LhsEval surfaceVolume = Toolbox::template decay<LhsEval>(intQuants.porosity());
168 if (params_.transport_phase_ == Phase::WATER) {
169 surfaceVolume *= Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx)) *
170 Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx));
171 }
else if (params_.transport_phase_ == Phase::GAS) {
172 surfaceVolume *= Toolbox::template decay<LhsEval>(fs.saturation(gasPhaseIdx)) *
173 Toolbox::template decay<LhsEval>(fs.invB(gasPhaseIdx));
174 }
else if (params_.transport_phase_ == Phase::SOLVENT) {
175 if constexpr (enableSolvent) {
176 surfaceVolume *= Toolbox::template decay<LhsEval>( intQuants.solventSaturation()) *
177 Toolbox::template decay<LhsEval>(intQuants.solventInverseFormationVolumeFactor());
180 OPM_THROW(std::runtime_error,
"Transport phase is GAS/WATER/SOLVENT");
184 surfaceVolume = max(surfaceVolume, 1e-10);
187 const LhsEval freeFoam = surfaceVolume *
188 Toolbox::template decay<LhsEval>(intQuants.foamConcentration());
191 const LhsEval adsorbedFoam =
192 Toolbox::template decay<LhsEval>(1.0 - intQuants.porosity()) *
193 Toolbox::template decay<LhsEval>(intQuants.foamRockDensity()) *
194 Toolbox::template decay<LhsEval>(intQuants.foamAdsorbed());
196 const LhsEval accumulationFoam = freeFoam + adsorbedFoam;
197 storage[contiFoamEqIdx] += accumulationFoam;
201 const ElementContext& elemCtx,
205 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
206 const unsigned inIdx = extQuants.interiorIndex();
211 switch (transportPhase()) {
213 const unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
214 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
215 if (upIdx == inIdx) {
216 flux[contiFoamEqIdx] =
217 extQuants.volumeFlux(waterPhaseIdx) *
218 up.fluidState().invB(waterPhaseIdx) *
219 up.foamConcentration();
221 flux[contiFoamEqIdx] =
222 extQuants.volumeFlux(waterPhaseIdx) *
223 decay<Scalar>(up.fluidState().invB(waterPhaseIdx)) *
224 decay<Scalar>(up.foamConcentration());
229 const unsigned upIdx = extQuants.upstreamIndex(gasPhaseIdx);
230 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
231 if (upIdx == inIdx) {
232 flux[contiFoamEqIdx] =
233 extQuants.volumeFlux(gasPhaseIdx) *
234 up.fluidState().invB(gasPhaseIdx) *
235 up.foamConcentration();
237 flux[contiFoamEqIdx] =
238 extQuants.volumeFlux(gasPhaseIdx) *
239 decay<Scalar>(up.fluidState().invB(gasPhaseIdx)) *
240 decay<Scalar>(up.foamConcentration());
245 if constexpr (enableSolvent) {
246 const unsigned upIdx = extQuants.solventUpstreamIndex();
247 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
248 if (upIdx == inIdx) {
249 flux[contiFoamEqIdx] =
250 extQuants.solventVolumeFlux() *
251 up.solventInverseFormationVolumeFactor() *
252 up.foamConcentration();
254 flux[contiFoamEqIdx] =
255 extQuants.solventVolumeFlux() *
256 decay<Scalar>(up.solventInverseFormationVolumeFactor()) *
257 decay<Scalar>(up.foamConcentration());
260 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
264 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
276 return static_cast<Scalar
>(0.0);
279 template <
class DofEntity>
281 [[maybe_unused]] std::ostream& outstream,
282 [[maybe_unused]]
const DofEntity& dof)
284 const unsigned dofIdx = model.dofMapper().index(dof);
285 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
286 outstream << priVars[foamConcentrationIdx];
289 template <
class DofEntity>
291 [[maybe_unused]] std::istream& instream,
292 [[maybe_unused]]
const DofEntity& dof)
294 const unsigned dofIdx = model.dofMapper().index(dof);
295 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
296 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
298 instream >> priVars0[foamConcentrationIdx];
301 priVars1[foamConcentrationIdx] = priVars0[foamConcentrationIdx];
308 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
309 return params_.foamRockDensity_[satnumRegionIdx];
316 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
317 return params_.foamAllowDesorption_[satnumRegionIdx];
324 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
325 return params_.adsorbedFoamTable_[satnumRegionIdx];
332 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
333 return params_.gasMobilityMultiplierTable_[pvtnumRegionIdx];
338 const unsigned scvIdx,
339 const unsigned timeIdx)
341 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
342 return params_.foamCoefficients_[satnumRegionIdx];
346 {
return params_.transport_phase_; }
352template <
class TypeTag>
353BlackOilFoamParams<typename BlackOilFoamModule<TypeTag, true>::Scalar>
354BlackOilFoamModule<TypeTag, true>::params_;
363template <
class TypeTag>
378 static constexpr bool enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>();
380 static constexpr int foamConcentrationIdx = Indices::foamConcentrationIdx;
381 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
382 static constexpr unsigned oilPhaseIdx = FluidSystem::oilPhaseIdx;
383 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
395 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
396 foamConcentration_ = priVars.makeEvaluation(foamConcentrationIdx, timeIdx);
397 const auto& fs = asImp_().fluidState_;
400 Evaluation mobilityReductionFactor = 1.0;
401 if constexpr (
false) {
405 const auto& foamCoefficients = FoamModule::foamCoefficients(elemCtx, dofIdx, timeIdx);
407 const Scalar fm_mob = foamCoefficients.fm_mob;
409 const Scalar fm_surf = foamCoefficients.fm_surf;
410 const Scalar ep_surf = foamCoefficients.ep_surf;
412 const Scalar fm_oil = foamCoefficients.fm_oil;
413 const Scalar fl_oil = foamCoefficients.fl_oil;
414 const Scalar ep_oil = foamCoefficients.ep_oil;
416 const Scalar fm_dry = foamCoefficients.fm_dry;
417 const Scalar ep_dry = foamCoefficients.ep_dry;
419 const Scalar fm_cap = foamCoefficients.fm_cap;
420 const Scalar ep_cap = foamCoefficients.ep_cap;
422 const Evaluation C_surf = foamConcentration_;
423 const Evaluation Ca = 1e10;
424 const Evaluation S_o = fs.saturation(oilPhaseIdx);
425 const Evaluation S_w = fs.saturation(waterPhaseIdx);
427 const Evaluation F1 = pow(C_surf / fm_surf, ep_surf);
428 const Evaluation F2 = pow((fm_oil - S_o) / (fm_oil - fl_oil), ep_oil);
429 const Evaluation F3 = pow(fm_cap / Ca, ep_cap);
430 const Evaluation F7 = 0.5 + atan(ep_dry * (S_w - fm_dry)) / std::numbers::pi_v<Scalar>;
432 mobilityReductionFactor = 1. / (1. + fm_mob * F1 * F2 * F3 * F7);
437 const auto& gasMobilityMultiplier = FoamModule::gasMobilityMultiplierTable(elemCtx, dofIdx, timeIdx);
438 mobilityReductionFactor = gasMobilityMultiplier.eval(foamConcentration_,
true);
442 switch (FoamModule::transportPhase()) {
444 asImp_().mobility_[waterPhaseIdx] *= mobilityReductionFactor;
447 asImp_().mobility_[gasPhaseIdx] *= mobilityReductionFactor;
450 if constexpr (enableSolvent) {
451 asImp_().solventMobility_ *= mobilityReductionFactor;
453 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
457 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
460 foamRockDensity_ = FoamModule::foamRockDensity(elemCtx, dofIdx, timeIdx);
462 const auto& adsorbedFoamTable = FoamModule::adsorbedFoamTable(elemCtx, dofIdx, timeIdx);
463 foamAdsorbed_ = adsorbedFoamTable.eval(foamConcentration_,
true);
464 if (!FoamModule::foamAllowDesorption(elemCtx, dofIdx, timeIdx)) {
465 throw std::runtime_error(
"Foam module does not support the 'no desorption' option.");
470 {
return foamConcentration_; }
473 {
return foamRockDensity_; }
476 {
return foamAdsorbed_; }
480 {
return *
static_cast<Implementation*
>(
this); }
Contains the parameters to extend the black-oil model to include the effects of foam.
Contains classes extending the black-oil model. \detail This file holds dummy definitions,...
Declares the properties required by the black oil model.
Evaluation foamConcentration_
Definition: blackoilfoammodules.hh:482
void foamPropertiesUpdate_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the intensive properties needed to handle polymers from the primary variables.
Definition: blackoilfoammodules.hh:391
const Evaluation & foamAdsorbed() const
Definition: blackoilfoammodules.hh:475
Scalar foamRockDensity() const
Definition: blackoilfoammodules.hh:472
Evaluation foamAdsorbed_
Definition: blackoilfoammodules.hh:484
Implementation & asImp_()
Definition: blackoilfoammodules.hh:479
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:469
Scalar foamRockDensity_
Definition: blackoilfoammodules.hh:483
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Contains the high level supplements required to extend the black oil model to include the effects of ...
Definition: blackoilfoammodules.hh:66
static const TabulatedFunction & adsorbedFoamTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:320
static Scalar primaryVarWeight(unsigned pvIdx)
Definition: blackoilfoammodules.hh:130
static void deserializeEntity(Model &model, std::istream &instream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:290
static const TabulatedFunction & gasMobilityMultiplierTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:328
static void registerParameters()
Register all run-time parameters for the black-oil foam module.
Definition: blackoilfoammodules.hh:104
static Phase transportPhase()
Definition: blackoilfoammodules.hh:345
static void serializeEntity(const Model &model, std::ostream &outstream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:280
static bool primaryVarApplies(unsigned pvIdx)
Definition: blackoilfoammodules.hh:119
static void computeFlux(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:200
static bool eqApplies(unsigned eqIdx)
Definition: blackoilfoammodules.hh:138
static Scalar eqWeight(unsigned eqIdx)
Definition: blackoilfoammodules.hh:150
static Scalar computeUpdateError(const PrimaryVariables &, const EqVector &)
Return how much a Newton-Raphson update is considered an error.
Definition: blackoilfoammodules.hh:271
static void registerOutputModules(Model &, Simulator &)
Register all foam specific VTK and ECL output modules.
Definition: blackoilfoammodules.hh:110
static std::string primaryVarName(unsigned pvIdx)
Definition: blackoilfoammodules.hh:124
static OPM_HOST_DEVICE void addStorage(StorageType &storage, const IntensiveQuantities &intQuants)
Definition: blackoilfoammodules.hh:160
static std::string eqName(unsigned eqIdx)
Definition: blackoilfoammodules.hh:143
static const Scalar foamRockDensity(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:304
static void setParams(BlackOilFoamParams< Scalar > &¶ms)
Set parameters.
Definition: blackoilfoammodules.hh:96
static const BlackOilFoamParams< Scalar >::FoamCoefficients & foamCoefficients(const ElementContext &elemCtx, const unsigned scvIdx, const unsigned timeIdx)
Definition: blackoilfoammodules.hh:337
static bool foamAllowDesorption(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:312
Definition: blackoilfoammodules.hh:57
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:159
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