BlackoilWells.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_BLACKOILWELLS_HEADER_INCLUDED
21 #define OPM_BLACKOILWELLS_HEADER_INCLUDED
22 
24 #include <dune/grid/CpGrid.hpp>
25 #include <opm/common/ErrorMacros.hpp>
26 #include <opm/core/utility/SparseTable.hpp>
28 #include <opm/parser/eclipse/Deck/Deck.hpp>
29 #include <dune/common/fvector.hh>
30 #include <vector>
31 #include <iostream>
32 
33 
34 namespace Opm
35 {
38  class BlackoilWells : public BlackoilDefs
39  {
40  public:
41  void init(Opm::DeckConstPtr deck,
42  const Dune::CpGrid& grid,
43  const Opm::Rock<3>& rock);
44 
45  // Well-centric interface. Mostly used by pressure solver.
46  int numWells() const;
48  WellType type(int wellnum) const;
50  WellControl control(int wellnum) const;
51  double target(int wellnum) const;
52  double referenceDepth(int wellnum) const;
53  int numPerforations(int wellnum) const;
54  int wellCell(int wellnum, int perfnum) const;
55  double wellIndex(int wellnum, int perfnum) const;
56 
57  // Updating rates and pressures after pressure solve.
58  void update(int num_cells,
59  const std::vector<double>& well_perf_pressures,
60  const std::vector<double>& well_perf_fluxes);
61 
62  // Cell-centric interface. Mostly used by transport solver.
63  double perforationPressure(int cell) const;
64  double wellToReservoirFlux(int cell) const;
65  CompVec injectionMixture(int cell) const;
66 
67  // Simple well report ...
68  class WellReport
69  {
70  public:
71  static WellReport* report()
72  {
73  if (well_report_ == 0x0)
74  well_report_ = new WellReport;
75  return well_report_;
76  }
77  void clearAll()
78  {
79  perfPressure.clear();
80  cellPressure.clear();
81  massRate.clear();
82  cellId.clear();
83  }
84  std::vector<double> perfPressure;
85  std::vector<double> cellPressure;
86  std::vector<BlackoilDefs::CompVec> massRate; // (surface volumes)
87  std::vector<int> cellId;
88  protected:
90  private:
91  static WellReport* well_report_;
92  };
93 
94  private:
95  // Use the Peaceman well model to compute well indices
96  double computeWellIndex(double radius, const Dune::FieldVector<double, 3>& cubical,
97  const Opm::Rock<3>::PermTensor& permeability, double skin_factor) const;
98 
99  struct WellData { WellType type; WellControl control; double target; double reference_bhp_depth; };
100  std::vector<WellData> well_data_;
101  struct PerfData { int cell; double well_index; };
102  Opm::SparseTable<PerfData> perf_data_;
103  std::vector<double> well_cell_flux_;
104  std::vector<double> well_cell_pressure_;
105  Dune::FieldVector<double, 3> injection_mixture_;
106  std::vector<std::string> well_names_;
107  };
108 
109  BlackoilWells::WellReport* BlackoilWells::WellReport::well_report_ = 0x0;
110 
111  // ------------ Method implementations --------------
112 
113 
114  // Forward declaration of some helper functions.
115  namespace
116  {
117  int prod_control_mode(const std::string& control);
118  int inje_control_mode(const std::string& control);
119  template<class grid_t>
120  const Dune::FieldVector<double,3> getCubeDim(const grid_t& grid, int cell);
121 
122  } // anon namespace
123 
124  inline void BlackoilWells::init(Opm::DeckConstPtr deck,
125  const Dune::CpGrid& grid,
126  const Opm::Rock<3>& rock)
127  {
128  if (!deck->hasKeyword("WELSPECS")) {
129  OPM_MESSAGE("Missing keyword \"WELSPECS\" in deck, initializing no wells.");
130  return;
131  }
132  if (!deck->hasKeyword("COMPDAT")) {
133  OPM_MESSAGE("Missing keyword \"COMPDAT\" in deck, initializing no wells.");
134  return;
135  }
136  if (!(deck->hasKeyword("WCONINJE") || deck->hasKeyword("WCONPROD")) ) {
137  OPM_THROW(std::runtime_error, "Needed field is missing in file");
138  }
139  using namespace Opm;
140 
141  // Get WELLSPECS data
142  Opm::DeckKeywordConstPtr welspecsKeyword = deck->getKeyword("WELSPECS");
143  const int num_welspecs = welspecsKeyword->size();
144  well_names_.reserve(num_welspecs);
145  well_data_.reserve(num_welspecs);
146  for (int i=0; i<num_welspecs; ++i) {
147  well_names_.push_back(welspecsKeyword->getRecord(i)->getItem("WELL")->getString(0));
148  WellData wd;
149  well_data_.push_back(wd);
150  well_data_.back().reference_bhp_depth =
151  welspecsKeyword->getRecord(i)->getItem("REF_DEPTH")->getSIDouble(0);
152  }
153 
154  // Get COMPDAT data
155  Opm::DeckKeywordConstPtr compdatKeyword = deck->getKeyword("COMPDAT");
156  const int num_compdats = compdatKeyword->size();
157  std::vector<std::vector<PerfData> > wellperf_data(num_welspecs);
158  for (int kw=0; kw<num_compdats; ++kw) {
159  Opm::DeckRecordConstPtr compdatRecord = compdatKeyword->getRecord(kw);
160  std::string name = compdatRecord->getItem("WELL")->getString(0);
161  std::string::size_type len = name.find('*');
162  if (len != std::string::npos) {
163  name = name.substr(0, len);
164  }
165 
166  // global_cell is a map from compressed cells to Cartesian grid cells
167  const std::vector<int>& global_cell = grid.globalCell();
168  const std::array<int, 3>& cpgdim = grid.logicalCartesianSize();
169  std::map<int,int> cartesian_to_compressed;
170  for (int i=0; i<int(global_cell.size()); ++i) {
171  cartesian_to_compressed.insert(std::make_pair(global_cell[i], i));
172  }
173  bool found = false;
174  for (int wix=0; wix<num_welspecs; ++wix) {
175  if (well_names_[wix].compare(0,len, name) == 0) { //equal
176  int ix = compdatRecord->getItem("I")->getInt(0) - 1;
177  int jy = compdatRecord->getItem("J")->getInt(0) - 1;
178  int kz1 = compdatRecord->getItem("K1")->getInt(0) - 1;
179  int kz2 = compdatRecord->getItem("K2")->getInt(0) - 1;
180  for (int kz = kz1; kz <= kz2; ++kz) {
181  int cart_grid_indx = ix + cpgdim[0]*(jy + cpgdim[1]*kz);
182  std::map<int, int>::const_iterator cgit =
183  cartesian_to_compressed.find(cart_grid_indx);
184  if (cgit == cartesian_to_compressed.end()) {
185  OPM_THROW(std::runtime_error, "Cell with i,j,k indices " << ix << ' ' << jy << ' '
186  << kz << " not found!");
187  }
188  int cell = cgit->second;
189  PerfData pd;
190  pd.cell = cell;
191  if (compdatRecord->getItem("CF")->getSIDouble(0) > 0.0) {
192  pd.well_index = compdatRecord->getItem("CF")->getSIDouble(0);
193  } else {
194  double radius = 0.5*compdatRecord->getItem("DIAMETER")->getSIDouble(0);
195  if (radius <= 0.0) {
196  radius = 0.5*unit::feet;
197  OPM_MESSAGE("Warning: Well bore internal radius set to " << radius);
198  }
199  Dune::FieldVector<double, 3> cubical = getCubeDim(grid, cell);
200  const Rock<3>::PermTensor permeability = rock.permeability(cell);
201  pd.well_index = computeWellIndex(radius, cubical, permeability,
202  compdatRecord->getItem("SKIN")->getSIDouble(0));
203  }
204  wellperf_data[wix].push_back(pd);
205  }
206  found = true;
207  break;
208  }
209  }
210  if (!found) {
211  OPM_THROW(std::runtime_error, "Undefined well name: " << compdatRecord->getItem("WELL")->getString(0)
212  << " in COMPDAT");
213  }
214  }
215  for (int w = 0; w < num_welspecs; ++w) {
216  perf_data_.appendRow(wellperf_data[w].begin(), wellperf_data[w].end());
217  if (well_data_[w].reference_bhp_depth == -1e100) {
218  // It was defaulted. Set reference depth to minimum perforation depth.
219  double min_depth = 1e100;
220  int num_wperfs = wellperf_data[w].size();
221  for (int perf = 0; perf < num_wperfs; ++perf) {
222  double depth = grid.cellCentroid(wellperf_data[w][perf].cell)[2];
223  min_depth = std::min(min_depth, depth);
224  }
225  well_data_[w].reference_bhp_depth = min_depth;
226  }
227  }
228 
229  // Get WCONINJE data
230  injection_mixture_ = 0.0;
231  if (deck->hasKeyword("WCONINJE")) {
232  Opm::DeckKeywordConstPtr wconinjeKeyword = deck->getKeyword("WCONINJE");
233  const int num_wconinjes = wconinjeKeyword->size();
234  int injector_component = -1;
235  for (int kw=0; kw<num_wconinjes; ++kw) {
236  Opm::DeckRecordConstPtr wconinjeRecord = wconinjeKeyword->getRecord(kw);
237  std::string name = wconinjeRecord->getItem("WELL")->getString(0);
238  std::string::size_type len = name.find('*');
239  if (len != std::string::npos) {
240  name = name.substr(0, len);
241  }
242 
243  bool well_found = false;
244  for (int wix=0; wix<num_welspecs; ++wix) {
245  if (well_names_[wix].compare(0,len, name) == 0) { //equal
246  well_found = true;
247  well_data_[wix].type = Injector;
248  int m = inje_control_mode(wconinjeRecord->getItem("CMODE")->getString(0));
249  switch(m) {
250  case 0: // RATE
251  well_data_[wix].control = Rate;
252  // TODO: convert rate to SI!
253  well_data_[wix].target = wconinjeRecord->getItem("RATE")->getRawDouble(0);
254  break;
255  case 1: // RESV
256  well_data_[wix].control = Rate;
257  // TODO: convert rate to SI!
258  well_data_[wix].target = wconinjeRecord->getItem("RESV")->getRawDouble(0);
259  break;
260  case 2: // BHP
261  well_data_[wix].control = Pressure;
262  well_data_[wix].target = wconinjeRecord->getItem("BHP")->getSIDouble(0);
263  break;
264  case 3: // THP
265  well_data_[wix].control = Pressure;
266  well_data_[wix].target = wconinjeRecord->getItem("THP")->getSIDouble(0);
267  break;
268  default:
269  OPM_THROW(std::runtime_error, "Unknown well control mode; WCONIJE = "
270  << wconinjeRecord->getItem("CMODE")->getString(0)
271  << " in input file");
272  }
273  int itp = -1;
274  if (wconinjeRecord->getItem("TYPE")->getString(0) == "WATER") {
275  itp = Water;
276  } else if (wconinjeRecord->getItem("TYPE")->getString(0) == "OIL") {
277  itp = Oil;
278  } else if (wconinjeRecord->getItem("TYPE")->getString(0) == "GAS") {
279  itp = Gas;
280  }
281  if (itp == -1 || (injector_component != -1 && itp != injector_component)) {
282  if (itp == -1) {
283  OPM_THROW(std::runtime_error, "Error in injector specification, found no known fluid type.");
284  } else {
285  OPM_THROW(std::runtime_error, "Error in injector specification, we can only handle a single injection fluid.");
286  }
287  } else {
288  injector_component = itp;
289  }
290  }
291  }
292  if (!well_found) {
293  OPM_THROW(std::runtime_error, "Undefined well name: " << wconinjeRecord->getItem("WELL")->getString(0)
294  << " in WCONINJE");
295  }
296  }
297  if (injector_component != -1) {
298  injection_mixture_[injector_component] = 1.0;
299  }
300  } else {
301  // No WCONINJE.
302  // This default is only invoked if production wells
303  // start injecting, (and only if there are no injection wells).
304  // In other words, only if we have a primary production type scenario.
305  // In this case we expect the flow to be very small, and not affect
306  // the simulation in any significant way.
307  injection_mixture_[Oil] = 1.0;
308  }
309 
310  // Get WCONPROD data
311  if (deck->hasKeyword("WCONPROD")) {
312  Opm::DeckKeywordConstPtr wconprodKeyword = deck->getKeyword("WCONPROD");
313  const int num_wconprods = wconprodKeyword->size();
314  for (int kw=0; kw<num_wconprods; ++kw) {
315  Opm::DeckRecordConstPtr wconprodRecord = wconprodKeyword->getRecord(kw);
316  std::string name = wconprodRecord->getItem("WELL")->getString(0);
317  std::string::size_type len = name.find('*');
318  if (len != std::string::npos) {
319  name = name.substr(0, len);
320  }
321 
322  bool well_found = false;
323  for (int wix=0; wix<num_welspecs; ++wix) {
324  if (well_names_[wix].compare(0,len, name) == 0) { //equal
325  well_found = true;
326  well_data_[wix].type = Producer;
327  int m = prod_control_mode(wconprodRecord->getItem("CMODE")->getString(0));
328  switch(m) {
329  case 0: // ORAT
330  well_data_[wix].control = Rate;
331  well_data_[wix].target = wconprodRecord->getItem("ORAT")->getSIDouble(0);
332  break;
333  case 1: // WRAT
334  well_data_[wix].control = Rate;
335  well_data_[wix].target = wconprodRecord->getItem("WRAT")->getSIDouble(0);
336  break;
337  case 2: // GRAT
338  well_data_[wix].control = Rate;
339  well_data_[wix].target = wconprodRecord->getItem("GRAT")->getSIDouble(0);
340  break;
341  case 3: // LRAT
342  well_data_[wix].control = Rate;
343  well_data_[wix].target = wconprodRecord->getItem("LRAT")->getSIDouble(0);
344  break;
345  case 4: // RESV
346  well_data_[wix].control = Rate;
347  well_data_[wix].target = wconprodRecord->getItem("RESV")->getSIDouble(0);
348  break;
349  case 5: // BHP
350  well_data_[wix].control = Pressure;
351  well_data_[wix].target = wconprodRecord->getItem("BHP")->getSIDouble(0);
352  break;
353  case 6: // THP
354  well_data_[wix].control = Pressure;
355  well_data_[wix].target = wconprodRecord->getItem("THP")->getSIDouble(0);
356  break;
357  default:
358  OPM_THROW(std::runtime_error, "Unknown well control mode; WCONPROD = "
359  << wconprodRecord->getItem("CMODE")->getString(0)
360  << " in input file");
361  }
362  }
363  }
364  if (!well_found) {
365  OPM_THROW(std::runtime_error, "Undefined well name: " << wconprodRecord->getItem("WELL")->getString(0)
366  << " in WCONPROD");
367  }
368  }
369  }
370 
371  // Get WELTARG data
372  if (deck->hasKeyword("WELTARG")) {
373  Opm::DeckKeywordConstPtr weltargKeyword = deck->getKeyword("WELTARG");
374  const int num_weltargs = weltargKeyword->size();
375  for (int kw=0; kw<num_weltargs; ++kw) {
376  Opm::DeckRecordConstPtr weltargRecord = weltargKeyword->getRecord(kw);
377  std::string name = weltargRecord->getItem("WELL")->getString(0);
378  std::string::size_type len = name.find('*');
379  if (len != std::string::npos) {
380  name = name.substr(0, len);
381  }
382  bool well_found = false;
383  for (int wix=0; wix<num_welspecs; ++wix) {
384  if (well_names_[wix].compare(0,len, name) == 0) { //equal
385  well_found = true;
386  // TODO: convert to SI!
387  well_data_[wix].target = weltargRecord->getItem("NEW_VALUE")->getRawDouble(0);
388  break;
389  }
390  }
391  if (!well_found) {
392  OPM_THROW(std::runtime_error, "Undefined well name: " << weltargRecord->getItem("WELL")->getString(0)
393  << " in WELTARG");
394  }
395  }
396  }
397 
398  // Debug output.
399  std::cout << "\t WELL DATA" << std::endl;
400  for(int i=0; i< int(well_data_.size()); ++i) {
401  std::cout << i << ": " << well_data_[i].type << " "
402  << well_data_[i].control << " " << well_data_[i].target
403  << std::endl;
404  }
405 
406  std::cout << "\n\t PERF DATA" << std::endl;
407  for(int i=0; i< int(perf_data_.size()); ++i) {
408  for(int j=0; j< int(perf_data_[i].size()); ++j) {
409  std::cout << i << ": " << perf_data_[i][j].cell << " "
410  << perf_data_[i][j].well_index << std::endl;
411  }
412  }
413 
414  // Ensuring that they have the right size.
415  well_cell_pressure_.resize(grid.numCells(), -1e100);
416  well_cell_flux_.resize(grid.numCells(), 0.0);
417  }
418 
419  inline int BlackoilWells::numWells() const
420  {
421  return well_data_.size();
422  }
423 
425  {
426  return well_data_[wellnum].type;
427  }
428 
430  {
431  return well_data_[wellnum].control;
432  }
433 
434  inline double BlackoilWells::target(int wellnum) const
435  {
436  return well_data_[wellnum].target;
437  }
438 
439  inline double BlackoilWells::referenceDepth(int wellnum) const
440  {
441  return well_data_[wellnum].reference_bhp_depth;
442  }
443 
444  inline int BlackoilWells::numPerforations(int wellnum) const
445  {
446  return perf_data_[wellnum].size();
447  }
448 
449  inline int BlackoilWells::wellCell(int wellnum, int perfnum) const
450  {
451  return perf_data_[wellnum][perfnum].cell;
452  }
453 
454  inline double BlackoilWells::wellIndex(int wellnum, int perfnum) const
455  {
456  return perf_data_[wellnum][perfnum].well_index;
457  }
458 
459  inline void BlackoilWells::update(int num_cells,
460  const std::vector<double>& well_perf_pressures,
461  const std::vector<double>& well_perf_fluxes)
462  {
463  // Input is per perforation, data members store for all cells.
464  assert(perf_data_.dataSize() == int(well_perf_pressures.size()));
465  well_cell_pressure_.resize(num_cells, -1e100);
466  well_cell_flux_.resize(num_cells, 0.0);
467  int pcount = 0;
468  for (int w = 0; w < numWells(); ++w) {
469  for (int perf = 0; perf < numPerforations(w); ++perf) {
470  int cell = wellCell(w, perf);
471  well_cell_pressure_[cell] = well_perf_pressures[pcount];
472  well_cell_flux_[cell] = well_perf_fluxes[pcount];
473  ++pcount;
474  }
475  }
476  assert(pcount == perf_data_.dataSize());
477  }
478 
479  inline double BlackoilWells::wellToReservoirFlux(int cell) const
480  {
481  return well_cell_flux_[cell];
482  }
483 
484  inline double BlackoilWells::perforationPressure(int cell) const
485  {
486  return well_cell_pressure_[cell];
487  }
488 
489  inline Dune::FieldVector<double, 3> BlackoilWells::injectionMixture(int cell) const
490  {
491  return injection_mixture_;
492  }
493 
494  inline double BlackoilWells::computeWellIndex(double radius,
495  const Dune::FieldVector<double, 3>& cubical,
496  const Opm::Rock<3>::PermTensor& permeability,
497  double skin_factor) const
498  {
499  // Use the Peaceman well model to compute well indices.
500  // radius is the radius of the well.
501  // cubical contains [dx, dy, dz] of the cell.
502  // (Note that the well model asumes that each cell is a cuboid).
503  // permeability is the permeability of the given cell.
504  // returns the well index of the cell.
505 
506  // sse: Using the Peaceman modell.
507  // NOTE: The formula is valid for cartesian grids, so the result can be a bit
508  // (in worst case: there is no upper bound for the error) off the mark.
509  double effective_perm = sqrt(permeability(0,0) * permeability(1,1));
510  // sse: The formula for r_0 can be found on page 39 of
511  // "Well Models for Mimetic Finite Differerence Methods and Improved Representation
512  // of Wells in Multiscale Methods" by Ingeborg Skjelkvåle Ligaarden.
513  assert(permeability(0,0) > 0.0);
514  assert(permeability(1,1) > 0.0);
515  double kxoy = permeability(0,0) / permeability(1,1);
516  double kyox = permeability(1,1) / permeability(0,0);
517  double r0_denominator = pow(kyox, 0.25) + pow(kxoy, 0.25);
518  double r0_numerator = sqrt((sqrt(kyox)*cubical[0]*cubical[0]) +
519  (sqrt(kxoy)*cubical[1]*cubical[1]));
520  assert(r0_denominator > 0.0);
521  double r0 = 0.28 * r0_numerator / r0_denominator;
522  assert(radius > 0.0);
523  assert(r0 > 0.0);
524  if (r0 < radius) {
525  std::cout << "ERROR: Too big well radius detected.";
526  std::cout << "Specified well radius is " << radius
527  << " while r0 is " << r0 << ".\n";
528  }
529 
530  const double two_pi = 6.2831853071795864769252867665590057683943387987502116419498;
531 
532  double wi_denominator = log(r0 / radius) + skin_factor;
533  double wi_numerator = two_pi * cubical[2];
534  assert(wi_denominator > 0.0);
535  double wi = effective_perm * wi_numerator / wi_denominator;
536  assert(wi > 0.0);
537  return wi;
538  }
539 
540 
541 
542  // ------------- Helper functions for init() --------------
543 
544  namespace
545  {
546 
547  int prod_control_mode(const std::string& control){
548  const int num_prod_control_modes = 8;
549  static std::string prod_control_modes[num_prod_control_modes] =
550  {std::string("ORAT"), std::string("WRAT"), std::string("GRAT"),
551  std::string("LRAT"), std::string("RESV"), std::string("BHP"),
552  std::string("THP"), std::string("GRUP") };
553  int m = -1;
554  for (int i=0; i<num_prod_control_modes; ++i) {
555  if (control == prod_control_modes[i]) {
556  m = i;
557  break;
558  }
559  }
560  if (m >= 0) {
561  return m;
562  } else {
563  OPM_THROW(std::runtime_error, "Unknown well control mode = " << control << " in input file");
564  }
565  }
566 
567  int inje_control_mode(const std::string& control)
568  {
569  const int num_inje_control_modes = 5;
570  static std::string inje_control_modes[num_inje_control_modes] =
571  {std::string("RATE"), std::string("RESV"), std::string("BHP"),
572  std::string("THP"), std::string("GRUP") };
573  int m = -1;
574  for (int i=0; i<num_inje_control_modes; ++i) {
575  if (control == inje_control_modes[i]) {
576  m = i;
577  break;
578  }
579  }
580 
581  if (m >= 0) {
582  return m;
583  } else {
584  OPM_THROW(std::runtime_error, "Unknown well control mode = " << control << " in input file");
585  }
586  }
587 
588 
589  template<class grid_t>
590  const Dune::FieldVector<double,3> getCubeDim(const grid_t& grid, int cell)
591  {
592  Dune::FieldVector<double, 3> cube;
593  int num_local_faces = grid.numCellFaces(cell);
594  std::vector<double> x(num_local_faces);
595  std::vector<double> y(num_local_faces);
596  std::vector<double> z(num_local_faces);
597  for (int lf=0; lf<num_local_faces; ++ lf) {
598  int face = grid.cellFace(cell,lf);
599  const Dune::FieldVector<double,3>& centroid =
600  grid.faceCentroid(face);
601  x[lf] = centroid[0];
602  y[lf] = centroid[1];
603  z[lf] = centroid[2];
604  }
605  cube[0] = *max_element(x.begin(), x.end()) -
606  *min_element(x.begin(), x.end());
607  cube[1] = *max_element(y.begin(), y.end()) -
608  *min_element(y.begin(), y.end());
609  cube[2] = *max_element(z.begin(), z.end()) -
610  *min_element(z.begin(), z.end());
611  return cube;
612  }
613 
614  } // anon namespace
615 
616 } // namespace Opm
617 
618 
619 #endif // OPM_BLACKOILWELLS_HEADER_INCLUDED
double wellToReservoirFlux(int cell) const
Definition: BlackoilWells.hpp:479
Definition: BlackoilWells.hpp:47
std::vector< int > cellId
Definition: BlackoilWells.hpp:87
Definition: BlackoilFluid.hpp:31
double perforationPressure(int cell) const
Definition: BlackoilWells.hpp:484
std::vector< double > cellPressure
Definition: BlackoilWells.hpp:85
Dune::FieldVector< Scalar, numComponents > CompVec
Definition: BlackoilDefs.hpp:40
WellControl
Definition: BlackoilWells.hpp:49
Definition: BlackoilDefs.hpp:36
CompVec injectionMixture(int cell) const
Definition: BlackoilWells.hpp:489
Definition: BlackoilWells.hpp:68
Definition: BlackoilWells.hpp:49
double target(int wellnum) const
Definition: BlackoilWells.hpp:434
int numWells() const
Definition: BlackoilWells.hpp:419
int wellCell(int wellnum, int perfnum) const
Definition: BlackoilWells.hpp:449
void update(int num_cells, const std::vector< double > &well_perf_pressures, const std::vector< double > &well_perf_fluxes)
Definition: BlackoilWells.hpp:459
WellType
Definition: BlackoilWells.hpp:47
WellControl control(int wellnum) const
Definition: BlackoilWells.hpp:429
double wellIndex(int wellnum, int perfnum) const
Definition: BlackoilWells.hpp:454
std::vector< BlackoilDefs::CompVec > massRate
Definition: BlackoilWells.hpp:86
Definition: BlackoilDefs.hpp:36
void init(Opm::DeckConstPtr deck, const Dune::CpGrid &grid, const Opm::Rock< 3 > &rock)
Definition: BlackoilWells.hpp:124
ImmutableCMatrix PermTensor
Tensor type for read-only access to permeability.
Definition: Rock.hpp:39
static WellReport * report()
Definition: BlackoilWells.hpp:71
Definition: BlackoilDefs.hpp:30
A property class for porous media rock.
Definition: ImplicitTransportDefs.hpp:80
WellType type(int wellnum) const
Definition: BlackoilWells.hpp:424
Definition: BlackoilDefs.hpp:36
PermTensor permeability(int cell_index) const
Read-access to permeability.
Definition: Rock_impl.hpp:84
Definition: BlackoilWells.hpp:49
double referenceDepth(int wellnum) const
Definition: BlackoilWells.hpp:439
std::vector< double > perfPressure
Definition: BlackoilWells.hpp:84
void clearAll()
Definition: BlackoilWells.hpp:77
int numPerforations(int wellnum) const
Definition: BlackoilWells.hpp:444
Definition: BlackoilWells.hpp:38
Definition: BlackoilWells.hpp:47
WellReport()
Definition: BlackoilWells.hpp:89