blackoilintensivequantities.hh
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*/
28#ifndef EWOMS_BLACK_OIL_INTENSIVE_QUANTITIES_HH
29#define EWOMS_BLACK_OIL_INTENSIVE_QUANTITIES_HH
30
31#include "blackoilproperties.hh"
41
42#include <opm/common/TimingMacros.hpp>
43#include <opm/common/OpmLog/OpmLog.hpp>
44
45#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
46
47#include <opm/material/fluidstates/BlackOilFluidState.hpp>
48#include <opm/material/common/Valgrind.hpp>
49
51
52#include <opm/utility/CopyablePtr.hpp>
53
54#include <dune/common/fmatrix.hh>
55
56#include <cstring>
57#include <utility>
58
59#include <fmt/format.h>
60
61namespace Opm {
69template <class TypeTag>
71 : public GetPropType<TypeTag, Properties::DiscIntensiveQuantities>
72 , public GetPropType<TypeTag, Properties::FluxModule>::FluxIntensiveQuantities
73 , public BlackOilDiffusionIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableDiffusion>() >
74 , public BlackOilDispersionIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableDispersion>() >
76 , public BlackOilExtboIntensiveQuantities<TypeTag>
78 , public BlackOilFoamIntensiveQuantities<TypeTag>
79 , public BlackOilBrineIntensiveQuantities<TypeTag>
80 , public BlackOilEnergyIntensiveQuantities<TypeTag>
81 , public BlackOilMICPIntensiveQuantities<TypeTag>
82{
85
95
96 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
97 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
98 enum { enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>() };
99 enum { enablePolymer = getPropValue<TypeTag, Properties::EnablePolymer>() };
100 enum { enableFoam = getPropValue<TypeTag, Properties::EnableFoam>() };
101 enum { enableBrine = getPropValue<TypeTag, Properties::EnableBrine>() };
102 enum { enableVapwat = getPropValue<TypeTag, Properties::EnableVapwat>() };
103 enum { has_disgas_in_water = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
104 enum { enableSaltPrecipitation = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>() };
105 enum { enableTemperature = getPropValue<TypeTag, Properties::EnableTemperature>() };
106 enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
107 enum { enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>() };
108 enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
109 enum { enableMICP = getPropValue<TypeTag, Properties::EnableMICP>() };
110 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
111 enum { numComponents = getPropValue<TypeTag, Properties::NumComponents>() };
112 enum { waterCompIdx = FluidSystem::waterCompIdx };
113 enum { oilCompIdx = FluidSystem::oilCompIdx };
114 enum { gasCompIdx = FluidSystem::gasCompIdx };
115 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
116 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
117 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
118 enum { dimWorld = GridView::dimensionworld };
119 enum { compositionSwitchIdx = Indices::compositionSwitchIdx };
120
121 static constexpr bool compositionSwitchEnabled = Indices::compositionSwitchIdx >= 0;
122 static constexpr bool waterEnabled = Indices::waterEnabled;
123 static constexpr bool gasEnabled = Indices::gasEnabled;
124 static constexpr bool oilEnabled = Indices::oilEnabled;
125
126 using Toolbox = MathToolbox<Evaluation>;
127 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
128 using FluxIntensiveQuantities = typename FluxModule::FluxIntensiveQuantities;
131
132 using DirectionalMobilityPtr = Opm::Utility::CopyablePtr<DirectionalMobility<TypeTag, Evaluation>>;
134
135
136public:
137 using FluidState = BlackOilFluidState<Evaluation,
138 FluidSystem,
139 enableTemperature,
140 enableEnergy,
141 compositionSwitchEnabled,
142 enableVapwat,
143 enableBrine,
144 enableSaltPrecipitation,
145 has_disgas_in_water,
146 Indices::numPhases>;
147 using ScalarFluidState = BlackOilFluidState<Scalar,
148 FluidSystem,
149 enableTemperature,
150 enableEnergy,
151 compositionSwitchEnabled,
152 enableVapwat,
153 enableBrine,
154 enableSaltPrecipitation,
155 has_disgas_in_water,
156 Indices::numPhases>;
158
160 {
161 if (compositionSwitchEnabled) {
162 fluidState_.setRs(0.0);
163 fluidState_.setRv(0.0);
164 }
165 if (enableVapwat) {
166 fluidState_.setRvw(0.0);
167 }
168 if (has_disgas_in_water) {
169 fluidState_.setRsw(0.0);
170 }
171 }
173
175
179 void update(const ElementContext& elemCtx, unsigned dofIdx, unsigned timeIdx)
180 {
181 ParentType::update(elemCtx, dofIdx, timeIdx);
182 OPM_TIMEBLOCK_LOCAL(blackoilIntensiveQuanititiesUpdate);
183 const auto& problem = elemCtx.problem();
184 const auto& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
185 const auto& linearizationType = problem.model().linearizer().getLinearizationType();
186 unsigned globalSpaceIdx = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
187 Scalar RvMax = FluidSystem::enableVaporizedOil()
188 ? problem.maxOilVaporizationFactor(timeIdx, globalSpaceIdx)
189 : 0.0;
190 Scalar RsMax = FluidSystem::enableDissolvedGas()
191 ? problem.maxGasDissolutionFactor(timeIdx, globalSpaceIdx)
192 : 0.0;
193 Scalar RswMax = FluidSystem::enableDissolvedGasInWater()
194 ? problem.maxGasDissolutionFactor(timeIdx, globalSpaceIdx)
195 : 0.0;
196
197 asImp_().updateTemperature_(elemCtx, dofIdx, timeIdx);
198
199 unsigned pvtRegionIdx = priVars.pvtRegionIndex();
200 fluidState_.setPvtRegionIndex(pvtRegionIdx);
201
202 asImp_().updateSaltConcentration_(elemCtx, dofIdx, timeIdx);
203
204 // extract the water and the gas saturations for convenience
205 Evaluation Sw = 0.0;
206 if constexpr (waterEnabled) {
207 if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Sw) {
208 Sw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
209 } else if(priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rsw ||
210 priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Disabled) {
211 // water is enabled but is not a primary variable i.e. one component/phase case
212 // or two-phase water + gas with only water present
213 Sw = 1.0;
214 } // else i.e. for MeaningWater() = Rvw, Sw is still 0.0;
215 }
216 Evaluation Sg = 0.0;
217 if constexpr (gasEnabled) {
218 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Sg) {
219 Sg = priVars.makeEvaluation(Indices::compositionSwitchIdx, timeIdx);
220 } else if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rv) {
221 Sg = 1.0 - Sw;
222 } else if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Disabled) {
223 if constexpr (waterEnabled) {
224 Sg = 1.0 - Sw; // two phase water + gas
225 } else {
226 // one phase case
227 Sg = 1.0;
228 }
229 }
230 }
231 Valgrind::CheckDefined(Sg);
232 Valgrind::CheckDefined(Sw);
233
234 Evaluation So = 1.0 - Sw - Sg;
235
236 // deal with solvent
237 if constexpr (enableSolvent) {
238 if(priVars.primaryVarsMeaningSolvent() == PrimaryVariables::SolventMeaning::Ss) {
239 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
240 So -= priVars.makeEvaluation(Indices::solventSaturationIdx, timeIdx);
241 } else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
242 Sg -= priVars.makeEvaluation(Indices::solventSaturationIdx, timeIdx);
243 }
244 }
245 }
246
247 if (FluidSystem::phaseIsActive(waterPhaseIdx))
248 fluidState_.setSaturation(waterPhaseIdx, Sw);
249
250 if (FluidSystem::phaseIsActive(gasPhaseIdx))
251 fluidState_.setSaturation(gasPhaseIdx, Sg);
252
253 if (FluidSystem::phaseIsActive(oilPhaseIdx))
254 fluidState_.setSaturation(oilPhaseIdx, So);
255
256 asImp_().solventPreSatFuncUpdate_(elemCtx, dofIdx, timeIdx);
257
258 // now we compute all phase pressures
259 std::array<Evaluation, numPhases> pC;
260 const auto& materialParams = problem.materialLawParams(globalSpaceIdx);
261 MaterialLaw::capillaryPressures(pC, materialParams, fluidState_);
262 problem.updateRelperms(mobility_, dirMob_, fluidState_, globalSpaceIdx);
263
264 // scaling the capillary pressure due to salt precipitation
265 if (BrineModule::hasPcfactTables() && priVars.primaryVarsMeaningBrine() == PrimaryVariables::BrineMeaning::Sp) {
266 unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, dofIdx, timeIdx);
267 const Evaluation Sp = priVars.makeEvaluation(Indices::saltConcentrationIdx, timeIdx);
268 const Evaluation porosityFactor = min(1.0 - Sp, 1.0); //phi/phi_0
269 const auto& pcfactTable = BrineModule::pcfactTable(satnumRegionIdx);
270 const Evaluation pcFactor = pcfactTable.eval(porosityFactor, /*extrapolation=*/true);
271 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
272 if (FluidSystem::phaseIsActive(phaseIdx)) {
273 pC[phaseIdx] *= pcFactor;
274 }
275 }
276
277 // oil is the reference phase for pressure
278 if (priVars.primaryVarsMeaningPressure() == PrimaryVariables::PressureMeaning::Pg) {
279 const Evaluation& pg = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
280 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
281 if (FluidSystem::phaseIsActive(phaseIdx))
282 fluidState_.setPressure(phaseIdx, pg + (pC[phaseIdx] - pC[gasPhaseIdx]));
283 } else if (priVars.primaryVarsMeaningPressure() == PrimaryVariables::PressureMeaning::Pw) {
284 const Evaluation& pw = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
285 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
286 if (FluidSystem::phaseIsActive(phaseIdx))
287 fluidState_.setPressure(phaseIdx, pw + (pC[phaseIdx] - pC[waterPhaseIdx]));
288 } else {
289 assert(FluidSystem::phaseIsActive(oilPhaseIdx));
290 const Evaluation& po = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
291 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
292 if (FluidSystem::phaseIsActive(phaseIdx))
293 fluidState_.setPressure(phaseIdx, po + (pC[phaseIdx] - pC[oilPhaseIdx]));
294 }
295
296 // update the Saturation functions for the blackoil solvent module.
297 asImp_().solventPostSatFuncUpdate_(elemCtx, dofIdx, timeIdx);
298
299 // update extBO parameters
300 asImp_().zFractionUpdate_(elemCtx, dofIdx, timeIdx);
301
302 Evaluation SoMax = 0.0;
303 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
304 SoMax = max(fluidState_.saturation(oilPhaseIdx),
305 problem.maxOilSaturation(globalSpaceIdx));
306 }
307 // take the meaning of the switching primary variable into account for the gas
308 // and oil phase compositions
309 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rs) {
310 const auto& Rs = priVars.makeEvaluation(Indices::compositionSwitchIdx, timeIdx);
311 fluidState_.setRs(Rs);
312 } else {
313 if (FluidSystem::enableDissolvedGas()) { // Add So > 0? i.e. if only water set rs = 0)
314 const Evaluation& RsSat = enableExtbo ? asImp_().rs() :
315 FluidSystem::saturatedDissolutionFactor(fluidState_,
316 oilPhaseIdx,
317 pvtRegionIdx,
318 SoMax);
319 fluidState_.setRs(min(RsMax, RsSat));
320 }
321 else if constexpr (compositionSwitchEnabled)
322 fluidState_.setRs(0.0);
323 }
324 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rv) {
325 const auto& Rv = priVars.makeEvaluation(Indices::compositionSwitchIdx, timeIdx);
326 fluidState_.setRv(Rv);
327 } else {
328 if (FluidSystem::enableVaporizedOil() ) { // Add Sg > 0? i.e. if only water set rv = 0)
329 const Evaluation& RvSat = enableExtbo ? asImp_().rv() :
330 FluidSystem::saturatedDissolutionFactor(fluidState_,
331 gasPhaseIdx,
332 pvtRegionIdx,
333 SoMax);
334 fluidState_.setRv(min(RvMax, RvSat));
335 }
336 else if constexpr (compositionSwitchEnabled)
337 fluidState_.setRv(0.0);
338 }
339
340 if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rvw) {
341 const auto& Rvw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
342 fluidState_.setRvw(Rvw);
343 } else {
344 if (FluidSystem::enableVaporizedWater()) { // Add Sg > 0? i.e. if only water set rv = 0)
345 const Evaluation& RvwSat = FluidSystem::saturatedVaporizationFactor(fluidState_,
346 gasPhaseIdx,
347 pvtRegionIdx);
348 fluidState_.setRvw(RvwSat);
349 }
350 }
351
352 if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rsw) {
353 const auto& Rsw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
354 fluidState_.setRsw(Rsw);
355 } else {
356 if (FluidSystem::enableDissolvedGasInWater()) {
357 const Evaluation& RswSat = FluidSystem::saturatedDissolutionFactor(fluidState_,
358 waterPhaseIdx,
359 pvtRegionIdx);
360 fluidState_.setRsw(min(RswMax, RswSat));
361 }
362 }
363
364 typename FluidSystem::template ParameterCache<Evaluation> paramCache;
365 paramCache.setRegionIndex(pvtRegionIdx);
366 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
367 paramCache.setMaxOilSat(SoMax);
368 }
369 paramCache.updateAll(fluidState_);
370
371 // compute the phase densities and transform the phase permeabilities into mobilities
372 int nmobilities = 1;
373 std::vector<std::array<Evaluation,numPhases>*> mobilities = {&mobility_};
374 if (dirMob_) {
375 for (int i=0; i<3; i++) {
376 nmobilities += 1;
377 mobilities.push_back(&(dirMob_->getArray(i)));
378 }
379 }
380 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
381 if (!FluidSystem::phaseIsActive(phaseIdx))
382 continue;
383 const auto& b = FluidSystem::inverseFormationVolumeFactor(fluidState_, phaseIdx, pvtRegionIdx);
384 fluidState_.setInvB(phaseIdx, b);
385 const auto& mu = FluidSystem::viscosity(fluidState_, paramCache, phaseIdx);
386 for (int i = 0; i<nmobilities; i++) {
387 if (enableExtbo && phaseIdx == oilPhaseIdx) {
388 (*mobilities[i])[phaseIdx] /= asImp_().oilViscosity();
389 }
390 else if (enableExtbo && phaseIdx == gasPhaseIdx) {
391 (*mobilities[i])[phaseIdx] /= asImp_().gasViscosity();
392 }
393 else {
394 (*mobilities[i])[phaseIdx] /= mu;
395 }
396 }
397 }
398 Valgrind::CheckDefined(mobility_);
399
400 // calculate the phase densities
401 Evaluation rho;
402 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
403 rho = fluidState_.invB(waterPhaseIdx);
404 rho *= FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
405 if (FluidSystem::enableDissolvedGasInWater()) {
406 rho +=
407 fluidState_.invB(waterPhaseIdx) *
408 fluidState_.Rsw() *
409 FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
410 }
411 fluidState_.setDensity(waterPhaseIdx, rho);
412 }
413
414 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
415 rho = fluidState_.invB(gasPhaseIdx);
416 rho *= FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
417 if (FluidSystem::enableVaporizedOil()) {
418 rho +=
419 fluidState_.invB(gasPhaseIdx) *
420 fluidState_.Rv() *
421 FluidSystem::referenceDensity(oilPhaseIdx, pvtRegionIdx);
422 }
423 if (FluidSystem::enableVaporizedWater()) {
424 rho +=
425 fluidState_.invB(gasPhaseIdx) *
426 fluidState_.Rvw() *
427 FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
428 }
429 fluidState_.setDensity(gasPhaseIdx, rho);
430 }
431
432 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
433 rho = fluidState_.invB(oilPhaseIdx);
434 rho *= FluidSystem::referenceDensity(oilPhaseIdx, pvtRegionIdx);
435 if (FluidSystem::enableDissolvedGas()) {
436 rho +=
437 fluidState_.invB(oilPhaseIdx) *
438 fluidState_.Rs() *
439 FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
440 }
441 fluidState_.setDensity(oilPhaseIdx, rho);
442 }
443
444 // retrieve the porosity from the problem
445 referencePorosity_ = problem.porosity(elemCtx, dofIdx, timeIdx);
446 porosity_ = referencePorosity_;
447
448 // the porosity must be modified by the compressibility of the
449 // rock...
450 Scalar rockCompressibility = problem.rockCompressibility(globalSpaceIdx);
451 if (rockCompressibility > 0.0) {
452 Scalar rockRefPressure = problem.rockReferencePressure(globalSpaceIdx);
453 Evaluation x;
454 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
455 x = rockCompressibility*(fluidState_.pressure(oilPhaseIdx) - rockRefPressure);
456 } else if (FluidSystem::phaseIsActive(waterPhaseIdx)){
457 x = rockCompressibility*(fluidState_.pressure(waterPhaseIdx) - rockRefPressure);
458 } else {
459 x = rockCompressibility*(fluidState_.pressure(gasPhaseIdx) - rockRefPressure);
460 }
461 porosity_ *= 1.0 + x + 0.5*x*x;
462 }
463
464 // deal with water induced rock compaction
465 porosity_ *= problem.template rockCompPoroMultiplier<Evaluation>(*this, globalSpaceIdx);
466
467 // the MICP processes change the porosity
468 if constexpr (enableMICP){
469 Evaluation biofilm_ = priVars.makeEvaluation(Indices::biofilmConcentrationIdx, timeIdx, linearizationType);
470 Evaluation calcite_ = priVars.makeEvaluation(Indices::calciteConcentrationIdx, timeIdx, linearizationType);
471 porosity_ += - biofilm_ - calcite_;
472 }
473
474 // deal with salt-precipitation
475 if (enableSaltPrecipitation && priVars.primaryVarsMeaningBrine() == PrimaryVariables::BrineMeaning::Sp) {
476 Evaluation Sp = priVars.makeEvaluation(Indices::saltConcentrationIdx, timeIdx);
477 porosity_ *= (1.0 - Sp);
478 }
479
480 rockCompTransMultiplier_ = problem.template rockCompTransMultiplier<Evaluation>(*this, globalSpaceIdx);
481
482 asImp_().solventPvtUpdate_(elemCtx, dofIdx, timeIdx);
483 asImp_().zPvtUpdate_();
484 asImp_().polymerPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
485 asImp_().updateEnergyQuantities_(elemCtx, dofIdx, timeIdx, paramCache);
486 asImp_().foamPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
487 asImp_().MICPPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
488 asImp_().saltPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
489
490 // update the quantities which are required by the chosen
491 // velocity model
492 FluxIntensiveQuantities::update_(elemCtx, dofIdx, timeIdx);
493
494 // update the diffusion specific quantities of the intensive quantities
495 DiffusionIntensiveQuantities::update_(fluidState_, paramCache, elemCtx, dofIdx, timeIdx);
496
497 // update the dispersion specific quantities of the intensive quantities
498 DispersionIntensiveQuantities::update_(elemCtx, dofIdx, timeIdx);
499
500#ifndef NDEBUG
501 // some safety checks in debug mode
502 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
503 if (!FluidSystem::phaseIsActive(phaseIdx))
504 continue;
505
506 assert(isfinite(fluidState_.density(phaseIdx)));
507 assert(isfinite(fluidState_.saturation(phaseIdx)));
508 assert(isfinite(fluidState_.temperature(phaseIdx)));
509 assert(isfinite(fluidState_.pressure(phaseIdx)));
510 assert(isfinite(fluidState_.invB(phaseIdx)));
511 }
512 assert(isfinite(fluidState_.Rs()));
513 assert(isfinite(fluidState_.Rv()));
514
515#endif
516 }
517
521 const FluidState& fluidState() const
522 { return fluidState_; }
523
527 const Evaluation& mobility(unsigned phaseIdx) const
528 { return mobility_[phaseIdx]; }
529
530 const Evaluation& mobility(unsigned phaseIdx, FaceDir::DirEnum facedir) const
531 {
532 using Dir = FaceDir::DirEnum;
533 if (dirMob_) {
534 switch(facedir) {
535 case Dir::XMinus:
536 case Dir::XPlus:
537 return dirMob_->mobilityX_[phaseIdx];
538 case Dir::YMinus:
539 case Dir::YPlus:
540 return dirMob_->mobilityY_[phaseIdx];
541 case Dir::ZMinus:
542 case Dir::ZPlus:
543 return dirMob_->mobilityZ_[phaseIdx];
544 default:
545 throw std::runtime_error("Unexpected face direction");
546 }
547 }
548 else {
549 return mobility_[phaseIdx];
550 }
551
552 }
553
557 const Evaluation& porosity() const
558 { return porosity_; }
559
563 const Evaluation& rockCompTransMultiplier() const
564 { return rockCompTransMultiplier_; }
565
573 auto pvtRegionIndex() const
574 -> decltype(std::declval<FluidState>().pvtRegionIndex())
575 { return fluidState_.pvtRegionIndex(); }
576
580 Evaluation relativePermeability(unsigned phaseIdx) const
581 {
582 // warning: slow
583 return fluidState_.viscosity(phaseIdx)*mobility(phaseIdx);
584 }
585
592 Scalar referencePorosity() const
593 { return referencePorosity_; }
594
595private:
603
604 Implementation& asImp_()
605 { return *static_cast<Implementation*>(this); }
606
607 FluidState fluidState_;
608 Scalar referencePorosity_;
609 Evaluation porosity_;
610 Evaluation rockCompTransMultiplier_;
611 std::array<Evaluation,numPhases> mobility_;
612
613 // Instead of writing a custom copy constructor and a custom assignment operator just to handle
614 // the dirMob_ unique ptr member variable when copying BlackOilIntensiveQuantites (see for example
615 // updateIntensitiveQuantities_() in fvbaseelementcontext.hh for a copy example) we write the below
616 // custom wrapper class CopyablePtr which wraps the unique ptr and makes it copyable.
617 //
618 // The advantage of this approach is that we avoid having to call all the base class copy constructors and
619 // assignment operators explicitly (which is needed when writing the custom copy constructor and assignment
620 // operators) which could become a maintenance burden. For example, when adding a new base class (if that should
621 // be needed sometime in the future) to BlackOilIntensiveQuantites we could forget to update the copy
622 // constructor and assignment operators.
623 //
624 // We want each copy of the BlackOilIntensiveQuantites to be unique, (TODO: why?) so we have to make a copy
625 // of the unique_ptr each time we copy construct or assign to it from another BlackOilIntensiveQuantites.
626 // (On the other hand, if a copy could share the ptr with the original, a shared_ptr could be used instead and the
627 // wrapper would not be needed)
628 DirectionalMobilityPtr dirMob_;
629};
630
631} // namespace Opm
632
633#endif
Contains the classes required to extend the black-oil model by brine.
Classes required for molecular diffusion.
Classes required for mechanical dispersion.
Contains the classes required to extend the black-oil model by energy.
Contains the classes required to extend the black-oil model by solvent component. For details,...
Contains the classes required to extend the black-oil model to include the effects of foam.
Contains the classes required to extend the black-oil model by MICP.
Contains the classes required to extend the black-oil model by polymer.
Declares the properties required by the black oil model.
Contains the classes required to extend the black-oil model by solvents.
Definition: blackoilbrinemodules.hh:340
Contains the high level supplements required to extend the black oil model by brine.
Definition: blackoilbrinemodules.hh:50
static const TabulatedFunction & pcfactTable(unsigned satnumRegionIdx)
Definition: blackoilbrinemodules.hh:266
static bool hasPcfactTables()
Definition: blackoilbrinemodules.hh:310
Provides the volumetric quantities required for the calculation of molecular diffusive fluxes.
Definition: blackoildiffusionmodule.hh:274
Provides the volumetric quantities required for the calculation of dispersive fluxes.
Definition: blackoildispersionmodule.hh:278
Provides the volumetric quantities required for the equations needed by the energys extension of the ...
Definition: blackoilenergymodules.hh:333
Provides the volumetric quantities required for the equations needed by the solvents extension of the...
Definition: blackoilextbomodules.hh:399
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilfoammodules.hh:381
Contains the quantities which are are constant within a finite volume in the black-oil model.
Definition: blackoilintensivequantities.hh:82
const Evaluation & porosity() const
Returns the average porosity within the control volume.
Definition: blackoilintensivequantities.hh:557
const Evaluation & mobility(unsigned phaseIdx) const
Returns the effective mobility of a given phase within the control volume.
Definition: blackoilintensivequantities.hh:527
void update(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Definition: blackoilintensivequantities.hh:179
Evaluation relativePermeability(unsigned phaseIdx) const
Returns the relative permeability of a given phase within the control volume.
Definition: blackoilintensivequantities.hh:580
auto pvtRegionIndex() const -> decltype(std::declval< FluidState >().pvtRegionIndex())
Returns the index of the PVT region used to calculate the thermodynamic quantities.
Definition: blackoilintensivequantities.hh:573
const FluidState & fluidState() const
Returns the phase state for the control-volume.
Definition: blackoilintensivequantities.hh:521
BlackOilIntensiveQuantities & operator=(const BlackOilIntensiveQuantities &other)=default
const Evaluation & rockCompTransMultiplier() const
Definition: blackoilintensivequantities.hh:563
BlackOilIntensiveQuantities(const BlackOilIntensiveQuantities &other)=default
BlackOilIntensiveQuantities()
Definition: blackoilintensivequantities.hh:159
BlackOilFluidState< Scalar, FluidSystem, enableTemperature, enableEnergy, compositionSwitchEnabled, enableVapwat, enableBrine, enableSaltPrecipitation, has_disgas_in_water, Indices::numPhases > ScalarFluidState
Definition: blackoilintensivequantities.hh:156
const Evaluation & mobility(unsigned phaseIdx, FaceDir::DirEnum facedir) const
Definition: blackoilintensivequantities.hh:530
Scalar referencePorosity() const
Returns the porosity of the rock at reference conditions.
Definition: blackoilintensivequantities.hh:592
BlackOilFluidState< Evaluation, FluidSystem, enableTemperature, enableEnergy, compositionSwitchEnabled, enableVapwat, enableBrine, enableSaltPrecipitation, has_disgas_in_water, Indices::numPhases > FluidState
Definition: blackoilintensivequantities.hh:146
Provides the volumetric quantities required for the equations needed by the MICP extension of the bla...
Definition: blackoilmicpmodules.hh:371
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilpolymermodules.hh:552
Provides the volumetric quantities required for the equations needed by the solvents extension of the...
Definition: blackoilsolventmodules.hh:520
This file contains definitions related to directional mobilities.
Definition: blackoilboundaryratevector.hh:37
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:235