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#if HAVE_ECL_INPUT
41#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
42#include <opm/common/OpmLog/OpmLog.hpp>
43#endif
44
45#include <array>
46#include <cmath>
47#include <stdexcept>
48
49namespace Opm {
50
57template <class TypeTag, bool enableDispersion>
59
60template <class TypeTag, bool enableDispersion>
62
66template <class TypeTag>
67class BlackOilDispersionModule<TypeTag, /*enableDispersion=*/false>
68{
74
75 enum { numPhases = FluidSystem::numPhases };
76
77public:
79
80#if HAVE_ECL_INPUT
81 static void initFromState(const EclipseState&)
82 {}
83#endif
84
89 template <class Context>
90 static void addDispersiveFlux(RateVector&,
91 const Context&,
92 unsigned,
93 unsigned)
94 {}
95
96 template<class IntensiveQuantities, class Scalar>
97 static void addDispersiveFlux(RateVector&,
98 const IntensiveQuantities&,
99 const IntensiveQuantities&,
100 const Evaluation&,
101 const Scalar&)
102 {}
103};
104
108template <class TypeTag>
109class BlackOilDispersionModule<TypeTag, /*enableDispersion=*/true>
110{
122
123 enum { numPhases = FluidSystem::numPhases };
124 enum { numComponents = FluidSystem::numComponents };
125 enum { conti0EqIdx = Indices::conti0EqIdx };
126 enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
127 enum { enableMICP = getPropValue<TypeTag, Properties::EnableMICP>() };
128
129 static constexpr unsigned contiMicrobialEqIdx = Indices::contiMicrobialEqIdx;
130 static constexpr unsigned contiOxygenEqIdx = Indices::contiOxygenEqIdx;
131 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
132 static constexpr unsigned contiUreaEqIdx = Indices::contiUreaEqIdx;
133
134 using Toolbox = MathToolbox<Evaluation>;
135
136public:
138
139#if HAVE_ECL_INPUT
140 static void initFromState(const EclipseState& eclState)
141 {
142 if (!eclState.getSimulationConfig().rock_config().dispersion()) {
143 return;
144 }
145
146 if (eclState.getSimulationConfig().hasVAPWAT() || eclState.getSimulationConfig().hasVAPOIL()) {
147 OpmLog::warning("Dispersion is activated in combination with VAPWAT/VAPOIL. \n"
148 "Water/oil is still allowed to vaporize, but dispersion in the "
149 "gas phase is ignored.");
150 }
151 }
152#endif
153
158 template <class Context>
159 static void addDispersiveFlux(RateVector& flux, const Context& context,
160 unsigned spaceIdx, unsigned timeIdx)
161 {
162 // Only work if dispersion is enabled by DISPERC in the deck
163 if (!context.simulator().vanguard().eclState().getSimulationConfig().rock_config().dispersion()) {
164 return;
165 }
166 const auto& extQuants = context.extensiveQuantities(spaceIdx, timeIdx);
167 const auto& inIq = context.intensiveQuantities(extQuants.interiorIndex(), timeIdx);
168 const auto& exIq = context.intensiveQuantities(extQuants.exteriorIndex(), timeIdx);
169 const auto& dispersivity = extQuants.dispersivity();
170 const auto& normVelocityAvg = extQuants.normVelocityAvg();
171 addDispersiveFlux(flux, inIq, exIq, dispersivity, normVelocityAvg);
172 }
173
194 template<class IntensiveQuantities, class Scalar>
195 static void addDispersiveFlux(RateVector& flux,
196 const IntensiveQuantities& inIq,
197 const IntensiveQuantities& exIq,
198 const Evaluation& dispersivity,
199 const Scalar& normVelocityAvg)
200 {
201 const auto& inFs = inIq.fluidState();
202 const auto& exFs = exIq.fluidState();
203 Evaluation diffR = 0.0;
204 if constexpr(enableMICP) {
205 // The dispersion coefficients are given for mass concentrations
206 const Evaluation bAvg = (inFs.invB(waterPhaseIdx) + Toolbox::value(exFs.invB(waterPhaseIdx))) / 2;
207 diffR = inIq.microbialConcentration() - Toolbox::value(exIq.microbialConcentration());
208 flux[contiMicrobialEqIdx] +=
209 bAvg *
210 normVelocityAvg[waterPhaseIdx] *
211 dispersivity *
212 diffR;
213 diffR = inIq.oxygenConcentration() - Toolbox::value(exIq.oxygenConcentration());
214 flux[contiOxygenEqIdx] +=
215 bAvg *
216 normVelocityAvg[waterPhaseIdx] *
217 dispersivity *
218 diffR;
219 diffR = inIq.ureaConcentration() - Toolbox::value(exIq.ureaConcentration());
220 flux[contiUreaEqIdx] +=
221 bAvg *
222 normVelocityAvg[waterPhaseIdx] *
223 dispersivity *
224 diffR;
225 return;
226 }
227
228 unsigned pvtRegionIndex = inFs.pvtRegionIndex();
229 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
230 if (!FluidSystem::phaseIsActive(phaseIdx)) {
231 continue;
232 }
233
234 // no dispersion in water for blackoil models unless water can contain dissolved gas
235 if (!FluidSystem::enableDissolvedGasInWater() && FluidSystem::waterPhaseIdx == phaseIdx) {
236 continue;
237 }
238
239 // adding dispersion in the gas phase leads to
240 // convergence issues and unphysical results.
241 // we disable dispersion in the gas phase for now
242 if (FluidSystem::gasPhaseIdx == phaseIdx) {
243 continue;
244 }
245
246 // arithmetic mean of the phase's b factor
247 Evaluation bAvg = inFs.invB(phaseIdx);
248 bAvg += Toolbox::value(exFs.invB(phaseIdx));
249 bAvg /= 2;
250
251 Evaluation convFactor = 1.0;
252 if (FluidSystem::enableDissolvedGas() &&
253 FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) &&
254 phaseIdx == FluidSystem::oilPhaseIdx)
255 {
256 const Evaluation rsAvg = (inFs.Rs() + Toolbox::value(exFs.Rs())) / 2;
257 convFactor = 1.0 / (toMassFractionGasOil(pvtRegionIndex) + rsAvg);
258 diffR = inFs.Rs() - Toolbox::value(exFs.Rs());
259 }
260 if (FluidSystem::enableVaporizedOil() &&
261 FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) &&
262 phaseIdx == FluidSystem::gasPhaseIdx)
263 {
264 const Evaluation rvAvg = (inFs.Rv() + Toolbox::value(exFs.Rv())) / 2;
265 convFactor = toMassFractionGasOil(pvtRegionIndex) /
266 (1.0 + rvAvg * toMassFractionGasOil(pvtRegionIndex));
267 diffR = inFs.Rv() - Toolbox::value(exFs.Rv());
268 }
269 if (FluidSystem::enableDissolvedGasInWater() && phaseIdx == FluidSystem::waterPhaseIdx) {
270 const Evaluation rsAvg = (inFs.Rsw() + Toolbox::value(exFs.Rsw())) / 2;
271 convFactor = 1.0 / (toMassFractionGasWater(pvtRegionIndex) + rsAvg);
272 diffR = inFs.Rsw() - Toolbox::value(exFs.Rsw());
273 }
274 if (FluidSystem::enableVaporizedWater() && phaseIdx == FluidSystem::gasPhaseIdx) {
275 const Evaluation rvAvg = (inFs.Rvw() + Toolbox::value(exFs.Rvw())) / 2;
276 convFactor = toMassFractionGasWater(pvtRegionIndex) /
277 (1.0 + rvAvg * toMassFractionGasWater(pvtRegionIndex));
278 diffR = inFs.Rvw() - Toolbox::value(exFs.Rvw());
279 }
280
281 // mass flux of solvent component
282 const unsigned solventCompIdx = FluidSystem::solventComponentIndex(phaseIdx);
283 const unsigned activeSolventCompIdx = Indices::canonicalToActiveComponentIndex(solventCompIdx);
284 flux[conti0EqIdx + activeSolventCompIdx] +=
285 -bAvg *
286 normVelocityAvg[phaseIdx] *
287 convFactor *
288 dispersivity *
289 diffR;
290
291 // mass flux of solute component
292 const unsigned soluteCompIdx = FluidSystem::soluteComponentIndex(phaseIdx);
293 const unsigned activeSoluteCompIdx = Indices::canonicalToActiveComponentIndex(soluteCompIdx);
294 flux[conti0EqIdx + activeSoluteCompIdx] +=
295 bAvg *
296 normVelocityAvg[phaseIdx] *
297 convFactor *
298 dispersivity *
299 diffR;
300 }
301 }
302
303private:
304 static Scalar toMassFractionGasOil (unsigned regionIdx)
305 {
306 const Scalar rhoO = FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, regionIdx);
307 const Scalar rhoG = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
308 return rhoO / rhoG;
309 }
310
311 static Scalar toMassFractionGasWater (unsigned regionIdx)
312 {
313 const Scalar rhoW = FluidSystem::referenceDensity(FluidSystem::waterPhaseIdx, regionIdx);
314 const Scalar rhoG = FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, regionIdx);
315 return rhoW / rhoG;
316 }
317};
318
326template <class TypeTag, bool enableDispersion>
328
332template <class TypeTag>
333class BlackOilDispersionIntensiveQuantities<TypeTag, /*enableDispersion=*/false>
334{
338
339public:
343 Scalar normVelocityCell(unsigned, unsigned) const
344 {
345 throw std::logic_error("Method normVelocityCell() "
346 "does not make sense if dispersion is disabled");
347 }
348
349protected:
354 template<class ElementContext>
355 void update_(ElementContext&,
356 unsigned,
357 unsigned)
358 {}
359};
360
364template <class TypeTag>
365class BlackOilDispersionIntensiveQuantities<TypeTag, /*enableDispersion=*/true>
366{
373 enum { numPhases = FluidSystem::numPhases };
374 enum { numComponents = FluidSystem::numComponents };
375 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
376 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
377 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
378 enum { gasCompIdx = FluidSystem::gasCompIdx };
379 enum { oilCompIdx = FluidSystem::oilCompIdx };
380 enum { waterCompIdx = FluidSystem::waterCompIdx };
381 enum { conti0EqIdx = Indices::conti0EqIdx };
382 enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
383
384public:
388 Scalar normVelocityCell(unsigned phaseIdx) const
389 { return normVelocityCell_[phaseIdx]; }
390
391protected:
401 template<class ElementContext>
402 void update_(const ElementContext& elemCtx, unsigned dofIdx, unsigned timeIdx)
403 {
404 // Only work if dispersion is enabled by DISPERC in the deck
405 if (!elemCtx.simulator().vanguard().eclState().getSimulationConfig().rock_config().dispersion()) {
406 return;
407 }
408 const auto& problem = elemCtx.simulator().problem();
409 if (problem.model().linearizer().getVelocityInfo().empty()) {
410 return;
411 }
412 const std::array<int, 3> phaseIdxs = {gasPhaseIdx, oilPhaseIdx, waterPhaseIdx};
413 const std::array<int, 3> compIdxs = {gasCompIdx, oilCompIdx, waterCompIdx};
414 const auto& velocityInf = problem.model().linearizer().getVelocityInfo();
415 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
416 const auto& velocityInfos = velocityInf[globalDofIdx];
417 for (unsigned i = 0; i < phaseIdxs.size(); ++i) {
418 normVelocityCell_[i] = 0;
419 }
420 for (const auto& velocityInfo : velocityInfos) {
421 for (unsigned i = 0; i < phaseIdxs.size(); ++i) {
422 if (FluidSystem::phaseIsActive(phaseIdxs[i])) {
423 normVelocityCell_[phaseIdxs[i]] = max( normVelocityCell_[phaseIdxs[i]],
424 std::abs(velocityInfo.velocity[conti0EqIdx +
425 Indices::canonicalToActiveComponentIndex(compIdxs[i])]));
426 }
427 }
428 }
429 }
430
431private:
432 std::array<Scalar, numPhases> normVelocityCell_{};
433};
434
441template <class TypeTag, bool enableDispersion>
442class BlackOilDispersionExtensiveQuantities;
443
447template <class TypeTag>
448class BlackOilDispersionExtensiveQuantities<TypeTag, /*enableDispersion=*/false>
449{
455
456 enum { numPhases = FluidSystem::numPhases };
457
458protected:
463 void update_(const ElementContext&,
464 unsigned,
465 unsigned)
466 {}
467
468 template <class Context, class FluidState>
469 void updateBoundary_(const Context&,
470 unsigned,
471 unsigned,
472 const FluidState&)
473 {}
474
475public:
476 using ScalarArray = Scalar[numPhases];
477
478 static void update(ScalarArray&,
479 const IntensiveQuantities&,
480 const IntensiveQuantities&)
481 {}
482
487 Scalar dispersivity() const
488 {
489 throw std::logic_error("The method dispersivity() does not "
490 "make sense if dispersion is disabled.");
491 }
492
500 Scalar normVelocityAvg(unsigned) const
501 {
502 throw std::logic_error("The method normVelocityAvg() "
503 "does not make sense if dispersion is disabled.");
504 }
505};
506
510template <class TypeTag>
511class BlackOilDispersionExtensiveQuantities<TypeTag, /*enableDispersion=*/true>
512{
518 using Toolbox = MathToolbox<Evaluation>;
520
521 enum { dimWorld = GridView::dimensionworld };
522 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
523 enum { numComponents = getPropValue<TypeTag, Properties::NumComponents>() };
524
525 using DimVector = Dune::FieldVector<Scalar, dimWorld>;
526 using DimEvalVector = Dune::FieldVector<Evaluation, dimWorld>;
527
528public:
529 using ScalarArray = std::array<Scalar, numPhases>;
530 static void update(ScalarArray& normVelocityAvg,
531 const IntensiveQuantities& intQuantsInside,
532 const IntensiveQuantities& intQuantsOutside)
533 {
534 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
535 if (!FluidSystem::phaseIsActive(phaseIdx)) {
536 continue;
537 }
538 // no dispersion in water for blackoil models unless water can contain dissolved gas
539 if (!FluidSystem::enableDissolvedGasInWater() && FluidSystem::waterPhaseIdx == phaseIdx) {
540 continue;
541 }
542 // adding dispersion in the gas phase leads to
543 // convergence issues and unphysical results.
544 // we disable dispersion in the gas phase for now
545 if (FluidSystem::gasPhaseIdx == phaseIdx) {
546 continue;
547 }
548 // use the arithmetic average for the effective
549 // velocity coefficients at the face's integration point.
550 normVelocityAvg[phaseIdx] =
551 0.5 * (intQuantsInside.normVelocityCell(phaseIdx) +
552 intQuantsOutside.normVelocityCell(phaseIdx));
553 Valgrind::CheckDefined(normVelocityAvg[phaseIdx]);
554 }
555 }
556
557protected:
558 template <class Context, class FluidState>
559 void updateBoundary_(const Context&,
560 unsigned,
561 unsigned,
562 const FluidState&)
563 { throw std::runtime_error("Not implemented: Dispersion across boundary not implemented for blackoil"); }
564
565public:
572 Scalar dispersivity() const
573 { return dispersivity_; }
574
582 Scalar normVelocityAvg(unsigned phaseIdx) const
583 { return normVelocityAvg_[phaseIdx]; }
584
585 const auto& normVelocityAvg() const
586 { return normVelocityAvg_; }
587
588private:
589 Scalar dispersivity_;
590 ScalarArray normVelocityAvg_;
591};
592
593} // namespace Opm
594
595#endif
Declares the properties required by the black oil model.
Definition: blackoildispersionmodule.hh:449
void updateBoundary_(const Context &, unsigned, unsigned, const FluidState &)
Definition: blackoildispersionmodule.hh:469
void update_(const ElementContext &, unsigned, unsigned)
Update the quantities required to calculate the dispersive fluxes.
Definition: blackoildispersionmodule.hh:463
Scalar[numPhases] ScalarArray
Definition: blackoildispersionmodule.hh:476
static void update(ScalarArray &, const IntensiveQuantities &, const IntensiveQuantities &)
Definition: blackoildispersionmodule.hh:478
Scalar normVelocityAvg(unsigned) const
The effective filter velocity coefficient in a fluid phase at the face's integration point.
Definition: blackoildispersionmodule.hh:500
Scalar dispersivity() const
The dispersivity the face.
Definition: blackoildispersionmodule.hh:487
Provides the quantities required to calculate dispersive mass fluxes.
Definition: blackoildispersionmodule.hh:512
Scalar dispersivity() const
The dispersivity of the face.
Definition: blackoildispersionmodule.hh:572
static void update(ScalarArray &normVelocityAvg, const IntensiveQuantities &intQuantsInside, const IntensiveQuantities &intQuantsOutside)
Definition: blackoildispersionmodule.hh:530
std::array< Scalar, numPhases > ScalarArray
Definition: blackoildispersionmodule.hh:529
void updateBoundary_(const Context &, unsigned, unsigned, const FluidState &)
Definition: blackoildispersionmodule.hh:559
const auto & normVelocityAvg() const
Definition: blackoildispersionmodule.hh:585
Scalar normVelocityAvg(unsigned phaseIdx) const
The effective velocity coefficient in a fluid phase at the face's integration point.
Definition: blackoildispersionmodule.hh:582
Provides the quantities required to calculate dispersive mass fluxes.
Definition: blackoildispersionmodule.hh:61
Scalar normVelocityCell(unsigned, unsigned) const
Returns the max. norm of the filter velocity of the cell.
Definition: blackoildispersionmodule.hh:343
void update_(ElementContext &, unsigned, unsigned)
Update the quantities required to calculate dispersive fluxes.
Definition: blackoildispersionmodule.hh:355
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:402
Scalar normVelocityCell(unsigned phaseIdx) const
Returns the max. norm of the filter velocity of the cell.
Definition: blackoildispersionmodule.hh:388
Provides the volumetric quantities required for the calculation of dispersive fluxes.
Definition: blackoildispersionmodule.hh:327
static void addDispersiveFlux(RateVector &, const Context &, unsigned, unsigned)
Adds the dispersive flux to the flux vector over a flux integration point.
Definition: blackoildispersionmodule.hh:90
static void addDispersiveFlux(RateVector &, const IntensiveQuantities &, const IntensiveQuantities &, const Evaluation &, const Scalar &)
Definition: blackoildispersionmodule.hh:97
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:195
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:159
Provides the auxiliary methods required for consideration of the dispersion equation.
Definition: blackoildispersionmodule.hh:58
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: blackoilboundaryratevector.hh:39
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