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 <dune/common/fmatrix.hh>
32
33#include <opm/common/TimingMacros.hpp>
34
35#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
36
37#include <opm/material/fluidstates/BlackOilFluidState.hpp>
38#include <opm/material/common/Valgrind.hpp>
39
52
53#include <opm/utility/CopyablePtr.hpp>
54
55#include <array>
56#include <cassert>
57#include <cstring>
58#include <stdexcept>
59#include <utility>
60#include <vector>
61
62namespace Opm {
63
71template <class TypeTag>
73 : public GetPropType<TypeTag, Properties::DiscIntensiveQuantities>
74 , public GetPropType<TypeTag, Properties::FluxModule>::FluxIntensiveQuantities
75 , public BlackOilDiffusionIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableDiffusion>() >
76 , public BlackOilDispersionIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableDispersion>() >
77 , public BlackOilSolventIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableSolvent>()>
78 , public BlackOilExtboIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableExtbo>()>
79 , public BlackOilPolymerIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnablePolymer>()>
80 , public BlackOilFoamIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableFoam>()>
81 , public BlackOilBrineIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableBrine>()>
82 , public BlackOilEnergyIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnergyModuleType>()>
83 , public BlackOilBioeffectsIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableBioeffects>()>
84 , public BlackOilConvectiveMixingIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableConvectiveMixing>()>
85{
88
97
98 enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
99 enum { enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>() };
100 enum { enablePolymer = getPropValue<TypeTag, Properties::EnablePolymer>() };
101 enum { enableFoam = getPropValue<TypeTag, Properties::EnableFoam>() };
102 enum { enableBrine = getPropValue<TypeTag, Properties::EnableBrine>() };
103 enum { enableVapwat = getPropValue<TypeTag, Properties::EnableVapwat>() };
104 enum { enableDisgasInWater = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
105 enum { enableSaltPrecipitation = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>() };
106 static constexpr EnergyModules energyModuleType = getPropValue<TypeTag, Properties::EnergyModuleType>();
107 enum { enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>() };
108 enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
109 enum { enableConvectiveMixing = getPropValue<TypeTag, Properties::EnableConvectiveMixing>() };
110 enum { enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>() };
111 enum { enableMICP = Indices::enableMICP };
112 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
113 enum { waterCompIdx = FluidSystem::waterCompIdx };
114 enum { oilCompIdx = FluidSystem::oilCompIdx };
115 enum { gasCompIdx = FluidSystem::gasCompIdx };
116 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
117 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
118 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
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 FluxIntensiveQuantities = typename FluxModule::FluxIntensiveQuantities;
130
131 using DirectionalMobilityPtr = Utility::CopyablePtr<DirectionalMobility<TypeTag>>;
136
137public:
138 using FluidState = BlackOilFluidState<Evaluation,
139 FluidSystem,
140 energyModuleType != EnergyModules::NoTemperature,
141 energyModuleType == EnergyModules::FullyImplicitThermal,
142 compositionSwitchEnabled,
143 enableVapwat,
144 enableBrine,
145 enableSaltPrecipitation,
146 enableDisgasInWater,
147 Indices::numPhases>;
148 using ScalarFluidState = BlackOilFluidState<Scalar,
149 FluidSystem,
150 energyModuleType != EnergyModules::NoTemperature,
151 energyModuleType == EnergyModules::FullyImplicitThermal,
152 compositionSwitchEnabled,
153 enableVapwat,
154 enableBrine,
155 enableSaltPrecipitation,
156 enableDisgasInWater,
157 Indices::numPhases>;
159
161 {
162 if constexpr (compositionSwitchEnabled) {
163 fluidState_.setRs(0.0);
164 fluidState_.setRv(0.0);
165 }
166 if constexpr (enableVapwat) {
167 fluidState_.setRvw(0.0);
168 }
169 if constexpr (enableDisgasInWater) {
170 fluidState_.setRsw(0.0);
171 }
172 }
174
176
177 void updateTempSalt(const Problem& problem,
178 const PrimaryVariables& priVars,
179 const unsigned globalSpaceIdx,
180 const unsigned timeIdx,
181 const LinearizationType& lintype)
182 {
183 asImp_().updateTemperature_(problem, priVars, globalSpaceIdx, timeIdx, lintype);
184 if constexpr (enableBrine) {
185 asImp_().updateSaltConcentration_(priVars, timeIdx, lintype);
186 }
187 }
188
189 void updateSaturations(const PrimaryVariables& priVars,
190 const unsigned timeIdx,
191 [[maybe_unused]] const LinearizationType lintype)
192 {
193 // extract the water and the gas saturations for convenience
194 Evaluation Sw = 0.0;
195 if constexpr (waterEnabled) {
196 if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Sw) {
197 assert(Indices::waterSwitchIdx >= 0);
198 if constexpr (Indices::waterSwitchIdx >= 0) {
199 Sw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
200 }
201 }
202 else if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rsw ||
203 priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Disabled)
204 {
205 // water is enabled but is not a primary variable i.e. one component/phase case
206 // or two-phase water + gas with only water present
207 Sw = 1.0;
208 } // else i.e. for MeaningWater() = Rvw, Sw is still 0.0;
209 }
210 Evaluation Sg = 0.0;
211 if constexpr (gasEnabled) {
212 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Sg) {
213 assert(Indices::compositionSwitchIdx >= 0);
214 if constexpr (compositionSwitchEnabled) {
215 Sg = priVars.makeEvaluation(Indices::compositionSwitchIdx, timeIdx);
216 }
217 }
218 else if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rv) {
219 Sg = 1.0 - Sw;
220 }
221 else if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Disabled) {
222 if constexpr (waterEnabled) {
223 Sg = 1.0 - Sw; // two phase water + gas
224 } else {
225 // one phase case
226 Sg = 1.0;
227 }
228 }
229 }
230 Valgrind::CheckDefined(Sg);
231 Valgrind::CheckDefined(Sw);
232
233 Evaluation So = 1.0 - Sw - Sg;
234
235 // deal with solvent
236 if constexpr (enableSolvent) {
237 if (priVars.primaryVarsMeaningSolvent() == PrimaryVariables::SolventMeaning::Ss) {
238 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
239 So -= priVars.makeEvaluation(Indices::solventSaturationIdx, timeIdx);
240 }
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
251 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
252 fluidState_.setSaturation(gasPhaseIdx, Sg);
253 }
254
255 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
256 fluidState_.setSaturation(oilPhaseIdx, So);
257 }
258 }
259
260 template <class ...Args>
262 const PrimaryVariables& priVars,
263 const unsigned globalSpaceIdx,
264 const unsigned timeIdx,
265 const LinearizationType& lintype)
266 {
267
268 // Solvent saturation manipulation:
269 // After this, gas saturation will actually be (gas sat + solvent sat)
270 // until set back to just gas saturation in the corresponding call to
271 // solventPostSatFuncUpdate_() further down.
272 if constexpr (enableSolvent) {
273 asImp_().solventPreSatFuncUpdate_(priVars, timeIdx, lintype);
274 }
275
276 // Phase relperms.
277 problem.template updateRelperms<FluidState, Args...>(mobility_, dirMob_, fluidState_, globalSpaceIdx);
278
279 // now we compute all phase pressures
280 using EvalArr = std::array<Evaluation, numPhases>;
281 EvalArr pC;
282 const auto& materialParams = problem.materialLawParams(globalSpaceIdx);
283 MaterialLaw::template capillaryPressures<EvalArr, FluidState, Args...>(pC, materialParams, fluidState_);
284
285 // scaling the capillary pressure due to porosity changes
286 if constexpr (enableBrine) {
288 priVars.primaryVarsMeaningBrine() == PrimaryVariables::BrineMeaning::Sp)
289 {
290 const unsigned satnumRegionIdx = problem.satnumRegionIndex(globalSpaceIdx);
291 const Evaluation Sp = priVars.makeEvaluation(Indices::saltConcentrationIdx, timeIdx);
292 const Evaluation porosityFactor = min(1.0 - Sp, 1.0); //phi/phi_0
293 const auto& pcfactTable = BrineModule::pcfactTable(satnumRegionIdx);
294 const Evaluation pcFactor = pcfactTable.eval(porosityFactor, /*extrapolation=*/true);
295 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
296 if (FluidSystem::phaseIsActive(phaseIdx)) {
297 pC[phaseIdx] *= pcFactor;
298 }
299 }
300 }
301 }
302 else if constexpr (enableBioeffects) {
303 if (BioeffectsModule::hasPcfactTables() && referencePorosity_ > 0) {
304 unsigned satnumRegionIdx = problem.satnumRegionIndex(globalSpaceIdx);
305 const Evaluation Sb = priVars.makeEvaluation(Indices::biofilmVolumeFractionIdx, timeIdx);
306 const Evaluation porosityFactor = min(1.0 - Sb/referencePorosity_, 1.0); //phi/phi_0
307 const auto& pcfactTable = BioeffectsModule::pcfactTable(satnumRegionIdx);
308 const Evaluation pcFactor = pcfactTable.eval(porosityFactor, /*extrapolation=*/true);
309 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
310 if (FluidSystem::phaseIsActive(phaseIdx)) {
311 pC[phaseIdx] *= pcFactor;
312 }
313 }
314 }
315 }
316
317 // oil is the reference phase for pressure
318 if (priVars.primaryVarsMeaningPressure() == PrimaryVariables::PressureMeaning::Pg) {
319 const Evaluation& pg = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
320 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
321 if (FluidSystem::phaseIsActive(phaseIdx)) {
322 fluidState_.setPressure(phaseIdx, pg + (pC[phaseIdx] - pC[gasPhaseIdx]));
323 }
324 }
325 }
326 else if (priVars.primaryVarsMeaningPressure() == PrimaryVariables::PressureMeaning::Pw) {
327 const Evaluation& pw = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
328 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
329 if (FluidSystem::phaseIsActive(phaseIdx)) {
330 fluidState_.setPressure(phaseIdx, pw + (pC[phaseIdx] - pC[waterPhaseIdx]));
331 }
332 }
333 }
334 else {
335 assert(FluidSystem::phaseIsActive(oilPhaseIdx));
336 const Evaluation& po = priVars.makeEvaluation(Indices::pressureSwitchIdx, timeIdx);
337 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
338 if (FluidSystem::phaseIsActive(phaseIdx)) {
339 fluidState_.setPressure(phaseIdx, po + (pC[phaseIdx] - pC[oilPhaseIdx]));
340 }
341 }
342 }
343
344 // Update the Saturation functions for the blackoil solvent module.
345 // Including setting gas saturation back to hydrocarbon gas saturation.
346 // Note that this depend on the pressures, so it must be called AFTER the pressures
347 // have been updated.
348 if constexpr (enableSolvent) {
349 asImp_().solventPostSatFuncUpdate_(problem, priVars, globalSpaceIdx, timeIdx, lintype);
350 }
351 }
352
353 void updateRsRvRsw(const Problem& problem, const PrimaryVariables& priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
354 {
355 const unsigned pvtRegionIdx = priVars.pvtRegionIndex();
356
357 const Scalar RvMax = FluidSystem::enableVaporizedOil()
358 ? problem.maxOilVaporizationFactor(timeIdx, globalSpaceIdx)
359 : 0.0;
360 const Scalar RsMax = FluidSystem::enableDissolvedGas()
361 ? problem.maxGasDissolutionFactor(timeIdx, globalSpaceIdx)
362 : 0.0;
363 const Scalar RswMax = FluidSystem::enableDissolvedGasInWater()
364 ? problem.maxGasDissolutionFactor(timeIdx, globalSpaceIdx)
365 : 0.0;
366
367 Evaluation SoMax = 0.0;
368 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
369 SoMax = max(fluidState_.saturation(oilPhaseIdx),
370 problem.maxOilSaturation(globalSpaceIdx));
371 }
372
373 // take the meaning of the switching primary variable into account for the gas
374 // and oil phase compositions
375
376 if constexpr (compositionSwitchEnabled) {
377 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rs) {
378 const auto& Rs = priVars.makeEvaluation(Indices::compositionSwitchIdx, timeIdx);
379 fluidState_.setRs(Rs);
380 }
381 else {
382 if (FluidSystem::enableDissolvedGas()) { // Add So > 0? i.e. if only water set rs = 0)
383 const Evaluation& RsSat = enableExtbo ? asImp_().rs() :
384 FluidSystem::saturatedDissolutionFactor(fluidState_,
385 oilPhaseIdx,
386 pvtRegionIdx,
387 SoMax);
388 fluidState_.setRs(min(RsMax, RsSat));
389 }
390 else {
391 fluidState_.setRs(0.0);
392 }
393 }
394
395 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rv) {
396 const auto& Rv = priVars.makeEvaluation(Indices::compositionSwitchIdx, timeIdx);
397 fluidState_.setRv(Rv);
398 }
399 else {
400 if (FluidSystem::enableVaporizedOil() ) { // Add Sg > 0? i.e. if only water set rv = 0)
401 const Evaluation& RvSat = enableExtbo ? asImp_().rv() :
402 FluidSystem::saturatedDissolutionFactor(fluidState_,
403 gasPhaseIdx,
404 pvtRegionIdx,
405 SoMax);
406 fluidState_.setRv(min(RvMax, RvSat));
407 }
408 else {
409 fluidState_.setRv(0.0);
410 }
411 }
412 }
413
414 if constexpr (enableVapwat) {
415 if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rvw) {
416 const auto& Rvw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
417 fluidState_.setRvw(Rvw);
418 }
419 else {
420 if (FluidSystem::enableVaporizedWater()) { // Add Sg > 0? i.e. if only water set rv = 0)
421 const Evaluation& RvwSat = FluidSystem::saturatedVaporizationFactor(fluidState_,
422 gasPhaseIdx,
423 pvtRegionIdx);
424 fluidState_.setRvw(RvwSat);
425 }
426 }
427 }
428
429 if constexpr (enableDisgasInWater) {
430 if (priVars.primaryVarsMeaningWater() == PrimaryVariables::WaterMeaning::Rsw) {
431 const auto& Rsw = priVars.makeEvaluation(Indices::waterSwitchIdx, timeIdx);
432 fluidState_.setRsw(Rsw);
433 }
434 else {
435 if (FluidSystem::enableDissolvedGasInWater()) {
436 const Evaluation& RswSat = FluidSystem::saturatedDissolutionFactor(fluidState_,
437 waterPhaseIdx,
438 pvtRegionIdx);
439 fluidState_.setRsw(min(RswMax, RswSat));
440 }
441 }
442 }
443 }
444
446 {
447 OPM_TIMEBLOCK_LOCAL(updateMobilityAndInvB, Subsystem::PvtProps);
448 const unsigned pvtRegionIdx = fluidState_.pvtRegionIndex();
449
450 // compute the phase densities and transform the phase permeabilities into mobilities
451 int nmobilities = 1;
452 constexpr int max_nmobilities = 4;
453 std::array<std::array<Evaluation, numPhases>*, max_nmobilities> mobilities = { &mobility_};
454 if (dirMob_) {
455 for (int i = 0; i < 3; ++i) {
456 mobilities[nmobilities] = &(dirMob_->getArray(i));
457 ++nmobilities;
458 }
459 }
460 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
461 if (!FluidSystem::phaseIsActive(phaseIdx)) {
462 continue;
463 }
464 const auto [b, mu] = FluidSystem::inverseFormationVolumeFactorAndViscosity(fluidState_, phaseIdx, pvtRegionIdx);
465 fluidState_.setInvB(phaseIdx, b);
466 for (int i = 0; i < nmobilities; ++i) {
467 if (enableExtbo && phaseIdx == oilPhaseIdx) {
468 (*mobilities[i])[phaseIdx] /= asImp_().oilViscosity();
469 }
470 else if (enableExtbo && phaseIdx == gasPhaseIdx) {
471 (*mobilities[i])[phaseIdx] /= asImp_().gasViscosity();
472 }
473 else {
474 (*mobilities[i])[phaseIdx] /= mu;
475 }
476 }
477 }
478 Valgrind::CheckDefined(mobility_);
479 }
480
482 {
483 const unsigned pvtRegionIdx = fluidState_.pvtRegionIndex();
484
485 // calculate the phase densities
486 Evaluation rho;
487 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
488 rho = fluidState_.invB(waterPhaseIdx);
489 rho *= FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
490 if (FluidSystem::enableDissolvedGasInWater()) {
491 rho += fluidState_.invB(waterPhaseIdx) *
492 fluidState_.Rsw() *
493 FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
494 }
495 fluidState_.setDensity(waterPhaseIdx, rho);
496 }
497
498 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
499 rho = fluidState_.invB(gasPhaseIdx);
500 rho *= FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
501 if (FluidSystem::enableVaporizedOil()) {
502 rho += fluidState_.invB(gasPhaseIdx) *
503 fluidState_.Rv() *
504 FluidSystem::referenceDensity(oilPhaseIdx, pvtRegionIdx);
505 }
506 if (FluidSystem::enableVaporizedWater()) {
507 rho += fluidState_.invB(gasPhaseIdx) *
508 fluidState_.Rvw() *
509 FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
510 }
511 fluidState_.setDensity(gasPhaseIdx, rho);
512 }
513
514 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
515 rho = fluidState_.invB(oilPhaseIdx);
516 rho *= FluidSystem::referenceDensity(oilPhaseIdx, pvtRegionIdx);
517 if (FluidSystem::enableDissolvedGas()) {
518 rho += fluidState_.invB(oilPhaseIdx) *
519 fluidState_.Rs() *
520 FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
521 }
522 fluidState_.setDensity(oilPhaseIdx, rho);
523 }
524 }
525
526 void updatePorosity(const ElementContext& elemCtx, unsigned dofIdx, unsigned timeIdx)
527 {
528 const auto& problem = elemCtx.problem();
529 const auto& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
530 const unsigned globalSpaceIdx = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
531 // Retrieve the reference porosity from the problem.
532 referencePorosity_ = problem.porosity(elemCtx, dofIdx, timeIdx);
533 // Account for other effects.
534 this->updatePorosityImpl(problem, priVars, globalSpaceIdx, timeIdx);
535 }
536
537 void updatePorosity(const Problem& problem, const PrimaryVariables& priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
538 {
539 // Retrieve the reference porosity from the problem.
540 referencePorosity_ = problem.porosity(globalSpaceIdx, timeIdx);
541 // Account for other effects.
542 this->updatePorosityImpl(problem, priVars, globalSpaceIdx, timeIdx);
543 }
544
545 void updatePorosityImpl(const Problem& problem, const PrimaryVariables& priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
546 {
547 const auto& linearizationType = problem.model().linearizer().getLinearizationType();
548
549 // Start from the reference porosity.
550 porosity_ = referencePorosity_;
551
552 // the porosity must be modified by the compressibility of the
553 // rock...
554 const Scalar rockCompressibility = problem.rockCompressibility(globalSpaceIdx);
555 if (rockCompressibility > 0.0) {
556 const Scalar rockRefPressure = problem.rockReferencePressure(globalSpaceIdx);
557 Evaluation x;
558 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
559 x = rockCompressibility * (fluidState_.pressure(oilPhaseIdx) - rockRefPressure);
560 }
561 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
562 x = rockCompressibility * (fluidState_.pressure(waterPhaseIdx) - rockRefPressure);
563 }
564 else {
565 x = rockCompressibility * (fluidState_.pressure(gasPhaseIdx) - rockRefPressure);
566 }
567 porosity_ *= 1.0 + x + 0.5 * x * x;
568 }
569
570 // deal with water induced rock compaction
571 porosity_ *= problem.template rockCompPoroMultiplier<Evaluation>(*this, globalSpaceIdx);
572
573 // deal with bioeffects (minimum porosity of 1e-8 to prevent numerical issues)
574 if constexpr (enableBioeffects) {
575 const Evaluation biofilm_ = priVars.makeEvaluation(Indices::biofilmVolumeFractionIdx,
576 timeIdx, linearizationType);
577 Evaluation calcite_ = 0.0;
578 if constexpr (enableMICP) {
579 calcite_ = priVars.makeEvaluation(Indices::calciteVolumeFractionIdx, timeIdx, linearizationType);
580 }
581 porosity_ -= min(biofilm_ + calcite_, referencePorosity_ - 1e-8);
582 }
583
584 // deal with salt-precipitation
585 if (enableSaltPrecipitation && priVars.primaryVarsMeaningBrine() == PrimaryVariables::BrineMeaning::Sp) {
586 const Evaluation Sp = priVars.makeEvaluation(Indices::saltConcentrationIdx, timeIdx);
587 porosity_ *= (1.0 - Sp);
588 }
589 }
590
592 {
593 // some safety checks in debug mode
594 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
595 if (!FluidSystem::phaseIsActive(phaseIdx)) {
596 continue;
597 }
598
599 assert(isfinite(fluidState_.density(phaseIdx)));
600 assert(isfinite(fluidState_.saturation(phaseIdx)));
601 assert(isfinite(fluidState_.temperature(phaseIdx)));
602 assert(isfinite(fluidState_.pressure(phaseIdx)));
603 assert(isfinite(fluidState_.invB(phaseIdx)));
604 }
605 assert(isfinite(fluidState_.Rs()));
606 assert(isfinite(fluidState_.Rv()));
607 }
608
612 template <class ...Args>
613 void update(const ElementContext& elemCtx, unsigned dofIdx, unsigned timeIdx)
614 {
615 ParentType::update(elemCtx, dofIdx, timeIdx);
616 const auto& problem = elemCtx.problem();
617 const auto& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
618 const unsigned globalSpaceIdx = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
619
620 updateCommonPart<Args...>(problem, priVars, globalSpaceIdx, timeIdx);
621
622 updatePorosity(elemCtx, dofIdx, timeIdx);
623
624 // Below: things I want to move to elemCtx-less versions but have not done yet.
625
626 if constexpr (enableSolvent) {
627 asImp_().solventPvtUpdate_(elemCtx, dofIdx, timeIdx);
628 }
629 if constexpr (enableExtbo) {
630 asImp_().zPvtUpdate_();
631 }
632 if constexpr (enablePolymer) {
633 asImp_().polymerPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
634 }
635 if constexpr (energyModuleType == EnergyModules::FullyImplicitThermal) {
636 asImp_().updateEnergyQuantities_(elemCtx, dofIdx, timeIdx);
637 }
638 if constexpr (enableFoam) {
639 asImp_().foamPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
640 }
641 if constexpr (enableBioeffects) {
642 asImp_().bioeffectsPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
643 }
644 if constexpr (enableBrine) {
645 asImp_().saltPropertiesUpdate_(elemCtx, dofIdx, timeIdx);
646 }
647 if constexpr (enableConvectiveMixing) {
648 // The ifs are here is to avoid extra calculations for
649 // cases with dry runs and without CO2STORE and DRSDTCON.
650 if (!problem.simulator().vanguard().eclState().getIOConfig().initOnly()) {
651 if (problem.simulator().vanguard().eclState().runspec().co2Storage()) {
652 if (problem.drsdtconIsActive(globalSpaceIdx, problem.simulator().episodeIndex())) {
653 asImp_().updateSaturatedDissolutionFactor_();
654 }
655 }
656 }
657 }
658
659 // update the quantities which are required by the chosen
660 // velocity model
661 FluxIntensiveQuantities::update_(elemCtx, dofIdx, timeIdx);
662
663 // update the diffusion specific quantities of the intensive quantities
664 if constexpr (enableDiffusion) {
665 DiffusionIntensiveQuantities::update_(fluidState_, priVars.pvtRegionIndex(), elemCtx, dofIdx, timeIdx);
666 }
667
668 // update the dispersion specific quantities of the intensive quantities
669 if constexpr (enableDispersion) {
670 DispersionIntensiveQuantities::update_(elemCtx, dofIdx, timeIdx);
671 }
672 }
673
674 template <class ...Args>
675 void update(const Problem& problem, const PrimaryVariables& priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
676 {
677 // This is the version of update() that does not use any ElementContext.
678 // It is limited by some modules that are not yet adapted to that.
679 static_assert(!enableSolvent);
680 static_assert(!enableExtbo);
681 static_assert(!enablePolymer);
682 static_assert(!enableFoam);
683 static_assert(!enableMICP);
684 static_assert(!enableBrine);
685 static_assert(!enableDiffusion);
686 static_assert(!enableDispersion);
687
688 this->extrusionFactor_ = 1.0;// to avoid fixing parent update
689 updateCommonPart<Args...>(problem, priVars, globalSpaceIdx, timeIdx);
690 // Porosity requires separate calls so this can be instantiated with ReservoirProblem from the examples/ directory.
691 updatePorosity(problem, priVars, globalSpaceIdx, timeIdx);
692
693 // TODO: Here we should do the parts for solvent etc. at the bottom of the other update() function.
694 }
695
696 // This function updated the parts that are common to the IntensiveQuantities regardless of extensions used.
697 template <class ...Args>
698 void updateCommonPart(const Problem& problem, const PrimaryVariables& priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
699 {
700 OPM_TIMEBLOCK_LOCAL(blackoilIntensiveQuanititiesUpdate, Subsystem::SatProps | Subsystem::PvtProps);
701
702 const auto& linearizationType = problem.model().linearizer().getLinearizationType();
703 const unsigned pvtRegionIdx = priVars.pvtRegionIndex();
704
705 fluidState_.setPvtRegionIndex(pvtRegionIdx);
706
707 updateTempSalt(problem, priVars, globalSpaceIdx, timeIdx, linearizationType);
708 updateSaturations(priVars, timeIdx, linearizationType);
709 updateRelpermAndPressures<Args...>(problem, priVars, globalSpaceIdx, timeIdx, linearizationType);
710
711 // update extBO parameters
712 if constexpr (enableExtbo) {
713 asImp_().zFractionUpdate_(priVars, timeIdx);
714 }
715
716 updateRsRvRsw(problem, priVars, globalSpaceIdx, timeIdx);
719
720 rockCompTransMultiplier_ = problem.template rockCompTransMultiplier<Evaluation>(*this, globalSpaceIdx);
721
722#ifndef NDEBUG
724#endif
725 }
726
730 const FluidState& fluidState() const
731 { return fluidState_; }
732
736 const Evaluation& mobility(unsigned phaseIdx) const
737 { return mobility_[phaseIdx]; }
738
739 const Evaluation& mobility(unsigned phaseIdx, FaceDir::DirEnum facedir) const
740 {
741 using Dir = FaceDir::DirEnum;
742 if (dirMob_) {
743 switch (facedir) {
744 case Dir::XMinus:
745 case Dir::XPlus:
746 return dirMob_->getArray(0)[phaseIdx];
747 case Dir::YMinus:
748 case Dir::YPlus:
749 return dirMob_->getArray(1)[phaseIdx];
750 case Dir::ZMinus:
751 case Dir::ZPlus:
752 return dirMob_->getArray(2)[phaseIdx];
753 default:
754 throw std::runtime_error("Unexpected face direction");
755 }
756 }
757 else {
758 return mobility_[phaseIdx];
759 }
760 }
761
765 const Evaluation& porosity() const
766 { return porosity_; }
767
771 const Evaluation& rockCompTransMultiplier() const
772 { return rockCompTransMultiplier_; }
773
781 auto pvtRegionIndex() const -> decltype(std::declval<FluidState>().pvtRegionIndex())
782 { return fluidState_.pvtRegionIndex(); }
783
787 Evaluation relativePermeability(unsigned phaseIdx) const
788 {
789 // warning: slow
790 return fluidState_.viscosity(phaseIdx) * mobility(phaseIdx);
791 }
792
799 Scalar referencePorosity() const
800 { return referencePorosity_; }
801
802 const Evaluation& permFactor() const
803 {
804 if constexpr (enableBioeffects) {
806 }
807 else if constexpr (enableSaltPrecipitation) {
808 return BrineIntQua::permFactor();
809 }
810 else {
811 throw std::logic_error("permFactor() called but salt precipitation or bioeffects are disabled");
812 }
813 }
814
818 OPM_HOST_DEVICE const auto& getFluidSystem() const
819 {
820 return fluidState_.fluidSystem();
821 }
822
823private:
831
832 Implementation& asImp_()
833 { return *static_cast<Implementation*>(this); }
834
835 FluidState fluidState_;
836 Scalar referencePorosity_;
837 Evaluation porosity_;
838 Evaluation rockCompTransMultiplier_;
839 std::array<Evaluation, numPhases> mobility_;
840
841 // Instead of writing a custom copy constructor and a custom assignment operator just to handle
842 // the dirMob_ unique ptr member variable when copying BlackOilIntensiveQuantites (see for example
843 // updateIntensitiveQuantities_() in fvbaseelementcontext.hh for a copy example) we write the below
844 // custom wrapper class CopyablePtr which wraps the unique ptr and makes it copyable.
845 //
846 // The advantage of this approach is that we avoid having to call all the base class copy constructors and
847 // assignment operators explicitly (which is needed when writing the custom copy constructor and assignment
848 // operators) which could become a maintenance burden. For example, when adding a new base class (if that should
849 // be needed sometime in the future) to BlackOilIntensiveQuantites we could forget to update the copy
850 // constructor and assignment operators.
851 //
852 // We want each copy of the BlackOilIntensiveQuantites to be unique, (TODO: why?) so we have to make a copy
853 // of the unique_ptr each time we copy construct or assign to it from another BlackOilIntensiveQuantites.
854 // (On the other hand, if a copy could share the ptr with the original, a shared_ptr could be used instead and the
855 // wrapper would not be needed)
856 DirectionalMobilityPtr dirMob_;
857};
858
859} // namespace Opm
860
861#endif
Contains the classes required to extend the black-oil model by bioeffects.
Contains the classes required to extend the black-oil model by brine.
Classes required for dynamic convective mixing.
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 polymer.
Declares the properties required by the black oil model.
Contains the classes required to extend the black-oil model by solvents.
Provides the volumetric quantities required for the equations needed by the bioeffects extension of t...
Definition: blackoilbioeffectsmodules.hh:521
const Evaluation & permFactor() const
Definition: blackoilbioeffectsmodules.hh:593
Contains the high level supplements required to extend the black oil model by bioeffects.
Definition: blackoilbioeffectsmodules.hh:95
static bool hasPcfactTables()
Definition: blackoilbioeffectsmodules.hh:484
static const TabulatedFunction & pcfactTable(unsigned satnumRegionIdx)
Definition: blackoilbioeffectsmodules.hh:479
Definition: blackoilbrinemodules.hh:368
Contains the high level supplements required to extend the black oil model by brine.
Definition: blackoilbrinemodules.hh:58
static const TabulatedFunction & pcfactTable(unsigned satnumRegionIdx)
Definition: blackoilbrinemodules.hh:300
static bool hasPcfactTables()
Definition: blackoilbrinemodules.hh:346
Provides the volumetric quantities required for the equations needed by the convective mixing (DRSDTC...
Definition: blackoilconvectivemixingmodule.hh:428
Provides the volumetric quantities required for the calculation of molecular diffusive fluxes.
Definition: blackoildiffusionmodule.hh:353
Provides the volumetric quantities required for the calculation of dispersive fluxes.
Definition: blackoildispersionmodule.hh:321
Provides the volumetric quantities required for the equations needed by the energys extension of the ...
Definition: blackoilenergymodules.hh:342
Provides the volumetric quantities required for the equations needed by the solvents extension of the...
Definition: blackoilextbomodules.hh:382
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilfoammodules.hh:370
Contains the quantities which are are constant within a finite volume in the black-oil model.
Definition: blackoilintensivequantities.hh:85
void updateTempSalt(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx, const LinearizationType &lintype)
Definition: blackoilintensivequantities.hh:177
void updatePorosity(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
Definition: blackoilintensivequantities.hh:537
void updateCommonPart(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
Definition: blackoilintensivequantities.hh:698
const Evaluation & porosity() const
Returns the average porosity within the control volume.
Definition: blackoilintensivequantities.hh:765
void assertFiniteMembers()
Definition: blackoilintensivequantities.hh:591
const Evaluation & mobility(unsigned phaseIdx) const
Returns the effective mobility of a given phase within the control volume.
Definition: blackoilintensivequantities.hh:736
void updateMobilityAndInvB()
Definition: blackoilintensivequantities.hh:445
void update(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Definition: blackoilintensivequantities.hh:613
Evaluation relativePermeability(unsigned phaseIdx) const
Returns the relative permeability of a given phase within the control volume.
Definition: blackoilintensivequantities.hh:787
void updatePorosity(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Definition: blackoilintensivequantities.hh:526
auto pvtRegionIndex() const -> decltype(std::declval< FluidState >().pvtRegionIndex())
Returns the index of the PVT region used to calculate the thermodynamic quantities.
Definition: blackoilintensivequantities.hh:781
const Evaluation & permFactor() const
Definition: blackoilintensivequantities.hh:802
void updatePorosityImpl(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
Definition: blackoilintensivequantities.hh:545
void update(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
Definition: blackoilintensivequantities.hh:675
void updateRelpermAndPressures(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx, const LinearizationType &lintype)
Definition: blackoilintensivequantities.hh:261
OPM_HOST_DEVICE const auto & getFluidSystem() const
Returns the fluid system used by this intensive quantities.
Definition: blackoilintensivequantities.hh:818
const FluidState & fluidState() const
Returns the phase state for the control-volume.
Definition: blackoilintensivequantities.hh:730
void updateSaturations(const PrimaryVariables &priVars, const unsigned timeIdx, const LinearizationType lintype)
Definition: blackoilintensivequantities.hh:189
BlackOilIntensiveQuantities & operator=(const BlackOilIntensiveQuantities &other)=default
GetPropType< TypeTag, Properties::Problem > Problem
Definition: blackoilintensivequantities.hh:158
const Evaluation & rockCompTransMultiplier() const
Definition: blackoilintensivequantities.hh:771
BlackOilFluidState< Evaluation, FluidSystem, energyModuleType !=EnergyModules::NoTemperature, energyModuleType==EnergyModules::FullyImplicitThermal, compositionSwitchEnabled, enableVapwat, enableBrine, enableSaltPrecipitation, enableDisgasInWater, Indices::numPhases > FluidState
Definition: blackoilintensivequantities.hh:147
BlackOilFluidState< Scalar, FluidSystem, energyModuleType !=EnergyModules::NoTemperature, energyModuleType==EnergyModules::FullyImplicitThermal, compositionSwitchEnabled, enableVapwat, enableBrine, enableSaltPrecipitation, enableDisgasInWater, Indices::numPhases > ScalarFluidState
Definition: blackoilintensivequantities.hh:157
BlackOilIntensiveQuantities(const BlackOilIntensiveQuantities &other)=default
BlackOilIntensiveQuantities()
Definition: blackoilintensivequantities.hh:160
const Evaluation & mobility(unsigned phaseIdx, FaceDir::DirEnum facedir) const
Definition: blackoilintensivequantities.hh:739
Scalar referencePorosity() const
Returns the porosity of the rock at reference conditions.
Definition: blackoilintensivequantities.hh:799
void updatePhaseDensities()
Definition: blackoilintensivequantities.hh:481
void updateRsRvRsw(const Problem &problem, const PrimaryVariables &priVars, const unsigned globalSpaceIdx, const unsigned timeIdx)
Definition: blackoilintensivequantities.hh:353
Provides the volumetric quantities required for the equations needed by the polymers extension of the...
Definition: blackoilpolymermodules.hh:568
Provides the volumetric quantities required for the equations needed by the solvents extension of the...
Definition: blackoilsolventmodules.hh:553
This file contains definitions related to directional mobilities.
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
Definition: linearizationtype.hh:34