28#ifndef EWOMS_BLACK_OIL_FOAM_MODULE_HH
29#define EWOMS_BLACK_OIL_FOAM_MODULE_HH
33#include <dune/common/fvector.hh>
35#include <opm/common/OpmLog/OpmLog.hpp>
38#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
39#include <opm/input/eclipse/EclipseState/Tables/FoamadsTable.hpp>
40#include <opm/input/eclipse/EclipseState/Tables/FoammobTable.hpp>
57template <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>();
85 static constexpr unsigned numPhases = FluidSystem::numPhases;
87 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
94 static void initFromState(
const EclipseState& eclState)
98 if (enableFoam && !eclState.runspec().phases().active(Phase::FOAM)) {
99 throw std::runtime_error(
"Non-trivial foam treatment requested at compile time, but "
100 "the deck does not contain the FOAM keyword");
102 else if (!enableFoam && eclState.runspec().phases().active(Phase::FOAM)) {
103 throw std::runtime_error(
"Foam treatment disabled at compile time, but the deck "
104 "contains the FOAM keyword");
107 if (!eclState.runspec().phases().active(Phase::FOAM)) {
111 params_.transport_phase_ = eclState.getInitConfig().getFoamConfig().getTransportPhase();
113 if (eclState.getInitConfig().getFoamConfig().getMobilityModel() != FoamConfig::MobilityModel::TAB) {
114 throw std::runtime_error(
"In FOAMOPTS, only TAB is allowed for the gas mobility factor reduction model.");
117 const auto& tableManager = eclState.getTableManager();
118 const unsigned int numSatRegions = tableManager.getTabdims().getNumSatTables();
119 params_.setNumSatRegions(numSatRegions);
120 const unsigned int numPvtRegions = tableManager.getTabdims().getNumPVTTables();
121 params_.gasMobilityMultiplierTable_.resize(numPvtRegions);
124 const FoamConfig& foamConf = eclState.getInitConfig().getFoamConfig();
125 if (numSatRegions != foamConf.size()) {
126 throw std::runtime_error(
"Inconsistent sizes, number of saturation regions differ from the number of elements "
127 "in FoamConfig, which typically corresponds to the number of records in FOAMROCK.");
131 const auto& foamadsTables = tableManager.getFoamadsTables();
132 if (foamadsTables.empty()) {
133 throw std::runtime_error(
"FOAMADS must be specified in FOAM runs");
135 if (numSatRegions != foamadsTables.size()) {
136 throw std::runtime_error(
"Inconsistent sizes, number of saturation regions differ from the "
137 "number of FOAMADS tables.");
141 for (std::size_t satReg = 0; satReg < numSatRegions; ++satReg) {
142 const auto& rec = foamConf.getRecord(satReg);
144 params_.foamCoefficients_[satReg].fm_min = rec.minimumSurfactantConcentration();
145 params_.foamCoefficients_[satReg].fm_surf = rec.referenceSurfactantConcentration();
146 params_.foamCoefficients_[satReg].ep_surf = rec.exponent();
147 params_.foamRockDensity_[satReg] = rec.rockDensity();
148 params_.foamAllowDesorption_[satReg] = rec.allowDesorption();
149 const auto& foamadsTable = foamadsTables.template getTable<FoamadsTable>(satReg);
150 const auto& conc = foamadsTable.getFoamConcentrationColumn();
151 const auto& ads = foamadsTable.getAdsorbedFoamColumn();
152 params_.adsorbedFoamTable_[satReg].setXYContainers(conc, ads);
156 const auto& foammobTables = tableManager.getFoammobTables();
157 if (foammobTables.empty()) {
161 throw std::runtime_error(
"FOAMMOB must be specified in FOAM runs");
163 if (numPvtRegions != foammobTables.size()) {
164 throw std::runtime_error(
"Inconsistent sizes, number of PVT regions differ from the "
165 "number of FOAMMOB tables.");
169 for (std::size_t pvtReg = 0; pvtReg < numPvtRegions; ++pvtReg) {
170 const auto& foammobTable = foammobTables.template getTable<FoammobTable>(pvtReg);
171 const auto& conc = foammobTable.getFoamConcentrationColumn();
172 const auto& mobMult = foammobTable.getMobilityMultiplierColumn();
173 params_.gasMobilityMultiplierTable_[pvtReg].setXYContainers(conc, mobMult);
191 if constexpr (enableFoam) {
192 if (Parameters::Get<Parameters::EnableVtkOutput>()) {
193 OpmLog::warning(
"VTK output requested, currently unsupported by the foam module.");
201 if constexpr (enableFoam)
202 return pvIdx == foamConcentrationIdx;
210 return "foam_concentration";
218 return static_cast<Scalar
>(1.0);
223 if constexpr (enableFoam)
224 return eqIdx == contiFoamEqIdx;
230 static std::string
eqName([[maybe_unused]]
unsigned eqIdx)
237 static Scalar
eqWeight([[maybe_unused]]
unsigned eqIdx)
242 return static_cast<Scalar
>(1.0);
246 template <
class LhsEval>
247 static void addStorage(Dune::FieldVector<LhsEval, numEq>& storage,
248 const IntensiveQuantities& intQuants)
250 if constexpr (enableFoam) {
251 const auto& fs = intQuants.fluidState();
253 LhsEval surfaceVolume = Toolbox::template decay<LhsEval>(intQuants.porosity());
254 if (params_.transport_phase_ == Phase::WATER) {
255 surfaceVolume *= (Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx))
256 * Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx)));
257 }
else if (params_.transport_phase_ == Phase::GAS) {
258 surfaceVolume *= (Toolbox::template decay<LhsEval>(fs.saturation(gasPhaseIdx))
259 * Toolbox::template decay<LhsEval>(fs.invB(gasPhaseIdx)));
260 }
else if (params_.transport_phase_ == Phase::SOLVENT) {
261 if constexpr (enableSolvent) {
262 surfaceVolume *= (Toolbox::template decay<LhsEval>( intQuants.solventSaturation())
263 * Toolbox::template decay<LhsEval>(intQuants.solventInverseFormationVolumeFactor()));
266 throw std::runtime_error(
"Transport phase is GAS/WATER/SOLVENT");
270 surfaceVolume = max(surfaceVolume, 1e-10);
273 const LhsEval freeFoam = surfaceVolume
274 * Toolbox::template decay<LhsEval>(intQuants.foamConcentration());
277 const LhsEval adsorbedFoam =
278 Toolbox::template decay<LhsEval>(1.0 - intQuants.porosity())
279 * Toolbox::template decay<LhsEval>(intQuants.foamRockDensity())
280 * Toolbox::template decay<LhsEval>(intQuants.foamAdsorbed());
282 LhsEval accumulationFoam = freeFoam + adsorbedFoam;
283 storage[contiFoamEqIdx] += accumulationFoam;
288 [[maybe_unused]]
const ElementContext& elemCtx,
289 [[maybe_unused]]
unsigned scvfIdx,
290 [[maybe_unused]]
unsigned timeIdx)
293 if constexpr (enableFoam) {
294 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
295 const unsigned inIdx = extQuants.interiorIndex();
302 const unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
303 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
304 if (upIdx == inIdx) {
305 flux[contiFoamEqIdx] =
306 extQuants.volumeFlux(waterPhaseIdx)
307 *up.fluidState().invB(waterPhaseIdx)
308 *up.foamConcentration();
310 flux[contiFoamEqIdx] =
311 extQuants.volumeFlux(waterPhaseIdx)
312 *decay<Scalar>(up.fluidState().invB(waterPhaseIdx))
313 *decay<Scalar>(up.foamConcentration());
318 const unsigned upIdx = extQuants.upstreamIndex(gasPhaseIdx);
319 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
320 if (upIdx == inIdx) {
321 flux[contiFoamEqIdx] =
322 extQuants.volumeFlux(gasPhaseIdx)
323 *up.fluidState().invB(gasPhaseIdx)
324 *up.foamConcentration();
326 flux[contiFoamEqIdx] =
327 extQuants.volumeFlux(gasPhaseIdx)
328 *decay<Scalar>(up.fluidState().invB(gasPhaseIdx))
329 *decay<Scalar>(up.foamConcentration());
333 case Phase::SOLVENT: {
334 if constexpr (enableSolvent) {
335 const unsigned upIdx = extQuants.solventUpstreamIndex();
336 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
337 if (upIdx == inIdx) {
338 flux[contiFoamEqIdx] =
339 extQuants.solventVolumeFlux()
340 *up.solventInverseFormationVolumeFactor()
341 *up.foamConcentration();
343 flux[contiFoamEqIdx] =
344 extQuants.solventVolumeFlux()
345 *decay<Scalar>(up.solventInverseFormationVolumeFactor())
346 *decay<Scalar>(up.foamConcentration());
349 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
354 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
368 return static_cast<Scalar
>(0.0);
371 template <
class DofEntity>
373 [[maybe_unused]] std::ostream& outstream,
374 [[maybe_unused]]
const DofEntity& dof)
376 if constexpr (enableFoam) {
377 unsigned dofIdx = model.dofMapper().index(dof);
378 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
379 outstream << priVars[foamConcentrationIdx];
383 template <
class DofEntity>
385 [[maybe_unused]] std::istream& instream,
386 [[maybe_unused]]
const DofEntity& dof)
388 if constexpr (enableFoam) {
389 unsigned dofIdx = model.dofMapper().index(dof);
390 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
391 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
393 instream >> priVars0[foamConcentrationIdx];
396 priVars1[foamConcentrationIdx] = priVars0[foamConcentrationIdx];
404 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
405 return params_.foamRockDensity_[satnumRegionIdx];
412 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
413 return params_.foamAllowDesorption_[satnumRegionIdx];
420 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
421 return params_.adsorbedFoamTable_[satnumRegionIdx];
428 unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
429 return params_.gasMobilityMultiplierTable_[pvtnumRegionIdx];
434 const unsigned scvIdx,
435 const unsigned timeIdx)
437 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
438 return params_.foamCoefficients_[satnumRegionIdx];
442 return params_.transport_phase_;
449template <
class TypeTag,
bool enableFoam>
450BlackOilFoamParams<typename BlackOilFoamModule<TypeTag, enableFoam>::Scalar>
451BlackOilFoamModule<TypeTag, enableFoam>::params_;
460template <class TypeTag, bool enableFoam = getPropValue<TypeTag, Properties::EnableFoam>()>
475 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
476 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
478 static constexpr int foamConcentrationIdx = Indices::foamConcentrationIdx;
479 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
480 static constexpr unsigned oilPhaseIdx = FluidSystem::oilPhaseIdx;
481 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
494 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
496 const auto& fs =
asImp_().fluidState_;
499 Evaluation mobilityReductionFactor = 1.0;
506 const Scalar fm_mob = foamCoefficients.fm_mob;
508 const Scalar fm_surf = foamCoefficients.fm_surf;
509 const Scalar ep_surf = foamCoefficients.ep_surf;
511 const Scalar fm_oil = foamCoefficients.fm_oil;
512 const Scalar fl_oil = foamCoefficients.fl_oil;
513 const Scalar ep_oil = foamCoefficients.ep_oil;
515 const Scalar fm_dry = foamCoefficients.fm_dry;
516 const Scalar ep_dry = foamCoefficients.ep_dry;
518 const Scalar fm_cap = foamCoefficients.fm_cap;
519 const Scalar ep_cap = foamCoefficients.ep_cap;
522 const Evaluation Ca = 1e10;
523 const Evaluation S_o = fs.saturation(oilPhaseIdx);
524 const Evaluation S_w = fs.saturation(waterPhaseIdx);
526 Evaluation F1 = pow(C_surf/fm_surf, ep_surf);
527 Evaluation F2 = pow((fm_oil-S_o)/(fm_oil-fl_oil), ep_oil);
528 Evaluation F3 = pow(fm_cap/Ca, ep_cap);
529 Evaluation F7 = 0.5 + atan(ep_dry*(S_w-fm_dry))/M_PI;
531 mobilityReductionFactor = 1./(1. + fm_mob*F1*F2*F3*F7);
543 asImp_().mobility_[waterPhaseIdx] *= mobilityReductionFactor;
547 asImp_().mobility_[gasPhaseIdx] *= mobilityReductionFactor;
550 case Phase::SOLVENT: {
551 if constexpr (enableSolvent) {
552 asImp_().solventMobility_ *= mobilityReductionFactor;
554 throw std::runtime_error(
"Foam transport phase is SOLVENT but SOLVENT is not activated.");
559 throw std::runtime_error(
"Foam transport phase must be GAS/WATER/SOLVENT.");
568 throw std::runtime_error(
"Foam module does not support the 'no desorption' option.");
583 {
return *
static_cast<Implementation*
>(
this); }
590template <
class TypeTag>
605 {
throw std::runtime_error(
"foamConcentration() called but foam is disabled"); }
608 {
throw std::runtime_error(
"foamRockDensity() called but foam is disabled"); }
611 {
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:607
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:604
void foamPropertiesUpdate_(const ElementContext &, unsigned, unsigned)
Definition: blackoilfoammodules.hh:598
Scalar foamAdsorbed() const
Definition: blackoilfoammodules.hh:610
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilfoammodules.hh:462
const Evaluation & foamConcentration() const
Definition: blackoilfoammodules.hh:572
Implementation & asImp_()
Definition: blackoilfoammodules.hh:582
Scalar foamRockDensity_
Definition: blackoilfoammodules.hh:586
const Evaluation & foamAdsorbed() const
Definition: blackoilfoammodules.hh:578
Evaluation foamAdsorbed_
Definition: blackoilfoammodules.hh:587
Evaluation foamConcentration_
Definition: blackoilfoammodules.hh:585
Scalar foamRockDensity() const
Definition: blackoilfoammodules.hh:575
void foamPropertiesUpdate_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the intensive properties needed to handle polymers from the primary variables.
Definition: blackoilfoammodules.hh:490
Contains the high level supplements required to extend the black oil model to include the effects of ...
Definition: blackoilfoammodules.hh:59
static bool eqApplies(unsigned eqIdx)
Definition: blackoilfoammodules.hh:221
static void registerOutputModules(Model &, Simulator &)
Register all foam specific VTK and ECL output modules.
Definition: blackoilfoammodules.hh:188
static void registerParameters()
Register all run-time parameters for the black-oil foam module.
Definition: blackoilfoammodules.hh:181
static std::string primaryVarName(unsigned pvIdx)
Definition: blackoilfoammodules.hh:207
static Scalar eqWeight(unsigned eqIdx)
Definition: blackoilfoammodules.hh:237
static void deserializeEntity(Model &model, std::istream &instream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:384
static std::string eqName(unsigned eqIdx)
Definition: blackoilfoammodules.hh:230
static bool primaryVarApplies(unsigned pvIdx)
Definition: blackoilfoammodules.hh:199
static void addStorage(Dune::FieldVector< LhsEval, numEq > &storage, const IntensiveQuantities &intQuants)
Definition: blackoilfoammodules.hh:247
static bool foamAllowDesorption(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:408
static Scalar primaryVarWeight(unsigned pvIdx)
Definition: blackoilfoammodules.hh:213
static const BlackOilFoamParams< Scalar >::FoamCoefficients & foamCoefficients(const ElementContext &elemCtx, const unsigned scvIdx, const unsigned timeIdx)
Definition: blackoilfoammodules.hh:433
static void computeFlux(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:287
static Scalar computeUpdateError(const PrimaryVariables &, const EqVector &)
Return how much a Newton-Raphson update is considered an error.
Definition: blackoilfoammodules.hh:363
static const Scalar foamRockDensity(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:400
static void serializeEntity(const Model &model, std::ostream &outstream, const DofEntity &dof)
Definition: blackoilfoammodules.hh:372
static const TabulatedFunction & adsorbedFoamTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:416
static Phase transportPhase()
Definition: blackoilfoammodules.hh:441
static const TabulatedFunction & gasMobilityMultiplierTable(const ElementContext &elemCtx, unsigned scvIdx, unsigned timeIdx)
Definition: blackoilfoammodules.hh:424
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.
Definition: blackoilboundaryratevector.hh:37
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:235
Definition: blackoilfoamparams.hh:59
Struct holding the parameters for the BlackoilFoamModule class.
Definition: blackoilfoamparams.hh:40
Tabulated1DFunction< Scalar > TabulatedFunction
Definition: blackoilfoamparams.hh:41