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/ErrorMacros.hpp>
38#include <opm/common/OpmLog/OpmLog.hpp>
39#include <opm/common/utility/gpuDecorators.hpp>
41#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
43#include <opm/material/common/MathToolbox.hpp>
44#include <opm/material/common/Valgrind.hpp>
45#include <opm/material/thermal/EnergyModuleType.hpp>
60template <
class TypeTag>
61class NewTranIntensiveQuantities;
63template <
class TypeTag>
64class NewTranExtensiveQuantities;
66template <
class TypeTag>
67class NewTranBaseProblem;
73template <
class TypeTag>
92template <
class TypeTag>
100template <
class TypeTag>
105 void update_(
const ElementContext&,
unsigned,
unsigned)
113template <
class TypeTag>
126 enum { dimWorld = GridView::dimensionworld };
127 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
128 enum { numPhases = FluidSystem::numPhases };
130 static constexpr bool enableConvectiveMixing = getPropValue<TypeTag, Properties::EnableConvectiveMixing>();
131 static constexpr bool enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>();
132 static constexpr bool enableEnergy =
133 getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal;
134 static constexpr bool enablePolymer = getPropValue<TypeTag, Properties::EnablePolymer>();
135 static constexpr bool enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>();
137 using Toolbox = MathToolbox<Evaluation>;
138 using DimVector = Dune::FieldVector<Scalar, dimWorld>;
139 using EvalDimVector = Dune::FieldVector<Evaluation, dimWorld>;
140 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
142 using ConvectiveMixingModule = BlackOilConvectiveMixingModule<TypeTag, enableConvectiveMixing>;
151 OPM_THROW(std::invalid_argument,
"The ECL transmissibility module does not provide an explicit intrinsic permeability");
162 OPM_THROW(std::invalid_argument,
"The ECL transmissibility module does not provide explicit potential gradients");
172 {
return pressureDifference_[phaseIdx]; }
182 OPM_THROW(std::invalid_argument,
"The ECL transmissibility module does not provide explicit filter velocities");
194 OPM_HOST_DEVICE
const Evaluation&
volumeFlux(
unsigned phaseIdx)
const
195 {
return volumeFlux_[phaseIdx]; }
207 assert(phaseIdx < numPhases);
209 return upIdx_[phaseIdx];
221 assert(phaseIdx < numPhases);
223 return dnIdx_[phaseIdx];
226 OPM_HOST_DEVICE
void updateSolvent(
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
228 if constexpr (enableSolvent) {
229 asImp_().updateVolumeFluxTrans(elemCtx, scvfIdx, timeIdx);
233 OPM_HOST_DEVICE
void updatePolymer(
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
235 if constexpr (enablePolymer) {
236 asImp_().updateShearMultipliers(elemCtx, scvfIdx, timeIdx);
243 std::array<short, numPhases>& dnIdx,
245 Evaluation (&pressureDifferences)[numPhases],
246 const ElementContext& elemCtx,
250 const auto& problem = elemCtx.problem();
251 const auto& stencil = elemCtx.stencil(timeIdx);
252 const auto& scvf = stencil.interiorFace(scvfIdx);
253 unsigned interiorDofIdx = scvf.interiorIndex();
254 unsigned exteriorDofIdx = scvf.exteriorIndex();
256 assert(interiorDofIdx != exteriorDofIdx);
258 unsigned I = stencil.globalSpaceIndex(interiorDofIdx);
259 unsigned J = stencil.globalSpaceIndex(exteriorDofIdx);
260 Scalar trans = problem.transmissibility(elemCtx, interiorDofIdx, exteriorDofIdx);
261 Scalar faceArea = scvf.area();
262 Scalar thpresInToEx = problem.thresholdPressure(I, J);
263 Scalar thpresExToIn = problem.thresholdPressure(J, I);
268 Scalar g = elemCtx.problem().gravity()[dimWorld - 1];
270 const auto& intQuantsIn = elemCtx.intensiveQuantities(interiorDofIdx, timeIdx);
271 const auto& intQuantsEx = elemCtx.intensiveQuantities(exteriorDofIdx, timeIdx);
278 Scalar zIn = problem.dofCenterDepth(elemCtx, interiorDofIdx, timeIdx);
279 Scalar zEx = problem.dofCenterDepth(elemCtx, exteriorDofIdx, timeIdx);
283 Scalar distZ = zIn - zEx;
285 Scalar Vin = elemCtx.dofVolume(interiorDofIdx, 0);
286 Scalar Vex = elemCtx.dofVolume(exteriorDofIdx, 0);
288 for (
unsigned phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
289 if (!FluidSystem::phaseIsActive(phaseIdx))
293 pressureDifferences[phaseIdx],
306 problem.moduleParams());
308 const bool upwindIsInterior = (
static_cast<unsigned>(upIdx[phaseIdx]) == interiorDofIdx);
309 const IntensiveQuantities& up = upwindIsInterior ? intQuantsIn : intQuantsEx;
311 const Evaluation transMult = (intQuantsIn.rockCompTransMultiplier() + Toolbox::value(intQuantsEx.rockCompTransMultiplier()))/2;
313 const auto& materialLawManager = problem.materialLawManager();
314 FaceDir::DirEnum facedir = FaceDir::DirEnum::Unknown;
315 if (materialLawManager->hasDirectionalRelperms()) {
316 facedir = scvf.faceDirFromDirId();
318 if (upwindIsInterior)
320 pressureDifferences[phaseIdx]*up.mobility(phaseIdx, facedir)*transMult*(-trans/faceArea);
323 pressureDifferences[phaseIdx]*
324 (Toolbox::value(up.mobility(phaseIdx, facedir))*transMult*(-trans/faceArea));
328 template<
class EvalType,
class ModuleParamsT = ModuleParams>
332 const IntensiveQuantities& intQuantsIn,
333 const IntensiveQuantities& intQuantsEx,
334 const unsigned phaseIdx,
335 const unsigned interiorDofIdx,
336 const unsigned exteriorDofIdx,
339 const unsigned globalIndexIn,
340 const unsigned globalIndexEx,
342 const Scalar thpresInToEx,
343 const Scalar thpresExToIn,
344 const ModuleParamsT& moduleParams)
349 if (intQuantsIn.mobility(phaseIdx) <= 0.0 &&
350 intQuantsEx.mobility(phaseIdx) <= 0.0)
352 upIdx = interiorDofIdx;
353 dnIdx = exteriorDofIdx;
360 const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
361 Scalar rhoEx = Toolbox::value(intQuantsEx.fluidState().density(phaseIdx));
362 Evaluation rhoAvg = (rhoIn + rhoEx)/2;
364 if constexpr (enableConvectiveMixing) {
365 ConvectiveMixingModule::modifyAvgDensity(rhoAvg, intQuantsIn, intQuantsEx, phaseIdx, moduleParams.convectiveMixingModuleParam);
368 const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
369 Evaluation pressureExterior = Toolbox::value(intQuantsEx.fluidState().pressure(phaseIdx));
372 pressureExterior += Toolbox::value(rhoAvg)*(distZg);
374 pressureExterior += rhoAvg*(distZg);
383 upIdx = exteriorDofIdx;
384 dnIdx = interiorDofIdx;
387 upIdx = interiorDofIdx;
388 dnIdx = exteriorDofIdx;
394 upIdx = interiorDofIdx;
395 dnIdx = exteriorDofIdx;
397 else if (Vin < Vex) {
398 upIdx = exteriorDofIdx;
399 dnIdx = interiorDofIdx;
405 if (globalIndexIn < globalIndexEx) {
406 upIdx = interiorDofIdx;
407 dnIdx = exteriorDofIdx;
410 upIdx = exteriorDofIdx;
411 dnIdx = interiorDofIdx;
438 OPM_HOST_DEVICE
void calculateGradients_(
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
440 Valgrind::SetUndefined(*
this);
448 template <
class Flu
idState>
452 const FluidState& exFluidState)
454 const auto& scvf = elemCtx.stencil(timeIdx).boundaryFace(scvfIdx);
455 const Scalar faceArea = scvf.area();
456 const Scalar zEx = scvf.integrationPos()[dimWorld - 1];
457 const auto& problem = elemCtx.problem();
458 const unsigned globalSpaceIdx = elemCtx.globalSpaceIndex(0, timeIdx);
459 const auto& intQuantsIn = elemCtx.intensiveQuantities(0, timeIdx);
471 pressureDifference_);
476 if constexpr (enableSolvent) {
477 if (upIdx_[gasPhaseIdx] == 0) {
478 const Scalar trans = problem.transmissibilityBoundary(globalSpaceIdx, scvfIdx);
479 const Scalar transModified = trans * Toolbox::value(intQuantsIn.rockCompTransMultiplier());
480 const auto solventFlux = pressureDifference_[gasPhaseIdx] * intQuantsIn.mobility(gasPhaseIdx) * (-transModified/faceArea);
481 asImp_().setSolventVolumeFlux(solventFlux);
483 asImp_().setSolventVolumeFlux(0.0);
492 template <
class Problem,
class Flu
idState,
class EvaluationContainer>
494 const unsigned globalSpaceIdx,
495 const IntensiveQuantities& intQuantsIn,
496 const unsigned bfIdx,
497 const double faceArea,
499 const FluidState& exFluidState,
500 std::array<short, numPhases>& upIdx,
501 std::array<short, numPhases>& dnIdx,
506 bool enableBoundaryMassFlux = problem.nonTrivialBoundaryConditions();
507 if (!enableBoundaryMassFlux)
510 Scalar trans = problem.transmissibilityBoundary(globalSpaceIdx, bfIdx);
515 Scalar g = problem.gravity()[dimWorld - 1];
522 Scalar zIn = problem.dofCenterDepth(globalSpaceIdx);
526 Scalar distZ = zIn - zEx;
528 for (
unsigned phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
529 if (!FluidSystem::phaseIsActive(phaseIdx))
534 const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
535 const auto& rhoEx = exFluidState.density(phaseIdx);
536 Evaluation rhoAvg = (rhoIn + rhoEx)/2;
538 const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
539 Evaluation pressureExterior = exFluidState.pressure(phaseIdx);
540 pressureExterior += rhoAvg*(distZ*g);
548 const unsigned interiorDofIdx = 0;
550 upIdx[phaseIdx] = -1;
551 dnIdx[phaseIdx] = interiorDofIdx;
554 upIdx[phaseIdx] = interiorDofIdx;
555 dnIdx[phaseIdx] = -1;
558 Evaluation transModified = trans;
560 if (upIdx[phaseIdx] == interiorDofIdx) {
564 const auto& up = intQuantsIn;
567 const Scalar transMult = Toolbox::value(up.rockCompTransMultiplier());
568 transModified *= transMult;
576 const auto& matParams = problem.materialLawParams(globalSpaceIdx);
577 std::array<typename FluidState::ValueType,numPhases> kr;
578 MaterialLaw::relativePermeabilities(kr, matParams, exFluidState);
580 const auto& mob = kr[phaseIdx]/exFluidState.viscosity(phaseIdx);
599 Implementation& asImp_()
600 {
return *
static_cast<Implementation*
>(
this); }
602 const Implementation& asImp_()
const
603 {
return *
static_cast<const Implementation*
>(
this); }
606 Evaluation volumeFlux_[numPhases];
610 Evaluation pressureDifference_[numPhases];
613 std::array<short, numPhases> upIdx_;
614 std::array<short, numPhases> dnIdx_;
Classes required for dynamic convective mixing.
Contains classes extending the black-oil model. \detail This file holds dummy definitions,...
Declares the properties required by the black oil model.
Provides the defaults for the parameters required by the transmissibility based volume flux calculati...
Definition: NewTranFluxModule.hpp:94
Provides the ECL flux module.
Definition: NewTranFluxModule.hpp:115
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:449
static OPM_HOST_DEVICE void volumeAndPhasePressureDifferences(std::array< short, numPhases > &upIdx, std::array< short, numPhases > &dnIdx, Evaluation(&volumeFlux)[numPhases], Evaluation(&pressureDifferences)[numPhases], const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: NewTranFluxModule.hpp:242
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:592
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:219
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:171
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:493
OPM_HOST_DEVICE const DimMatrix & intrinsicPermeability() const
Return the intrinsic permeability tensor at a face [m^2].
Definition: NewTranFluxModule.hpp:149
OPM_HOST_DEVICE void calculateGradients_(const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Update the required gradients for interior faces.
Definition: NewTranFluxModule.hpp:438
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:205
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:194
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:180
static OPM_HOST_DEVICE void calculatePhasePressureDiff_(short &upIdx, short &dnIdx, EvalType &pressureDifference, const IntensiveQuantities &intQuantsIn, const IntensiveQuantities &intQuantsEx, const unsigned phaseIdx, const unsigned interiorDofIdx, const unsigned exteriorDofIdx, const Scalar Vin, const Scalar Vex, const unsigned globalIndexIn, const unsigned globalIndexEx, const Scalar distZg, const Scalar thpresInToEx, const Scalar thpresExToIn, const ModuleParamsT &moduleParams)
Definition: NewTranFluxModule.hpp:329
OPM_HOST_DEVICE void updatePolymer(const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: NewTranFluxModule.hpp:233
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:160
OPM_HOST_DEVICE void updateSolvent(const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Definition: NewTranFluxModule.hpp:226
OPM_HOST_DEVICE void calculateBoundaryFluxes_(const ElementContext &, unsigned, unsigned)
Definition: NewTranFluxModule.hpp:595
Provides the intensive quantities for the ECL flux module.
Definition: NewTranFluxModule.hpp:102
void update_(const ElementContext &, unsigned, unsigned)
Definition: NewTranFluxModule.hpp:105
Declare the properties used by the infrastructure code of the finite volume discretizations.
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
Specifies a flux module which uses ECL transmissibilities.
Definition: NewTranFluxModule.hpp:75
static void registerParameters()
Register all run-time parameters for the flux module.
Definition: NewTranFluxModule.hpp:83