My Project
Loading...
Searching...
No Matches
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
97 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
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>() };
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
174 BlackOilIntensiveQuantities& operator=(const BlackOilIntensiveQuantities& other) = default;
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.
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
Provides the volumetric quantities required for the calculation of molecular diffusive fluxes.
Provides the volumetric quantities required for the calculation of dispersive fluxes.
Provides the volumetric quantities required for the equations needed by the energys extension of the ...
Provides the volumetric quantities required for the equations needed by the solvents extension of the...
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
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
const Evaluation & rockCompTransMultiplier() const
The pressure-dependent transmissibility multiplier due to rock compressibility.
Definition blackoilintensivequantities.hh:563
Scalar referencePorosity() const
Returns the porosity of the rock at reference conditions.
Definition blackoilintensivequantities.hh:592
Provides the volumetric quantities required for the equations needed by the MICP extension of the bla...
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Provides the volumetric quantities required for the equations needed by the solvents extension of the...
This file contains definitions related to directional mobilities.
This file contains a set of helper functions used by VFPProd / VFPInj.
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
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:242