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