UpscalerBase_impl.hpp
Go to the documentation of this file.
1 //===========================================================================
2 //
3 // File: UpscalerBase_impl.hpp
4 //
5 // Created: Thu Apr 29 10:22:06 2010
6 //
7 // Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
8 //
9 // $Date$
10 //
11 // $Revision$
12 //
13 //===========================================================================
14 
15 /*
16  Copyright 2010 SINTEF ICT, Applied Mathematics.
17  Copyright 2010 Statoil ASA.
18 
19  This file is part of The Open Reservoir Simulator Project (OpenRS).
20 
21  OpenRS is free software: you can redistribute it and/or modify
22  it under the terms of the GNU General Public License as published by
23  the Free Software Foundation, either version 3 of the License, or
24  (at your option) any later version.
25 
26  OpenRS is distributed in the hope that it will be useful,
27  but WITHOUT ANY WARRANTY; without even the implied warranty of
28  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29  GNU General Public License for more details.
30 
31  You should have received a copy of the GNU General Public License
32  along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
33 */
34 
35 #ifndef OPM_UPSCALERBASE_IMPL_HEADER
36 #define OPM_UPSCALERBASE_IMPL_HEADER
37 
38 #include <opm/porsol/common/setupGridAndProps.hpp>
39 #include <opm/porsol/common/setupBoundaryConditions.hpp>
40 #include <opm/porsol/common/ReservoirPropertyTracerFluid.hpp>
41 
42 #include <iostream>
43 
44 namespace Opm
45 {
46 
47  template <class Traits>
49  : bctype_(Fixed),
50  twodim_hack_(false),
51  residual_tolerance_(1e-8),
52  linsolver_maxit_(0),
53  linsolver_prolongate_factor_(1.0),
54  linsolver_verbosity_(0),
55  linsolver_type_(3),
56  linsolver_smooth_steps_(1)
57  {
58  }
59 
60 
61 
62 
63  template <class Traits>
64  inline void UpscalerBase<Traits>::init(const Opm::parameter::ParameterGroup& param)
65  {
66  initImpl(param);
67  initFinal(param);
68  }
69 
70 
71 
72 
73  template <class Traits>
74  inline void UpscalerBase<Traits>::initImpl(const Opm::parameter::ParameterGroup& param)
75  {
76  // Request the boundary condition type parameter early since,
77  // depending on the actual type, we may have to manufacture
78  // and insert other parameters into the ParameterGroup prior
79  // to constructing the grid and associated properties.
80  //
81  int bct = param.get<int>("boundary_condition_type");
82  bctype_ = static_cast<BoundaryConditionType>(bct);
83 
84  // Import control parameters pertaining to reduced physical
85  // dimensionality ("2d_hack = true" precludes periodic
86  // boundary conditions in the Z direction), and linear solves.
87  //
88  twodim_hack_ = param.getDefault("2d_hack", twodim_hack_);
89  residual_tolerance_ = param.getDefault("residual_tolerance", residual_tolerance_);
90  linsolver_verbosity_ = param.getDefault("linsolver_verbosity", linsolver_verbosity_);
91  linsolver_type_ = param.getDefault("linsolver_type", linsolver_type_);
92  linsolver_maxit_ = param.getDefault("linsolver_max_iterations", linsolver_maxit_);
93  linsolver_prolongate_factor_ = param.getDefault("linsolver_prolongate_factor", linsolver_prolongate_factor_);
94  linsolver_smooth_steps_ = param.getDefault("linsolver_smooth_steps", linsolver_smooth_steps_);
95 
96  // Ensure sufficient grid support for requested boundary
97  // condition type.
98  //
99  Opm::parameter::ParameterGroup temp_param = param;
100  if (bctype_ == Linear || bctype_ == Periodic) {
101  if (!temp_param.has("use_unique_boundary_ids")) {
102  temp_param.insertParameter("use_unique_boundary_ids", "true");
103  }
104  }
105  if (bctype_ == Periodic) {
106  if (!temp_param.has("periodic_extension")) {
107  temp_param.insertParameter("periodic_extension", "true");
108  }
109  }
110 
111  setupGridAndProps(temp_param, grid_, res_prop_);
112  ginterf_.init(grid_);
113  }
114 
115 
116 
117 
118  template <class Traits>
119  inline void UpscalerBase<Traits>::initFinal(const Opm::parameter::ParameterGroup& param)
120  {
121  // Report any unused parameters.
122  std::cout << "==================== Unused parameters: ====================\n";
123  param.displayUsage();
124  std::cout << "================================================================\n";
125  }
126 
127 
128 
129 
130  template <class Traits>
131  inline void UpscalerBase<Traits>::init(Opm::DeckConstPtr deck,
132  BoundaryConditionType bctype,
133  double perm_threshold,
134  double residual_tolerance,
135  int linsolver_verbosity,
136  int linsolver_type,
137  bool twodim_hack,
138  int linsolver_maxit,
139  double linsolver_prolongate_factor,
140  int linsolver_smooth_steps)
141  {
142  bctype_ = bctype;
143  residual_tolerance_ = residual_tolerance;
144  linsolver_verbosity_ = linsolver_verbosity;
145  linsolver_type_ = linsolver_type;
146  linsolver_maxit_ = linsolver_maxit;
147  linsolver_prolongate_factor_ = linsolver_prolongate_factor;
148  linsolver_smooth_steps_ = linsolver_smooth_steps;
149  twodim_hack_ = twodim_hack;
150 
151  // Faking some parameters depending on bc type.
152  bool periodic_ext = (bctype_ == Periodic);
153  bool turn_normals = false;
154  bool clip_z = (bctype_ == Periodic);
155  bool unique_bids = (bctype_ == Linear || bctype_ == Periodic);
156  std::string rock_list("no_list");
157  setupGridAndPropsEclipse(deck,
158  periodic_ext, turn_normals, clip_z, unique_bids,
159  perm_threshold, rock_list,
160  useJ<ResProp>(), 1.0, 0.0,
161  grid_, res_prop_);
162  ginterf_.init(grid_);
163  }
164 
165 
166 
167 
168  template <class Traits>
169  inline const typename UpscalerBase<Traits>::GridType&
171  {
172  return grid_;
173  }
174 
175 
176 
177 
178  template <class Traits>
179  inline void
181  {
182  if ((type == Periodic && bctype_ != Periodic)
183  || (type != Periodic && bctype_ == Periodic)) {
184  OPM_THROW(std::runtime_error, "Cannot switch to or from Periodic boundary condition, "
185  "periodic must be set in init() params.");
186  } else {
187  bctype_ = type;
188  if (type == Periodic || type == Linear) {
189  grid_.setUniqueBoundaryIds(true);
190  } else {
191  grid_.setUniqueBoundaryIds(false);
192  }
193  }
194  }
195 
196 
197 
198 
199  template <class Traits>
200  inline void
201  UpscalerBase<Traits>::setPermeability(const int cell_index, const permtensor_t& k)
202  {
203  res_prop_.permeabilityModifiable(cell_index) = k;
204  }
205 
206 
207 
208 
209  template <class Traits>
210  inline typename UpscalerBase<Traits>::permtensor_t
212  {
213  ReservoirPropertyTracerFluid fluid;
214  return upscaleEffectivePerm(fluid);
215  }
216 
217 
218 
219 
220  template <class Traits>
221  template <class FluidInterface>
222  inline typename UpscalerBase<Traits>::permtensor_t
223  UpscalerBase<Traits>::upscaleEffectivePerm(const FluidInterface& fluid)
224  {
225  int num_cells = ginterf_.numberOfCells();
226  // No source or sink.
227  std::vector<double> src(num_cells, 0.0);
228  // Just water.
229  std::vector<double> sat(num_cells, 1.0);
230  // Gravity.
231  Dune::FieldVector<double, 3> gravity(0.0);
232  // gravity[2] = -Dune::unit::gravity;
233 
234  permtensor_t upscaled_K(3, 3, (double*)0);
235  for (int pdd = 0; pdd < Dimension; ++pdd) {
236  setupUpscalingConditions(ginterf_, bctype_, pdd, 1.0, 1.0, twodim_hack_, bcond_);
237  if (pdd == 0) {
238  // Only on first iteration, since we do not change the
239  // structure of the system, the way the flow solver is
240  // implemented.
241  flow_solver_.init(ginterf_, res_prop_, gravity, bcond_);
242  }
243 
244  // Run pressure solver.
245  bool same_matrix = (bctype_ != Fixed) && (pdd != 0);
246  flow_solver_.solve(fluid, sat, bcond_, src, residual_tolerance_,
247  linsolver_verbosity_,
248  linsolver_type_, same_matrix,
249  linsolver_maxit_, linsolver_prolongate_factor_,
250  linsolver_smooth_steps_);
251  double max_mod = flow_solver_.postProcessFluxes();
252  std::cout << "Max mod = " << max_mod << std::endl;
253 
254  // Compute upscaled K.
255  double Q[Dimension] = { 0 };
256  switch (bctype_) {
257  case Fixed:
258  Q[pdd] = computeAverageVelocity(flow_solver_.getSolution(), pdd, pdd);
259  break;
260  case Linear:
261  case Periodic:
262  for (int i = 0; i < Dimension; ++i) {
263  Q[i] = computeAverageVelocity(flow_solver_.getSolution(), i, pdd);
264  }
265  break;
266  default:
267  OPM_THROW(std::runtime_error, "Unknown boundary type: " << bctype_);
268  }
269  double delta = computeDelta(pdd);
270  for (int i = 0; i < Dimension; ++i) {
271  upscaled_K(i, pdd) = Q[i] * delta;
272  }
273  }
274  return upscaled_K;
275  }
276 
277 
278 
279 
280  template <class Traits>
281  template <class FlowSol>
282  double UpscalerBase<Traits>::computeAverageVelocity(const FlowSol& flow_solution,
283  const int flow_dir,
284  const int pdrop_dir) const
285  {
286  double side1_flux = 0.0;
287  double side2_flux = 0.0;
288  double side1_area = 0.0;
289  double side2_area = 0.0;
290 
291  int num_faces = 0;
292  int num_bdyfaces = 0;
293  int num_side1 = 0;
294  int num_side2 = 0;
295 
296  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
297  for (FaceIter f = c->facebegin(); f != c->faceend(); ++f) {
298  ++num_faces;
299  if (f->boundary()) {
300  ++num_bdyfaces;
301  int canon_bid = bcond_.getCanonicalBoundaryId(f->boundaryId());
302  if ((canon_bid - 1)/2 == flow_dir) {
303  double flux = flow_solution.outflux(f);
304  double area = f->area();
305  double norm_comp = f->normal()[flow_dir];
306  // std::cout << "bid " << f->boundaryId() << " area " << area << " n " << norm_comp << std::endl;
307  if (canon_bid - 1 == 2*flow_dir) {
308  ++num_side1;
309  if (flow_dir == pdrop_dir && flux > 0.0) {
310 #ifdef VERBOSE
311  std::cerr << "Flow may be in wrong direction at bid: " << f->boundaryId()<<" (canonical: "<<canon_bid
312  << ") Magnitude: " << std::fabs(flux) << std::endl;
313 #endif
314  // OPM_THROW(std::runtime_error, "Detected outflow at entry face: " << face);
315  }
316  side1_flux += flux*norm_comp;
317  side1_area += area;
318  } else {
319  assert(canon_bid - 1 == 2*flow_dir + 1);
320  ++num_side2;
321  if (flow_dir == pdrop_dir && flux < 0.0) {
322 #ifdef VERBOSE
323  std::cerr << "Flow may be in wrong direction at bid: " << f->boundaryId()
324  << " Magnitude: " << std::fabs(flux) << std::endl;
325 #endif
326  // OPM_THROW(std::runtime_error, "Detected inflow at exit face: " << face);
327  }
328  side2_flux += flux*norm_comp;
329  side2_area += area;
330  }
331  }
332  }
333  }
334  }
335 // std::cout << "Faces: " << num_faces << " Boundary faces: " << num_bdyfaces
336 // << " Side 1 faces: " << num_side1 << " Side 2 faces: " << num_side2 << std::endl;
337  // q is the average velocity.
338  return 0.5*(side1_flux/side1_area + side2_flux/side2_area);
339  }
340 
341 
342 
343 
344  template <class Traits>
345  inline double UpscalerBase<Traits>::computeDelta(const int flow_dir) const
346  {
347  double side1_pos = 0.0;
348  double side2_pos = 0.0;
349  double side1_area = 0.0;
350  double side2_area = 0.0;
351  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
352  for (FaceIter f = c->facebegin(); f != c->faceend(); ++f) {
353  if (f->boundary()) {
354  int canon_bid = bcond_.getCanonicalBoundaryId(f->boundaryId());
355  if ((canon_bid - 1)/2 == flow_dir) {
356  double area = f->area();
357  double pos_comp = f->centroid()[flow_dir];
358  if (canon_bid - 1 == 2*flow_dir) {
359  side1_pos += area*pos_comp;
360  side1_area += area;
361  } else {
362  side2_pos += area*pos_comp;
363  side2_area += area;
364  }
365  }
366  }
367  }
368  }
369  // delta is the average length.
370  return side2_pos/side2_area - side1_pos/side1_area;
371  }
372 
373 
374 
375 
376  template <class Traits>
378  {
379  double total_vol = 0.0;
380  double total_pore_vol = 0.0;
381  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
382  total_vol += c->volume();
383  total_pore_vol += c->volume()*res_prop_.porosity(c->index());
384  }
385  return total_pore_vol/total_vol;
386  }
387 
388 
389  template <class Traits>
391  {
392  double total_net_vol = 0.0;
393  double total_pore_vol = 0.0;
394  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
395  total_net_vol += c->volume()*res_prop_.ntg(c->index());
396  total_pore_vol += c->volume()*res_prop_.porosity(c->index())*res_prop_.ntg(c->index());
397  }
398  if (total_net_vol>0.0) return total_pore_vol/total_net_vol;
399  else return 0.0;
400  }
401 
402  template <class Traits>
404  {
405  double total_vol = 0.0;
406  double total_net_vol = 0.0;
407  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
408  total_vol += c->volume();
409  total_net_vol += c->volume()*res_prop_.ntg(c->index());
410  }
411  return total_net_vol/total_vol;
412  }
413 
414  template <class Traits>
415  double UpscalerBase<Traits>::upscaleSWCR(const bool NTG) const
416  {
417  double total_swcr = 0.0;
418  double total_pore_vol = 0.0;
419  if (NTG) {
420  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
421  total_swcr += c->volume()*res_prop_.porosity(c->index())*res_prop_.ntg(c->index())*res_prop_.swcr(c->index());
422  total_pore_vol += c->volume()*res_prop_.porosity(c->index())*res_prop_.ntg(c->index());
423  }
424  }
425  else {
426  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
427  total_swcr += c->volume()*res_prop_.porosity(c->index())*res_prop_.swcr(c->index());
428  total_pore_vol += c->volume()*res_prop_.porosity(c->index());
429  }
430  }
431  return total_swcr/total_pore_vol;
432  }
433 
434  template <class Traits>
435  double UpscalerBase<Traits>::upscaleSOWCR(const bool NTG) const
436  {
437  double total_sowcr = 0.0;
438  double total_pore_vol = 0.0;
439  if (NTG) {
440  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
441  total_sowcr += c->volume()*res_prop_.porosity(c->index())*res_prop_.ntg(c->index())*res_prop_.sowcr(c->index());
442  total_pore_vol += c->volume()*res_prop_.porosity(c->index())*res_prop_.ntg(c->index());
443  }
444  }
445  else {
446  for (CellIter c = ginterf_.cellbegin(); c != ginterf_.cellend(); ++c) {
447  total_sowcr += c->volume()*res_prop_.porosity(c->index())*res_prop_.sowcr(c->index());
448  total_pore_vol += c->volume()*res_prop_.porosity(c->index());
449  }
450  }
451  return total_sowcr/total_pore_vol;
452  }
453 
454 } // namespace Opm
455 
456 
457 
458 #endif // OPM_UPSCALERBASE_IMPL_HEADER
Dune::CpGrid GridType
Definition: UpscalerBase.hpp:57
Definition: applier.hpp:18
virtual void initFinal(const Opm::parameter::ParameterGroup &param)
Definition: UpscalerBase_impl.hpp:119
const GridType & grid() const
Access the grid.
Definition: UpscalerBase_impl.hpp:170
ResProp::MutablePermTensor permtensor_t
A type for the upscaled permeability.
Definition: UpscalerBase.hpp:63
double upscaleNetPorosity() const
Definition: UpscalerBase_impl.hpp:390
void setBoundaryConditionType(BoundaryConditionType type)
Definition: UpscalerBase_impl.hpp:180
double computeDelta(const int flow_dir) const
Definition: UpscalerBase_impl.hpp:345
CellIter::FaceIterator FaceIter
Definition: UpscalerBase.hpp:128
permtensor_t upscaleEffectivePerm(const FluidInterface &fluid)
Definition: UpscalerBase_impl.hpp:223
virtual void initImpl(const Opm::parameter::ParameterGroup &param)
Definition: UpscalerBase_impl.hpp:74
double upscaleNTG() const
Definition: UpscalerBase_impl.hpp:403
double upscalePorosity() const
Definition: UpscalerBase_impl.hpp:377
Opm::DeckConstPtr deck(parser->parseFile(file, parseMode))
UpscalerBase()
Default constructor.
Definition: UpscalerBase_impl.hpp:48
double computeAverageVelocity(const FlowSol &flow_solution, const int flow_dir, const int pdrop_dir) const
Definition: UpscalerBase_impl.hpp:282
BoundaryConditionType
Definition: UpscalerBase.hpp:65
void init(const Opm::parameter::ParameterGroup &param)
Initializes the upscaler from parameters.
Definition: UpscalerBase_impl.hpp:64
GridInterface::CellIterator CellIter
Definition: UpscalerBase.hpp:127
permtensor_t upscaleSinglePhase()
Definition: UpscalerBase_impl.hpp:211
double upscaleSWCR(const bool NTG) const
Definition: UpscalerBase_impl.hpp:415
double upscaleSOWCR(const bool NTG) const
Definition: UpscalerBase_impl.hpp:435
void setPermeability(const int cell_index, const permtensor_t &k)
Definition: UpscalerBase_impl.hpp:201