opm-simulators
blackoillocalresidual.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_LOCAL_RESIDUAL_HH
29 #define EWOMS_BLACK_OIL_LOCAL_RESIDUAL_HH
30 
31 #include <opm/material/common/MathToolbox.hpp>
32 #include <opm/material/fluidstates/BlackOilFluidState.hpp>
33 
44 
45 #include <cassert>
46 
47 namespace Opm {
48 
54 template <class TypeTag>
55 class BlackOilLocalResidual : public GetPropType<TypeTag, Properties::DiscLocalResidual>
56 {
65 
66  enum { conti0EqIdx = Indices::conti0EqIdx };
67  enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
68  enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
69  enum { numComponents = getPropValue<TypeTag, Properties::NumComponents>() };
70 
71  enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
72  enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
73  enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
74 
75  enum { gasCompIdx = FluidSystem::gasCompIdx };
76  enum { oilCompIdx = FluidSystem::oilCompIdx };
77  enum { waterCompIdx = FluidSystem::waterCompIdx };
78  enum { compositionSwitchIdx = Indices::compositionSwitchIdx };
79 
80  static constexpr bool waterEnabled = Indices::waterEnabled;
81  static constexpr bool gasEnabled = Indices::gasEnabled;
82  static constexpr bool oilEnabled = Indices::oilEnabled;
83  static constexpr bool compositionSwitchEnabled = (compositionSwitchIdx >= 0);
84 
85  static constexpr bool blackoilConserveSurfaceVolume = getPropValue<TypeTag, Properties::BlackoilConserveSurfaceVolume>();
86  static constexpr bool enableFullyImplicitThermal = (getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal);
87  static constexpr bool enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>();
88  static constexpr bool enableConvectiveMixing = getPropValue<TypeTag, Properties::EnableConvectiveMixing>();
89 
90  using Toolbox = MathToolbox<Evaluation>;
100 
101 public:
105  template <class LhsEval>
106  void computeStorage(Dune::FieldVector<LhsEval, numEq>& storage,
107  const ElementContext& elemCtx,
108  unsigned dofIdx,
109  unsigned timeIdx) const
110  {
111  // retrieve the intensive quantities for the SCV at the specified point in time
112  const IntensiveQuantities& intQuants = elemCtx.intensiveQuantities(dofIdx, timeIdx);
113  const auto& fs = intQuants.fluidState();
114 
115  storage = 0.0;
116 
117  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
118  if (!FluidSystem::phaseIsActive(phaseIdx)) {
119  if (Indices::numPhases == 3) { // add trivial equation for the pseudo phase
120  const unsigned activeCompIdx =
121  FluidSystem::canonicalToActiveCompIdx(FluidSystem::solventComponentIndex(phaseIdx));
122  if (timeIdx == 0) {
123  storage[conti0EqIdx + activeCompIdx] = variable<LhsEval>(0.0, conti0EqIdx + activeCompIdx);
124  }
125  else {
126  storage[conti0EqIdx + activeCompIdx] = 0.0;
127  }
128  }
129  continue;
130  }
131 
132  const unsigned activeCompIdx =
133  FluidSystem::canonicalToActiveCompIdx(FluidSystem::solventComponentIndex(phaseIdx));
134  const LhsEval surfaceVolume =
135  Toolbox::template decay<LhsEval>(fs.saturation(phaseIdx)) *
136  Toolbox::template decay<LhsEval>(fs.invB(phaseIdx)) *
137  Toolbox::template decay<LhsEval>(intQuants.porosity());
138 
139  storage[conti0EqIdx + activeCompIdx] += surfaceVolume;
140 
141  // account for dissolved gas
142  if (phaseIdx == oilPhaseIdx && FluidSystem::enableDissolvedGas()) {
143  const unsigned activeGasCompIdx = FluidSystem::canonicalToActiveCompIdx(gasCompIdx);
144  storage[conti0EqIdx + activeGasCompIdx] +=
145  Toolbox::template decay<LhsEval>(intQuants.fluidState().Rs()) *
146  surfaceVolume;
147  }
148 
149  // account for dissolved gas in water phase
150  if (phaseIdx == waterPhaseIdx && FluidSystem::enableDissolvedGasInWater()) {
151  const unsigned activeGasCompIdx = FluidSystem::canonicalToActiveCompIdx(gasCompIdx);
152  storage[conti0EqIdx + activeGasCompIdx] +=
153  Toolbox::template decay<LhsEval>(intQuants.fluidState().Rsw()) *
154  surfaceVolume;
155  }
156 
157  // account for vaporized oil
158  if (phaseIdx == gasPhaseIdx && FluidSystem::enableVaporizedOil()) {
159  const unsigned activeOilCompIdx = FluidSystem::canonicalToActiveCompIdx(oilCompIdx);
160  storage[conti0EqIdx + activeOilCompIdx] +=
161  Toolbox::template decay<LhsEval>(intQuants.fluidState().Rv()) *
162  surfaceVolume;
163  }
164 
165  // account for vaporized water
166  if (phaseIdx == gasPhaseIdx && FluidSystem::enableVaporizedWater()) {
167  const unsigned activeWaterCompIdx = FluidSystem::canonicalToActiveCompIdx(waterCompIdx);
168  storage[conti0EqIdx + activeWaterCompIdx] +=
169  Toolbox::template decay<LhsEval>(intQuants.fluidState().Rvw()) *
170  surfaceVolume;
171  }
172  }
173 
174  adaptMassConservationQuantities_(storage, intQuants.pvtRegionIndex());
175 
176  // deal with solvents (if present)
177  SolventModule::addStorage(storage, intQuants);
178 
179  // deal with zFracton (if present)
180  ExtboModule::addStorage(storage, intQuants);
181 
182  // deal with polymer (if present)
183  PolymerModule::addStorage(storage, intQuants);
184 
185  // deal with energy (if present)
186  EnergyModule::addStorage(storage, intQuants);
187 
188  // deal with foam (if present)
189  FoamModule::addStorage(storage, intQuants);
190 
191  // deal with salt (if present)
192  BrineModule::addStorage(storage, intQuants);
193 
194  // deal with bioeffects (if present)
195  BioeffectsModule::addStorage(storage, intQuants);
196  }
197 
201  void computeFlux(RateVector& flux,
202  const ElementContext& elemCtx,
203  unsigned scvfIdx,
204  unsigned timeIdx) const
205  {
206  assert(timeIdx == 0);
207 
208  flux = 0.0;
209 
210  const ExtensiveQuantities& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
211  unsigned focusDofIdx = elemCtx.focusDofIndex();
212  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
213  if (!FluidSystem::phaseIsActive(phaseIdx)) {
214  continue;
215  }
216 
217  const unsigned upIdx = static_cast<unsigned>(extQuants.upstreamIndex(phaseIdx));
218  const IntensiveQuantities& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
219  const unsigned pvtRegionIdx = up.pvtRegionIndex();
220  if (upIdx == focusDofIdx) {
221  evalPhaseFluxes_<Evaluation>(flux, phaseIdx, pvtRegionIdx, extQuants, up.fluidState());
222  }
223  else {
224  evalPhaseFluxes_<Scalar>(flux, phaseIdx, pvtRegionIdx, extQuants, up.fluidState());
225  }
226  }
227  // deal with solvents (if present)
228  SolventModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
229 
230  // deal with zFracton (if present)
231  ExtboModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
232 
233  // deal with polymer (if present)
234  PolymerModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
235 
236  // deal with energy (if present)
237  EnergyModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
238 
239  // deal with foam (if present)
240  FoamModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
241 
242  // deal with salt (if present)
243  BrineModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
244 
245  // deal with bioeffects (if present)
246  BioeffectsModule::computeFlux(flux, elemCtx, scvfIdx, timeIdx);
247 
248  // deal with diffusion (if present)
249  DiffusionModule::addDiffusiveFlux(flux, elemCtx, scvfIdx, timeIdx);
250 
251  // deal with convective mixing (if enabled)
252  ConvectiveMixingModule::addConvectiveMixingFlux(flux, elemCtx, scvfIdx, timeIdx);
253  }
254 
258  void computeSource(RateVector& source,
259  const ElementContext& elemCtx,
260  unsigned dofIdx,
261  unsigned timeIdx) const
262  {
263  // retrieve the source term intrinsic to the problem
264  elemCtx.problem().source(source, elemCtx, dofIdx, timeIdx);
265 
266  // deal with MICP (if present)
267  BioeffectsModule::addSource(source, elemCtx, dofIdx, timeIdx);
268 
269  // scale the source term of the energy equation
270  if constexpr (enableFullyImplicitThermal) {
271  source[Indices::contiEnergyEqIdx] *=
272  getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
273  }
274  }
275 
280  template <class UpEval, class FluidState>
281  static void evalPhaseFluxes_(RateVector& flux,
282  unsigned phaseIdx,
283  unsigned pvtRegionIdx,
284  const ExtensiveQuantities& extQuants,
285  const FluidState& upFs)
286  {
287  const auto& invB = getInvB_<FluidSystem, FluidState, UpEval>(upFs, phaseIdx, pvtRegionIdx);
288  const auto& surfaceVolumeFlux = invB*extQuants.volumeFlux(phaseIdx);
289  const unsigned activeCompIdx =
290  FluidSystem::canonicalToActiveCompIdx(FluidSystem::solventComponentIndex(phaseIdx));
291 
292  if constexpr (blackoilConserveSurfaceVolume) {
293  flux[conti0EqIdx + activeCompIdx] += surfaceVolumeFlux;
294  }
295  else {
296  flux[conti0EqIdx + activeCompIdx] += surfaceVolumeFlux *
297  FluidSystem::referenceDensity(phaseIdx, pvtRegionIdx);
298  }
299 
300  if (phaseIdx == oilPhaseIdx) {
301  // dissolved gas (in the oil phase).
302  if (FluidSystem::enableDissolvedGas()) {
303  const auto& Rs = BlackOil::getRs_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
304 
305  const unsigned activeGasCompIdx = FluidSystem::canonicalToActiveCompIdx(gasCompIdx);
306  if constexpr (blackoilConserveSurfaceVolume) {
307  flux[conti0EqIdx + activeGasCompIdx] += Rs * surfaceVolumeFlux;
308  }
309  else {
310  flux[conti0EqIdx + activeGasCompIdx] +=
311  Rs * surfaceVolumeFlux *
312  FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
313  }
314  }
315  } else if (phaseIdx == waterPhaseIdx) {
316  // dissolved gas (in the water phase).
317  if (FluidSystem::enableDissolvedGasInWater()) {
318  const auto& Rsw = BlackOil::getRsw_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
319 
320  const unsigned activeGasCompIdx = FluidSystem::canonicalToActiveCompIdx(gasCompIdx);
321  if constexpr (blackoilConserveSurfaceVolume) {
322  flux[conti0EqIdx + activeGasCompIdx] += Rsw * surfaceVolumeFlux;
323  }
324  else {
325  flux[conti0EqIdx + activeGasCompIdx] +=
326  Rsw * surfaceVolumeFlux *
327  FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
328  }
329  }
330  }
331  else if (phaseIdx == gasPhaseIdx) {
332  // vaporized oil (in the gas phase).
333  if (FluidSystem::enableVaporizedOil()) {
334  const auto& Rv = BlackOil::getRv_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
335 
336  const unsigned activeOilCompIdx = FluidSystem::canonicalToActiveCompIdx(oilCompIdx);
337  if constexpr (blackoilConserveSurfaceVolume) {
338  flux[conti0EqIdx + activeOilCompIdx] += Rv * surfaceVolumeFlux;
339  }
340  else {
341  flux[conti0EqIdx + activeOilCompIdx] +=
342  Rv * surfaceVolumeFlux *
343  FluidSystem::referenceDensity(oilPhaseIdx, pvtRegionIdx);
344  }
345  }
346  // vaporized water (in the gas phase).
347  if (FluidSystem::enableVaporizedWater()) {
348  const auto& Rvw = BlackOil::getRvw_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
349 
350  const unsigned activeWaterCompIdx = FluidSystem::canonicalToActiveCompIdx(waterCompIdx);
351  if constexpr (blackoilConserveSurfaceVolume) {
352  flux[conti0EqIdx + activeWaterCompIdx] += Rvw * surfaceVolumeFlux;
353  }
354  else {
355  flux[conti0EqIdx + activeWaterCompIdx] +=
356  Rvw * surfaceVolumeFlux *
357  FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
358  }
359  }
360  }
361  }
362 
374  template <class Scalar>
375  static void adaptMassConservationQuantities_(Dune::FieldVector<Scalar, numEq>& container,
376  unsigned pvtRegionIdx)
377  {
378  if constexpr (!blackoilConserveSurfaceVolume) {
379  // convert "surface volume" to mass. this is complicated a bit by the fact that
380  // not all phases are necessarily enabled. (we here assume that if a fluid phase
381  // is disabled, its respective "main" component is not considered as well.)
382 
383  if constexpr (waterEnabled) {
384  const unsigned activeWaterCompIdx = FluidSystem::canonicalToActiveCompIdx(waterCompIdx);
385  container[conti0EqIdx + activeWaterCompIdx] *=
386  FluidSystem::referenceDensity(waterPhaseIdx, pvtRegionIdx);
387  }
388 
389  if constexpr (gasEnabled) {
390  const unsigned activeGasCompIdx = FluidSystem::canonicalToActiveCompIdx(gasCompIdx);
391  container[conti0EqIdx + activeGasCompIdx] *=
392  FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
393  }
394 
395  if constexpr (oilEnabled) {
396  const unsigned activeOilCompIdx = FluidSystem::canonicalToActiveCompIdx(oilCompIdx);
397  container[conti0EqIdx + activeOilCompIdx] *=
398  FluidSystem::referenceDensity(oilPhaseIdx, pvtRegionIdx);
399  }
400  }
401  }
402 };
403 
404 } // namespace Opm
405 
406 #endif
Contains the high level supplements required to extend the black oil model by solvents.
Definition: blackoilsolventmodules.hh:68
Contains the classes required to extend the black-oil model to include the effects of foam...
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
Contains the high level supplements required to extend the black oil model to include the effects of ...
Definition: blackoilfoammodules.hh:59
Contains the classes required to extend the black-oil model by solvent component. ...
void computeStorage(Dune::FieldVector< LhsEval, numEq > &storage, const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx) const
Evaluate the amount all conservation quantities (e.g.
Definition: blackoillocalresidual.hh:106
void computeFlux(RateVector &flux, const ElementContext &elemCtx, unsigned scvfIdx, unsigned timeIdx) const
Evaluates the total mass flux of all conservation quantities over a face of a sub-control volume...
Definition: blackoillocalresidual.hh:201
static void evalPhaseFluxes_(RateVector &flux, unsigned phaseIdx, unsigned pvtRegionIdx, const ExtensiveQuantities &extQuants, const FluidState &upFs)
Helper function to calculate the flux of mass in terms of conservation quantities via specific fluid ...
Definition: blackoillocalresidual.hh:281
Classes required for dynamic convective mixing.
Contains the classes required to extend the black-oil model by solvents.
Classes required for molecular diffusion.
static void adaptMassConservationQuantities_(Dune::FieldVector< Scalar, numEq > &container, unsigned pvtRegionIdx)
Helper function to convert the mass-related parts of a Dune::FieldVector that stores conservation qua...
Definition: blackoillocalresidual.hh:375
Contains the high level supplements required to extend the black oil model by brine.
Definition: blackoilbrinemodules.hh:57
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Contains the high level supplements required to extend the black oil model by energy.
Definition: blackoilenergymodules.hh:62
Declares the properties required by the black oil model.
Definition: blackoilconvectivemixingmodule.hh:99
Calculates the local residual of the black oil model.
Definition: blackoillocalresidual.hh:55
Contains the classes required to extend the black-oil model by brine.
Contains the high level supplements required to extend the black oil model.
Definition: blackoilextbomodules.hh:63
Contains the classes required to extend the black-oil model by bioeffects.
Contains the classes required to extend the black-oil model by energy.
Contains the high level supplements required to extend the black oil model by bioeffects.
Definition: blackoilbioeffectsmodules.hh:94
void computeSource(RateVector &source, const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx) const
Calculate the source term of the equation.
Definition: blackoillocalresidual.hh:258
Contains the classes required to extend the black-oil model by polymer.
Contains the high level supplements required to extend the black oil model by polymer.
Definition: blackoilpolymermodules.hh:64
Provides the auxiliary methods required for consideration of the diffusion equation.
Definition: blackoildiffusionmodule.hh:54