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
34namespace Opm
35{
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 ...
69 {
70 public:
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 const auto& 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").get< std::string >(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 const auto& 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 const auto& compdatRecord = compdatKeyword.getRecord(kw);
160 std::string name = compdatRecord.getItem("WELL").get< std::string >(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").get< int >(0) - 1;
177 int jy = compdatRecord.getItem("J").get< int >(0) - 1;
178 int kz1 = compdatRecord.getItem("K1").get< int >(0) - 1;
179 int kz2 = compdatRecord.getItem("K2").get< int >(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").get< std::string >(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 const auto& 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 const auto& wconinjeRecord = wconinjeKeyword.getRecord(kw);
237 std::string name = wconinjeRecord.getItem("WELL").get< std::string >(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").get< std::string >(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").get< double >(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").get< double >(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").get< std::string >(0)
271 << " in input file");
272 }
273 int itp = -1;
274 if (wconinjeRecord.getItem("TYPE").get< std::string >(0) == "WATER") {
275 itp = Water;
276 } else if (wconinjeRecord.getItem("TYPE").get< std::string >(0) == "OIL") {
277 itp = Oil;
278 } else if (wconinjeRecord.getItem("TYPE").get< std::string >(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").get< std::string >(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 const auto& wconprodKeyword = deck->getKeyword("WCONPROD");
313 const int num_wconprods = wconprodKeyword.size();
314 for (int kw=0; kw<num_wconprods; ++kw) {
315 const auto& wconprodRecord = wconprodKeyword.getRecord(kw);
316 std::string name = wconprodRecord.getItem("WELL").get< std::string >(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").get< std::string >(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").get< std::string >(0)
360 << " in input file");
361 }
362 }
363 }
364 if (!well_found) {
365 OPM_THROW(std::runtime_error, "Undefined well name: " << wconprodRecord.getItem("WELL").get< std::string >(0)
366 << " in WCONPROD");
367 }
368 }
369 }
370
371 // Get WELTARG data
372 if (deck->hasKeyword("WELTARG")) {
373 const auto& weltargKeyword = deck->getKeyword("WELTARG");
374 const int num_weltargs = weltargKeyword.size();
375 for (int kw=0; kw<num_weltargs; ++kw) {
376 const auto& weltargRecord = weltargKeyword.getRecord(kw);
377 std::string name = weltargRecord.getItem("WELL").get< std::string >(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").get< double >(0);
388 break;
389 }
390 }
391 if (!well_found) {
392 OPM_THROW(std::runtime_error, "Undefined well name: " << weltargRecord.getItem("WELL").get< std::string >(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
Definition: BlackoilDefs.hpp:31
Dune::FieldVector< Scalar, numComponents > CompVec
Definition: BlackoilDefs.hpp:40
@ Gas
Definition: BlackoilDefs.hpp:36
@ Oil
Definition: BlackoilDefs.hpp:36
@ Water
Definition: BlackoilDefs.hpp:36
Definition: BlackoilWells.hpp:69
static WellReport * report()
Definition: BlackoilWells.hpp:71
std::vector< double > cellPressure
Definition: BlackoilWells.hpp:85
std::vector< BlackoilDefs::CompVec > massRate
Definition: BlackoilWells.hpp:86
void clearAll()
Definition: BlackoilWells.hpp:77
WellReport()
Definition: BlackoilWells.hpp:89
std::vector< double > perfPressure
Definition: BlackoilWells.hpp:84
std::vector< int > cellId
Definition: BlackoilWells.hpp:87
Definition: BlackoilWells.hpp:39
double target(int wellnum) const
Definition: BlackoilWells.hpp:434
double wellToReservoirFlux(int cell) const
Definition: BlackoilWells.hpp:479
WellType
Definition: BlackoilWells.hpp:47
@ Injector
Definition: BlackoilWells.hpp:47
@ Producer
Definition: BlackoilWells.hpp:47
int numWells() const
Definition: BlackoilWells.hpp:419
double referenceDepth(int wellnum) const
Definition: BlackoilWells.hpp:439
double perforationPressure(int cell) const
Definition: BlackoilWells.hpp:484
double wellIndex(int wellnum, int perfnum) const
Definition: BlackoilWells.hpp:454
void init(Opm::DeckConstPtr deck, const Dune::CpGrid &grid, const Opm::Rock< 3 > &rock)
Definition: BlackoilWells.hpp:124
WellType type(int wellnum) const
Definition: BlackoilWells.hpp:424
WellControl control(int wellnum) const
Definition: BlackoilWells.hpp:429
void update(int num_cells, const std::vector< double > &well_perf_pressures, const std::vector< double > &well_perf_fluxes)
Definition: BlackoilWells.hpp:459
int numPerforations(int wellnum) const
Definition: BlackoilWells.hpp:444
WellControl
Definition: BlackoilWells.hpp:49
@ Rate
Definition: BlackoilWells.hpp:49
@ Pressure
Definition: BlackoilWells.hpp:49
CompVec injectionMixture(int cell) const
Definition: BlackoilWells.hpp:489
int wellCell(int wellnum, int perfnum) const
Definition: BlackoilWells.hpp:449
A property class for porous media rock.
Definition: ImplicitTransportDefs.hpp:80
PermTensor permeability(int cell_index) const
Read-access to permeability.
Definition: Rock_impl.hpp:84
ImmutableCMatrix PermTensor
Tensor type for read-only access to permeability.
Definition: Rock.hpp:39
Definition: BlackoilFluid.hpp:32