30 #ifndef EWOMS_DARCY_FLUX_MODULE_HH 31 #define EWOMS_DARCY_FLUX_MODULE_HH 33 #include <dune/common/fmatrix.hh> 34 #include <dune/common/fvector.hh> 36 #include <opm/common/Exceptions.hpp> 38 #include <opm/material/common/Valgrind.hpp> 48 #include <type_traits> 52 template <
class TypeTag>
55 template <
class TypeTag>
58 template <
class TypeTag>
65 template <
class TypeTag>
84 template <
class TypeTag>
85 class DarcyBaseProblem
92 template <
class TypeTag>
93 class DarcyIntensiveQuantities
95 using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
98 void update_(
const ElementContext&,
120 template <
class TypeTag>
121 class DarcyExtensiveQuantities
123 using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
124 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
125 using Evaluation = GetPropType<TypeTag, Properties::Evaluation>;
126 using GridView = GetPropType<TypeTag, Properties::GridView>;
127 using Implementation = GetPropType<TypeTag, Properties::ExtensiveQuantities>;
128 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
129 using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
131 enum { dimWorld = GridView::dimensionworld };
132 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
134 using Toolbox = MathToolbox<Evaluation>;
135 using EvalDimVector = Dune::FieldVector<Evaluation, dimWorld>;
136 using DimVector = Dune::FieldVector<Scalar, dimWorld>;
137 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
154 {
return potentialGrad_[phaseIdx]; }
163 {
return filterVelocity_[phaseIdx]; }
175 {
return volumeFlux_[phaseIdx]; }
178 short upstreamIndex_(
unsigned phaseIdx)
const 179 {
return upstreamDofIdx_[phaseIdx]; }
181 short downstreamIndex_(
unsigned phaseIdx)
const 182 {
return downstreamDofIdx_[phaseIdx]; }
193 const auto& gradCalc = elemCtx.gradientCalculator();
196 const auto& scvf = elemCtx.stencil(timeIdx).interiorFace(faceIdx);
197 const auto& faceNormal = scvf.normal();
199 const unsigned i = scvf.interiorIndex();
200 const unsigned j = scvf.exteriorIndex();
201 interiorDofIdx_ =
static_cast<short>(i);
202 exteriorDofIdx_ =
static_cast<short>(j);
203 const unsigned focusDofIdx = elemCtx.focusDofIndex();
206 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
207 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
208 Valgrind::SetUndefined(potentialGrad_[phaseIdx]);
213 gradCalc.calculateGradient(potentialGrad_[phaseIdx],
217 Valgrind::CheckDefined(potentialGrad_[phaseIdx]);
221 if (Parameters::Get<Parameters::EnableGravity>()) {
224 const auto& gIn = elemCtx.problem().gravity(elemCtx, i, timeIdx);
225 const auto& gEx = elemCtx.problem().gravity(elemCtx, j, timeIdx);
227 const auto& intQuantsIn = elemCtx.intensiveQuantities(i, timeIdx);
228 const auto& intQuantsEx = elemCtx.intensiveQuantities(j, timeIdx);
230 const auto& posIn = elemCtx.pos(i, timeIdx);
231 const auto& posEx = elemCtx.pos(j, timeIdx);
232 const auto& posFace = scvf.integrationPos();
235 DimVector distVecIn(posIn);
236 DimVector distVecEx(posEx);
237 DimVector distVecTotal(posEx);
239 distVecIn -= posFace;
240 distVecEx -= posFace;
241 distVecTotal -= posIn;
242 const Scalar absDistTotalSquared = distVecTotal.two_norm2();
243 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
244 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
251 if (std::is_same<Scalar, Evaluation>::value ||
252 interiorDofIdx_ == static_cast<int>(focusDofIdx))
254 const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
255 pStatIn = -rhoIn * (gIn * distVecIn);
258 const Scalar rhoIn = Toolbox::value(intQuantsIn.fluidState().density(phaseIdx));
259 pStatIn = -rhoIn * (gIn * distVecIn);
266 if (std::is_same<Scalar, Evaluation>::value ||
267 exteriorDofIdx_ == static_cast<int>(focusDofIdx))
269 const Evaluation& rhoEx = intQuantsEx.fluidState().density(phaseIdx);
270 pStatEx = -rhoEx * (gEx * distVecEx);
273 const Scalar rhoEx = Toolbox::value(intQuantsEx.fluidState().density(phaseIdx));
274 pStatEx = -rhoEx * (gEx * distVecEx);
281 Dune::FieldVector<Evaluation, dimWorld> f(distVecTotal);
282 f *= (pStatEx - pStatIn) / absDistTotalSquared;
285 for (
unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
286 potentialGrad_[phaseIdx][dimIdx] += f[dimIdx];
289 for (
unsigned dimIdx = 0; dimIdx < potentialGrad_[phaseIdx].size(); ++dimIdx) {
290 if (!isfinite(potentialGrad_[phaseIdx][dimIdx])) {
291 throw NumericalProblem(
"Non-finite potential gradient for phase '" 292 + std::string(FluidSystem::phaseName(phaseIdx)) +
"'");
298 Valgrind::SetUndefined(K_);
299 elemCtx.problem().intersectionIntrinsicPermeability(K_, elemCtx, faceIdx, timeIdx);
300 Valgrind::CheckDefined(K_);
302 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
303 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
304 Valgrind::SetUndefined(potentialGrad_[phaseIdx]);
309 Evaluation tmp = 0.0;
310 for (
unsigned dimIdx = 0; dimIdx < faceNormal.size(); ++dimIdx) {
311 tmp += potentialGrad_[phaseIdx][dimIdx]*faceNormal[dimIdx];
315 upstreamDofIdx_[phaseIdx] = exteriorDofIdx_;
316 downstreamDofIdx_[phaseIdx] = interiorDofIdx_;
319 upstreamDofIdx_[phaseIdx] = interiorDofIdx_;
320 downstreamDofIdx_[phaseIdx] = exteriorDofIdx_;
325 const auto& up = elemCtx.intensiveQuantities(upstreamDofIdx_[phaseIdx], timeIdx);
326 if (upstreamDofIdx_[phaseIdx] == static_cast<int>(focusDofIdx)) {
327 mobility_[phaseIdx] = up.mobility(phaseIdx);
330 mobility_[phaseIdx] = Toolbox::value(up.mobility(phaseIdx));
341 template <
class Flu
idState>
343 unsigned boundaryFaceIdx,
345 const FluidState& fluidState)
347 const auto& gradCalc = elemCtx.gradientCalculator();
351 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
352 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
353 Valgrind::SetUndefined(potentialGrad_[phaseIdx]);
358 gradCalc.calculateBoundaryGradient(potentialGrad_[phaseIdx],
362 Valgrind::CheckDefined(potentialGrad_[phaseIdx]);
365 const auto& scvf = elemCtx.stencil(timeIdx).boundaryFace(boundaryFaceIdx);
366 const auto i = scvf.interiorIndex();
367 interiorDofIdx_ =
static_cast<short>(i);
368 exteriorDofIdx_ = -1;
369 int focusDofIdx = elemCtx.focusDofIndex();
372 const auto& intQuantsIn = elemCtx.intensiveQuantities(i, timeIdx);
373 K_ = intQuantsIn.intrinsicPermeability();
376 if (Parameters::Get<Parameters::EnableGravity>()) {
379 const auto& gIn = elemCtx.problem().gravity(elemCtx, i, timeIdx);
380 const auto& posIn = elemCtx.pos(i, timeIdx);
381 const auto& posFace = scvf.integrationPos();
384 DimVector distVecIn(posIn);
385 distVecIn -= posFace;
386 const Scalar absDistSquared = distVecIn.two_norm2();
387 const Scalar gTimesDist = gIn * distVecIn;
389 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
390 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
395 const Evaluation rhoIn = intQuantsIn.fluidState().density(phaseIdx);
396 const Evaluation pStatIn = -gTimesDist * rhoIn;
398 Valgrind::CheckDefined(pStatIn);
404 EvalDimVector f(distVecIn);
405 f *= pStatIn / absDistSquared;
408 for (
unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
409 potentialGrad_[phaseIdx][dimIdx] += f[dimIdx];
412 Valgrind::CheckDefined(potentialGrad_[phaseIdx]);
413 for (
unsigned dimIdx = 0; dimIdx < potentialGrad_[phaseIdx].size(); ++dimIdx) {
414 if (!isfinite(potentialGrad_[phaseIdx][dimIdx])) {
415 throw NumericalProblem(
"Non-finite potential gradient for phase '" 416 + std::string(FluidSystem::phaseName(phaseIdx)) +
"'");
423 const auto& faceNormal = scvf.normal();
425 const auto& matParams = elemCtx.problem().materialLawParams(elemCtx, i, timeIdx);
427 std::array<Scalar, numPhases> kr;
428 MaterialLaw::relativePermeabilities(kr, matParams, fluidState);
429 Valgrind::CheckDefined(kr);
431 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
432 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
436 Evaluation tmp = 0.0;
437 for (
unsigned dimIdx = 0; dimIdx < faceNormal.size(); ++dimIdx) {
438 tmp += potentialGrad_[phaseIdx][dimIdx] * faceNormal[dimIdx];
442 upstreamDofIdx_[phaseIdx] = exteriorDofIdx_;
443 downstreamDofIdx_[phaseIdx] = interiorDofIdx_;
446 upstreamDofIdx_[phaseIdx] = interiorDofIdx_;
447 downstreamDofIdx_[phaseIdx] = exteriorDofIdx_;
451 if (upstreamDofIdx_[phaseIdx] < 0) {
452 if (interiorDofIdx_ == focusDofIdx) {
453 mobility_[phaseIdx] = kr[phaseIdx] / fluidState.viscosity(phaseIdx);
456 mobility_[phaseIdx] = Toolbox::value(kr[phaseIdx]) /
457 Toolbox::value(fluidState.viscosity(phaseIdx));
460 else if (upstreamDofIdx_[phaseIdx] != focusDofIdx) {
461 mobility_[phaseIdx] = Toolbox::value(intQuantsIn.mobility(phaseIdx));
464 mobility_[phaseIdx] = intQuantsIn.mobility(phaseIdx);
466 Valgrind::CheckDefined(mobility_[phaseIdx]);
478 const auto& scvf = elemCtx.stencil(timeIdx).interiorFace(scvfIdx);
479 const DimVector& normal = scvf.normal();
480 Valgrind::CheckDefined(normal);
482 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
483 filterVelocity_[phaseIdx] = 0.0;
484 volumeFlux_[phaseIdx] = 0.0;
485 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
489 asImp_().calculateFilterVelocity_(phaseIdx);
490 Valgrind::CheckDefined(filterVelocity_[phaseIdx]);
492 volumeFlux_[phaseIdx] = 0.0;
493 for (
unsigned i = 0; i < normal.size(); ++i) {
494 volumeFlux_[phaseIdx] += filterVelocity_[phaseIdx][i] * normal[i];
506 unsigned boundaryFaceIdx,
509 const auto& scvf = elemCtx.stencil(timeIdx).boundaryFace(boundaryFaceIdx);
510 const DimVector& normal = scvf.normal();
511 Valgrind::CheckDefined(normal);
513 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
514 if (!elemCtx.model().phaseIsConsidered(phaseIdx)) {
515 filterVelocity_[phaseIdx] = 0.0;
516 volumeFlux_[phaseIdx] = 0.0;
520 asImp_().calculateFilterVelocity_(phaseIdx);
521 Valgrind::CheckDefined(filterVelocity_[phaseIdx]);
522 volumeFlux_[phaseIdx] = 0.0;
523 for (
unsigned i = 0; i < normal.size(); ++i) {
524 volumeFlux_[phaseIdx] += filterVelocity_[phaseIdx][i] * normal[i];
529 void calculateFilterVelocity_(
unsigned phaseIdx)
532 assert(isfinite(mobility_[phaseIdx]));
533 for (
unsigned i = 0; i < K_.M(); ++i) {
534 for (
unsigned j = 0; j < K_.N(); ++j) {
535 assert(std::isfinite(K_[i][j]));
540 K_.mv(potentialGrad_[phaseIdx], filterVelocity_[phaseIdx]);
541 filterVelocity_[phaseIdx] *= - mobility_[phaseIdx];
544 for (
unsigned i = 0; i < filterVelocity_[phaseIdx].size(); ++i) {
545 assert(isfinite(filterVelocity_[phaseIdx][i]));
551 Implementation& asImp_()
552 {
return *
static_cast<Implementation*
>(
this); }
554 const Implementation& asImp_()
const 555 {
return *
static_cast<const Implementation*
>(
this); }
562 std::array<Evaluation, numPhases> mobility_;
565 std::array<EvalDimVector, numPhases> filterVelocity_;
569 std::array<Evaluation, numPhases> volumeFlux_;
572 std::array<EvalDimVector, numPhases> potentialGrad_;
575 std::array<short, numPhases> upstreamDofIdx_;
576 std::array<short, numPhases> downstreamDofIdx_;
577 short interiorDofIdx_;
578 short exteriorDofIdx_;
Provides the defaults for the parameters required by the Darcy velocity approach. ...
Definition: darcyfluxmodule.hh:59
const DimMatrix & intrinsicPermability() const
Returns the intrinsic permeability tensor for a given sub-control volume face.
Definition: darcyfluxmodule.hh:144
void calculateGradients_(const ElementContext &elemCtx, unsigned faceIdx, unsigned timeIdx)
Calculate the gradients which are required to determine the volumetric fluxes.
Definition: darcyfluxmodule.hh:189
const EvalDimVector & filterVelocity(unsigned phaseIdx) const
Return the filter velocity of a fluid phase at the face's integration point [m/s].
Definition: darcyfluxmodule.hh:162
Defines the common properties required by the porous medium multi-phase models.
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
const EvalDimVector & potentialGrad(unsigned phaseIdx) const
Return the pressure potential gradient of a fluid phase at the face's integration point [Pa/m]...
Definition: darcyfluxmodule.hh:153
This method contains all callback classes for quantities that are required by some extensive quantiti...
Callback class for a phase pressure.
Definition: quantitycallbacks.hh:133
Callback class for a phase pressure.
Definition: quantitycallbacks.hh:84
Provides the Darcy flux module
Definition: darcyfluxmodule.hh:56
void calculateBoundaryFluxes_(const ElementContext &elemCtx, unsigned boundaryFaceIdx, unsigned timeIdx)
Calculate the volumetric fluxes at a boundary face of all fluid phases.
Definition: darcyfluxmodule.hh:505
void setPhaseIndex(unsigned phaseIdx)
Set the index of the fluid phase for which the pressure should be returned.
Definition: quantitycallbacks.hh:163
const Evaluation & volumeFlux(unsigned phaseIdx) const
Return the volume flux of a fluid phase at the face's integration point .
Definition: darcyfluxmodule.hh:174
Provides the intensive quantities for the Darcy flux module.
Definition: darcyfluxmodule.hh:53
static void registerParameters()
Register all run-time parameters for the flux module.
Definition: darcyfluxmodule.hh:75
Specifies a flux module which uses the Darcy relation.
Definition: darcyfluxmodule.hh:66
void calculateBoundaryGradients_(const ElementContext &elemCtx, unsigned boundaryFaceIdx, unsigned timeIdx, const FluidState &fluidState)
Calculate the gradients at the grid boundary which are required to determine the volumetric fluxes...
Definition: darcyfluxmodule.hh:342
void calculateFluxes_(const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx)
Calculate the volumetric fluxes of all phases.
Definition: darcyfluxmodule.hh:476
Defines the common parameters for the porous medium multi-phase models.
void setPhaseIndex(unsigned phaseIdx)
Set the index of the fluid phase for which the pressure should be returned.
Definition: quantitycallbacks.hh:109