RateConverter.hpp
Go to the documentation of this file.
1/*
2 Copyright 2014, 2015 SINTEF ICT, Applied Mathematics.
3 Copyright 2014, 2015 Statoil ASA.
4 Copyright 2017, IRIS
5
6 This file is part of the Open Porous Media Project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#ifndef OPM_RATECONVERTER_HPP_HEADER_INCLUDED
23#define OPM_RATECONVERTER_HPP_HEADER_INCLUDED
24
25#include <opm/grid/utility/RegionMapping.hpp>
26
28
31
32#include <dune/grid/common/gridenums.hh>
33#include <dune/grid/common/rangegenerators.hh>
34
35#include <array>
36#include <cassert>
37#include <unordered_map>
38#include <utility>
39#include <vector>
40
51namespace Opm {
52 namespace RateConverter {
53
69 template <class FluidSystem, class Region>
71 public:
72 using Scalar = typename FluidSystem::Scalar;
79 SurfaceToReservoirVoidage(const Region& region)
80 : rmap_ (region)
81 , attr_ (rmap_, Attributes())
82 {}
83
92 template <typename ElementContext, class Simulator>
93 void defineState(const Simulator& simulator)
94 {
95 // create map from cell to region and set all attributes to
96 // zero
97 for (const auto& reg : rmap_.activeRegions()) {
98 auto& ra = attr_.attributes(reg);
99 ra.pressure = 0.0;
100 ra.temperature = 0.0;
101 ra.rs = 0.0;
102 ra.rv = 0.0;
103 ra.pv = 0.0;
104 ra.saltConcentration = 0.0;
105 ra.rsw = 0.0;
106 ra.rvw = 0.0;
107 }
108
109 // quantities for pore volume average
110 std::unordered_map<RegionId, Attributes> attributes_pv;
111
112 // quantities for hydrocarbon volume average
113 std::unordered_map<RegionId, Attributes> attributes_hpv;
114
115 for (const auto& reg : rmap_.activeRegions()) {
116 attributes_pv.insert({reg, Attributes()});
117 attributes_hpv.insert({reg, Attributes()});
118 }
119
120 ElementContext elemCtx( simulator );
121 const auto& gridView = simulator.gridView();
122 const auto& comm = gridView.comm();
123
125 for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
126 elemCtx.updatePrimaryStencil(elem);
127 elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
128 const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0);
129 const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
130 const auto& fs = intQuants.fluidState();
131 // use pore volume weighted averages.
132 const Scalar pv_cell =
133 simulator.model().dofTotalVolume(simulator.vanguard().gridEquilIdxToGridIdx(cellIdx))
134 * intQuants.porosity().value();
135
136 // only count oil and gas filled parts of the domain
137 Scalar hydrocarbon = 1.0;
138 if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
139 hydrocarbon -= fs.saturation(FluidSystem::waterPhaseIdx).value();
140 }
141
142 const int reg = rmap_.region(cellIdx);
143 assert(reg >= 0);
144
145 // sum p, rs, rv, and T.
146 const Scalar hydrocarbonPV = pv_cell*hydrocarbon;
147 if (hydrocarbonPV > 0.) {
148 auto& attr = attributes_hpv[reg];
149 attr.pv += hydrocarbonPV;
150 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
151 attr.rs += fs.Rs().value() * hydrocarbonPV;
152 attr.rv += fs.Rv().value() * hydrocarbonPV;
153 const Scalar oilPV = pv_cell * fs.saturation(FluidSystem::oilPhaseIdx).value();
154 const Scalar gasPV = pv_cell * fs.saturation(FluidSystem::gasPhaseIdx).value();
155 attr.rs_oil += fs.Rs().value() * oilPV;
156 attr.oil_pv += oilPV;
157 attr.rv_gas += fs.Rv().value() * gasPV;
158 attr.gas_pv += gasPV;
159 }
160 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
161 attr.pressure += fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbonPV;
162 attr.temperature += fs.temperature(FluidSystem::oilPhaseIdx).value() * hydrocarbonPV;
163 } else {
164 assert(FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx));
165 attr.pressure += fs.pressure(FluidSystem::gasPhaseIdx).value() * hydrocarbonPV;
166 attr.temperature += fs.temperature(FluidSystem::gasPhaseIdx).value() * hydrocarbonPV;
167 }
168 attr.saltConcentration += fs.saltConcentration().value() * hydrocarbonPV;
169 if (FluidSystem::enableDissolvedGasInWater()) {
170 attr.rsw += fs.Rsw().value() * hydrocarbonPV; // scale with total volume?
171 }
172 if (FluidSystem::enableVaporizedWater()) {
173 attr.rvw += fs.Rvw().value() * hydrocarbonPV; // scale with total volume?
174 }
175 }
176
177 if (pv_cell > 0.) {
178 auto& attr = attributes_pv[reg];
179 attr.pv += pv_cell;
180 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
181 attr.rs += fs.Rs().value() * pv_cell;
182 attr.rv += fs.Rv().value() * pv_cell;
183 }
184 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
185 attr.pressure += fs.pressure(FluidSystem::oilPhaseIdx).value() * pv_cell;
186 attr.temperature += fs.temperature(FluidSystem::oilPhaseIdx).value() * pv_cell;
187 } else if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
188 attr.pressure += fs.pressure(FluidSystem::gasPhaseIdx).value() * pv_cell;
189 attr.temperature += fs.temperature(FluidSystem::gasPhaseIdx).value() * pv_cell;
190 } else {
191 assert(FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx));
192 attr.pressure += fs.pressure(FluidSystem::waterPhaseIdx).value() * pv_cell;
193 attr.temperature += fs.temperature(FluidSystem::waterPhaseIdx).value() * pv_cell;
194 }
195 attr.saltConcentration += fs.saltConcentration().value() * pv_cell;
196 if (FluidSystem::enableDissolvedGasInWater()) {
197 attr.rsw += fs.Rsw().value() * pv_cell;
198 }
199 if (FluidSystem::enableVaporizedWater()) {
200 attr.rvw += fs.Rvw().value() * pv_cell;
201 }
202 }
203 }
204
205 OPM_END_PARALLEL_TRY_CATCH("SurfaceToReservoirVoidage::defineState() failed: ", simulator.vanguard().grid().comm());
206
207 this->sumRates(attributes_hpv,
208 attributes_pv,
209 comm);
210 }
211
218
246 template <class Coeff>
247 void
248 calcCoeff(const RegionId r, const int pvtRegionIdx, Coeff& coeff) const;
249
250 template <class Coeff , class Rates>
251 void
252 calcCoeff(const RegionId r, const int pvtRegionIdx, const Rates& surface_rates, Coeff& coeff) const;
253
254 template <class Coeff>
255 void
256 calcCoeff( const int pvtRegionIdx,
257 const Scalar p,
258 const Scalar rs,
259 const Scalar rv,
260 const Scalar rsw,
261 const Scalar rvw,
262 const Scalar T,
263 const Scalar saltConcentration,
264 Coeff& coeff) const;
265
266 template <class Coeff>
267 void
268 calcInjCoeff(const RegionId r, const int pvtRegionIdx, Coeff& coeff) const;
269
292 template <class Rates>
294 const int pvtRegionIdx,
295 const Rates& surface_rates,
296 Rates& voidage_rates) const;
297
332 template <typename SurfaceRates, typename VoidageRates>
333 void calcReservoirVoidageRates(const int pvtRegionIdx,
334 const Scalar p,
335 const Scalar rs,
336 const Scalar rv,
337 const Scalar rsw,
338 const Scalar rvw,
339 const Scalar T,
340 const Scalar saltConcentration,
341 const SurfaceRates& surface_rates,
342 VoidageRates& voidage_rates) const;
343
344 template <class Rates>
345 std::pair<Scalar, Scalar>
347 const Scalar rvMax,
348 const Rates& surface_rates) const;
349
362 template <class SolventModule>
363 void
364 calcCoeffSolvent(const RegionId r, const int pvtRegionIdx, Scalar& coeff) const
365 {
366 const auto& ra = attr_.attributes(r);
367 const Scalar p = ra.pressure;
368 const Scalar T = ra.temperature;
369 const auto& solventPvt = SolventModule::solventPvt();
370 const Scalar bs = solventPvt.inverseFormationVolumeFactor(pvtRegionIdx, T, p);
371 coeff = 1.0 / bs;
372 }
373
374 private:
378 const RegionMapping<Region> rmap_;
379
383 struct Attributes {
384 Attributes()
385 : data{0.0}
386 , pressure(data[0])
387 , temperature(data[1])
388 , rs(data[2])
389 , rv(data[3])
390 , rsw(data[4])
391 , rvw(data[5])
392 , pv(data[6])
393 , saltConcentration(data[7])
394 , rs_oil(data[8])
395 , oil_pv(data[9])
396 , rv_gas(data[10])
397 , gas_pv(data[11])
398 {}
399
400 Attributes(const Attributes& rhs)
401 : Attributes()
402 {
403 this->data = rhs.data;
404 }
405
406 Attributes& operator=(const Attributes& rhs)
407 {
408 this->data = rhs.data;
409 return *this;
410 }
411
412 std::array<Scalar,12> data;
413 Scalar& pressure;
414 Scalar& temperature;
415 Scalar& rs;
416 Scalar& rv;
417 Scalar& rsw;
418 Scalar& rvw;
419 Scalar& pv;
420 Scalar& saltConcentration;
421 // Oil (gas) volume weighted Rs (Rv) and corresponding weights.
422 Scalar& rs_oil;
423 Scalar& oil_pv;
424 Scalar& rv_gas;
425 Scalar& gas_pv;
426 };
427
428 void sumRates(std::unordered_map<RegionId,Attributes>& attributes_hpv,
429 std::unordered_map<RegionId,Attributes>& attributes_pv,
431
432 RegionAttributeHelpers::RegionAttributes<RegionId, Attributes> attr_;
433 };
434
435 } // namespace RateConverter
436} // namespace Opm
437
438#endif /* OPM_RATECONVERTER_HPP_HEADER_INCLUDED */
#define OPM_END_PARALLEL_TRY_CATCH(prefix, comm)
Catch exception and throw in a parallel try-catch clause.
Definition: DeferredLoggingErrorHelpers.hpp:197
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:160
Definition: RateConverter.hpp:70
std::pair< Scalar, Scalar > inferDissolvedVaporisedRatio(const Scalar rsMax, const Scalar rvMax, const Rates &surface_rates) const
SurfaceToReservoirVoidage(const Region &region)
Definition: RateConverter.hpp:79
void calcReservoirVoidageRates(const RegionId r, const int pvtRegionIdx, const Rates &surface_rates, Rates &voidage_rates) const
void calcCoeff(const RegionId r, const int pvtRegionIdx, const Rates &surface_rates, Coeff &coeff) const
void calcInjCoeff(const RegionId r, const int pvtRegionIdx, Coeff &coeff) const
void calcCoeff(const RegionId r, const int pvtRegionIdx, Coeff &coeff) const
void calcCoeff(const int pvtRegionIdx, const Scalar p, const Scalar rs, const Scalar rv, const Scalar rsw, const Scalar rvw, const Scalar T, const Scalar saltConcentration, Coeff &coeff) const
void defineState(const Simulator &simulator)
Definition: RateConverter.hpp:93
typename RegionMapping< Region >::RegionId RegionId
Definition: RateConverter.hpp:217
void calcReservoirVoidageRates(const int pvtRegionIdx, const Scalar p, const Scalar rs, const Scalar rv, const Scalar rsw, const Scalar rvw, const Scalar T, const Scalar saltConcentration, const SurfaceRates &surface_rates, VoidageRates &voidage_rates) const
void calcCoeffSolvent(const RegionId r, const int pvtRegionIdx, Scalar &coeff) const
Definition: RateConverter.hpp:364
typename FluidSystem::Scalar Scalar
Definition: RateConverter.hpp:72
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:87
Vanguard & vanguard()
Return a reference to the grid manager of simulation.
Definition: simulator.hh:242
const GridView & gridView() const
Return the grid view for which the simulation is done.
Definition: simulator.hh:254
Model & model()
Return the physical model used in the simulation.
Definition: simulator.hh:260
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: blackoilbioeffectsmodules.hh:45
int RegionId
Definition: WellConstraints.hpp:38