31 #ifndef OPM_NEWTRAN_FLUX_MODULE_HPP 32 #define OPM_NEWTRAN_FLUX_MODULE_HPP 34 #include <dune/common/fvector.hh> 35 #include <dune/common/fmatrix.hh> 37 #include <opm/common/OpmLog/OpmLog.hpp> 39 #include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp> 41 #include <opm/material/common/MathToolbox.hpp> 42 #include <opm/material/common/Valgrind.hpp> 47 #include <opm/models/blackoil/blackoilmoduleparams.hh> 50 #include <opm/common/utility/gpuDecorators.hpp> 56 template <
class TypeTag>
59 template <
class TypeTag>
62 template <
class TypeTag>
69 template <
class TypeTag>
88 template <
class TypeTag>
89 class NewTranBaseProblem
96 template <
class TypeTag>
97 class NewTranIntensiveQuantities
99 using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
101 void update_(
const ElementContext&,
unsigned,
unsigned)
109 template <
class TypeTag>
110 class NewTranExtensiveQuantities
112 using Implementation = GetPropType<TypeTag, Properties::ExtensiveQuantities>;
114 using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
115 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
116 using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
117 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
118 using Evaluation = GetPropType<TypeTag, Properties::Evaluation>;
119 using GridView = GetPropType<TypeTag, Properties::GridView>;
120 using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
122 enum { dimWorld = GridView::dimensionworld };
123 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
124 enum { numPhases = FluidSystem::numPhases };
125 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
126 enum { enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>() };
127 enum { enableEnergy = getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal };
129 static constexpr
bool enableConvectiveMixing = getPropValue<TypeTag, Properties::EnableConvectiveMixing>();
132 using Toolbox = MathToolbox<Evaluation>;
133 using DimVector = Dune::FieldVector<Scalar, dimWorld>;
134 using EvalDimVector = Dune::FieldVector<Evaluation, dimWorld>;
135 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
137 using ConvectiveMixingModule = BlackOilConvectiveMixingModule<TypeTag, enableConvectiveMixing>;
138 using ModuleParams = BlackoilModuleParams<ConvectiveMixingModuleParam<Scalar>>;
145 throw std::invalid_argument(
"The ECL transmissibility module does not provide an explicit intrinsic permeability");
156 throw std::invalid_argument(
"The ECL transmissibility module does not provide explicit potential gradients");
166 {
return pressureDifference_[phaseIdx]; }
176 throw std::invalid_argument(
"The ECL transmissibility module does not provide explicit filter velocities");
188 OPM_HOST_DEVICE
const Evaluation&
volumeFlux(
unsigned phaseIdx)
const 189 {
return volumeFlux_[phaseIdx]; }
201 assert(phaseIdx < numPhases);
203 return upIdx_[phaseIdx];
215 assert(phaseIdx < numPhases);
217 return dnIdx_[phaseIdx];
220 OPM_HOST_DEVICE
void updateSolvent(
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
221 { asImp_().updateVolumeFluxTrans(elemCtx, scvfIdx, timeIdx); }
223 OPM_HOST_DEVICE
void updatePolymer(
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
224 { asImp_().updateShearMultipliers(elemCtx, scvfIdx, timeIdx); }
228 OPM_HOST_DEVICE
static void volumeAndPhasePressureDifferences(std::array<short, numPhases>& upIdx,
229 std::array<short, numPhases>& dnIdx,
231 Evaluation (&pressureDifferences)[numPhases],
232 const ElementContext& elemCtx,
236 const auto& problem = elemCtx.problem();
237 const auto& stencil = elemCtx.stencil(timeIdx);
238 const auto& scvf = stencil.interiorFace(scvfIdx);
239 unsigned interiorDofIdx = scvf.interiorIndex();
240 unsigned exteriorDofIdx = scvf.exteriorIndex();
242 assert(interiorDofIdx != exteriorDofIdx);
244 unsigned I = stencil.globalSpaceIndex(interiorDofIdx);
245 unsigned J = stencil.globalSpaceIndex(exteriorDofIdx);
246 Scalar trans = problem.transmissibility(elemCtx, interiorDofIdx, exteriorDofIdx);
247 Scalar faceArea = scvf.area();
248 Scalar thpres = problem.thresholdPressure(I, J);
253 Scalar g = elemCtx.problem().gravity()[dimWorld - 1];
255 const auto& intQuantsIn = elemCtx.intensiveQuantities(interiorDofIdx, timeIdx);
256 const auto& intQuantsEx = elemCtx.intensiveQuantities(exteriorDofIdx, timeIdx);
263 Scalar zIn = problem.dofCenterDepth(elemCtx, interiorDofIdx, timeIdx);
264 Scalar zEx = problem.dofCenterDepth(elemCtx, exteriorDofIdx, timeIdx);
268 Scalar distZ = zIn - zEx;
270 Scalar Vin = elemCtx.dofVolume(interiorDofIdx, 0);
271 Scalar Vex = elemCtx.dofVolume(exteriorDofIdx, 0);
273 for (
unsigned phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
274 if (!FluidSystem::phaseIsActive(phaseIdx))
276 calculatePhasePressureDiff_(upIdx[phaseIdx],
278 pressureDifferences[phaseIdx],
290 problem.moduleParams());
292 const bool upwindIsInterior = (
static_cast<unsigned>(upIdx[phaseIdx]) == interiorDofIdx);
293 const IntensiveQuantities& up = upwindIsInterior ? intQuantsIn : intQuantsEx;
295 const Evaluation transMult = (intQuantsIn.rockCompTransMultiplier() + Toolbox::value(intQuantsEx.rockCompTransMultiplier()))/2;
297 const auto& materialLawManager = problem.materialLawManager();
298 FaceDir::DirEnum facedir = FaceDir::DirEnum::Unknown;
299 if (materialLawManager->hasDirectionalRelperms()) {
300 facedir = scvf.faceDirFromDirId();
302 if (upwindIsInterior)
304 pressureDifferences[phaseIdx]*up.mobility(phaseIdx, facedir)*transMult*(-trans/faceArea);
307 pressureDifferences[phaseIdx]*
308 (Toolbox::value(up.mobility(phaseIdx, facedir))*transMult*(-trans/faceArea));
312 template<
class EvalType>
313 OPM_HOST_DEVICE
static void calculatePhasePressureDiff_(
short& upIdx,
316 const IntensiveQuantities& intQuantsIn,
317 const IntensiveQuantities& intQuantsEx,
318 const unsigned phaseIdx,
319 const unsigned interiorDofIdx,
320 const unsigned exteriorDofIdx,
323 const unsigned globalIndexIn,
324 const unsigned globalIndexEx,
327 const ModuleParams& moduleParams)
332 if (intQuantsIn.mobility(phaseIdx) <= 0.0 &&
333 intQuantsEx.mobility(phaseIdx) <= 0.0)
335 upIdx = interiorDofIdx;
336 dnIdx = exteriorDofIdx;
343 const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
344 Scalar rhoEx = Toolbox::value(intQuantsEx.fluidState().density(phaseIdx));
345 Evaluation rhoAvg = (rhoIn + rhoEx)/2;
347 if constexpr(enableConvectiveMixing) {
348 ConvectiveMixingModule::modifyAvgDensity(rhoAvg, intQuantsIn, intQuantsEx, phaseIdx, moduleParams.convectiveMixingModuleParam);
351 const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
352 Evaluation pressureExterior = Toolbox::value(intQuantsEx.fluidState().pressure(phaseIdx));
355 pressureExterior += Toolbox::value(rhoAvg)*(distZg);
357 pressureExterior += rhoAvg*(distZg);
366 upIdx = exteriorDofIdx;
367 dnIdx = interiorDofIdx;
370 upIdx = interiorDofIdx;
371 dnIdx = exteriorDofIdx;
377 upIdx = interiorDofIdx;
378 dnIdx = exteriorDofIdx;
380 else if (Vin < Vex) {
381 upIdx = exteriorDofIdx;
382 dnIdx = interiorDofIdx;
388 if (globalIndexIn < globalIndexEx) {
389 upIdx = interiorDofIdx;
390 dnIdx = exteriorDofIdx;
393 upIdx = exteriorDofIdx;
394 dnIdx = interiorDofIdx;
420 OPM_HOST_DEVICE
void calculateGradients_(
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
422 Valgrind::SetUndefined(*
this);
424 volumeAndPhasePressureDifferences(upIdx_ , dnIdx_, volumeFlux_, pressureDifference_, elemCtx, scvfIdx, timeIdx);
430 template <
class Flu
idState>
434 const FluidState& exFluidState)
436 const auto& scvf = elemCtx.stencil(timeIdx).boundaryFace(scvfIdx);
437 const Scalar faceArea = scvf.area();
438 const Scalar zEx = scvf.integrationPos()[dimWorld - 1];
439 const auto& problem = elemCtx.problem();
440 const unsigned globalSpaceIdx = elemCtx.globalSpaceIndex(0, timeIdx);
441 const auto& intQuantsIn = elemCtx.intensiveQuantities(0, timeIdx);
453 pressureDifference_);
458 if constexpr (enableSolvent) {
459 if (upIdx_[gasPhaseIdx] == 0) {
460 const Scalar trans = problem.transmissibilityBoundary(globalSpaceIdx, scvfIdx);
461 const Scalar transModified = trans * Toolbox::value(intQuantsIn.rockCompTransMultiplier());
462 const auto solventFlux = pressureDifference_[gasPhaseIdx] * intQuantsIn.mobility(gasPhaseIdx) * (-transModified/faceArea);
463 asImp_().setSolventVolumeFlux(solventFlux);
465 asImp_().setSolventVolumeFlux(0.0);
474 template <
class Problem,
class Flu
idState,
class EvaluationContainer>
476 const unsigned globalSpaceIdx,
477 const IntensiveQuantities& intQuantsIn,
478 const unsigned bfIdx,
479 const double faceArea,
481 const FluidState& exFluidState,
482 std::array<short, numPhases>& upIdx,
483 std::array<short, numPhases>& dnIdx,
488 bool enableBoundaryMassFlux = problem.nonTrivialBoundaryConditions();
489 if (!enableBoundaryMassFlux)
492 Scalar trans = problem.transmissibilityBoundary(globalSpaceIdx, bfIdx);
497 Scalar g = problem.gravity()[dimWorld - 1];
504 Scalar zIn = problem.dofCenterDepth(globalSpaceIdx);
508 Scalar distZ = zIn - zEx;
510 for (
unsigned phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
511 if (!FluidSystem::phaseIsActive(phaseIdx))
516 const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
517 const auto& rhoEx = exFluidState.density(phaseIdx);
518 Evaluation rhoAvg = (rhoIn + rhoEx)/2;
520 const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
521 Evaluation pressureExterior = exFluidState.pressure(phaseIdx);
522 pressureExterior += rhoAvg*(distZ*g);
530 const unsigned interiorDofIdx = 0;
532 upIdx[phaseIdx] = -1;
533 dnIdx[phaseIdx] = interiorDofIdx;
536 upIdx[phaseIdx] = interiorDofIdx;
537 dnIdx[phaseIdx] = -1;
540 Evaluation transModified = trans;
542 if (upIdx[phaseIdx] == interiorDofIdx) {
546 const auto& up = intQuantsIn;
549 const Scalar transMult = Toolbox::value(up.rockCompTransMultiplier());
550 transModified *= transMult;
558 const auto& matParams = problem.materialLawParams(globalSpaceIdx);
559 std::array<typename FluidState::ValueType,numPhases> kr;
560 MaterialLaw::relativePermeabilities(kr, matParams, exFluidState);
562 const auto& mob = kr[phaseIdx]/exFluidState.viscosity(phaseIdx);
577 OPM_HOST_DEVICE
void calculateBoundaryFluxes_(
const ElementContext&,
unsigned,
unsigned)
581 Implementation& asImp_()
582 {
return *
static_cast<Implementation*
>(
this); }
584 const Implementation& asImp_()
const 585 {
return *
static_cast<const Implementation*
>(
this); }
588 Evaluation volumeFlux_[numPhases];
592 Evaluation pressureDifference_[numPhases];
595 std::array<short, numPhases> upIdx_;
596 std::array<short, numPhases> dnIdx_;
601 #endif // OPM_NEWTRAN_FLUX_MODULE_HPP static void registerParameters()
Register all run-time parameters for the flux module.
Definition: NewTranFluxModule.hpp:79
Provides the intensive quantities for the ECL flux module.
Definition: NewTranFluxModule.hpp:57
OPM_HOST_DEVICE void calculateBoundaryGradients_(const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx, const FluidState &exFluidState)
Update the required gradients for boundary faces.
Definition: NewTranFluxModule.hpp:431
OPM_HOST_DEVICE const Evaluation & volumeFlux(unsigned phaseIdx) const
Return the volume flux of a fluid phase at the face's integration point .
Definition: NewTranFluxModule.hpp:188
OPM_HOST_DEVICE unsigned upstreamIndex_(unsigned phaseIdx) const
Returns the local index of the degree of freedom in which is in upstream direction.
Definition: NewTranFluxModule.hpp:199
Classes required for dynamic convective mixing.
Specifies a flux module which uses ECL transmissibilities.
Definition: NewTranFluxModule.hpp:70
OPM_HOST_DEVICE void calculateFluxes_(const ElementContext &, unsigned, unsigned)
Update the volumetric fluxes for all fluid phases on the interior faces of the context.
Definition: NewTranFluxModule.hpp:574
OPM_HOST_DEVICE const Evaluation & pressureDifference(unsigned phaseIdx) const
Return the gravity corrected pressure difference between the interior and the exterior of a face...
Definition: NewTranFluxModule.hpp:165
OPM_HOST_DEVICE unsigned downstreamIndex_(unsigned phaseIdx) const
Returns the local index of the degree of freedom in which is in downstream direction.
Definition: NewTranFluxModule.hpp:213
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Provides the ECL flux module.
Definition: NewTranFluxModule.hpp:60
Declares the properties required by the black oil model.
static OPM_HOST_DEVICE void calculateBoundaryGradients_(const Problem &problem, const unsigned globalSpaceIdx, const IntensiveQuantities &intQuantsIn, const unsigned bfIdx, const double faceArea, const double zEx, const FluidState &exFluidState, std::array< short, numPhases > &upIdx, std::array< short, numPhases > &dnIdx, EvaluationContainer &volumeFlux, EvaluationContainer &pressureDifference)
Update the required gradients for boundary faces.
Definition: NewTranFluxModule.hpp:475
Declare the properties used by the infrastructure code of the finite volume discretizations.
OPM_HOST_DEVICE const EvalDimVector & filterVelocity(unsigned) const
Return the filter velocity of a fluid phase at the face's integration point [m/s].
Definition: NewTranFluxModule.hpp:174
OPM_HOST_DEVICE const EvalDimVector & potentialGrad(unsigned) const
Return the pressure potential gradient of a fluid phase at the face's integration point [Pa/m]...
Definition: NewTranFluxModule.hpp:154
Provides the defaults for the parameters required by the transmissibility based volume flux calculati...
Definition: NewTranFluxModule.hpp:63
OPM_HOST_DEVICE const DimMatrix & intrinsicPermeability() const
Return the intrinsic permeability tensor at a face [m^2].
Definition: NewTranFluxModule.hpp:143
OPM_HOST_DEVICE void calculateGradients_(const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Update the required gradients for interior faces.
Definition: NewTranFluxModule.hpp:420