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> 56 template <
class TypeTag,
bool enableFoamV>
64 template <
class TypeTag>
79 using Toolbox = MathToolbox<Evaluation>;
81 using TabulatedFunction =
typename BlackOilFoamParams<Scalar>::TabulatedFunction;
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.");
119 static bool primaryVarApplies(
unsigned pvIdx)
121 return pvIdx == foamConcentrationIdx;
124 static std::string primaryVarName([[maybe_unused]]
unsigned pvIdx)
126 assert(primaryVarApplies(pvIdx));
127 return "foam_concentration";
130 static Scalar primaryVarWeight([[maybe_unused]]
unsigned pvIdx)
132 assert(primaryVarApplies(pvIdx));
135 return static_cast<Scalar
>(1.0);
138 static bool eqApplies(
unsigned eqIdx)
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>
160 OPM_HOST_DEVICE
static void addStorage(StorageType& storage,
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;
200 static void computeFlux(RateVector& flux,
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>
280 static void serializeEntity([[maybe_unused]]
const Model& model,
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>
290 static void deserializeEntity([[maybe_unused]] Model& model,
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];
304 static const Scalar foamRockDensity(
const ElementContext& elemCtx,
308 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
309 return params_.foamRockDensity_[satnumRegionIdx];
312 static bool foamAllowDesorption(
const ElementContext& elemCtx,
316 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
317 return params_.foamAllowDesorption_[satnumRegionIdx];
320 static const TabulatedFunction& adsorbedFoamTable(
const ElementContext& elemCtx,
324 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
325 return params_.adsorbedFoamTable_[satnumRegionIdx];
328 static const TabulatedFunction& gasMobilityMultiplierTable(
const ElementContext& elemCtx,
332 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
333 return params_.gasMobilityMultiplierTable_[pvtnumRegionIdx];
336 static const typename BlackOilFoamParams<Scalar>::FoamCoefficients&
337 foamCoefficients(
const ElementContext& elemCtx,
338 const unsigned scvIdx,
339 const unsigned timeIdx)
341 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
342 return params_.foamCoefficients_[satnumRegionIdx];
345 static Phase transportPhase()
346 {
return params_.transport_phase_; }
349 static BlackOilFoamParams<Scalar> params_;
352 template <
class TypeTag>
353 BlackOilFoamParams<typename BlackOilFoamModule<TypeTag, true>::Scalar>
354 BlackOilFoamModule<TypeTag, true>::params_;
363 template <
class TypeTag>
378 static constexpr
bool enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>();
380 static constexpr
unsigned 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.");
469 const Evaluation& foamConcentration()
const 470 {
return foamConcentration_; }
472 Scalar foamRockDensity()
const 473 {
return foamRockDensity_; }
475 const Evaluation& foamAdsorbed()
const 476 {
return foamAdsorbed_; }
479 Implementation& asImp_()
480 {
return *
static_cast<Implementation*
>(
this); }
482 Evaluation foamConcentration_;
483 Scalar foamRockDensity_;
484 Evaluation foamAdsorbed_;
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: blackoilfoammodules.hh:57
Contains the parameters to extend the black-oil model to include the effects of foam.
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.
Struct holding the parameters for the BlackoilFoamModule class.
Definition: blackoilfoamparams.hpp:43
static void setParams(BlackOilFoamParams< Scalar > &¶ms)
Set parameters.
Definition: blackoilfoammodules.hh:96
Declares the properties required by the black oil model.
Declare the properties used by the infrastructure code of the finite volume discretizations.
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
Contains the high level supplements required to extend the black oil model to include the effects of ...
Definition: blackoilfoammodules.hh:65
static void registerOutputModules(Model &, Simulator &)
Register all foam specific VTK and ECL output modules.
Definition: blackoilfoammodules.hh:110
Declare the properties used by the infrastructure code of the finite volume discretizations.
static void registerParameters()
Register all run-time parameters for the black-oil foam module.
Definition: blackoilfoammodules.hh:104
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
static Scalar computeUpdateError(const PrimaryVariables &, const EqVector &)
Return how much a Newton-Raphson update is considered an error.
Definition: blackoilfoammodules.hh:271