PeriodicHelpers.hpp
Go to the documentation of this file.
1//===========================================================================
2//
3// File: PeriodicHelpers.hpp
4//
5// Created: Fri Aug 14 10:59:57 2009
6//
7// Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
8// Bård Skaflestad <bard.skaflestad@sintef.no>
9//
10// $Date$
11//
12// $Revision$
13//
14//===========================================================================
15
16/*
17 Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
18 Copyright 2009, 2010 Statoil ASA.
19
20 This file is part of The Open Reservoir Simulator Project (OpenRS).
21
22 OpenRS is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26
27 OpenRS is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
34*/
35
36#ifndef OPENRS_PERIODICHELPERS_HEADER
37#define OPENRS_PERIODICHELPERS_HEADER
38
41#include <dune/common/fvector.hh>
42#include <array>
43#include <algorithm>
44#include <iostream>
45
46namespace Opm
47{
48
49
50
51
52
53 template <class BCs>
54 void storeFlowCond(BCs& bcs,
55 const std::vector<BoundaryFaceInfo>& bfinfo,
56 const std::array<FlowBC, 6>& fconditions,
57 const std::array<double, 6>& side_areas)
58 {
59 int num_bdy = bfinfo.size();
60 for (int i = 0; i < num_bdy; ++i) {
61 FlowBC face_bc = fconditions[bfinfo[i].canon_pos];
62 if (face_bc.isNeumann()) {
63 face_bc = FlowBC(FlowBC::Neumann, face_bc.outflux()*bfinfo[i].area/side_areas[bfinfo[i].canon_pos]);
64 }
65 bcs.flowCond(bfinfo[i].bid) = face_bc;
66 }
67 }
68
69
70
71
72
73 template <class BCs>
74 void storeSatCond(BCs& bcs,
75 const std::vector<BoundaryFaceInfo>& bfinfo,
76 const std::array<SatBC, 6>& sconditions)
77 {
78 int num_bdy = bfinfo.size();
79 for (int i = 0; i < num_bdy; ++i) {
80 bcs.satCond(bfinfo[i].bid) = sconditions[bfinfo[i].canon_pos];
81 }
82 }
83
84
85 template <class BC>
86 std::array<bool, 6> extractPeriodic(const std::array<BC, 6>& bcs)
87 {
88 std::array<bool, 6> retval = {{ bcs[0].isPeriodic(),
89 bcs[1].isPeriodic(),
90 bcs[2].isPeriodic(),
91 bcs[3].isPeriodic(),
92 bcs[4].isPeriodic(),
93 bcs[5].isPeriodic() }};
94 return retval;
95 }
96
97
104 template <class BCs, class GridInterface>
105 void createPeriodic(BCs& fbcs,
106 const GridInterface& g,
107 const std::array<FlowBC, 2*GridInterface::Dimension>& fconditions,
108 const std::array<SatBC, 2*GridInterface::Dimension>& sconditions,
109 double spatial_tolerance = 1e-6)
110 {
111 static_assert(BCs::HasFlowConds, "");
112 static_assert(BCs::HasSatConds, "");
113 // Check the conditions given.
114 for (int i = 0; i < GridInterface::Dimension; ++i) {
115 if (fconditions[2*i].isPeriodic()) {
116 assert(fconditions[2*i + 1].isPeriodic());
117 assert(fconditions[2*i].pressureDifference() == -fconditions[2*i + 1].pressureDifference());
118 assert(sconditions[2*i].isPeriodic());
119 assert(sconditions[2*i + 1].isPeriodic());
120 assert(sconditions[2*i].saturationDifference() == 0.0);
121 assert(sconditions[2*i + 1].saturationDifference() == 0.0);
122 }
123 }
124 std::vector<BoundaryFaceInfo> bfinfo;
125 std::array<double, 6> side_areas;
126 createPeriodicImpl(fbcs, bfinfo, side_areas, g, extractPeriodic(fconditions), spatial_tolerance);
127 storeFlowCond(fbcs, bfinfo, fconditions, side_areas);
128 storeSatCond(fbcs, bfinfo, sconditions);
129 }
130
131
132
133
134 template <class BCs, class GridInterface>
135 void createPeriodic(BCs& fbcs,
136 const GridInterface& g,
137 const std::array<FlowBC, 2*GridInterface::Dimension>& fconditions,
138 double spatial_tolerance = 1e-6)
139 {
140 static_assert(BCs::HasFlowConds, "");
141 static_assert(!BCs::HasSatConds, "");
142 // Check the conditions given.
143 for (int i = 0; i < GridInterface::Dimension; ++i) {
144 if (fconditions[2*i].isPeriodic()) {
145 assert(fconditions[2*i + 1].isPeriodic());
146 assert(fconditions[2*i].pressureDifference() == -fconditions[2*i + 1].pressureDifference());
147 }
148 }
149 std::vector<BoundaryFaceInfo> bfinfo;
150 std::array<double, 6> side_areas;
151 createPeriodicImpl(fbcs, bfinfo, side_areas, g, extractPeriodic(fconditions), spatial_tolerance);
152 storeFlowCond(fbcs, bfinfo, fconditions, side_areas);
153 }
154
155
156
157
158 template <class BCs, class GridInterface>
159 void createPeriodic(BCs& fbcs,
160 const GridInterface& g,
161 const std::array<SatBC, 2*GridInterface::Dimension>& sconditions,
162 double spatial_tolerance = 1e-6)
163 {
164 static_assert(!BCs::HasFlowConds, "");
165 static_assert(BCs::HasSatConds, "");
166 // Check the conditions given.
167 for (int i = 0; i < GridInterface::Dimension; ++i) {
168 if (sconditions[2*i].isPeriodic()) {
169 assert(sconditions[2*i + 1].isPeriodic());
170 assert(sconditions[2*i].saturationDifference() == -sconditions[2*i + 1].saturationDifference());
171 }
172 }
173 std::vector<BoundaryFaceInfo> bfinfo;
174 std::array<double, 6> side_areas;
175 createPeriodicImpl(fbcs, bfinfo, side_areas, g, extractPeriodic(sconditions), spatial_tolerance);
176 storeSatCond(fbcs, bfinfo, sconditions);
177 }
178
179
180
182 template <class BCs, class GridInterface>
183 void createPeriodicImpl(BCs& fbcs,
184 std::vector<BoundaryFaceInfo>& bfinfo,
185 std::array<double, 6>& side_areas,
186 const GridInterface& g,
187 const std::array<bool, 2*GridInterface::Dimension>& is_periodic,
188 double spatial_tolerance = 1e-6)
189 {
190#if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
191 findPeriodicPartners(bfinfo, side_areas, g.grid().leafGridView(), is_periodic, spatial_tolerance);
192#else
193 findPeriodicPartners(bfinfo, side_areas, g.grid().leafView(), is_periodic, spatial_tolerance);
194#endif
195 int num_bdy = bfinfo.size();
196 // This will likely change with boundarySegmentIndex() instead of boundaryId():
197 int max_bid = num_bdy;
198
199 // Resize the conditions object. We clear it first to make sure it's all defaults.
200 fbcs.clear();
201 fbcs.resize(max_bid + 1);
202
203 // Now we have all the info, and the object to store it in. So we store it...
204 for (int i = 0; i < num_bdy; ++i) {
205 int bid1 = bfinfo[i].bid;
206 int bid2 = bfinfo[i].partner_bid;
207 if (bid1 < bid2) {
208 // If there is no periodic partner, bid2 will be zero, so we will not end up here.
209 fbcs.setPeriodicPartners(bid1, bid2);
210 }
211 fbcs.setCanonicalBoundaryId(bid1, bfinfo[i].canon_pos + 1);
212 }
213 }
214
215
216
223 template <class BCs, class GridInterface>
224 void createLinear(BCs& fbcs,
225 const GridInterface& g,
226 const double pdrop,
227 const int pddir,
228 const double bdy_sat,
229 const bool twodim_hack = false,
230 const double spatial_tolerance = 1e-6)
231 {
232 // NOTE: Section copied from createPeriodicImpl().
233 // Pick out all boundary faces, simultaneously find the
234 // bounding box of their centroids, and the max id.
235 typedef typename GridInterface::CellIterator CI;
236 typedef typename CI::FaceIterator FI;
237 typedef typename GridInterface::Vector Vector;
238 std::vector<FI> bface_iters;
239 Vector low(1e100);
240 Vector hi(-1e100);
241 int max_bid = 0;
242 for (CI c = g.cellbegin(); c != g.cellend(); ++c) {
243 for (FI f = c->facebegin(); f != c->faceend(); ++f) {
244 if (f->boundaryId()) {
245 bface_iters.push_back(f);
246 Vector fcent = f->centroid();
247 for (int dd = 0; dd < GridInterface::Dimension; ++dd) {
248 low[dd] = std::min(low[dd], fcent[dd]);
249 hi[dd] = std::max(hi[dd], fcent[dd]);
250 }
251 max_bid = std::max(max_bid, f->boundaryId());
252 }
253 }
254 }
255 int num_bdy = bface_iters.size();
256 if (max_bid != num_bdy) {
257 OPM_THROW(std::runtime_error, "createLinear() assumes that every boundary face has a unique boundary id. That seems to be violated.");
258 }
259 fbcs.resize(max_bid + 1);
260
261 // Iterate over boundary faces, setting boundary conditions for their corresponding ids.
262 double cmin = low[pddir];
263 double cmax = hi[pddir];
264 double cdelta = cmax - cmin;
265
266 for (int i = 0; i < num_bdy; ++i) {
267 Vector fcent = bface_iters[i]->centroid();
268 int canon_pos = -1;
269 for (int dd = 0; dd < GridInterface::Dimension; ++dd) {
270 double coord = fcent[dd];
271 if (fabs(coord - low[dd]) <= spatial_tolerance) {
272 canon_pos = 2*dd;
273 break;
274 } else if (fabs(coord - hi[dd]) <= spatial_tolerance) {
275 canon_pos = 2*dd + 1;
276 break;
277 }
278 }
279 if (canon_pos == -1) {
280 std::cerr << "Centroid: " << fcent << "\n";
281 std::cerr << "Bounding box min: " << low << "\n";
282 std::cerr << "Bounding box max: " << hi << "\n";
283 OPM_THROW(std::runtime_error, "Boundary face centroid not on bounding box. Maybe the grid is not an axis-aligned shoe-box?");
284 }
285 double relevant_coord = fcent[pddir];
286 double pressure = pdrop*(1.0 - (relevant_coord - cmin)/cdelta);
287 int bid = bface_iters[i]->boundaryId();
288 fbcs.setCanonicalBoundaryId(bid, canon_pos + 1);
289 fbcs.satCond(bid) = SatBC(SatBC::Dirichlet, bdy_sat);
290 fbcs.flowCond(bid) = FlowBC(FlowBC::Dirichlet, pressure);
291 if (twodim_hack && canon_pos >= 4) {
292 // Noflow for Z- and Z+ boundaries in the 3d-grid-that-is-really-2d case.
293 fbcs.flowCond(bid) = FlowBC(FlowBC::Neumann, 0.0);
294 }
295 }
296 }
297
298
299} // namespace Opm
300
301#endif // OPENRS_PERIODICHELPERS_HEADER
@ Neumann
Definition: BoundaryConditions.hpp:58
@ Dirichlet
Definition: BoundaryConditions.hpp:58
bool isNeumann() const
Type query.
Definition: BoundaryConditions.hpp:91
A class for representing a flow boundary condition.
Definition: BoundaryConditions.hpp:122
double outflux() const
Query a Neumann condition.
Definition: BoundaryConditions.hpp:154
A class for representing a saturation boundary condition.
Definition: BoundaryConditions.hpp:176
Definition: BlackoilFluid.hpp:32
void storeFlowCond(BCs &bcs, const std::vector< BoundaryFaceInfo > &bfinfo, const std::array< FlowBC, 6 > &fconditions, const std::array< double, 6 > &side_areas)
Definition: PeriodicHelpers.hpp:54
void storeSatCond(BCs &bcs, const std::vector< BoundaryFaceInfo > &bfinfo, const std::array< SatBC, 6 > &sconditions)
Definition: PeriodicHelpers.hpp:74
void createPeriodicImpl(BCs &fbcs, std::vector< BoundaryFaceInfo > &bfinfo, std::array< double, 6 > &side_areas, const GridInterface &g, const std::array< bool, 2 *GridInterface::Dimension > &is_periodic, double spatial_tolerance=1e-6)
Common implementation for the various createPeriodic functions.
Definition: PeriodicHelpers.hpp:183
void createLinear(BCs &fbcs, const GridInterface &g, const double pdrop, const int pddir, const double bdy_sat, const bool twodim_hack=false, const double spatial_tolerance=1e-6)
Makes a boundary condition object representing linear boundary conditions in any cartesian direction....
Definition: PeriodicHelpers.hpp:224
void createPeriodic(BCs &fbcs, const GridInterface &g, const std::array< FlowBC, 2 *GridInterface::Dimension > &fconditions, const std::array< SatBC, 2 *GridInterface::Dimension > &sconditions, double spatial_tolerance=1e-6)
Makes a boundary condition object representing periodic boundary conditions in any cartesian directio...
Definition: PeriodicHelpers.hpp:105
void findPeriodicPartners(std::vector< BoundaryFaceInfo > &bfinfo, std::array< double, 6 > &side_areas, const GridView &g, const std::array< bool, 2 *GridView::dimension > &is_periodic, double spatial_tolerance=1e-6)
Common implementation for the various createPeriodic functions.
Definition: BoundaryPeriodicity.hpp:86
std::array< bool, 6 > extractPeriodic(const std::array< BC, 6 > &bcs)
Definition: PeriodicHelpers.hpp:86