SteadyStateUpscalerImplicit_impl.hpp
Go to the documentation of this file.
1//===========================================================================
2//
3// File: SteadyStateUpscaler_impl.hpp
4//
5// Created: Fri Aug 28 14:07:51 2009
6//
7// Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
8// Brd Skaflestad <bard.skaflestad@sintef.no>
9//
10// $Date$
11//
12// $Revision$
13//
14//===========================================================================
15
16/*
17 Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
18 Copyright 2009, 2010 Statoil ASA.
19
20 This file is part of The Open Reservoir Simulator Project (OpenRS).
21
22 OpenRS is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26
27 OpenRS is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
34*/
35
36#ifndef OPM_STEADYSTATEUPSCALERIMPLICIT_IMPL_HEADER
37#define OPM_STEADYSTATEUPSCALERIMPLICIT_IMPL_HEADER
38#include <boost/date_time/posix_time/posix_time.hpp>
39
44#include <opm/input/eclipse/Units/Units.hpp>
45
47#include <algorithm>
48#include <iostream>
49
50namespace Opm
51{
52
53
54
55 template <class Traits>
57 : Super(),
58 use_gravity_(false),
59 output_vtk_(false),
60 output_ecl_(false),
61 print_inoutflows_(false),
62 simulation_steps_(10),
63 init_stepsize_(10),
64 relperm_threshold_(1.0e-8),
65 maximum_mobility_contrast_(1.0e9),
66 sat_change_year_(1.0e-5),
67 max_it_(100),
68 max_stepsize_(1e4),
69 dt_sat_tol_(1e-2),
70 use_maxdiff_(true)
71 {
72 }
73
74
75
76
77 template <class Traits>
78 inline void SteadyStateUpscalerImplicit<Traits>::initImpl(const Opm::ParameterGroup& param)
79 {
80 Super::initImpl(param);
81 use_gravity_ = param.getDefault("use_gravity", use_gravity_);
82 output_vtk_ = param.getDefault("output_vtk", output_vtk_);
83 output_ecl_ = param.getDefault("output_ecl", output_ecl_);
84 if (output_ecl_) {
85 grid_adapter_.init(Super::grid());
86 }
87 print_inoutflows_ = param.getDefault("print_inoutflows", print_inoutflows_);
88 simulation_steps_ = param.getDefault("simulation_steps", simulation_steps_);
89 init_stepsize_ = Opm::unit::convert::from(param.getDefault("init_stepsize", init_stepsize_),
90 Opm::unit::day);
91 relperm_threshold_ = param.getDefault("relperm_threshold", relperm_threshold_);
92 maximum_mobility_contrast_ = param.getDefault("maximum_mobility_contrast", maximum_mobility_contrast_);
93 sat_change_year_ = param.getDefault("sat_change_year", sat_change_year_);
94 dt_sat_tol_ = param.getDefault("dt_sat_tol", dt_sat_tol_);
95 max_it_ = param.getDefault("max_it", max_it_);
96 max_stepsize_ = Opm::unit::convert::from(param.getDefault("max_stepsize", max_stepsize_),Opm::unit::year);
97 use_maxdiff_ = param.getDefault("use_maxdiff", use_maxdiff_);
98 transport_solver_.init(param);
99 // Set viscosities and densities if given.
100 double v1_default = this->res_prop_.viscosityFirstPhase();
101 double v2_default = this->res_prop_.viscositySecondPhase();
102 this->res_prop_.setViscosities(param.getDefault("viscosity1", v1_default), param.getDefault("viscosity2", v2_default));
103 double d1_default = this->res_prop_.densityFirstPhase();
104 double d2_default = this->res_prop_.densitySecondPhase();
105 this->res_prop_.setDensities(param.getDefault("density1", d1_default), param.getDefault("density2", d2_default));
106 }
107
108
109
110
111 namespace {
112 double maxMobility(double m1, double m2)
113 {
114 return std::max(m1, m2);
115 }
116 // The matrix variant expects diagonal mobilities.
117 template <class SomeMatrixType>
118 double maxMobility(double m1, SomeMatrixType& m2)
119 {
120 double m = m1;
121 for (int i = 0; i < std::min(m2.numRows(), m2.numCols()); ++i) {
122 m = std::max(m, m2(i,i));
123 }
124 return m;
125 }
126 void thresholdMobility(double& m, double threshold)
127 {
128 m = std::max(m, threshold);
129 }
130 // The matrix variant expects diagonal mobilities.
131 template <class SomeMatrixType>
132 void thresholdMobility(SomeMatrixType& m, double threshold)
133 {
134 for (int i = 0; i < std::min(m.numRows(), m.numCols()); ++i) {
135 m(i, i) = std::max(m(i, i), threshold);
136 }
137 }
138
139 // Workaround: duplicate of Opm::destripe in opm-simulators.
140 inline std::vector< double > destripe( const std::vector< double >& v,
141 size_t stride,
142 size_t offset )
143 {
144 std::vector< double > dst( v.size() / stride );
145 size_t di = 0;
146 for( size_t i = offset; i < v.size(); i += stride ) {
147 dst[ di++ ] = v[ i ];
148 }
149 return dst;
150 }
151
154 void waterSatToBothSat(const std::vector<double>& sw,
155 std::vector<double>& sboth)
156 {
157 int num = sw.size();
158 sboth.resize(2*num);
159 for (int i = 0; i < num; ++i) {
160 sboth[2*i] = sw[i];
161 sboth[2*i + 1] = 1.0 - sw[i];
162 }
163 }
164
165
166 } // anon namespace
167
168
169
170
171 template <class Traits>
172 inline std::pair<typename SteadyStateUpscalerImplicit<Traits>::permtensor_t,
175 upscaleSteadyState(const int flow_direction,
176 const std::vector<double>& initial_saturation,
177 const double boundary_saturation,
178 const double pressure_drop,
179 const permtensor_t& upscaled_perm,
180 bool& success)
181 {
182 static int count = 0;
183 ++count;
184 int num_cells = this->ginterf_.numberOfCells();
185 // No source or sink.
186 std::vector<double> src(num_cells, 0.0);
187 Opm::SparseVector<double> injection(num_cells);
188 // Gravity.
189 Dune::FieldVector<double, 3> gravity(0.0);
190 if (use_gravity_) {
191 gravity[2] = Opm::unit::gravity;
192 }
193
194 if (gravity.two_norm() > 0.0) {
195 OPM_MESSAGE("Warning: Gravity is experimental for flow solver.");
196 }
197
198 // Put pore volume in vector.
199 std::vector<double> pore_vol;
200 pore_vol.reserve(num_cells);
201 double tot_pore_vol = 0.0;
202 typedef typename GridInterface::CellIterator CellIterT;
203 for (CellIterT c = this->ginterf_.cellbegin(); c != this->ginterf_.cellend(); ++c) {
204 double cell_pore_vol = c->volume()*this->res_prop_.porosity(c->index());
205 pore_vol.push_back(cell_pore_vol);
206 tot_pore_vol += cell_pore_vol;
207 }
208
209 // Set up initial saturation profile.
210 std::vector<double> saturation = initial_saturation;
211
212 // Set up boundary conditions.
213 setupUpscalingConditions(this->ginterf_, this->bctype_, flow_direction,
214 pressure_drop, boundary_saturation, this->twodim_hack_, this->bcond_);
215
216 // Set up solvers.
217 if (flow_direction == 0) {
218 this->flow_solver_.init(this->ginterf_, this->res_prop_, gravity, this->bcond_);
219 }
220 transport_solver_.initObj(this->ginterf_, this->res_prop_, this->bcond_);
221
222 // Run pressure solver.
223 this->flow_solver_.solve(this->res_prop_, saturation, this->bcond_, src,
224 this->residual_tolerance_, this->linsolver_verbosity_, this->linsolver_type_);
225 double max_mod = this->flow_solver_.postProcessFluxes();
226 std::cout << "Max mod = " << max_mod << std::endl;
227
228 // Do a run till steady state.
229 std::vector<double> saturation_old = saturation;
230 bool stationary = false;
231 int it_count = 0;
232 double stepsize = init_stepsize_;
233 double ecl_time = 0.0;
234 std::vector<double> ecl_sat;
235 std::vector<double> ecl_press;
236 while ((!stationary) && (it_count < max_it_)) { // && transport_cost < max_transport_cost_)
237 // Run transport solver.
238 std::cout << "Running transport step " << it_count << " with stepsize "
239 << stepsize/Opm::unit::year << " years." << std::endl;
240 bool converged = transport_solver_.transportSolve(saturation, stepsize, gravity,
241 this->flow_solver_.getSolution(), injection);
242 // Run pressure solver.
243 if (converged) {
244 // this->flow_solver_.solve(this->res_prop_, saturation, this->bcond_, src,
245 // this->residual_tolerance_, this->linsolver_verbosity_, this->linsolver_type_);
246 // max_mod = this->flow_solver_.postProcessFluxes();
247 // std::cout << "Max mod of fluxes= " << max_mod << std::endl;
248 this->flow_solver_.postProcessFluxes();
249 // Print in-out flows if requested.
250 if (print_inoutflows_) {
251 std::pair<double, double> w_io, o_io;
252 computeInOutFlows(w_io, o_io, this->flow_solver_.getSolution(), saturation);
253 std::cout << "Pressure step " << it_count
254 << "\nWater flow [in] " << w_io.first
255 << " [out] " << w_io.second
256 << "\nOil flow [in] " << o_io.first
257 << " [out] " << o_io.second
258 << std::endl;
259 }
260 // Output.
261 if (output_vtk_) {
262 writeVtkOutput(this->ginterf_,
263 this->res_prop_,
264 this->flow_solver_.getSolution(),
265 saturation,
266 std::string("output-steadystate")
267 + '-' + std::to_string(count)
268 + '-' + std::to_string(flow_direction)
269 + '-' + std::to_string(it_count));
270 }
271 if (output_ecl_) {
272 const char* fd = "xyz";
273 std::string basename = std::string("ecldump-steadystate")
274 + '-' + std::to_string(boundary_saturation)
275 + '-' + std::to_string(fd[flow_direction])
276 + '-' + std::to_string(pressure_drop);
277 waterSatToBothSat(saturation, ecl_sat);
278 getCellPressure(ecl_press, this->ginterf_, this->flow_solver_.getSolution());
279 data::Solution solution;
280 solution.insert( "PRESSURE" , UnitSystem::measure::pressure , ecl_press , data::TargetType::RESTART_SOLUTION );
281 solution.insert( "SWAT" , UnitSystem::measure::identity , destripe( ecl_sat, 2, 0) , data::TargetType::RESTART_SOLUTION );
282 ecl_time += stepsize;
283 boost::posix_time::ptime ecl_startdate( boost::gregorian::date(2012, 1, 1) );
284 boost::posix_time::ptime ecl_curdate = ecl_startdate + boost::posix_time::seconds(int(ecl_time));
285 boost::posix_time::ptime epoch( boost::gregorian::date( 1970, 1, 1 ) );
286 auto ecl_posix_time = ( ecl_curdate - epoch ).total_seconds();
287 const auto* cgrid = grid_adapter_.c_grid();
288 Opm::writeECLData(cgrid->cartdims[ 0 ],
289 cgrid->cartdims[ 1 ],
290 cgrid->cartdims[ 2 ],
291 cgrid->number_of_cells,
292 solution, it_count,
293 ecl_time, ecl_posix_time,
294 "./", basename);
295 }
296 // Comparing old to new.
297 double maxdiff = 0.0;
298 double euclidean_diff = 0.0;
299 for (int i = 0; i < num_cells; ++i) {
300 const double sat_diff_cell = saturation[i] - saturation_old[i];
301 maxdiff = std::max(maxdiff, std::fabs(sat_diff_cell));
302 euclidean_diff += sat_diff_cell * sat_diff_cell * pore_vol[i];
303 }
304 euclidean_diff = std::sqrt(euclidean_diff / tot_pore_vol);
305 double ds_year;
306 if (use_maxdiff_) {
307 ds_year = maxdiff*Opm::unit::year/stepsize;
308 std::cout << "Maximum saturation change/year: " << ds_year << std::endl;
309 if (maxdiff < dt_sat_tol_) {
310 stepsize=std::min(max_stepsize_,2*stepsize);
311 }
312 }
313 else {
314 ds_year = euclidean_diff*Opm::unit::year/stepsize;
315 std::cout << "Euclidean saturation change/year: " << ds_year << std::endl;
316 if (euclidean_diff < dt_sat_tol_) {
317 stepsize=std::min(max_stepsize_,2*stepsize);
318 }
319 }
320 if (ds_year < sat_change_year_) {
321 stationary = true;
322 }
323 } else {
324 std::cerr << "Cutting time step\n";
325 stepsize=stepsize/2.0;
326 }
327 ++it_count;
328 // Copy to old.
329 saturation_old = saturation;
330 }
331 success = stationary;
332
333 // Compute phase mobilities.
334 // First: compute maximal mobilities.
335 typedef typename Super::ResProp::Mobility Mob;
336 Mob m;
337 double m1max = 0;
338 double m2max = 0;
339 for (int c = 0; c < num_cells; ++c) {
340 this->res_prop_.phaseMobility(0, c, saturation[c], m.mob);
341 m1max = maxMobility(m1max, m.mob);
342 this->res_prop_.phaseMobility(1, c, saturation[c], m.mob);
343 m2max = maxMobility(m2max, m.mob);
344 }
345 // Second: set thresholds.
346 const double mob1_abs_thres = relperm_threshold_ / this->res_prop_.viscosityFirstPhase();
347 const double mob1_rel_thres = m1max / maximum_mobility_contrast_;
348 const double mob1_threshold = std::max(mob1_abs_thres, mob1_rel_thres);
349 const double mob2_abs_thres = relperm_threshold_ / this->res_prop_.viscositySecondPhase();
350 const double mob2_rel_thres = m2max / maximum_mobility_contrast_;
351 const double mob2_threshold = std::max(mob2_abs_thres, mob2_rel_thres);
352 // Third: extract and threshold.
353 std::vector<Mob> mob1(num_cells);
354 std::vector<Mob> mob2(num_cells);
355 for (int c = 0; c < num_cells; ++c) {
356 this->res_prop_.phaseMobility(0, c, saturation[c], mob1[c].mob);
357 thresholdMobility(mob1[c].mob, mob1_threshold);
358 this->res_prop_.phaseMobility(1, c, saturation[c], mob2[c].mob);
359 thresholdMobility(mob2[c].mob, mob2_threshold);
360 }
361
362 // Compute upscaled relperm for each phase.
363 ReservoirPropertyFixedMobility<Mob> fluid_first(mob1);
364 permtensor_t eff_Kw = Super::upscaleEffectivePerm(fluid_first);
365 ReservoirPropertyFixedMobility<Mob> fluid_second(mob2);
366 permtensor_t eff_Ko = Super::upscaleEffectivePerm(fluid_second);
367
368 // Set the steady state saturation fields for eventual outside access.
369 last_saturation_state_.swap(saturation);
370
371 // Compute the (anisotropic) upscaled mobilities.
372 // eff_Kw := lambda_w*K
373 // => lambda_w = eff_Kw*inv(K);
374 permtensor_t lambda_w(matprod(eff_Kw, inverse3x3(upscaled_perm)));
375 permtensor_t lambda_o(matprod(eff_Ko, inverse3x3(upscaled_perm)));
376
377 // Compute (anisotropic) upscaled relative permeabilities.
378 // lambda = k_r/mu
379 permtensor_t k_rw(lambda_w);
380 k_rw *= this->res_prop_.viscosityFirstPhase();
381 permtensor_t k_ro(lambda_o);
382 k_ro *= this->res_prop_.viscositySecondPhase();
383 return std::make_pair(k_rw, k_ro);
384 }
385
386
387
388
389 template <class Traits>
390 inline const std::vector<double>&
392 {
393 return last_saturation_state_;
394 }
395
396
397
398
399 template <class Traits>
401 {
402 typedef typename GridInterface::CellIterator CellIterT;
403 double pore_vol = 0.0;
404 double sat_vol = 0.0;
405 for (CellIterT c = this->ginterf_.cellbegin(); c != this->ginterf_.cellend(); ++c) {
406 double cell_pore_vol = c->volume()*this->res_prop_.porosity(c->index());
407 pore_vol += cell_pore_vol;
408 sat_vol += cell_pore_vol*last_saturation_state_[c->index()];
409 }
410 // Dividing by pore volume gives average saturations.
411 return sat_vol/pore_vol;
412 }
413
414
415 template <class Traits>
416 void SteadyStateUpscalerImplicit<Traits>::initSatLimits(std::vector<double>& s) const
417 {
418 for (int c = 0; c < int (s.size()); c++ ) {
419 double s_min = this->res_prop_.s_min(c);
420 double s_max = this->res_prop_.s_max(c);
421 s[c] = std::max(s_min+1e-4, s[c]);
422 s[c] = std::min(s_max-1e-4, s[c]);
423 }
424 }
425
426 template <class Traits>
427 void SteadyStateUpscalerImplicit<Traits>::setToCapillaryLimit(double average_s, std::vector<double>& s) const
428 {
429 int num_cells = this->ginterf_.numberOfCells();
430 std::vector<double> s_orig(num_cells, average_s);
431
432 initSatLimits(s_orig);
433 std::vector<double> cap_press(num_cells, 0.0);
434 typedef typename UpscalerBase<Traits>::ResProp ResPropT;
435 MatchSaturatedVolumeFunctor<GridInterface, ResPropT> func(this->ginterf_, this->res_prop_, s_orig, cap_press);
436 double cap_press_range = 1e2;
437 double mod_low = 1e100;
438 double mod_high = -1e100;
439 Opm::bracketZero(func, 0.0, cap_press_range, mod_low, mod_high);
440 const int max_iter = 40;
441 const double nonlinear_tolerance = 1e-12;
442 int iterations_used = -1;
443 typedef Opm::RegulaFalsi<Opm::ThrowOnError> RootFinder;
444 double mod_correct = RootFinder::solve(func, mod_low, mod_high, max_iter, nonlinear_tolerance, iterations_used);
445 std::cout << "Moved capillary pressure solution by " << mod_correct << " after "
446 << iterations_used << " iterations." << std::endl;
447 s = func.lastSaturations();
448 }
449
450
451 template <class Traits>
452 template <class FlowSol>
453 void SteadyStateUpscalerImplicit<Traits>::computeInOutFlows(std::pair<double, double>& water_inout,
454 std::pair<double, double>& oil_inout,
455 const FlowSol& flow_solution,
456 const std::vector<double>& saturations) const
457 {
458 typedef typename GridInterface::CellIterator CellIterT;
459 typedef typename CellIterT::FaceIterator FaceIterT;
460
461 double side1_flux = 0.0;
462 double side2_flux = 0.0;
463 double side1_flux_oil = 0.0;
464 double side2_flux_oil = 0.0;
465 std::map<int, double> frac_flow_by_bid;
466
467 // Two passes: First pass, deal with outflow, second pass, deal with inflow.
468 // This is for the periodic case, so that we are sure all fractional flows have
469 // been set in frac_flow_by_bid.
470 for (int pass = 0; pass < 2; ++pass) {
471 for (CellIterT c = this->ginterf_.cellbegin(); c != this->ginterf_.cellend(); ++c) {
472 for (FaceIterT f = c->facebegin(); f != c->faceend(); ++f) {
473 if (f->boundary()) {
474 double flux = flow_solution.outflux(f);
475 const SatBC& sc = this->bcond_.satCond(f);
476 if (flux < 0.0 && pass == 1) {
477 // This is an inflow face.
478 double frac_flow = 0.0;
479 if (sc.isPeriodic()) {
480 assert(sc.saturationDifference() == 0.0);
481 int partner_bid = this->bcond_.getPeriodicPartner(f->boundaryId());
482 std::map<int, double>::const_iterator it = frac_flow_by_bid.find(partner_bid);
483 if (it == frac_flow_by_bid.end()) {
484 OPM_THROW(std::runtime_error,
485 "Could not find periodic partner fractional flow. "
486 "Face bid = " + std::to_string(f->boundaryId()) +
487 " and partner bid = " + std::to_string(partner_bid));
488 }
489 frac_flow = it->second;
490 } else {
491 assert(sc.isDirichlet());
492 frac_flow = this->res_prop_.fractionalFlow(c->index(), sc.saturation());
493 }
494 side1_flux += flux*frac_flow;
495 side1_flux_oil += flux*(1.0 - frac_flow);
496 } else if (flux >= 0.0 && pass == 0) {
497 // This is an outflow face.
498 double frac_flow = this->res_prop_.fractionalFlow(c->index(), saturations[c->index()]);
499 if (sc.isPeriodic()) {
500 frac_flow_by_bid[f->boundaryId()] = frac_flow;
501 // std::cout << "Inserted bid " << f->boundaryId() << std::endl;
502 }
503 side2_flux += flux*frac_flow;
504 side2_flux_oil += flux*(1.0 - frac_flow);
505 }
506 }
507 }
508 }
509 }
510 water_inout = std::make_pair(side1_flux, side2_flux);
511 oil_inout = std::make_pair(side1_flux_oil, side2_flux_oil);
512 }
513
514
515
516
517} // namespace Opm
518
519
520#endif // OPM_STEADYSTATEUPSCALERIMPLICIT_IMPL_HEADER
bool isPeriodic() const
Type query.
Definition: BoundaryConditions.hpp:97
bool isDirichlet() const
Type query.
Definition: BoundaryConditions.hpp:85
Definition: GridInterfaceEuler.hpp:368
Scalar volume() const
Definition: GridInterfaceEuler.hpp:337
Definition: ReservoirPropertyFixedMobility.hpp:46
A class for representing a saturation boundary condition.
Definition: BoundaryConditions.hpp:176
double saturation() const
Query a Dirichlet condition.
Definition: BoundaryConditions.hpp:197
double saturationDifference() const
Query a Periodic condition.
Definition: BoundaryConditions.hpp:204
void initImpl(const Opm::ParameterGroup &param) override
Override from superclass.
Definition: SteadyStateUpscalerImplicit_impl.hpp:78
void computeInOutFlows(std::pair< double, double > &water_inout, std::pair< double, double > &oil_inout, const FlowSol &flow_solution, const std::vector< double > &saturations) const
Definition: SteadyStateUpscalerImplicit_impl.hpp:453
void initSatLimits(std::vector< double > &s) const
Ensure saturations are not outside table.
Definition: SteadyStateUpscalerImplicit_impl.hpp:416
Super::permtensor_t permtensor_t
Definition: SteadyStateUpscalerImplicit.hpp:57
double lastSaturationUpscaled() const
Definition: SteadyStateUpscalerImplicit_impl.hpp:400
std::pair< permtensor_t, permtensor_t > upscaleSteadyState(const int flow_direction, const std::vector< double > &initial_saturation, const double boundary_saturation, const double pressure_drop, const permtensor_t &upscaled_perm, bool &success)
Definition: SteadyStateUpscalerImplicit_impl.hpp:175
void setToCapillaryLimit(double average_s, std::vector< double > &s) const
Definition: SteadyStateUpscalerImplicit_impl.hpp:427
SteadyStateUpscalerImplicit()
Default constructor.
Definition: SteadyStateUpscalerImplicit_impl.hpp:56
const std::vector< double > & lastSaturationState() const
Definition: SteadyStateUpscalerImplicit_impl.hpp:391
A base class for upscaling.
Definition: UpscalerBase.hpp:56
Traits::template ResProp< Dimension >::Type ResProp
Definition: UpscalerBase.hpp:63
min[0]
Definition: elasticity_upscale_impl.hpp:146
void thresholdMobility(double &m, double threshold)
Definition: ImplicitAssembly.hpp:43
M matprod(const M &m1, const M &m2)
Definition: MatrixInverse.hpp:69
M inverse3x3(const M &m)
Definition: MatrixInverse.hpp:86
void writeECLData(int nx, int ny, int nz, int number_of_cells, data::Solution, const int current_step, const double current_time, time_t current_posix_time, const std::string &output_dir, const std::string &base_name)
void writeVtkOutput(const GridInterface &ginterf, const ReservoirProperties &rp, const FlowSol &flowsol, const std::vector< double > &saturation, const std::string &filename)
Definition: SimulatorUtilities.hpp:239
void setupUpscalingConditions(const GridInterface &g, int bct, int pddir, double pdrop, double bdy_sat, bool twodim_hack, BCs &bcs)
Definition: setupBoundaryConditions.hpp:99
void getCellPressure(std::vector< double > &cell_pressure, const GridInterface &ginterf, const FlowSol &flow_solution)
Definition: SimulatorUtilities.hpp:184
Definition: MatchSaturatedVolumeFunctor.hpp:68
const std::vector< double > & lastSaturations() const
Definition: MatchSaturatedVolumeFunctor.hpp:96