blackoildispersionmodule.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_DISPERSION_MODULE_HH
29#define EWOMS_DISPERSION_MODULE_HH
30
31#include <dune/common/fvector.hh>
32
33#include <opm/material/common/MathToolbox.hpp>
34#include <opm/material/common/Valgrind.hpp>
35
39
40#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
41#include <opm/common/OpmLog/OpmLog.hpp>
42
43#include <array>
44#include <cmath>
45#include <stdexcept>
46
47namespace Opm {
48
55template <class TypeTag, bool enableDispersion>
57
58template <class TypeTag, bool enableDispersion>
60
64template <class TypeTag>
65class BlackOilDispersionModule<TypeTag, /*enableDispersion=*/false>
66{
72
73public:
75
76 static void initFromState(const EclipseState&)
77 {}
78
83 template <class Context>
84 static void addDispersiveFlux(RateVector&,
85 const Context&,
86 unsigned,
87 unsigned)
88 {}
89
90 template<class IntensiveQuantities, class Scalar>
91 static void addDispersiveFlux(RateVector&,
92 const IntensiveQuantities&,
93 const IntensiveQuantities&,
94 const Evaluation&,
95 const Scalar&)
96 {}
97};
98
102template <class TypeTag>
103class BlackOilDispersionModule<TypeTag, /*enableDispersion=*/true>
104{
115
116 enum { numPhases = FluidSystem::numPhases };
117 enum { numComponents = FluidSystem::numComponents };
118 enum { conti0EqIdx = Indices::conti0EqIdx };
119 enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
120 enum { enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>() };
121 enum { enableMICP = Indices::enableMICP };
122
123 static constexpr unsigned contiMicrobialEqIdx = Indices::contiMicrobialEqIdx;
124 static constexpr unsigned contiOxygenEqIdx = Indices::contiOxygenEqIdx;
125 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
126 static constexpr unsigned contiUreaEqIdx = Indices::contiUreaEqIdx;
127
128 using Toolbox = MathToolbox<Evaluation>;
129
130public:
132
133 static void initFromState(const EclipseState& eclState)
134 {
135 if (!eclState.getSimulationConfig().rock_config().dispersion()) {
136 return;
137 }
138
139 if (eclState.getSimulationConfig().hasVAPWAT() || eclState.getSimulationConfig().hasVAPOIL()) {
140 OpmLog::warning("Dispersion is activated in combination with VAPWAT/VAPOIL. \n"
141 "Water/oil is still allowed to vaporize, but dispersion in the "
142 "gas phase is ignored.");
143 }
144 }
145
150 template <class Context>
151 static void addDispersiveFlux(RateVector& flux, const Context& context,
152 unsigned spaceIdx, unsigned timeIdx)
153 {
154 // Only work if dispersion is enabled by DISPERC in the deck
155 if (!context.simulator().vanguard().eclState().getSimulationConfig().rock_config().dispersion()) {
156 return;
157 }
158 const auto& extQuants = context.extensiveQuantities(spaceIdx, timeIdx);
159 const auto& inIq = context.intensiveQuantities(extQuants.interiorIndex(), timeIdx);
160 const auto& exIq = context.intensiveQuantities(extQuants.exteriorIndex(), timeIdx);
161 const auto& dispersivity = extQuants.dispersivity();
162 const auto& normVelocityAvg = extQuants.normVelocityAvg();
163 addDispersiveFlux(flux, inIq, exIq, dispersivity, normVelocityAvg);
164 }
165
186 template<class IntensiveQuantities, class Scalar>
187 static void addDispersiveFlux(RateVector& flux,
188 const IntensiveQuantities& inIq,
189 const IntensiveQuantities& exIq,
190 const Evaluation& dispersivity,
191 const Scalar& normVelocityAvg)
192 {
193 const auto& inFs = inIq.fluidState();
194 const auto& exFs = exIq.fluidState();
195 Evaluation diffR = 0.0;
196 if constexpr(enableBioeffects) {
197 // The dispersion coefficients are given for mass concentrations
198 const Evaluation bAvg = (inFs.invB(waterPhaseIdx) + Toolbox::value(exFs.invB(waterPhaseIdx))) / 2;
199 diffR = inIq.microbialConcentration() - Toolbox::value(exIq.microbialConcentration());
200 flux[contiMicrobialEqIdx] +=
201 bAvg *
202 normVelocityAvg[waterPhaseIdx] *
203 dispersivity *
204 diffR;
205 if constexpr(enableMICP) {
206 diffR = inIq.oxygenConcentration() - Toolbox::value(exIq.oxygenConcentration());
207 flux[contiOxygenEqIdx] +=
208 bAvg *
209 normVelocityAvg[waterPhaseIdx] *
210 dispersivity *
211 diffR;
212 diffR = inIq.ureaConcentration() - Toolbox::value(exIq.ureaConcentration());
213 flux[contiUreaEqIdx] +=
214 bAvg *
215 normVelocityAvg[waterPhaseIdx] *
216 dispersivity *
217 diffR;
218 return;
219 }
220 }
221
222 unsigned pvtRegionIndex = inFs.pvtRegionIndex();
223 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
224 if (!FluidSystem::phaseIsActive(phaseIdx)) {
225 continue;
226 }
227
228 // no dispersion in water for blackoil models unless water can contain dissolved gas
229 if (!FluidSystem::enableDissolvedGasInWater() && FluidSystem::waterPhaseIdx == phaseIdx) {
230 continue;
231 }
232
233 // adding dispersion in the gas phase leads to
234 // convergence issues and unphysical results.
235 // we disable dispersion in the gas phase for now
236 if (FluidSystem::gasPhaseIdx == phaseIdx) {
237 continue;
238 }
239
240 // arithmetic mean of the phase's b factor
241 Evaluation bAvg = inFs.invB(phaseIdx);
242 bAvg += Toolbox::value(exFs.invB(phaseIdx));
243 bAvg /= 2;
244
245 Evaluation convFactor = 1.0;
246 if (FluidSystem::enableDissolvedGas() &&
247 FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) &&
248 phaseIdx == FluidSystem::oilPhaseIdx)
249 {
250 const Evaluation rsAvg = (inFs.Rs() + Toolbox::value(exFs.Rs())) / 2;
251 convFactor = 1.0 / (toMassFractionGasOil(pvtRegionIndex) + rsAvg);
252 diffR = inFs.Rs() - Toolbox::value(exFs.Rs());
253 }
254 if (FluidSystem::enableVaporizedOil() &&
255 FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) &&
256 phaseIdx == FluidSystem::gasPhaseIdx)
257 {
258 const Evaluation rvAvg = (inFs.Rv() + Toolbox::value(exFs.Rv())) / 2;
259 convFactor = toMassFractionGasOil(pvtRegionIndex) /
260 (1.0 + rvAvg * toMassFractionGasOil(pvtRegionIndex));
261 diffR = inFs.Rv() - Toolbox::value(exFs.Rv());
262 }
263 if (FluidSystem::enableDissolvedGasInWater() && phaseIdx == FluidSystem::waterPhaseIdx) {
264 const Evaluation rsAvg = (inFs.Rsw() + Toolbox::value(exFs.Rsw())) / 2;
265 convFactor = 1.0 / (toMassFractionGasWater(pvtRegionIndex) + rsAvg);
266 diffR = inFs.Rsw() - Toolbox::value(exFs.Rsw());
267 }
268 if (FluidSystem::enableVaporizedWater() && phaseIdx == FluidSystem::gasPhaseIdx) {
269 const Evaluation rvAvg = (inFs.Rvw() + Toolbox::value(exFs.Rvw())) / 2;
270 convFactor = toMassFractionGasWater(pvtRegionIndex) /
271 (1.0 + rvAvg * toMassFractionGasWater(pvtRegionIndex));
272 diffR = inFs.Rvw() - Toolbox::value(exFs.Rvw());
273 }
274
275 // mass flux of solvent component
276 const unsigned solventCompIdx = FluidSystem::solventComponentIndex(phaseIdx);
277 const unsigned activeSolventCompIdx = FluidSystem::canonicalToActiveCompIdx(solventCompIdx);
278 flux[conti0EqIdx + activeSolventCompIdx] +=
279 -bAvg *
280 normVelocityAvg[phaseIdx] *
281 convFactor *
282 dispersivity *
283 diffR;
284
285 // mass flux of solute component
286 const unsigned soluteCompIdx = FluidSystem::soluteComponentIndex(phaseIdx);
287 const unsigned activeSoluteCompIdx = FluidSystem::canonicalToActiveCompIdx(soluteCompIdx);
288 flux[conti0EqIdx + activeSoluteCompIdx] +=
289 bAvg *
290 normVelocityAvg[phaseIdx] *
291 convFactor *
292 dispersivity *
293 diffR;
294 }
295 }
296
297private:
298 static Scalar toMassFractionGasOil (unsigned regionIdx)
299 {
300 const Scalar rhoO = FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, regionIdx);
301 const Scalar rhoG = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
302 return rhoO / rhoG;
303 }
304
305 static Scalar toMassFractionGasWater (unsigned regionIdx)
306 {
307 const Scalar rhoW = FluidSystem::referenceDensity(FluidSystem::waterPhaseIdx, regionIdx);
308 const Scalar rhoG = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
309 return rhoW / rhoG;
310 }
311};
312
320template <class TypeTag, bool enableDispersion>
322
326template <class TypeTag>
327class BlackOilDispersionIntensiveQuantities<TypeTag, /*enableDispersion=*/false>
328{
331
332public:
336 Scalar normVelocityCell(unsigned, unsigned) const
337 {
338 throw std::logic_error("Method normVelocityCell() "
339 "does not make sense if dispersion is disabled");
340 }
341
342protected:
347 template<class ElementContext>
348 void update_(ElementContext&,
349 unsigned,
350 unsigned)
351 {}
352};
353
357template <class TypeTag>
358class BlackOilDispersionIntensiveQuantities<TypeTag, /*enableDispersion=*/true>
359{
364
365 enum { numPhases = FluidSystem::numPhases };
366 enum { numComponents = FluidSystem::numComponents };
367 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
368 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
369 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
370 enum { gasCompIdx = FluidSystem::gasCompIdx };
371 enum { oilCompIdx = FluidSystem::oilCompIdx };
372 enum { waterCompIdx = FluidSystem::waterCompIdx };
373 enum { conti0EqIdx = Indices::conti0EqIdx };
374 enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
375
376public:
380 Scalar normVelocityCell(unsigned phaseIdx) const
381 { return normVelocityCell_[phaseIdx]; }
382
383protected:
393 template<class ElementContext>
394 void update_(const ElementContext& elemCtx, unsigned dofIdx, unsigned timeIdx)
395 {
396 // Only work if dispersion is enabled by DISPERC in the deck
397 if (!elemCtx.simulator().vanguard().eclState().getSimulationConfig().rock_config().dispersion()) {
398 return;
399 }
400 const auto& problem = elemCtx.simulator().problem();
401 if (problem.model().linearizer().getVelocityInfo().empty()) {
402 return;
403 }
404 const std::array<int, 3> phaseIdxs = {gasPhaseIdx, oilPhaseIdx, waterPhaseIdx};
405 const std::array<int, 3> compIdxs = {gasCompIdx, oilCompIdx, waterCompIdx};
406 const auto& velocityInf = problem.model().linearizer().getVelocityInfo();
407 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
408 const auto& velocityInfos = velocityInf[globalDofIdx];
409 for (unsigned i = 0; i < phaseIdxs.size(); ++i) {
410 normVelocityCell_[i] = 0;
411 }
412 for (const auto& velocityInfo : velocityInfos) {
413 for (unsigned i = 0; i < phaseIdxs.size(); ++i) {
414 if (FluidSystem::phaseIsActive(phaseIdxs[i])) {
415 normVelocityCell_[phaseIdxs[i]] = std::max(normVelocityCell_[phaseIdxs[i]],
416 std::abs(velocityInfo.velocity[conti0EqIdx +
417 FluidSystem::canonicalToActiveCompIdx(compIdxs[i])]));
418 }
419 }
420 }
421 }
422
423private:
424 std::array<Scalar, numPhases> normVelocityCell_{};
425};
426
433template <class TypeTag, bool enableDispersion>
434class BlackOilDispersionExtensiveQuantities;
435
439template <class TypeTag>
440class BlackOilDispersionExtensiveQuantities<TypeTag, /*enableDispersion=*/false>
441{
446
447 enum { numPhases = FluidSystem::numPhases };
448
449protected:
454 void update_(const ElementContext&,
455 unsigned,
456 unsigned)
457 {}
458
459 template <class Context, class FluidState>
460 void updateBoundary_(const Context&,
461 unsigned,
462 unsigned,
463 const FluidState&)
464 {}
465
466public:
467 using ScalarArray = Scalar[numPhases];
468
469 static void update(ScalarArray&,
470 const IntensiveQuantities&,
471 const IntensiveQuantities&)
472 {}
473
478 Scalar dispersivity() const
479 {
480 throw std::logic_error("The method dispersivity() does not "
481 "make sense if dispersion is disabled.");
482 }
483
491 Scalar normVelocityAvg(unsigned) const
492 {
493 throw std::logic_error("The method normVelocityAvg() "
494 "does not make sense if dispersion is disabled.");
495 }
496};
497
501template <class TypeTag>
502class BlackOilDispersionExtensiveQuantities<TypeTag, /*enableDispersion=*/true>
503{
507
508 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
509
510public:
511 using ScalarArray = std::array<Scalar, numPhases>;
512 static void update(ScalarArray& normVelocityAvg,
513 const IntensiveQuantities& intQuantsInside,
514 const IntensiveQuantities& intQuantsOutside)
515 {
516 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
517 if (!FluidSystem::phaseIsActive(phaseIdx)) {
518 continue;
519 }
520 // use the arithmetic average for the effective
521 // velocity coefficients at the face's integration point.
522 normVelocityAvg[phaseIdx] =
523 0.5 * (intQuantsInside.normVelocityCell(phaseIdx) +
524 intQuantsOutside.normVelocityCell(phaseIdx));
525 Valgrind::CheckDefined(normVelocityAvg[phaseIdx]);
526 }
527 }
528
529protected:
530 template <class Context, class FluidState>
531 void updateBoundary_(const Context&,
532 unsigned,
533 unsigned,
534 const FluidState&)
535 { throw std::runtime_error("Not implemented: Dispersion across boundary not implemented for blackoil"); }
536
537public:
544 Scalar dispersivity() const
545 { return dispersivity_; }
546
554 Scalar normVelocityAvg(unsigned phaseIdx) const
555 { return normVelocityAvg_[phaseIdx]; }
556
557 const auto& normVelocityAvg() const
558 { return normVelocityAvg_; }
559
560private:
561 Scalar dispersivity_;
562 ScalarArray normVelocityAvg_;
563};
564
565} // namespace Opm
566
567#endif
Declares the properties required by the black oil model.
Definition: blackoildispersionmodule.hh:441
void updateBoundary_(const Context &, unsigned, unsigned, const FluidState &)
Definition: blackoildispersionmodule.hh:460
void update_(const ElementContext &, unsigned, unsigned)
Update the quantities required to calculate the dispersive fluxes.
Definition: blackoildispersionmodule.hh:454
Scalar[numPhases] ScalarArray
Definition: blackoildispersionmodule.hh:467
static void update(ScalarArray &, const IntensiveQuantities &, const IntensiveQuantities &)
Definition: blackoildispersionmodule.hh:469
Scalar normVelocityAvg(unsigned) const
The effective filter velocity coefficient in a fluid phase at the face's integration point.
Definition: blackoildispersionmodule.hh:491
Scalar dispersivity() const
The dispersivity the face.
Definition: blackoildispersionmodule.hh:478
Provides the quantities required to calculate dispersive mass fluxes.
Definition: blackoildispersionmodule.hh:503
Scalar dispersivity() const
The dispersivity of the face.
Definition: blackoildispersionmodule.hh:544
static void update(ScalarArray &normVelocityAvg, const IntensiveQuantities &intQuantsInside, const IntensiveQuantities &intQuantsOutside)
Definition: blackoildispersionmodule.hh:512
std::array< Scalar, numPhases > ScalarArray
Definition: blackoildispersionmodule.hh:511
void updateBoundary_(const Context &, unsigned, unsigned, const FluidState &)
Definition: blackoildispersionmodule.hh:531
const auto & normVelocityAvg() const
Definition: blackoildispersionmodule.hh:557
Scalar normVelocityAvg(unsigned phaseIdx) const
The effective velocity coefficient in a fluid phase at the face's integration point.
Definition: blackoildispersionmodule.hh:554
Provides the quantities required to calculate dispersive mass fluxes.
Definition: blackoildispersionmodule.hh:59
Scalar normVelocityCell(unsigned, unsigned) const
Returns the max. norm of the filter velocity of the cell.
Definition: blackoildispersionmodule.hh:336
void update_(ElementContext &, unsigned, unsigned)
Update the quantities required to calculate dispersive fluxes.
Definition: blackoildispersionmodule.hh:348
void update_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the quantities required to calculate dispersive mass fluxes. This considers the linear disperi...
Definition: blackoildispersionmodule.hh:394
Scalar normVelocityCell(unsigned phaseIdx) const
Returns the max. norm of the filter velocity of the cell.
Definition: blackoildispersionmodule.hh:380
Provides the volumetric quantities required for the calculation of dispersive fluxes.
Definition: blackoildispersionmodule.hh:321
static void addDispersiveFlux(RateVector &, const Context &, unsigned, unsigned)
Adds the dispersive flux to the flux vector over a flux integration point.
Definition: blackoildispersionmodule.hh:84
static void addDispersiveFlux(RateVector &, const IntensiveQuantities &, const IntensiveQuantities &, const Evaluation &, const Scalar &)
Definition: blackoildispersionmodule.hh:91
static void initFromState(const EclipseState &)
Definition: blackoildispersionmodule.hh:76
static void initFromState(const EclipseState &eclState)
Definition: blackoildispersionmodule.hh:133
static void addDispersiveFlux(RateVector &flux, const IntensiveQuantities &inIq, const IntensiveQuantities &exIq, const Evaluation &dispersivity, const Scalar &normVelocityAvg)
Adds the mass flux due to dispersion to the flux vector over the integration point....
Definition: blackoildispersionmodule.hh:187
static void addDispersiveFlux(RateVector &flux, const Context &context, unsigned spaceIdx, unsigned timeIdx)
Adds the mass flux due to dispersion to the flux vector over the flux integration point.
Definition: blackoildispersionmodule.hh:151
Provides the auxiliary methods required for consideration of the dispersion equation.
Definition: blackoildispersionmodule.hh:56
Declare the properties used by the infrastructure code of the finite volume discretizations.
Defines the common properties required by the porous medium multi-phase models.
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