ComponentTransport.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2010 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_COMPONENTTRANSPORT_HEADER_INCLUDED
21 #define OPM_COMPONENTTRANSPORT_HEADER_INCLUDED
22 
25 #include <opm/core/utility/parameters/ParameterGroup.hpp>
26 
27 #include <array>
28 #include <vector>
29 #include <iostream>
30 
31 #include <stdlib.h>
32 #include <float.h>
33 #include <math.h>
34 #include <limits.h>
35 #include <assert.h>
36 #include <stdio.h>
37 
38 namespace Opm
39 {
40 
41 
42 template <class Grid, class Rock, class Fluid, class Wells>
44 {
45 public:
49  : pgrid_(0), prock_(0), pfluid_(0), pwells_(0), ptrans_(0),
50  min_surfvol_threshold_(0.0),
51  single_step_only_(false),
52  min_vtime_(0.0)
53  {
54  }
55 
56  void init(const Opm::parameter::ParameterGroup& param)
57  {
58  min_surfvol_threshold_ = param.getDefault("min_surfvol_threshold", min_surfvol_threshold_);
59  single_step_only_ = param.getDefault("single_step_only", single_step_only_);
60  min_vtime_ = param.getDefault("min_vtime", min_vtime_);
61  }
62 
63  void setup(const Grid& grid,
64  const Rock& rock,
65  const Fluid& fluid,
66  const Wells& wells,
67  const std::vector<double>& face_trans,
68  const typename Grid::Vector& gravity)
69  {
70  pgrid_ = &grid;
71  prock_ = &rock;
72  pfluid_ = &fluid;
73  pwells_ = &wells;
74  ptrans_ = &face_trans;
75  gravity_ = gravity;
76  }
77 
78 
81  double transport(const PhaseVec& external_pressure,
82  const CompVec& external_composition,
83  const std::vector<double>& face_flux,
84  const std::vector<PhaseVec>& cell_pressure,
85  const std::vector<PhaseVec>& face_pressure,
86  const double dt,
87  const double voldisclimit,
88  std::vector<CompVec>& cell_z)
89  {
90  int num_cells = pgrid_->numCells();
91  std::vector<CompVec> comp_change;
92  std::vector<double> cell_outflux;
93  std::vector<double> cell_max_ff_deriv;
94  std::vector<double> cell_gravflux;
95  std::vector<double> cell_max_mob_deriv;
96  double cur_time = 0.0;
97  updateFluidProperties(cell_pressure, face_pressure, cell_z,
98  external_pressure, external_composition);
99 // if (!volumeDiscrepancyAcceptable(voldisclimit)) {
100 // return 0.0;
101 // }
102  std::vector<CompVec> cell_z_start;
103  std::cout << "Transport solver target time: " << dt << std::endl;
104  std::cout << " Step Stepsize Remaining time\n";
105  int count = 0;
106  while (cur_time < dt) {
107  cell_z_start = cell_z;
108  computeChange(face_flux, comp_change, cell_outflux, cell_max_ff_deriv);
109  double min_time = 1e100;
110  for (int cell = 0; cell < num_cells; ++cell) {
111  double pvol = prock_->porosity(cell)*pgrid_->cellVolume(cell);
112  double vtime = pvol/(cell_outflux[cell]*cell_max_ff_deriv[cell]);
113  double gtime = 1e100; // No working CFL for gravity yet.
114  double max_nonzero_time = 1e100;
115  for (int comp = 0; comp < numComponents; ++comp) {
116  if (comp_change[cell][comp] < 0.0) {
117  if (cell_z[cell][comp] > min_surfvol_threshold_) {
118  max_nonzero_time = std::min(max_nonzero_time,
119  -cell_z[cell][comp]*pvol/comp_change[cell][comp]);
120  } else {
121  comp_change[cell][comp] = 0.0;
122  cell_z[cell][comp] = 0.0;
123  }
124  }
125  }
126  vtime = std::max(vtime,min_vtime_);
127  double time = std::min(std::min(vtime, gtime), max_nonzero_time);
128  min_time = std::min(time, min_time);
129  }
130  min_time *= 0.49; // Semi-random CFL factor... \TODO rigorize
131  double step_time = dt - cur_time;
132  if (min_time < step_time) {
133  step_time = min_time;
134  cur_time += min_time;
135  } else {
136  cur_time = dt;
137  }
138  // Check if remaining number of steps is excessive.
139  if ((dt - cur_time)/step_time > 10000) {
140  std::cout << "Collapsing transport stepsize detected." << std::endl;
141  return cur_time;
142  }
143  std::cout.precision(10);
144  std::cout << std::setw(6) << count++
145  << std::setw(24) << step_time
146  << std::setw(24) << dt - cur_time << std::endl;
147  std::cout.precision(16);
148  for (int cell = 0; cell < num_cells; ++cell) {
149  double pv = pgrid_->cellVolume(cell)*prock_->porosity(cell);
150  comp_change[cell] *= (step_time/pv);
151  cell_z[cell] += comp_change[cell];
152  }
153  // After changing z, we recompute fluid properties.
154  updateFluidProperties(cell_pressure, face_pressure, cell_z,
155  external_pressure, external_composition);
156  bool ok = volumeDiscrepancyAcceptable(voldisclimit);
157  if (!ok) {
158  // Roll back to last ok step.
159  cell_z = cell_z_start;
160  cur_time -= step_time;
161  return cur_time;
162  }
163  if (single_step_only_) {
164  return cur_time;
165  }
166  }
167  return dt;
168  }
169 
170 
171 private: // Data
172  const Grid* pgrid_;
173  const Rock* prock_;
174  const Fluid* pfluid_;
175  const Wells* pwells_;
176  const std::vector<double>* ptrans_;
177  typename Grid::Vector gravity_;
178 
179  struct AllTransportFluidData : public Opm::AllFluidData
180  {
181  std::vector<double> total_mobility;
182  std::vector<PhaseVec> fractional_flow;
183 
184  template <class G, class R>
185  void computeNew(const G& grid,
186  const R& rock,
187  const BlackoilFluid& fluid,
188  const typename Grid::Vector gravity,
189  const std::vector<PhaseVec>& cell_pressure,
190  const std::vector<PhaseVec>& face_pressure,
191  const std::vector<CompVec>& cell_z,
192  const CompVec& bdy_z,
193  const double dt)
194  {
195  Opm::AllFluidData::computeNew(grid, rock, fluid, gravity,
196  cell_pressure, face_pressure,
197  cell_z, bdy_z, dt);
198  int num = grid.numCells();
199  total_mobility.resize(num);
200  fractional_flow.resize(num);
201 #pragma omp parallel for
202  for (int i = 0; i < num; ++i) {
203  total_mobility[i] = 0.0;
204  for (int phase = 0; phase < numPhases; ++phase) {
205  total_mobility[i] += cell_data.mobility[i][phase];
206  }
207  fractional_flow[i] = cell_data.mobility[i];
208  fractional_flow[i] *= (1.0/total_mobility[i]);
209  }
210  }
211  };
212  AllTransportFluidData fluid_data_;
213  struct TransportFluidData
214  {
215  PhaseVec saturation;
216  PhaseVec mobility;
217  PhaseVec fractional_flow;
218  PhaseToCompMatrix phase_to_comp;
219  PhaseVec relperm;
220  PhaseVec viscosity;
221  };
222  TransportFluidData bdy_;
223  std::vector<int> perf_cells_;
224  std::vector<double> perf_flow_;
225  std::vector<TransportFluidData> perf_props_;
226  double min_surfvol_threshold_;
227  bool single_step_only_;
228  double min_vtime_;
229 
230 private: // Methods
231 
232  TransportFluidData computeProps(const PhaseVec& pressure,
233  const CompVec& composition)
234  {
235  BlackoilFluid::FluidState state = pfluid_->computeState(pressure, composition);
236  TransportFluidData data;
237  data.saturation = state.saturation_;
238  data.mobility = state.mobility_;
239  double total_mobility = 0.0;
240  for (int phase = 0; phase < numPhases; ++phase) {
241  total_mobility += state.mobility_[phase];
242  }
243  data.fractional_flow = state.mobility_;
244  data.fractional_flow /= total_mobility;
245  data.phase_to_comp = state.phase_to_comp_;
246  data.relperm = state.relperm_;
247  data.viscosity = state.viscosity_;
248  return data;
249  }
250 
251  void updateFluidProperties(const std::vector<PhaseVec>& cell_pressure,
252  const std::vector<PhaseVec>& face_pressure,
253  const std::vector<CompVec>& cell_z,
254  const PhaseVec& external_pressure,
255  const CompVec& external_composition)
256  {
257  // Properties in reservoir.
258  const double dummy_dt = 1.0;
259  fluid_data_.computeNew(*pgrid_, *prock_, *pfluid_, gravity_,
260  cell_pressure, face_pressure, cell_z, external_composition, dummy_dt);
261 
262  // Properties on boundary. \TODO no need to ever recompute this.
263  bdy_ = computeProps(external_pressure, external_composition);
264 
265  // Properties at well perforations.
266  // \TODO only need to recompute this once per pressure update.
267  // No, that is false, at production perforations the cell z is
268  // used, which may change every step.
269  perf_cells_.clear();
270  perf_flow_.clear();
271  perf_props_.clear();
272  Wells::WellReport::report()->clearAll();
273  int num_cells = pgrid_->numCells();
274  for (int cell = 0; cell < num_cells; ++cell) {
275  double flow = pwells_->wellToReservoirFlux(cell);
276  if (flow != 0.0) {
277  perf_cells_.push_back(cell);
278  perf_flow_.push_back(flow);
279  // \TODO handle capillary in perforation pressure below?
280  PhaseVec well_pressure = flow > 0.0 ? PhaseVec(pwells_->perforationPressure(cell)) : cell_pressure[cell];
281  CompVec well_mixture = flow > 0.0 ? pwells_->injectionMixture(cell) : cell_z[cell];
282  perf_props_.push_back(computeProps(well_pressure, well_mixture));
283  Wells::WellReport::report()->perfPressure.push_back(pwells_->perforationPressure(cell));
284  Wells::WellReport::report()->cellPressure.push_back(cell_pressure[cell][0]);
285  Wells::WellReport::report()->cellId.push_back(cell);
286  }
287  }
288  }
289 
290 
291 
292 
293  void cellData(int cell, TransportFluidData& tfd) const
294  {
295  tfd.saturation = fluid_data_.cell_data.saturation[cell];
296  tfd.mobility = fluid_data_.cell_data.mobility[cell];
297  tfd.fractional_flow = fluid_data_.fractional_flow[cell];
298  tfd.phase_to_comp = fluid_data_.cell_data.state_matrix[cell];
299  tfd.relperm = fluid_data_.cell_data.relperm[cell];
300  tfd.viscosity = fluid_data_.cell_data.viscosity[cell];
301  }
302 
303 
304 
305 
306  bool volumeDiscrepancyAcceptable(const double voldisclimit) const
307  {
308  double rel_voldiscr = *std::max_element(fluid_data_.relvoldiscr.begin(), fluid_data_.relvoldiscr.end());
309  if (rel_voldiscr > voldisclimit) {
310  std::cout << " Relative volume discrepancy too large: " << rel_voldiscr << std::endl;
311  return false;
312  } else {
313  return true;
314  }
315  }
316 
317 
318 
319  void computeChange(const std::vector<double>& face_flux,
320  std::vector<CompVec>& comp_change,
321  std::vector<double>& cell_outflux,
322  std::vector<double>& cell_max_ff_deriv)
323  {
324  const int num_cells = pgrid_->numCells();
325  comp_change.clear();
326  CompVec zero(0.0);
327  comp_change.resize(num_cells, zero);
328  cell_outflux.clear();
329  cell_outflux.resize(num_cells, 0.0);
330  cell_max_ff_deriv.clear();
331  cell_max_ff_deriv.resize(num_cells, 0.0);
332  CompVec surf_dens = pfluid_->surfaceDensities();
333  const int num_faces = pgrid_->numFaces();
334  std::vector<CompVec> face_change(num_faces);
335  std::vector<double> faces_max_ff_deriv(num_faces);
336 #pragma omp parallel for
337  for (int face = 0; face < num_faces; ++face) {
338  // Compute phase densities on face.
339  PhaseVec phase_dens(0.0);
340  for (int phase = 0; phase < numPhases; ++phase) {
341  const double* At = &fluid_data_.face_data.state_matrix[face][0][0]; // Already transposed since in Fortran order...
342  for (int comp = 0; comp < numPhases; ++comp) {
343  phase_dens[phase] += At[numPhases*phase + comp]*surf_dens[comp];
344  }
345  }
346  // Collect data from adjacent cells (or boundary).
347  int c[2];
348  TransportFluidData d[2];
349  for (int ix = 0; ix < 2; ++ix) {
350  c[ix] = pgrid_->faceCell(face, ix);
351  if (c[ix] >= 0) {
352  cellData(c[ix], d[ix]);
353  } else {
354  d[ix] = bdy_;
355  }
356  }
357  // Compute upwind directions.
358  int upwind_dir[numPhases] = { 0, 0, 0 };
359  PhaseVec vstar(face_flux[face]);
360  // double gravity_flux = gravity_*pgrid_->faceNormal(face)*pgrid_->faceArea(face);
361 
362  typename Grid::Vector centroid_diff = c[0] >= 0 ? pgrid_->cellCentroid(c[0]) : pgrid_->faceCentroid(face);
363  centroid_diff -= c[1] >= 0 ? pgrid_->cellCentroid(c[1]) : pgrid_->faceCentroid(face);
364  double gravity_flux = gravity_*centroid_diff*ptrans_->operator[](face);
365  PhaseVec rho_star(phase_dens);
366  process_face(&(d[0].mobility[0]), &(d[1].mobility[0]),
367  &vstar[0], gravity_flux, numPhases, &rho_star[0], upwind_dir);
368 
369  // Compute phase fluxes.
370  PhaseVec phase_mob;
371  double tot_mob = 0.0;
372  for (int phase = 0; phase < numPhases; ++phase) {
373  phase_mob[phase] = d[upwind_dir[phase] - 1].mobility[phase];
374  tot_mob += phase_mob[phase];
375  }
376  PhaseVec ff = phase_mob;
377  ff /= tot_mob;
378  PhaseVec phase_flux = ff;
379  phase_flux *= face_flux[face];
380  // Until we have proper bcs for transport, assume no gravity flow across bdys.
381  if (gravity_flux != 0.0 && c[0] >= 0 && c[1] >= 0) {
382  // Gravity contribution.
383  double omega = ff*phase_dens;
384  for (int phase = 0; phase < numPhases; ++phase) {
385  double gf = (phase_dens[phase] - omega)*gravity_flux;
386  phase_flux[phase] -= phase_mob[phase]*gf;
387  }
388  }
389 
390  // Estimate max derivative of ff.
391  double face_max_ff_deriv = 0.0;
392  // Only using total flux upwinding for this purpose.
393  // Aim is to reproduce old results first. \TODO fix, include gravity.
394  int downwind_cell = c[upwind_dir[0]%2]; // Keep in mind that upwind_dir[] \in {1, 2}
395  if (downwind_cell >= 0) { // Only contribution on inflow and internal faces.
396  // Evaluating all functions at upwind viscosity.
397  // Added for this version.
398  PhaseVec upwind_viscosity = d[upwind_dir[0] - 1].viscosity;
399  PhaseVec upwind_sat = d[upwind_dir[0] - 1].saturation;
400  PhaseVec upwind_relperm = d[upwind_dir[0] - 1].relperm;
401  PhaseVec downwind_mob(0.0);
402  PhaseVec upwind_mob(0.0);
403  double downwind_totmob = 0.0;
404  double upwind_totmob = 0.0;
405  for (int phase = 0; phase < numPhases; ++phase) {
406  downwind_mob[phase] = fluid_data_.cell_data.relperm[downwind_cell][phase]/upwind_viscosity[phase];
407  downwind_totmob += downwind_mob[phase];
408  upwind_mob[phase] = upwind_relperm[phase]/upwind_viscosity[phase];
409  upwind_totmob += upwind_mob[phase];
410  }
411  PhaseVec downwind_ff = downwind_mob;
412  downwind_ff /= downwind_totmob;
413  PhaseVec upwind_ff = upwind_mob;
414  upwind_ff /= upwind_totmob;
415  PhaseVec ff_diff = upwind_ff;
416  ff_diff -= downwind_ff;
417  for (int phase = 0; phase < numPhases; ++phase) {
418  if (std::fabs(ff_diff[phase]) > 1e-10) {
419  if (face_flux[face] != 0.0) {
420  double ff_deriv = ff_diff[phase]/(upwind_sat[phase] - fluid_data_.cell_data.saturation[downwind_cell][phase]);
421  // assert(ff_deriv >= 0.0);
422  face_max_ff_deriv = std::max(face_max_ff_deriv, std::fabs(ff_deriv));
423  }
424  }
425  }
426  }
427  faces_max_ff_deriv[face] = face_max_ff_deriv;
428 
429  // Compute z change.
430  CompVec change(0.0);
431  for (int phase = 0; phase < numPhases; ++phase) {
432  int upwind_ix = upwind_dir[phase] - 1; // Since process_face returns 1 or 2.
433  CompVec z_in_phase = d[upwind_ix].phase_to_comp[phase];
434  z_in_phase *= phase_flux[phase];
435  change += z_in_phase;
436  }
437  face_change[face] = change;
438  }
439 
440  // Update output variables
441 #pragma omp parallel for
442  for (int cell = 0; cell < num_cells; ++cell) {
443  const int num_local_faces = pgrid_->numCellFaces(cell);
444  for (int local = 0; local < num_local_faces; ++local) {
445  int face = pgrid_->cellFace(cell,local);
446  if (cell == pgrid_->faceCell(face, 0)) {
447  comp_change[cell] -= face_change[face];
448  if (face_flux[face] >= 0.0) {
449  cell_outflux[cell] += std::fabs(face_flux[face]);
450  }
451  } else if (cell == pgrid_->faceCell(face, 1)) {
452  comp_change[cell] += face_change[face];
453  if (face_flux[face] < 0.0) {
454  cell_outflux[cell] += std::fabs(face_flux[face]);
455  }
456  }
457  cell_max_ff_deriv[cell] = std::max(cell_max_ff_deriv[cell],
458  faces_max_ff_deriv[face]);
459  }
460  }
461 
462  // Done with all faces, now deal with well perforations.
463  int num_perf = perf_cells_.size();
464  for (int perf = 0; perf < num_perf; ++perf) {
465  int cell = perf_cells_[perf];
466  double flow = perf_flow_[perf];
467  assert(flow != 0.0);
468  const TransportFluidData& fl = perf_props_[perf];
469  // For injection, phase volumes depend on fractional
470  // flow of injection perforation, for production we
471  // use the fractional flow of the producing cell.
472  PhaseVec phase_flux = flow > 0.0 ? fl.fractional_flow : fluid_data_.fractional_flow[cell];
473  phase_flux *= flow;
474  // Conversion to mass flux is given at perforation state
475  // if injector, cell state if producer (this is ensured by
476  // updateFluidProperties()).
477  CompVec change(0.0);
478  for (int phase = 0; phase < numPhases; ++phase) {
479  CompVec z_in_phase = fl.phase_to_comp[phase];
480  z_in_phase *= phase_flux[phase];
481  change += z_in_phase;
482  }
483  comp_change[cell] += change;
484  Wells::WellReport::report()->massRate.push_back(change);
485  }
486  }
487 
488 
489  // Arguments are:
490  // [in] cmob1, cmob2: cell mobilities for adjacent cells
491  // [in, destroyed] vstar: total velocity (equal for all phases) on input, modified on output
492  // [in] gf: gravity flux
493  // [in] np: number of phases
494  // [in, destroyed] rho: density on face
495  // [out] ix: upwind cells for each phase (1 or 2)
496  static void
497  process_face(double *cmob1, double *cmob2, double *vstar, double gf,
498  int np, double *rho, int *ix)
499  {
500  int i,j,k,a,b,c;
501  double v, r, m;
502  for (i=0; i<np; ++i) {
503 
504  /* ============= */
505  /* same sign */
506 
507  /* r = max(rho)*/
508  j = 0; r = DBL_MIN;
509  for(k=0; k<np; ++k) { if (rho[k] > r) { r = rho[k]; j = k; } }
510  a = !(vstar[j]<0) && !(gf<0);
511  b = !(vstar[j]>0) && !(gf>0);
512  c = a || b;
513 
514  if ( !c ) {
515  rho[j] = NAN;
516  v = vstar[j] - gf;
517  if (v < 0) { ix[j] = 2; m = cmob2[j]; }
518  else { ix[j] = 1; m = cmob1[j]; }
519  for (k=0; k<np; ++k) { vstar[k] -= m *(rho[k]-r)*gf;}
520  continue;
521  }
522 
523 
524  /* ============= */
525  /* opposite sign */
526 
527  /* r = min(rho)*/
528  j = 0; r = DBL_MAX;
529  for(k=0; k<np; ++k) { if (rho[k] < r) { r = rho[k]; j = k; } }
530 
531  if ( c ) {
532  rho[j] = NAN;
533  v = vstar[j] + gf;
534  if (v < 0) { ix[j] = 2; m = cmob2[j]; }
535  else { ix[j] = 1; m = cmob1[j]; }
536  for (k=0; k<np; ++k) { vstar[k] -= m *(rho[k]-r)*gf;}
537  continue;
538  }
539  }
540  }
541 
542 
543 
544 
545  static void
546  phase_upwind_directions(int number_of_faces, int *face_cells, double *dflux, double *gflux, int np,
547  double *cmobility, double *fdensity, int *ix)
548  {
549  int k,f;
550  int c1, c2;
551  double *cmob1, *cmob2;
552  double *fden = (double*)malloc(np * sizeof *fden);
553  double *vstar = (double*)malloc(np * sizeof *vstar);
554  double gf;
555 
556  for (f=0; f<number_of_faces; ++f) {
557  gf = gflux[f];
558 
559  for (k=0; k<np; ++k) {
560  vstar[k] = dflux[f];
561  fden [k] = fdensity[np*f+k];
562  }
563  c1 = face_cells[2*f + 0];
564  c2 = face_cells[2*f + 1];
565  if (c1 != -1) {cmob1 = cmobility+np*c1;}
566  else {cmob1 = cmobility+np*c2;}
567  if (c2 != -1) {cmob2 = cmobility+np*c2;}
568  else {cmob2 = cmobility+np*c1;}
569  process_face(cmob1, cmob2, vstar, gf, np, fden, ix+np*f);
570 
571  }
572  free(fden);
573  free(vstar);
574  }
575 
576 };
577 
578 
579 } // namespace Opm
580 
581 
582 #endif // OPM_COMPONENTTRANSPORT_HEADER_INCLUDED
std::vector< PhaseVec > mobility
Definition: FluidStateBlackoil.hpp:84
Definition: BlackoilFluid.hpp:31
ExplicitCompositionalTransport()
Default constructor. Does nothing.
Definition: ComponentTransport.hpp:48
Dune::FieldVector< Scalar, numComponents > CompVec
Definition: BlackoilDefs.hpp:40
double wellToReservoirFlux(int cell) const
Definition: Wells.hpp:136
void init(const Opm::parameter::ParameterGroup &param)
Definition: ComponentTransport.hpp:56
Definition: BlackoilDefs.hpp:33
Definition: BlackoilDefs.hpp:34
Dune::FieldVector< Scalar, numPhases > PhaseVec
Definition: BlackoilDefs.hpp:41
double perforationPressure(int cell) const
Definition: Wells.hpp:130
Definition: BlackoilFluid.hpp:41
Definition: BlackoilFluid.hpp:405
double transport(const PhaseVec &external_pressure, const CompVec &external_composition, const std::vector< double > &face_flux, const std::vector< PhaseVec > &cell_pressure, const std::vector< PhaseVec > &face_pressure, const double dt, const double voldisclimit, std::vector< CompVec > &cell_z)
Definition: ComponentTransport.hpp:81
double porosity(int cell_index) const
Read-access to porosity.
Definition: Rock_impl.hpp:76
void setup(const Grid &grid, const Rock &rock, const Fluid &fluid, const Wells &wells, const std::vector< double > &face_trans, const typename Grid::Vector &gravity)
Definition: ComponentTransport.hpp:63
Definition: BlackoilDefs.hpp:30
A property class for porous media rock.
Definition: ImplicitTransportDefs.hpp:80
Dune::FieldVector< double, 3 > injectionMixture(int cell) const
Definition: Wells.hpp:141
Definition: Wells.hpp:37
void computeNew(const Grid &grid, const Rock &rock, const BlackoilFluid &fluid, const typename Grid::Vector gravity, const std::vector< PhaseVec > &cell_pressure, const std::vector< PhaseVec > &face_pressure, const std::vector< CompVec > &cell_z, const CompVec &bdy_z, const double dt)
Definition: BlackoilFluid.hpp:417
Definition: ComponentTransport.hpp:43
void zero(Matrix &A)
Zero-fill a.
Definition: Matrix.hpp:603
FluidStateBlackoil FluidState
Definition: BlackoilFluid.hpp:44