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