opm-upscaling
SimulatorUtilities.hpp
1 //===========================================================================
2 //
3 // File: SimulatorUtilities.hpp
4 //
5 // Created: Fri Aug 28 15:00:15 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_SIMULATORUTILITIES_HEADER
37 #define OPENRS_SIMULATORUTILITIES_HEADER
38 
39 
40 #include <opm/common/utility/platform_dependent/disable_warnings.h>
41 
42 #include <dune/common/version.hh>
43 #include <dune/common/fvector.hh>
44 #include <dune/grid/io/file/vtk/vtkwriter.hh>
45 
46 #include <opm/common/utility/platform_dependent/reenable_warnings.h>
47 
48 #include <opm/common/ErrorMacros.hpp>
49 #include <vector>
50 #include <fstream>
51 #include <algorithm>
52 #include <iterator>
53 
54 namespace Opm
55 {
56 
57 
64  template <class GridInterface, class FlowSol>
65  void estimateCellVelocity(std::vector<typename GridInterface::Vector>& cell_velocity,
66  const GridInterface& ginterf,
67  const FlowSol& flow_solution)
68  {
69  // Algorithm used is same as in halfFaceFluxToCellVelocity.hpp
70  // in the Sintef legacy c++ code.
71  cell_velocity.clear();
72  cell_velocity.resize(ginterf.numberOfCells());
73  for (typename GridInterface::CellIterator c = ginterf.cellbegin(); c != ginterf.cellend(); ++c) {
74  int numf = 0;
75  typename GridInterface::Vector cell_v(0.0);
76  typename GridInterface::CellIterator::FaceIterator f = c->facebegin();
77  for (; f != c->faceend(); ++f, ++numf) {
78  double flux = flow_solution.outflux(f);
79  typename GridInterface::Vector v = f->centroid();
80  v -= c->centroid();
81  v *= flux/c->volume();
82  cell_v += v;
83  }
84  cell_velocity[c->index()] = cell_v;//.two_norm();
85  }
86  }
87 
92  template <class GridInterface>
93  void estimateCellVelocitySimpleInterface(std::vector<typename GridInterface::Vector>& cell_velocity,
94  const GridInterface& grid,
95  const std::vector<double>& face_flux)
96  {
97  // Algorithm used is same as in halfFaceFluxToCellVelocity.hpp
98  // in the Sintef legacy c++ code.
99  typedef typename GridInterface::Vector Vec;
100  cell_velocity.clear();
101  cell_velocity.resize(grid.numCells(), Vec(0.0));
102  for (int face = 0; face < grid.numFaces(); ++face) {
103  int c[2] = { grid.faceCell(face, 0), grid.faceCell(face, 1) };
104  Vec fc = grid.faceCentroid(face);
105  double flux = face_flux[face];
106  for (int i = 0; i < 2; ++i) {
107  if (c[i] >= 0) {
108  Vec v_contrib = fc - grid.cellCentroid(c[i]);
109  v_contrib *= flux/grid.cellVolume(c[i]);
110  cell_velocity[c[i]] += (i == 0) ? v_contrib : -v_contrib;
111  }
112  }
113  }
114  }
115 
116 
125  template <class GridInterface, class FlowSol>
126  void estimateCellVelocity(std::vector<typename GridInterface::Vector>& cell_velocity,
127  const GridInterface& ginterf,
128  const FlowSol& flow_solution,
129  const std::vector<int>& partition,
130  const int my_partition)
131  {
132  // Algorithm used is same as in halfFaceFluxToCellVelocity.hpp
133  // in the Sintef legacy c++ code.
134  cell_velocity.clear();
135  cell_velocity.resize(ginterf.numberOfCells());
136  for (typename GridInterface::CellIterator c = ginterf.cellbegin(); c != ginterf.cellend(); ++c) {
137  if (partition[c->index()] != my_partition) {
138  cell_velocity[c->index()] = 0.0;
139  } else {
140  int numf = 0;
141  typename GridInterface::Vector cell_v(0.0);
142  typename GridInterface::CellIterator::FaceIterator f = c->facebegin();
143  for (; f != c->faceend(); ++f, ++numf) {
144  double flux = flow_solution.outflux(f);
145  typename GridInterface::Vector v = f->centroid();
146  v -= c->centroid();
147  v *= flux/c->volume();
148  cell_v += v;
149  }
150  cell_velocity[c->index()] = cell_v;//.two_norm();
151  }
152  }
153  }
154 
155 
156  template <class ReservoirProperty>
157  void computePhaseVelocities(std::vector<Dune::FieldVector<double, 3> >& phase_velocity_water,
158  std::vector<Dune::FieldVector<double, 3> >& phase_velocity_oil,
159  const ReservoirProperty& res_prop,
160  const std::vector<double>& saturation,
161  const std::vector<Dune::FieldVector<double, 3> >& cell_velocity)
162  {
163  assert(saturation.size() == cell_velocity.size());
164  int num_cells = saturation.size();
165  phase_velocity_water = cell_velocity;
166  phase_velocity_oil = cell_velocity;
167  for (int i = 0; i < num_cells; ++i) {
168  double f = res_prop.fractionalFlow(i, saturation[i]);
169  phase_velocity_water[i] *= f;
170  phase_velocity_oil[i] *= (1.0 - f);
171  }
172  }
173 
174 
175 
176 
181  template <class GridInterface, class FlowSol>
182  void getCellPressure(std::vector<double>& cell_pressure,
183  const GridInterface& ginterf,
184  const FlowSol& flow_solution)
185  {
186  cell_pressure.clear();
187  cell_pressure.resize(ginterf.numberOfCells());
188  for (typename GridInterface::CellIterator c = ginterf.cellbegin(); c != ginterf.cellend(); ++c) {
189  cell_pressure[c->index()] = flow_solution.pressure(c);
190  }
191  }
192 
197  template <class GridInterface, class FlowSol>
198  void getCellPressure(std::vector<double>& cell_pressure,
199  const GridInterface& ginterf,
200  const FlowSol& flow_solution,
201  const std::vector<int>& partition,
202  const int my_partition)
203  {
204  cell_pressure.clear();
205  cell_pressure.resize(ginterf.numberOfCells());
206  for (typename GridInterface::CellIterator c = ginterf.cellbegin(); c != ginterf.cellend(); ++c) {
207  if (partition[c->index()] != my_partition) {
208  cell_pressure[c->index()] = 0.0;
209  } else {
210  cell_pressure[c->index()] = flow_solution.pressure(c);
211  }
212  }
213  }
214 
215 
216 
222  template <class ReservoirProperties>
223  void computeCapPressure(std::vector<double>& cap_pressure,
224  const ReservoirProperties& rp,
225  const std::vector<double>& sat)
226  {
227  int num_cells = sat.size();
228  cap_pressure.resize(num_cells);
229  for (int cell = 0; cell < num_cells; ++cell) {
230  cap_pressure[cell] = rp.capillaryPressure(cell, sat[cell]);
231  }
232  }
233 
234 
236  template <class GridInterface, class ReservoirProperties, class FlowSol>
237  void writeVtkOutput(const GridInterface& ginterf,
238  const ReservoirProperties& rp,
239  const FlowSol& flowsol,
240  const std::vector<double>& saturation,
241  const std::string& filename)
242  {
243  // Extract data in proper format.
244  typedef typename GridInterface::Vector Vec;
245  std::vector<Vec> cell_velocity;
246  estimateCellVelocity(cell_velocity, ginterf, flowsol);
247  std::array<std::vector<Vec>, 2> phase_velocities;
248  computePhaseVelocities(phase_velocities[0], phase_velocities[1], rp, saturation, cell_velocity);
249  // Dune's vtk writer wants multi-component data to be flattened.
250  std::vector<double> cell_velocity_flat(&*cell_velocity.front().begin(),
251  &*cell_velocity.back().end());
252  std::vector<double> water_velocity_flat(&*phase_velocities[0].front().begin(),
253  &*phase_velocities[0].back().end());
254  std::vector<double> oil_velocity_flat(&*phase_velocities[1].front().begin(),
255  &*phase_velocities[1].back().end());
256  std::vector<double> cell_pressure;
257  getCellPressure(cell_pressure, ginterf, flowsol);
258  std::vector<double> cap_pressure;
259  computeCapPressure(cap_pressure, rp, saturation);
260  int num_cells = saturation.size();
261 // std::array<std::vector<double>, 2> phase_mobilities_;
262 // phase_mobilities_[0].resize(num_cells);
263 // phase_mobilities_[1].resize(num_cells);
264  std::vector<double> fractional_flow_(num_cells);
265  for (int i = 0; i < num_cells; ++i) {
266 // for (int phase = 0; phase < 2; ++phase) {
267 // rp.phaseMobility(phase, i, saturation[i], phase_mobilities_[phase][i]);
268 // }
269  fractional_flow_[i] = rp.fractionalFlow(i, saturation[i]);
270  }
271 
272  // Write data.
273  Dune::VTKWriter<typename GridInterface::GridType::LeafGridView> vtkwriter(ginterf.grid().leafGridView());
274  vtkwriter.addCellData(saturation, "saturation");
275  vtkwriter.addCellData(cell_pressure, "pressure");
276  vtkwriter.addCellData(cap_pressure, "capillary pressure");
277  vtkwriter.addCellData(fractional_flow_, "fractional flow [water]");
278 // vtkwriter.addCellData(phase_mobilities_[0], "phase mobility [water]");
279 // vtkwriter.addCellData(phase_mobilities_[1], "phase mobility [oil]");
280  vtkwriter.addCellData(cell_velocity_flat, "velocity", Vec::dimension);
281  vtkwriter.addCellData(water_velocity_flat, "phase velocity [water]", Vec::dimension);
282  vtkwriter.addCellData(oil_velocity_flat, "phase velocity [oil]", Vec::dimension);
283  vtkwriter.write(filename, Dune::VTK::ascii);
284  }
285 
286 
287  inline void writeField(const std::vector<double>& field,
288  const std::string& filename)
289  {
290  std::ofstream os(filename.c_str());
291  if (!os) {
292  OPM_THROW(std::runtime_error, "Could not open file " + filename);
293  }
294  os << field.size() << '\n';
295  std::ranges::copy(field, std::ostream_iterator<double>(os, "\n"));
296  }
297 
298 } // namespace Opm
299 
300 
301 #endif // OPENRS_SIMULATORUTILITIES_HEADER
void estimateCellVelocity(std::vector< typename GridInterface::Vector > &cell_velocity, const GridInterface &ginterf, const FlowSol &flow_solution)
Estimates a scalar cell velocity from outgoing fluxes.
Definition: SimulatorUtilities.hpp:65
void computeCapPressure(std::vector< double > &cap_pressure, const ReservoirProperties &rp, const std::vector< double > &sat)
Computes the capillary pressure in each cell from the cell saturations.
Definition: SimulatorUtilities.hpp:223
Inverting small matrices.
Definition: ImplicitAssembly.hpp:43
void getCellPressure(std::vector< double > &cell_pressure, const GridInterface &ginterf, const FlowSol &flow_solution)
Definition: SimulatorUtilities.hpp:182
void estimateCellVelocitySimpleInterface(std::vector< typename GridInterface::Vector > &cell_velocity, const GridInterface &grid, const std::vector< double > &face_flux)
Estimates a scalar cell velocity from face fluxes.
Definition: SimulatorUtilities.hpp:93