RegionAverageCalculator.hpp
Go to the documentation of this file.
1/*
2 Copyright 2021, Equinor
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 3 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
20#ifndef OPM_REGIONAVERAGECALCULATOR_HPP_HEADER_INCLUDED
21#define OPM_REGIONAVERAGECALCULATOR_HPP_HEADER_INCLUDED
22
26
27#include <dune/grid/common/gridenums.hh>
28#include <dune/grid/common/rangegenerators.hh>
29
30#include <algorithm>
31#include <cassert>
32#include <cmath>
33#include <memory>
34#include <stdexcept>
35#include <type_traits>
36#include <unordered_map>
37#include <utility>
38#include <vector>
39
50namespace Opm {
51 namespace RegionAverageCalculator {
52
64 template <class FluidSystem, class Region>
66 public:
75 const Region& region)
76 : phaseUsage_(phaseUsage)
77 , rmap_ (region)
78 , attr_ (rmap_, Attributes())
79 {
80 }
81
82
86 template <typename ElementContext, class Simulator>
87 void defineState(const Simulator& simulator)
88 {
89 int numRegions = 0;
90 const auto& gridView = simulator.gridView();
91 const auto& comm = gridView.comm();
92 for (const auto& reg : rmap_.activeRegions()) {
93 numRegions = std::max(numRegions, reg);
94 }
95 numRegions = comm.max(numRegions);
96 for (int reg = 1; reg <= numRegions ; ++ reg) {
97 if (!attr_.has(reg))
98 attr_.insert(reg, Attributes());
99 }
100 // create map from cell to region
101 // and set all attributes to zero
102 for (int reg = 1; reg <= numRegions ; ++ reg) {
103 auto& ra = attr_.attributes(reg);
104 ra.pressure = 0.0;
105 ra.pv = 0.0;
106
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 (int reg = 1; reg <= numRegions ; ++ reg) {
116 attributes_pv.insert({reg, Attributes()});
117 attributes_hpv.insert({reg, Attributes()});
118 }
119
120 ElementContext elemCtx( simulator );
121
123 for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
124 elemCtx.updatePrimaryStencil(elem);
125 elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
126 const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0);
127 const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
128 const auto& fs = intQuants.fluidState();
129 // use pore volume weighted averages.
130 const double pv_cell =
131 simulator.model().dofTotalVolume(cellIdx)
132 * intQuants.porosity().value();
133
134 // only count oil and gas filled parts of the domain
135 double hydrocarbon = 1.0;
136 const auto& pu = phaseUsage_;
138 hydrocarbon -= fs.saturation(FluidSystem::waterPhaseIdx).value();
139 }
140
141 const int reg = rmap_.region(cellIdx);
142 assert(reg >= 0);
143
144 // sum p, rs, rv, and T.
145 const double hydrocarbonPV = pv_cell*hydrocarbon;
146 if (hydrocarbonPV > 0.) {
147 auto& attr = attributes_hpv[reg];
148 attr.pv += hydrocarbonPV;
150 attr.pressure += fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbonPV;
151 } else {
153 attr.pressure += fs.pressure(FluidSystem::gasPhaseIdx).value() * hydrocarbonPV;
154 }
155 }
156
157 if (pv_cell > 0.) {
158 auto& attr = attributes_pv[reg];
159 attr.pv += pv_cell;
161 attr.pressure += fs.pressure(FluidSystem::oilPhaseIdx).value() * pv_cell;
163 attr.pressure += fs.pressure(FluidSystem::gasPhaseIdx).value() * pv_cell;
164 } else {
166 attr.pressure += fs.pressure(FluidSystem::waterPhaseIdx).value() * pv_cell;
167 }
168 }
169 }
170 OPM_END_PARALLEL_TRY_CATCH("AverageRegionalPressure::defineState(): ", simulator.vanguard().grid().comm());
171
172 for (int reg = 1; reg <= numRegions ; ++ reg) {
173 auto& ra = attr_.attributes(reg);
174 const double hpv_sum = comm.sum(attributes_hpv[reg].pv);
175 // TODO: should we have some epsilon here instead of zero?
176 if (hpv_sum > 0.) {
177 const auto& attri_hpv = attributes_hpv[reg];
178 const double p_hpv_sum = comm.sum(attri_hpv.pressure);
179 ra.pressure = p_hpv_sum / hpv_sum;
180 } else {
181 // using the pore volume to do the averaging
182 const auto& attri_pv = attributes_pv[reg];
183 const double pv_sum = comm.sum(attri_pv.pv);
184 // pore volums can be zero if a fipnum region is empty
185 if (pv_sum > 0) {
186 const double p_pv_sum = comm.sum(attri_pv.pressure);
187 ra.pressure = p_pv_sum / pv_sum;
188 }
189 }
190 }
191 }
192
199
204 double
205 pressure(const RegionId r) const
206 {
207 if (r == 0 ) // region 0 is the whole field
208 {
209 double pressure = 0.0;
210 int num_active_regions = 0;
211 for (const auto& attr : attr_.attributes()) {
212 const auto& value = *attr.second;
213 const auto& ra = value.attr_;
214 pressure += ra.pressure;
215 num_active_regions ++;
216 }
217 return pressure / num_active_regions;
218 }
219
220 const auto& ra = attr_.attributes(r);
221 return ra.pressure;
222 }
223
224
225 private:
229 const PhaseUsage phaseUsage_;
230
234 const RegionMapping<Region> rmap_;
235
239 struct Attributes {
240 Attributes()
241 : pressure(0.0)
242 , pv(0.0)
243
244 {}
245
246 double pressure;
247 double pv;
248
249 };
250
251 RegionAttributeHelpers::RegionAttributes<RegionId, Attributes> attr_;
252
253 };
254 } // namespace RegionAverageCalculator
255} // namespace Opm
256
257#endif /* OPM_REGIONAVERAGECALCULATOR_HPP_HEADER_INCLUDED */
#define OPM_END_PARALLEL_TRY_CATCH(prefix, comm)
Catch exception and throw in a parallel try-catch clause.
Definition: DeferredLoggingErrorHelpers.hpp:172
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:138
Definition: RegionAverageCalculator.hpp:65
AverageRegionalPressure(const PhaseUsage &phaseUsage, const Region &region)
Definition: RegionAverageCalculator.hpp:74
double pressure(const RegionId r) const
Definition: RegionAverageCalculator.hpp:205
void defineState(const Simulator &simulator)
Definition: RegionAverageCalculator.hpp:87
RegionMapping< Region >::RegionId RegionId
Definition: RegionAverageCalculator.hpp:198
bool water(const PhaseUsage &pu)
Definition: RegionAttributeHelpers.hpp:308
bool oil(const PhaseUsage &pu)
Definition: RegionAttributeHelpers.hpp:321
bool gas(const PhaseUsage &pu)
Definition: RegionAttributeHelpers.hpp:334
Definition: BlackoilPhases.hpp:27
PhaseUsage phaseUsage(const Phases &phases)
Determine the active phases.
int RegionId
Definition: WellConstraints.hpp:38
Definition: BlackoilPhases.hpp:46