opm-simulators
NewTranFluxModule.hpp
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
31 #ifndef OPM_NEWTRAN_FLUX_MODULE_HPP
32 #define OPM_NEWTRAN_FLUX_MODULE_HPP
33 
34 #include <dune/common/fvector.hh>
35 #include <dune/common/fmatrix.hh>
36 
37 #include <opm/common/ErrorMacros.hpp>
38 #include <opm/common/OpmLog/OpmLog.hpp>
39 #include <opm/common/utility/gpuDecorators.hpp>
40 
41 #include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
42 
43 #include <opm/material/common/MathToolbox.hpp>
44 #include <opm/material/common/Valgrind.hpp>
45 #include <opm/material/thermal/EnergyModuleType.hpp>
46 
47 #include <opm/models/blackoil/blackoilmoduleparams.hh>
51 
53 
55 
56 #include <array>
57 
58 namespace Opm {
59 
60 template <class TypeTag>
62 
63 template <class TypeTag>
65 
66 template <class TypeTag>
68 
73 template <class TypeTag>
75 {
79 
83  static void registerParameters()
84  { }
85 };
86 
92 template <class TypeTag>
93 class NewTranBaseProblem
94 { };
95 
100 template <class TypeTag>
101 class NewTranIntensiveQuantities
102 {
103  using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
104 protected:
105  void update_(const ElementContext&, unsigned, unsigned)
106  { }
107 };
108 
113 template <class TypeTag>
114 class NewTranExtensiveQuantities
115 {
116  using Implementation = GetPropType<TypeTag, Properties::ExtensiveQuantities>;
117 
118  using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
119  using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
120  using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
121  using Scalar = GetPropType<TypeTag, Properties::Scalar>;
122  using Evaluation = GetPropType<TypeTag, Properties::Evaluation>;
123  using GridView = GetPropType<TypeTag, Properties::GridView>;
124  using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
125 
126  enum { dimWorld = GridView::dimensionworld };
127  enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
128  enum { numPhases = FluidSystem::numPhases };
129 
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>();
136 
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>;
141 
142  using ConvectiveMixingModule = BlackOilConvectiveMixingModule<TypeTag, enableConvectiveMixing>;
143  using ModuleParams = BlackoilModuleParams<ConvectiveMixingModuleParam<Scalar>>;
144 
145 public:
149  OPM_HOST_DEVICE const DimMatrix& intrinsicPermeability() const
150  {
151  OPM_THROW(std::invalid_argument, "The ECL transmissibility module does not provide an explicit intrinsic permeability");
152  }
153 
160  OPM_HOST_DEVICE const EvalDimVector& potentialGrad(unsigned) const
161  {
162  OPM_THROW(std::invalid_argument, "The ECL transmissibility module does not provide explicit potential gradients");
163  }
164 
171  OPM_HOST_DEVICE const Evaluation& pressureDifference(unsigned phaseIdx) const
172  { return pressureDifference_[phaseIdx]; }
173 
180  OPM_HOST_DEVICE const EvalDimVector& filterVelocity(unsigned) const
181  {
182  OPM_THROW(std::invalid_argument, "The ECL transmissibility module does not provide explicit filter velocities");
183  }
184 
194  OPM_HOST_DEVICE const Evaluation& volumeFlux(unsigned phaseIdx) const
195  { return volumeFlux_[phaseIdx]; }
196 
197 protected:
205  OPM_HOST_DEVICE unsigned upstreamIndex_(unsigned phaseIdx) const
206  {
207  assert(phaseIdx < numPhases);
208 
209  return upIdx_[phaseIdx];
210  }
211 
219  OPM_HOST_DEVICE unsigned downstreamIndex_(unsigned phaseIdx) const
220  {
221  assert(phaseIdx < numPhases);
222 
223  return dnIdx_[phaseIdx];
224  }
225 
226  OPM_HOST_DEVICE void updateSolvent(const ElementContext& elemCtx, unsigned scvfIdx, unsigned timeIdx)
227  {
228  if constexpr (enableSolvent) {
229  asImp_().updateVolumeFluxTrans(elemCtx, scvfIdx, timeIdx);
230  }
231  }
232 
233  OPM_HOST_DEVICE void updatePolymer(const ElementContext& elemCtx, unsigned scvfIdx, unsigned timeIdx)
234  {
235  if constexpr (enablePolymer) {
236  asImp_().updateShearMultipliers(elemCtx, scvfIdx, timeIdx);
237  }
238  }
239 
240 public:
241 
242  OPM_HOST_DEVICE static void volumeAndPhasePressureDifferences(std::array<short, numPhases>& upIdx,
243  std::array<short, numPhases>& dnIdx,
244  Evaluation (&volumeFlux)[numPhases],
245  Evaluation (&pressureDifferences)[numPhases],
246  const ElementContext& elemCtx,
247  unsigned scvfIdx,
248  unsigned timeIdx)
249  {
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();
255 
256  assert(interiorDofIdx != exteriorDofIdx);
257 
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);
264 
265  // estimate the gravity correction: for performance reasons we use a simplified
266  // approach for this flux module that assumes that gravity is constant and always
267  // acts into the downwards direction. (i.e., no centrifuge experiments, sorry.)
268  Scalar g = elemCtx.problem().gravity()[dimWorld - 1];
269 
270  const auto& intQuantsIn = elemCtx.intensiveQuantities(interiorDofIdx, timeIdx);
271  const auto& intQuantsEx = elemCtx.intensiveQuantities(exteriorDofIdx, timeIdx);
272 
273  // this is quite hacky because the dune grid interface does not provide a
274  // cellCenterDepth() method (so we ask the problem to provide it). The "good"
275  // solution would be to take the Z coordinate of the element centroids, but since
276  // ECL seems to like to be inconsistent on that front, it needs to be done like
277  // here...
278  Scalar zIn = problem.dofCenterDepth(elemCtx, interiorDofIdx, timeIdx);
279  Scalar zEx = problem.dofCenterDepth(elemCtx, exteriorDofIdx, timeIdx);
280 
281  // the distances from the DOF's depths. (i.e., the additional depth of the
282  // exterior DOF)
283  Scalar distZ = zIn - zEx;
284 
285  Scalar Vin = elemCtx.dofVolume(interiorDofIdx, /*timeIdx=*/0);
286  Scalar Vex = elemCtx.dofVolume(exteriorDofIdx, /*timeIdx=*/0);
287 
288  for (unsigned phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
289  if (!FluidSystem::phaseIsActive(phaseIdx))
290  continue;
291  calculatePhasePressureDiff_(upIdx[phaseIdx],
292  dnIdx[phaseIdx],
293  pressureDifferences[phaseIdx],
294  intQuantsIn,
295  intQuantsEx,
296  phaseIdx,//input
297  interiorDofIdx,//input
298  exteriorDofIdx,//input
299  Vin,
300  Vex,
301  I,
302  J,
303  distZ*g,
304  thpresInToEx,
305  thpresExToIn,
306  problem.moduleParams());
307 
308  const bool upwindIsInterior = (static_cast<unsigned>(upIdx[phaseIdx]) == interiorDofIdx);
309  const IntensiveQuantities& up = upwindIsInterior ? intQuantsIn : intQuantsEx;
310  // Use arithmetic average (more accurate with harmonic, but that requires recomputing the transmissbility)
311  const Evaluation transMult = (intQuantsIn.rockCompTransMultiplier() + Toolbox::value(intQuantsEx.rockCompTransMultiplier()))/2;
312 
313  const auto& materialLawManager = problem.materialLawManager();
314  FaceDir::DirEnum facedir = FaceDir::DirEnum::Unknown;
315  if (materialLawManager->hasDirectionalRelperms()) {
316  facedir = scvf.faceDirFromDirId(); // direction (X, Y, or Z) of the face
317  }
318  if (upwindIsInterior)
319  volumeFlux[phaseIdx] =
320  pressureDifferences[phaseIdx]*up.mobility(phaseIdx, facedir)*transMult*(-trans/faceArea);
321  else
322  volumeFlux[phaseIdx] =
323  pressureDifferences[phaseIdx]*
324  (Toolbox::value(up.mobility(phaseIdx, facedir))*transMult*(-trans/faceArea));
325  }
326  }
327 
328  template<class EvalType, class ModuleParamsT = ModuleParams>
329  OPM_HOST_DEVICE static void calculatePhasePressureDiff_(short& upIdx,
330  short& dnIdx,
331  EvalType& pressureDifference,
332  const IntensiveQuantities& intQuantsIn,
333  const IntensiveQuantities& intQuantsEx,
334  const unsigned phaseIdx,
335  const unsigned interiorDofIdx,
336  const unsigned exteriorDofIdx,
337  const Scalar Vin,
338  const Scalar Vex,
339  const unsigned globalIndexIn,
340  const unsigned globalIndexEx,
341  const Scalar distZg,
342  const Scalar thpresInToEx,
343  const Scalar thpresExToIn,
344  const ModuleParamsT& moduleParams)
345  {
346 
347  // check shortcut: if the mobility of the phase is zero in the interior as
348  // well as the exterior DOF, we can skip looking at the phase.
349  if (intQuantsIn.mobility(phaseIdx) <= 0.0 &&
350  intQuantsEx.mobility(phaseIdx) <= 0.0)
351  {
352  upIdx = interiorDofIdx;
353  dnIdx = exteriorDofIdx;
354  pressureDifference = 0.0;
355  return;
356  }
357 
358  // do the gravity correction: compute the hydrostatic pressure for the
359  // external at the depth of the internal one
360  const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
361  Scalar rhoEx = Toolbox::value(intQuantsEx.fluidState().density(phaseIdx));
362  Evaluation rhoAvg = (rhoIn + rhoEx)/2;
363 
364  if constexpr (enableConvectiveMixing) {
365  ConvectiveMixingModule::modifyAvgDensity(rhoAvg, intQuantsIn, intQuantsEx, phaseIdx, moduleParams.convectiveMixingModuleParam);
366  }
367 
368  const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
369  Evaluation pressureExterior = Toolbox::value(intQuantsEx.fluidState().pressure(phaseIdx));
370  if (enableExtbo) // added stability; particulary useful for solvent migrating in pure water
371  // where the solvent fraction displays a 0/1 behaviour ...
372  pressureExterior += Toolbox::value(rhoAvg)*(distZg);
373  else
374  pressureExterior += rhoAvg*(distZg);
375 
376  pressureDifference = pressureExterior - pressureInterior;
377 
378  // decide the upstream index for the phase. for this we make sure that the
379  // degree of freedom which is regarded upstream if both pressures are equal
380  // is always the same: if the pressure is equal, the DOF with the lower
381  // global index is regarded to be the upstream one.
382  if (pressureDifference > 0.0) {
383  upIdx = exteriorDofIdx;
384  dnIdx = interiorDofIdx;
385  }
386  else if (pressureDifference < 0.0) {
387  upIdx = interiorDofIdx;
388  dnIdx = exteriorDofIdx;
389  }
390  else {
391  // if the pressure difference is zero, we chose the DOF which has the
392  // larger volume associated to it as upstream DOF
393  if (Vin > Vex) {
394  upIdx = interiorDofIdx;
395  dnIdx = exteriorDofIdx;
396  }
397  else if (Vin < Vex) {
398  upIdx = exteriorDofIdx;
399  dnIdx = interiorDofIdx;
400  }
401  else {
402  assert(Vin == Vex);
403  // if the volumes are also equal, we pick the DOF which exhibits the
404  // smaller global index
405  if (globalIndexIn < globalIndexEx) {
406  upIdx = interiorDofIdx;
407  dnIdx = exteriorDofIdx;
408  }
409  else {
410  upIdx = exteriorDofIdx;
411  dnIdx = interiorDofIdx;
412  }
413  }
414  }
415 
416  // apply the threshold pressure for the intersection. note that the concept
417  // of threshold pressure is a quite big hack that only makes sense for ECL
418  // datasets. (and even there, its physical justification is quite
419  // questionable IMO.)
420  const Scalar thpres = pressureDifference < 0.0 ? thpresInToEx : thpresExToIn;
421  if (thpres > 0.0) {
422  if (std::abs(Toolbox::value(pressureDifference)) > thpres) {
423  if (pressureDifference < 0.0)
424  pressureDifference += thpres;
425  else
426  pressureDifference -= thpres;
427  }
428  else {
429  pressureDifference = 0.0;
430  }
431  }
432  }
433 
434 protected:
438  OPM_HOST_DEVICE void calculateGradients_(const ElementContext& elemCtx, unsigned scvfIdx, unsigned timeIdx)
439  {
440  Valgrind::SetUndefined(*this);
441 
442  volumeAndPhasePressureDifferences(upIdx_ , dnIdx_, volumeFlux_, pressureDifference_, elemCtx, scvfIdx, timeIdx);
443  }
444 
448  template <class FluidState>
449  OPM_HOST_DEVICE void calculateBoundaryGradients_(const ElementContext& elemCtx,
450  unsigned scvfIdx,
451  unsigned timeIdx,
452  const FluidState& exFluidState)
453  {
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);
460 
462  globalSpaceIdx,
463  intQuantsIn,
464  scvfIdx,
465  faceArea,
466  zEx,
467  exFluidState,
468  upIdx_,
469  dnIdx_,
470  volumeFlux_,
471  pressureDifference_);
472 
473  // Treating solvent here and not in the static method, since that would require more
474  // extensive refactoring. It means that the TpfaLinearizer will not support bcs for solvent until this is
475  // addressed.
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);
482  } else {
483  asImp_().setSolventVolumeFlux(0.0);
484  }
485  }
486  }
487 
488 public:
492  template <class Problem, class FluidState, class EvaluationContainer>
493  OPM_HOST_DEVICE static void calculateBoundaryGradients_(const Problem& problem,
494  const unsigned globalSpaceIdx,
495  const IntensiveQuantities& intQuantsIn,
496  const unsigned bfIdx,
497  const double faceArea,
498  const double zEx,
499  const FluidState& exFluidState,
500  std::array<short, numPhases>& upIdx,
501  std::array<short, numPhases>& dnIdx,
502  EvaluationContainer& volumeFlux,
503  EvaluationContainer& pressureDifference)
504  {
505 
506  bool enableBoundaryMassFlux = problem.nonTrivialBoundaryConditions();
507  if (!enableBoundaryMassFlux)
508  return;
509 
510  Scalar trans = problem.transmissibilityBoundary(globalSpaceIdx, bfIdx);
511 
512  // estimate the gravity correction: for performance reasons we use a simplified
513  // approach for this flux module that assumes that gravity is constant and always
514  // acts into the downwards direction. (i.e., no centrifuge experiments, sorry.)
515  Scalar g = problem.gravity()[dimWorld - 1];
516 
517  // this is quite hacky because the dune grid interface does not provide a
518  // cellCenterDepth() method (so we ask the problem to provide it). The "good"
519  // solution would be to take the Z coordinate of the element centroids, but since
520  // ECL seems to like to be inconsistent on that front, it needs to be done like
521  // here...
522  Scalar zIn = problem.dofCenterDepth(globalSpaceIdx);
523 
524  // the distances from the DOF's depths. (i.e., the additional depth of the
525  // exterior DOF)
526  Scalar distZ = zIn - zEx;
527 
528  for (unsigned phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
529  if (!FluidSystem::phaseIsActive(phaseIdx))
530  continue;
531 
532  // do the gravity correction: compute the hydrostatic pressure for the
533  // integration position
534  const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
535  const auto& rhoEx = exFluidState.density(phaseIdx);
536  Evaluation rhoAvg = (rhoIn + rhoEx)/2;
537 
538  const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
539  Evaluation pressureExterior = exFluidState.pressure(phaseIdx);
540  pressureExterior += rhoAvg*(distZ*g);
541 
542  pressureDifference[phaseIdx] = pressureExterior - pressureInterior;
543 
544  // decide the upstream index for the phase. for this we make sure that the
545  // degree of freedom which is regarded upstream if both pressures are equal
546  // is always the same: if the pressure is equal, the DOF with the lower
547  // global index is regarded to be the upstream one.
548  const unsigned interiorDofIdx = 0; // Valid only for cell-centered FV.
549  if (pressureDifference[phaseIdx] > 0.0) {
550  upIdx[phaseIdx] = -1;
551  dnIdx[phaseIdx] = interiorDofIdx;
552  }
553  else {
554  upIdx[phaseIdx] = interiorDofIdx;
555  dnIdx[phaseIdx] = -1;
556  }
557 
558  Evaluation transModified = trans;
559 
560  if (upIdx[phaseIdx] == interiorDofIdx) {
561 
562  // this is slightly hacky because in the automatic differentiation case, it
563  // only works for the element centered finite volume method.
564  const auto& up = intQuantsIn;
565 
566  // deal with water induced rock compaction
567  const Scalar transMult = Toolbox::value(up.rockCompTransMultiplier());
568  transModified *= transMult;
569 
570  volumeFlux[phaseIdx] =
571  pressureDifference[phaseIdx]*up.mobility(phaseIdx)*(-transModified/faceArea);
572  }
573  else {
574  // compute the phase mobility using the material law parameters of the
575  // interior element. TODO: this could probably be done more efficiently
576  const auto& matParams = problem.materialLawParams(globalSpaceIdx);
577  std::array<typename FluidState::ValueType,numPhases> kr;
578  MaterialLaw::relativePermeabilities(kr, matParams, exFluidState);
579 
580  const auto& mob = kr[phaseIdx]/exFluidState.viscosity(phaseIdx);
581  volumeFlux[phaseIdx] =
582  pressureDifference[phaseIdx]*mob*(-transModified/faceArea);
583  }
584  }
585  }
586 
587 protected:
588 
592  OPM_HOST_DEVICE void calculateFluxes_(const ElementContext&, unsigned, unsigned)
593  { }
594 
595  OPM_HOST_DEVICE void calculateBoundaryFluxes_(const ElementContext&, unsigned, unsigned)
596  {}
597 
598 private:
599  Implementation& asImp_()
600  { return *static_cast<Implementation*>(this); }
601 
602  const Implementation& asImp_() const
603  { return *static_cast<const Implementation*>(this); }
604 
605  // the volumetric flux of all phases [m^3/s]
606  Evaluation volumeFlux_[numPhases];
607 
608  // the difference in effective pressure between the exterior and the interior degree
609  // of freedom [Pa]
610  Evaluation pressureDifference_[numPhases];
611 
612  // the local indices of the interior and exterior degrees of freedom
613  std::array<short, numPhases> upIdx_;
614  std::array<short, numPhases> dnIdx_;
615  };
616 
617 } // namespace Opm
618 
619 #endif // OPM_NEWTRAN_FLUX_MODULE_HPP
static void registerParameters()
Register all run-time parameters for the flux module.
Definition: NewTranFluxModule.hpp:83
Provides the intensive quantities for the ECL flux module.
Definition: NewTranFluxModule.hpp:61
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
OPM_HOST_DEVICE const Evaluation & volumeFlux(unsigned phaseIdx) const
Return the volume flux of a fluid phase at the face&#39;s integration point .
Definition: NewTranFluxModule.hpp:194
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
Specifies a flux module which uses ECL transmissibilities.
Definition: NewTranFluxModule.hpp:74
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 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
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
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.
Classes required for dynamic convective mixing.
Provides the ECL flux module.
Definition: NewTranFluxModule.hpp:64
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:493
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&#39;s integration point [m/s].
Definition: NewTranFluxModule.hpp:180
OPM_HOST_DEVICE const EvalDimVector & potentialGrad(unsigned) const
Return the pressure potential gradient of a fluid phase at the face&#39;s integration point [Pa/m]...
Definition: NewTranFluxModule.hpp:160
Provides the defaults for the parameters required by the transmissibility based volume flux calculati...
Definition: NewTranFluxModule.hpp:67
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