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
24
27
28#include <dune/grid/common/gridenums.hh>
29#include <dune/grid/common/rangegenerators.hh>
30
31#include <algorithm>
32#include <cassert>
33#include <unordered_map>
34
45namespace Opm {
46 namespace RegionAverageCalculator {
47
59 template <class FluidSystem, class Region>
61 public:
62 using Scalar = typename FluidSystem::Scalar;
71 const Region& region)
72 : phaseUsage_(phaseUsage)
73 , rmap_ (region)
74 , attr_ (rmap_, Attributes())
75 {
76 }
77
78
82 template <typename ElementContext, class Simulator>
83 void defineState(const Simulator& simulator)
84 {
85 int numRegions = 0;
86 const auto& gridView = simulator.gridView();
87 const auto& comm = gridView.comm();
88 for (const auto& reg : rmap_.activeRegions()) {
89 numRegions = std::max(numRegions, reg);
90 }
91 numRegions = comm.max(numRegions);
92 for (int reg = 1; reg <= numRegions ; ++ reg) {
93 if (!attr_.has(reg))
94 attr_.insert(reg, Attributes());
95 }
96 // create map from cell to region
97 // and set all attributes to zero
98 for (int reg = 1; reg <= numRegions ; ++ reg) {
99 auto& ra = attr_.attributes(reg);
100 ra.pressure = 0.0;
101 ra.pv = 0.0;
102
103 }
104
105 // quantities for pore volume average
106 std::unordered_map<RegionId, Attributes> attributes_pv;
107
108 // quantities for hydrocarbon volume average
109 std::unordered_map<RegionId, Attributes> attributes_hpv;
110
111 for (int reg = 1; reg <= numRegions ; ++ reg) {
112 attributes_pv.insert({reg, Attributes()});
113 attributes_hpv.insert({reg, Attributes()});
114 }
115
116 ElementContext elemCtx( simulator );
117
119 for (const auto& elem : elements(gridView, Dune::Partitions::interior)) {
120 elemCtx.updatePrimaryStencil(elem);
121 elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
122 const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0);
123 const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
124 const auto& fs = intQuants.fluidState();
125 // use pore volume weighted averages.
126 const Scalar pv_cell =
127 simulator.model().dofTotalVolume(cellIdx)
128 * intQuants.porosity().value();
129
130 // only count oil and gas filled parts of the domain
131 Scalar hydrocarbon = 1.0;
132 const auto& pu = phaseUsage_;
134 hydrocarbon -= fs.saturation(FluidSystem::waterPhaseIdx).value();
135 }
136
137 const int reg = rmap_.region(cellIdx);
138 assert(reg >= 0);
139
140 // sum p, rs, rv, and T.
141 const Scalar hydrocarbonPV = pv_cell*hydrocarbon;
142 if (hydrocarbonPV > 0.) {
143 auto& attr = attributes_hpv[reg];
144 attr.pv += hydrocarbonPV;
146 attr.pressure += fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbonPV;
147 } else {
149 attr.pressure += fs.pressure(FluidSystem::gasPhaseIdx).value() * hydrocarbonPV;
150 }
151 }
152
153 if (pv_cell > 0.) {
154 auto& attr = attributes_pv[reg];
155 attr.pv += pv_cell;
157 attr.pressure += fs.pressure(FluidSystem::oilPhaseIdx).value() * pv_cell;
159 attr.pressure += fs.pressure(FluidSystem::gasPhaseIdx).value() * pv_cell;
160 } else {
162 attr.pressure += fs.pressure(FluidSystem::waterPhaseIdx).value() * pv_cell;
163 }
164 }
165 }
166 OPM_END_PARALLEL_TRY_CATCH("AverageRegionalPressure::defineState(): ", simulator.vanguard().grid().comm());
167
168 for (int reg = 1; reg <= numRegions ; ++ reg) {
169 auto& ra = attr_.attributes(reg);
170 const Scalar hpv_sum = comm.sum(attributes_hpv[reg].pv);
171 // TODO: should we have some epsilon here instead of zero?
172 if (hpv_sum > 0.) {
173 const auto& attri_hpv = attributes_hpv[reg];
174 const Scalar p_hpv_sum = comm.sum(attri_hpv.pressure);
175 ra.pressure = p_hpv_sum / hpv_sum;
176 } else {
177 // using the pore volume to do the averaging
178 const auto& attri_pv = attributes_pv[reg];
179 const Scalar pv_sum = comm.sum(attri_pv.pv);
180 // pore volums can be zero if a fipnum region is empty
181 if (pv_sum > 0) {
182 const Scalar p_pv_sum = comm.sum(attri_pv.pressure);
183 ra.pressure = p_pv_sum / pv_sum;
184 }
185 }
186 }
187 }
188
195
200 Scalar
201 pressure(const RegionId r) const
202 {
203 if (r == 0 ) // region 0 is the whole field
204 {
205 Scalar pressure = 0.0;
206 int num_active_regions = 0;
207 for (const auto& attr : attr_.attributes()) {
208 const auto& value = *attr.second;
209 const auto& ra = value.attr_;
210 pressure += ra.pressure;
211 num_active_regions ++;
212 }
213 return pressure / num_active_regions;
214 }
215
216 const auto& ra = attr_.attributes(r);
217 return ra.pressure;
218 }
219
220
221 private:
225 const PhaseUsage phaseUsage_;
226
230 const RegionMapping<Region> rmap_;
231
235 struct Attributes {
236 Attributes()
237 : pressure(0.0)
238 , pv(0.0)
239
240 {}
241
243 Scalar pv;
244 };
245
246 RegionAttributeHelpers::RegionAttributes<RegionId, Attributes> attr_;
247
248 };
249 } // namespace RegionAverageCalculator
250} // namespace Opm
251
252#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:192
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:158
Definition: RegionAverageCalculator.hpp:60
typename FluidSystem::Scalar Scalar
Definition: RegionAverageCalculator.hpp:62
AverageRegionalPressure(const PhaseUsage &phaseUsage, const Region &region)
Definition: RegionAverageCalculator.hpp:70
void defineState(const Simulator &simulator)
Definition: RegionAverageCalculator.hpp:83
RegionMapping< Region >::RegionId RegionId
Definition: RegionAverageCalculator.hpp:194
Scalar pressure(const RegionId r) const
Definition: RegionAverageCalculator.hpp:201
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:92
Vanguard & vanguard()
Return a reference to the grid manager of simulation.
Definition: simulator.hh:260
const GridView & gridView() const
Return the grid view for which the simulation is done.
Definition: simulator.hh:272
Model & model()
Return the physical model used in the simulation.
Definition: simulator.hh:278
bool water(const PhaseUsage &pu)
Definition: RegionAttributeHelpers.hpp:309
bool oil(const PhaseUsage &pu)
Definition: RegionAttributeHelpers.hpp:322
bool gas(const PhaseUsage &pu)
Definition: RegionAttributeHelpers.hpp:335
Definition: blackoilboundaryratevector.hh:37
PhaseUsage phaseUsage(const Phases &phases)
Determine the active phases.
int RegionId
Definition: WellConstraints.hpp:37
Definition: BlackoilPhases.hpp:46