BlackoilSimulator.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2011 SINTEF ICT, Applied Mathematics.
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_BLACKOILSIMULATOR_HEADER_INCLUDED
21 #define OPM_BLACKOILSIMULATOR_HEADER_INCLUDED
22 
23 
24 
25 
26 #include <dune/grid/io/file/vtk/vtkwriter.hh>
27 #include <opm/core/utility/Units.hpp>
28 #include <opm/core/utility/parameters/ParameterGroup.hpp>
32 #include <opm/parser/eclipse/Parser/Parser.hpp>
33 #include <opm/parser/eclipse/Parser/ParseMode.hpp>
34 #include <opm/parser/eclipse/Deck/Deck.hpp>
35 #include <boost/filesystem/convenience.hpp>
36 #include <boost/lexical_cast.hpp>
37 #include <iostream>
38 #include <string>
39 #include <vector>
40 #include <numeric>
41 
42 
43 namespace Opm
44 {
45 
46  template<class GridT, class Rock, class FluidT, class Wells, class FlowSolver, class TransportSolver>
48  {
49  public:
50  void init(const Opm::parameter::ParameterGroup& param);
51  void simulate();
52 
53  typedef GridT Grid;
54  typedef FluidT Fluid;
55 
56  typedef typename Fluid::CompVec CompVec;
57  typedef typename Fluid::PhaseVec PhaseVec;
58 
59  struct State
60  {
61  std::vector<PhaseVec> cell_pressure_;
62  std::vector<PhaseVec> face_pressure_;
63  std::vector<double> well_bhp_pressure_;
64  std::vector<double> well_perf_pressure_;
65  std::vector<double> well_perf_flux_;
66  std::vector<CompVec> cell_z_;
67  };
68 
69  private:
70  Grid grid_;
71  Rock rock_;
72  Fluid fluid_;
73  Wells wells_;
74  FlowSolver flow_solver_;
75  TransportSolver transport_solver_;
76 
78  typename Grid::Vector gravity_;
79  std::vector<double> src_;
80 
81  State state_;
82 
83  PhaseVec bdy_pressure_;
84  CompVec bdy_z_;
85 
86  double total_time_;
87  double initial_stepsize_;
88  bool increase_stepsize_;
89  double stepsize_increase_factor_;
90  double minimum_stepsize_;
91  double maximum_stepsize_;
92  std::vector<double> report_times_;
93  bool do_impes_;
94  bool ignore_impes_stability_;
95  std::string output_dir_;
96  int output_interval_;
97 
98  static void output(const Grid& grid,
99  const Fluid& fluid,
100  const State& simstate,
101  const std::vector<double>& face_flux,
102  const int step,
103  const std::string& filebase);
104  };
105 
106 
107 
108 
109  // Method implementations below.
110 
111 
112 template<class Grid, class Rock, class Fluid, class Wells, class FlowSolver, class TransportSolver>
113 void
115 init(const Opm::parameter::ParameterGroup& param)
116 {
117  using namespace Opm;
118  std::string fileformat = param.getDefault<std::string>("fileformat", "cartesian");
119  if (fileformat == "eclipse") {
120  Opm::ParseMode parseMode;
121  Opm::ParserPtr parser(new Opm::Parser());
122  Opm::DeckConstPtr deck = parser->parseFile(param.get<std::string>("filename") , parseMode);
123  double z_tolerance = param.getDefault<double>("z_tolerance", 0.0);
124  bool periodic_extension = param.getDefault<bool>("periodic_extension", false);
125  bool turn_normals = param.getDefault<bool>("turn_normals", false);
126  grid_.processEclipseFormat(deck, z_tolerance, periodic_extension, turn_normals);
127  double perm_threshold_md = param.getDefault("perm_threshold_md", 0.0);
128  double perm_threshold = Opm::unit::convert::from(perm_threshold_md, Opm::prefix::milli*Opm::unit::darcy);
129  rock_.init(deck, grid_.globalCell(), perm_threshold);
130  fluid_.init(deck);
131  wells_.init(deck, grid_, rock_);
132  } else if (fileformat == "cartesian") {
133  std::array<int, 3> dims = {{ param.getDefault<int>("nx", 1),
134  param.getDefault<int>("ny", 1),
135  param.getDefault<int>("nz", 1) }};
136  std::array<double, 3> cellsz = {{ param.getDefault<double>("dx", 1.0),
137  param.getDefault<double>("dy", 1.0),
138  param.getDefault<double>("dz", 1.0) }};
139  grid_.createCartesian(dims, cellsz);
140  double default_poro = param.getDefault("default_poro", 1.0);
141  double default_perm_md = param.getDefault("default_perm_md", 100.0);
142  double default_perm = unit::convert::from(default_perm_md, prefix::milli*unit::darcy);
143  OPM_MESSAGE("Warning: For generated cartesian grids, we use uniform rock properties.");
144  rock_.init(grid_.size(0), default_poro, default_perm);
145 
146  Opm::ParseMode parseMode;
147  Opm::ParserPtr parser(new Opm::Parser());
148  Opm::DeckConstPtr deck = parser->parseFile(param.get<std::string>("filename") , parseMode);
149  fluid_.init(deck);
150  wells_.init(deck, grid_, rock_);
151  } else {
152  OPM_THROW(std::runtime_error, "Unknown file format string: " << fileformat);
153  }
154  flow_solver_.init(param);
155  transport_solver_.init(param);
156  if (param.has("timestep_file")) {
157  std::ifstream is(param.get<std::string>("timestep_file").c_str());
158  std::istream_iterator<double> beg(is);
159  std::istream_iterator<double> end;
160  report_times_.assign(beg, end);
161  // File contains deltas, we want accumulated times.
162  std::partial_sum(report_times_.begin(), report_times_.end(), report_times_.begin());
163  assert(!report_times_.empty());
164  total_time_ = report_times_.back();
165  initial_stepsize_ = report_times_.front();
166  } else {
167  total_time_ = param.getDefault("total_time", 30*unit::day);
168  initial_stepsize_ = param.getDefault("initial_stepsize", 1.0*unit::day);
169  increase_stepsize_ = param.getDefault("increase_stepsize", false);
170  if (increase_stepsize_) {
171  stepsize_increase_factor_ = param.getDefault("stepsize_increase_factor", 1.5);
172  maximum_stepsize_ = param.getDefault("maximum_stepsize", 1.0*unit::day);
173  } else {
174  stepsize_increase_factor_ = 1.0;
175  maximum_stepsize_ = 1e100;
176  }
177  }
178  minimum_stepsize_ = param.getDefault("minimum_stepsize", 0.0);
179  do_impes_ = param.getDefault("do_impes", false);
180  if (do_impes_) {
181  ignore_impes_stability_ = param.getDefault("ignore_impes_stability", false);
182  }
183  output_dir_ = param.getDefault<std::string>("output_dir", "output");
184  output_interval_ = param.getDefault("output_interval", 1);
185 
186  // Boundary conditions.
187  typedef Opm::FlowBC BC;
188  flow_bc_.resize(7);
189  bool bdy_dirichlet = param.getDefault("bdy_dirichlet", false);
190  if (bdy_dirichlet) {
191  flow_bc_.flowCond(1) = BC(BC::Dirichlet, param.get<double>("bdy_pressure_left"));
192  flow_bc_.flowCond(2) = BC(BC::Dirichlet, param.get<double>("bdy_pressure_right"));
193  } else if (param.getDefault("lateral_dirichlet", false)) {
194  flow_bc_.flowCond(1) = BC(BC::Dirichlet, -17.0); // Use a negative value to instruct flow solver
195  flow_bc_.flowCond(2) = BC(BC::Dirichlet, -17.0); // to use initial face pressures (hydrostatic)
196  flow_bc_.flowCond(3) = BC(BC::Dirichlet, -17.0); // as boundary conditions.
197  flow_bc_.flowCond(4) = BC(BC::Dirichlet, -17.0);
198  }
199 
200  // Gravity.
201  gravity_ = 0.0;
202  if (param.has("gravity")) {
203  std::string g = param.get<std::string>("gravity");
204  if (g == "standard") {
205  gravity_[2] = Opm::unit::gravity;
206  } else {
207  gravity_[2] = boost::lexical_cast<double>(g);
208  }
209  }
210 
211  // Initial state.
212  if (param.getDefault("spe9_init", false)) {
214  initializer.init(param, grid_, fluid_, gravity_, state_);
215  } else {
217  initializer.init(param, grid_, fluid_, gravity_, state_);
218  }
219 
220 
221 
222  // Write initial state to std::cout
223  /*
224  for (int cell = 0; cell < grid_.numCells(); ++cell) {
225  std::cout.precision(2);
226  std::cout << std::fixed << std::showpoint;
227 
228  std::cout << std::setw(5) << cell << std::setw(12) << grid_.cellCentroid(cell)[0]
229  << std::setw(12) << grid_.cellCentroid(cell)[1]
230  << std::setw(12) << grid_.cellCentroid(cell)[2]
231  << std::setw(20) << state_.cell_pressure_[cell][0]
232  << std::setw(15) << state_.cell_z_[cell][0]
233  << std::setw(15) << state_.cell_z_[cell][1]
234  << std::setw(15) << state_.cell_z_[cell][2]
235  << std::endl;
236  if ((cell+1)%nz == 0) {
237  std::cout << "------------------------------------------------------------------------------------------------------------------" << std::endl;
238  }
239 
240  }
241  */
242 
243  bdy_z_ = flow_solver_.inflowMixture();
244  bdy_pressure_ = 300.0*Opm::unit::barsa;
245  // PhaseVec bdy_pressure_(100.0*Opm::unit::barsa); // WELLS
246  // Rescale z values so that pore volume is filled exactly
247  // (to get zero initial volume discrepancy).
248  for (int cell = 0; cell < grid_.numCells(); ++cell) {
249  typename Fluid::FluidState state = fluid_.computeState(state_.cell_pressure_[cell], state_.cell_z_[cell]);
250  double fluid_vol_dens = state.total_phase_volume_density_;
251  state_.cell_z_[cell] *= 1.0/fluid_vol_dens;
252  }
253  int num_faces = grid_.numFaces();
254  state_.face_pressure_.resize(num_faces);
255  for (int face = 0; face < num_faces; ++face) {
256  int bid = grid_.boundaryId(face);
257  if (flow_bc_.flowCond(bid).isDirichlet() && flow_bc_.flowCond(bid).pressure() >= 0.0) {
258  state_.face_pressure_[face] = flow_bc_.flowCond(bid).pressure();
259  } else {
260  int c[2] = { grid_.faceCell(face, 0), grid_.faceCell(face, 1) };
261  state_.face_pressure_[face] = 0.0;
262  int num = 0;
263  for (int j = 0; j < 2; ++j) {
264  if (c[j] >= 0) {
265  state_.face_pressure_[face] += state_.cell_pressure_[c[j]];
266  ++num;
267  }
268  }
269  state_.face_pressure_[face] /= double(num);
270  }
271  }
272 
273  // Flow solver setup.
274  flow_solver_.setup(grid_, rock_, fluid_, wells_, gravity_, flow_bc_, &(state_.face_pressure_));
275 
276  // Transport solver setup.
277  transport_solver_.setup(grid_, rock_, fluid_, wells_, flow_solver_.faceTransmissibilities(), gravity_);
278 
279  // Simple source terms.
280  src_.resize(grid_.numCells(), 0.0);
281 
282  // Set initial well perforation pressures equal to cell pressures,
283  // and perforation fluxes equal to zero.
284  // Set initial well bhp values to the target if bhp well, or to
285  // first perforation pressure if not.
286  state_.well_perf_pressure_.clear();
287  for (int well = 0; well < wells_.numWells(); ++well) {
288  int num_perf = wells_.numPerforations(well);
289  for (int perf = 0; perf < num_perf; ++perf) {
290  int cell = wells_.wellCell(well, perf);
291  state_.well_perf_pressure_.push_back(state_.cell_pressure_[cell][Fluid::Liquid]);
292  }
293  if (wells_.control(well) == Wells::Pressure) {
294  state_.well_bhp_pressure_.push_back(wells_.target(well));
295  } else {
296  int cell = wells_.wellCell(well, 0);
297  state_.well_bhp_pressure_.push_back(state_.cell_pressure_[cell][Fluid::Liquid]);
298  }
299  }
300  state_.well_perf_flux_.clear();
301  state_.well_perf_flux_.resize(state_.well_perf_pressure_.size(), 0.0);
302  wells_.update(grid_.numCells(), state_.well_perf_pressure_, state_.well_perf_flux_);
303 
304  // Check for unused parameters (potential typos).
305  if (param.anyUnused()) {
306  std::cout << "***** WARNING: Unused parameters: *****\n";
307  param.displayUsage();
308  }
309 
310  // Write parameters used to file, ensuring directory exists.
311  std::string paramfilename = output_dir_ + "/simulator-parameters.param";
312  boost::filesystem::path fpath(paramfilename);
313  if (fpath.has_branch_path()) {
314  create_directories(fpath.branch_path());
315  }
316  param.writeParam(paramfilename);
317 }
318 
319 
320 
321 
322 
323 
324 
325 template<class Grid, class Rock, class Fluid, class Wells, class FlowSolver, class TransportSolver>
326 void
329 {
330  double voldisclimit = flow_solver_.volumeDiscrepancyLimit();
331  double stepsize = initial_stepsize_;
332  double current_time = 0.0;
333  int step = 0;
334  std::vector<double> face_flux;
335  State start_state;
336  std::string output_name = output_dir_ + "/" + "blackoil-output";
337  while (current_time < total_time_) {
338  start_state = state_;
339 
340  // Do not run past total_time_.
341  if (current_time + stepsize > total_time_) {
342  stepsize = total_time_ - current_time;
343  }
344  std::cout << "\n\n================ Simulation step number " << step
345  << " ==============="
346  << "\n Current time (days) " << Opm::unit::convert::to(current_time, Opm::unit::day)
347  << "\n Current stepsize (days) " << Opm::unit::convert::to(stepsize, Opm::unit::day)
348  << "\n Total time (days) " << Opm::unit::convert::to(total_time_, Opm::unit::day)
349  << "\n" << std::endl;
350 
351  // Solve flow system.
352  enum FlowSolver::ReturnCode result
353  = flow_solver_.solve(state_.cell_pressure_, state_.face_pressure_, state_.cell_z_, face_flux,
354  state_.well_bhp_pressure_,
355  state_.well_perf_pressure_, state_.well_perf_flux_, src_, stepsize);
356 
357  // Check if the flow solver succeeded.
358  if (result == FlowSolver::VolumeDiscrepancyTooLarge) {
359  OPM_THROW(std::runtime_error, "Flow solver refused to run due to too large volume discrepancy.");
360  } else if (result == FlowSolver::FailedToConverge) {
361  std::cout << "********* Nonlinear convergence failure: Shortening (pressure) stepsize, redoing step number " << step <<" **********" << std::endl;
362  stepsize *= 0.5;
363  state_ = start_state;
364  wells_.update(grid_.numCells(), start_state.well_perf_pressure_, start_state.well_perf_flux_);
365  continue;
366  }
367  assert(result == FlowSolver::SolveOk);
368 
369  // Update wells with new perforation pressures and fluxes.
370  wells_.update(grid_.numCells(), state_.well_perf_pressure_, state_.well_perf_flux_);
371 
372  // Transport and check volume discrepancy.
373  bool voldisc_ok = true;
374  if (!do_impes_) {
375  double actual_computed_time
376  = transport_solver_.transport(bdy_pressure_, bdy_z_,
377  face_flux, state_.cell_pressure_, state_.face_pressure_,
378  stepsize, voldisclimit, state_.cell_z_);
379  voldisc_ok = (actual_computed_time == stepsize);
380  if (voldisc_ok) {
381  // Just for output.
382  flow_solver_.volumeDiscrepancyAcceptable(state_.cell_pressure_, state_.face_pressure_,
383  state_.well_perf_pressure_, state_.cell_z_, stepsize);
384  }
385  } else {
386  // First check IMPES stepsize.
387  double max_dt = ignore_impes_stability_ ? 1e100 : flow_solver_.stableStepIMPES();
388  if (ignore_impes_stability_) {
389  std::cout << "Timestep was " << stepsize << " and max stepsize was not computed." << std::endl;
390  } else {
391  std::cout << "Timestep was " << stepsize << " and max stepsize was " << max_dt << std::endl;
392  }
393  if (stepsize < max_dt || stepsize <= minimum_stepsize_) {
394  flow_solver_.doStepIMPES(state_.cell_z_, stepsize);
395  voldisc_ok = flow_solver_.volumeDiscrepancyAcceptable(state_.cell_pressure_, state_.face_pressure_,
396  state_.well_perf_pressure_, state_.cell_z_, stepsize);
397  } else {
398  // Restarting step.
399  stepsize = max_dt/1.5;
400  std::cout << "Restarting pressure step with new timestep " << stepsize << std::endl;
401  state_ = start_state;
402  wells_.update(grid_.numCells(), start_state.well_perf_pressure_, start_state.well_perf_flux_);
403  continue;
404  }
405  }
406 
407  // If discrepancy too large, redo entire pressure step.
408  if (!voldisc_ok) {
409  std::cout << "********* Too large volume discrepancy: Shortening (pressure) stepsize, redoing step number " << step <<" **********" << std::endl;
410  stepsize *= 0.5;
411  state_ = start_state;
412  wells_.update(grid_.numCells(), start_state.well_perf_pressure_, start_state.well_perf_flux_);
413  continue;
414  }
415 
416  // Adjust time.
417  current_time += stepsize;
418  if (voldisc_ok && increase_stepsize_ && stepsize < maximum_stepsize_) {
419  stepsize *= stepsize_increase_factor_;
420  stepsize = std::min(maximum_stepsize_, stepsize);
421  }
422  // If using given timesteps, set stepsize to match.
423  if (!report_times_.empty()) {
424  if (current_time >= report_times_[step]) {
425  bool output_now = ((step + 1) % output_interval_ == 0);
426  if (output_now) {
427  output(grid_, fluid_, state_, face_flux, step, output_name);
428  }
429  ++step;
430  if (step == int(report_times_.size())) {
431  break;
432  }
433  }
434  stepsize = report_times_[step] - current_time;
435  } else {
436  bool output_now = ((step + 1) % output_interval_ == 0);
437  if (output_now) {
438  output(grid_, fluid_, state_, face_flux, step, output_name);
439  }
440  ++step;
441  }
442  }
443  if (step % output_interval_ != 0) {
444  // Output was not written at last step, write final output.
445  output(grid_, fluid_, state_, face_flux, step - 1, output_name);
446  }
447 }
448 
449 
450 
451 
452 
453 
454 template<class Grid, class Rock, class Fluid, class Wells, class FlowSolver, class TransportSolver>
455 void
457 output(const Grid& grid,
458  const Fluid& fluid,
459  const State& simstate,
460  const std::vector<double>& face_flux,
461  const int step,
462  const std::string& filebase)
463 {
464  // Compute saturations, total fluid volume density and mass fractions.
465  int num_cells = grid.numCells();
466  std::vector<typename Fluid::PhaseVec> sat(num_cells);
467  std::vector<typename Fluid::PhaseVec> mass_frac(num_cells);
468  std::vector<double> totflvol_dens(num_cells);
469  for (int cell = 0; cell < num_cells; ++cell) {
470  typename Fluid::FluidState fstate = fluid.computeState(simstate.cell_pressure_[cell], simstate.cell_z_[cell]);
471  sat[cell] = fstate.saturation_;
472  totflvol_dens[cell] = fstate.total_phase_volume_density_;
473  double totMass_dens = simstate.cell_z_[cell]*fluid.surfaceDensities();
474  mass_frac[cell][Fluid::Water] = simstate.cell_z_[cell][Fluid::Water]*fluid.surfaceDensities()[Fluid::Water]/totMass_dens;
475  mass_frac[cell][Fluid::Oil] = simstate.cell_z_[cell][Fluid::Oil]*fluid.surfaceDensities()[Fluid::Oil]/totMass_dens;
476  mass_frac[cell][Fluid::Gas] = simstate.cell_z_[cell][Fluid::Gas]*fluid.surfaceDensities()[Fluid::Gas]/totMass_dens;
477  }
478 
479  // Ensure directory exists.
480  boost::filesystem::path fpath(filebase);
481  if (fpath.has_branch_path()) {
482  create_directories(fpath.branch_path());
483  }
484 
485  // Output to VTK.
486  std::vector<typename Grid::Vector> cell_velocity;
487  Opm::estimateCellVelocitySimpleInterface(cell_velocity, grid, face_flux);
488  // Dune's vtk writer wants multi-component data to be flattened.
489  std::vector<double> cell_pressure_flat(&*simstate.cell_pressure_.front().begin(),
490  &*simstate.cell_pressure_.back().end());
491  std::vector<double> cell_velocity_flat(&*cell_velocity.front().begin(),
492  &*cell_velocity.back().end());
493  std::vector<double> z_flat(&*simstate.cell_z_.front().begin(),
494  &*simstate.cell_z_.back().end());
495  std::vector<double> sat_flat(&*sat.front().begin(),
496  &*sat.back().end());
497  std::vector<double> mass_frac_flat(&*mass_frac.front().begin(),
498  &*mass_frac.back().end());
499 #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
500  Dune::VTKWriter<typename Grid::LeafGridView> vtkwriter(grid.leafGridView());
501 #else
502  Dune::VTKWriter<typename Grid::LeafGridView> vtkwriter(grid.leafView());
503 #endif
504  vtkwriter.addCellData(cell_pressure_flat, "pressure", Fluid::numPhases);
505  vtkwriter.addCellData(cell_velocity_flat, "velocity", Grid::dimension);
506  vtkwriter.addCellData(z_flat, "z", Fluid::numComponents);
507  vtkwriter.addCellData(sat_flat, "sat", Fluid::numPhases);
508  vtkwriter.addCellData(mass_frac_flat, "massFrac", Fluid::numComponents);
509  vtkwriter.addCellData(totflvol_dens, "total fl. vol.");
510  vtkwriter.write(filebase + '-' + boost::lexical_cast<std::string>(step),
511  Dune::VTK::ascii);
512 
513  // Dump data for Matlab.
514  std::vector<double> zv[Fluid::numComponents];
515  for (int comp = 0; comp < Fluid::numComponents; ++comp) {
516  zv[comp].resize(grid.numCells());
517  for (int cell = 0; cell < grid.numCells(); ++cell) {
518  zv[comp][cell] = simstate.cell_z_[cell][comp];
519  }
520  }
521  std::vector<double> sv[Fluid::numPhases];
522  for (int phase = 0; phase < Fluid::numPhases; ++phase) {
523  sv[phase].resize(grid.numCells());
524  for (int cell = 0; cell < grid.numCells(); ++cell) {
525  sv[phase][cell] = sat[cell][phase];
526  }
527  }
528  std::string matlabdumpname(filebase + "-");
529  matlabdumpname += boost::lexical_cast<std::string>(step);
530  matlabdumpname += ".dat";
531  std::ofstream dump(matlabdumpname.c_str());
532  dump.precision(15);
533  std::vector<double> liq_press(num_cells);
534  for (int cell = 0; cell < num_cells; ++cell) {
535  liq_press[cell] = simstate.cell_pressure_[cell][Fluid::Liquid];
536  }
537  // Liquid phase pressure.
538  std::copy(liq_press.begin(), liq_press.end(),
539  std::ostream_iterator<double>(dump, " "));
540  dump << '\n';
541  // z (3 components)
542  for (int comp = 0; comp < Fluid::numComponents; ++comp) {
543  std::copy(zv[comp].begin(), zv[comp].end(),
544  std::ostream_iterator<double>(dump, " "));
545  dump << '\n';
546  }
547  // s (3 components)
548  for (int phase = 0; phase < Fluid::numPhases; ++phase) {
549  std::copy(sv[phase].begin(), sv[phase].end(),
550  std::ostream_iterator<double>(dump, " "));
551  dump << '\n';
552  }
553  // Total fluid volume
554  std::copy(totflvol_dens.begin(), totflvol_dens.end(),
555  std::ostream_iterator<double>(dump, " "));
556  dump << '\n';
557  // Well report ...
558  const double seconds_pr_day = 3600.*24.;
559  for (unsigned int perf=0; perf<Wells::WellReport::report()->perfPressure.size(); ++perf) {
560  dump << std::setw(8) << Wells::WellReport::report()->cellId[perf] << " "
561  << std::setw(22) << Wells::WellReport::report()->perfPressure[perf] << " "
562  << std::setw(22) << Wells::WellReport::report()->cellPressure[perf] << " "
563  << std::setw(22) << seconds_pr_day*Wells::WellReport::report()->massRate[perf][Fluid::Water] << " "
564  << std::setw(22) << seconds_pr_day*Wells::WellReport::report()->massRate[perf][Fluid::Oil] << " "
565  << std::setw(22) << seconds_pr_day*Wells::WellReport::report()->massRate[perf][Fluid::Gas] << '\n';
566  }
567  dump << '\n';
568 }
569 
570 
571 
572 
573 
574 } // namespace Opm
575 
576 
577 
578 
579 
580 #endif // OPM_BLACKOILSIMULATOR_HEADER_INCLUDED
std::vector< PhaseVec > face_pressure_
Definition: BlackoilSimulator.hpp:62
Definition: Wells.hpp:46
Initialize SPE9 type case.
Definition: BlackoilInitialization.hpp:193
Definition: BlackoilFluid.hpp:31
virtual void init(const Opm::parameter::ParameterGroup &param, const Grid &grid, const Fluid &fluid, typename Grid::Vector gravity, State &simstate)
Definition: BlackoilInitialization.hpp:59
Definition: BlackoilSimulator.hpp:59
std::vector< PhaseVec > cell_pressure_
Definition: BlackoilSimulator.hpp:61
virtual void init(const Opm::parameter::ParameterGroup &param, const Grid &grid, const Fluid &fluid, typename Grid::Vector gravity, State &simstate)
Definition: BlackoilInitialization.hpp:200
FluidT Fluid
Definition: BlackoilSimulator.hpp:54
std::vector< CompVec > cell_z_
Definition: BlackoilSimulator.hpp:66
std::vector< double > well_bhp_pressure_
Definition: BlackoilSimulator.hpp:63
void simulate()
Definition: BlackoilSimulator.hpp:328
std::vector< double > well_perf_pressure_
Definition: BlackoilSimulator.hpp:64
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:90
void init(const Opm::parameter::ParameterGroup &param)
Definition: BlackoilSimulator.hpp:115
Definition: BlackoilSimulator.hpp:47
Initialize basic cases.
Definition: BlackoilInitialization.hpp:52
GridT Grid
Definition: BlackoilSimulator.hpp:53
A class for representing a flow boundary condition.
Definition: BoundaryConditions.hpp:121
Fluid::CompVec CompVec
Definition: BlackoilSimulator.hpp:56
A property class for porous media rock.
Definition: ImplicitTransportDefs.hpp:80
std::vector< double > well_perf_flux_
Definition: BlackoilSimulator.hpp:65
Definition: Wells.hpp:37
Fluid::PhaseVec PhaseVec
Definition: BlackoilSimulator.hpp:57