From 1a182d4a48153ec40e9966b8250badb23f3662ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 14 Jan 2014 20:37:28 +0100 Subject: [PATCH 001/158] Add basic equilibration facility This commit adds a simple facility for calculating initial phase pressures assuming stationary conditions, a known reference pressure in the oil zone as well as the depth and capillary pressures at the water-oil and gas-oil contacts. Function 'Opm::equil::phasePressures()' uses a simple ODE/IVP-based approach, solved using the traditional RK4 method with constant step sizes, to derive the required pressure values. Specifically, we solve the ODE dp/dz = rho(z,p) * g with 'z' represening depth, 'p' being a phase pressure and 'rho' the associate phase density. Finally, 'g' is the acceleration of gravity. We assume that we can calculate phase densities, e.g., from table look-up. This assumption holds in the case of an ECLIPSE input deck. Using RK4 with constant step sizes is a limitation of this implementation. This, basically, assumes that the phase densities varies only smoothly with depth and pressure (at reservoir conditions). --- opm/core/simulator/initStateEquil.hpp | 173 +++++++ opm/core/simulator/initStateEquil_impl.hpp | 513 +++++++++++++++++++++ tests/test_equil.cpp | 89 ++++ 3 files changed, 775 insertions(+) create mode 100644 opm/core/simulator/initStateEquil.hpp create mode 100644 opm/core/simulator/initStateEquil_impl.hpp create mode 100644 tests/test_equil.cpp diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp new file mode 100644 index 000000000..61f7debc9 --- /dev/null +++ b/opm/core/simulator/initStateEquil.hpp @@ -0,0 +1,173 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_INITSTATEEQUIL_HEADER_INCLUDED +#define OPM_INITSTATEEQUIL_HEADER_INCLUDED + +#include +#include +#include +#include + +#include +#include +#include + +struct UnstructuredGrid; + +namespace Opm +{ + namespace equil { + template + class DensityCalculator; + + template <> + class DensityCalculator< BlackoilPropertiesInterface > { + public: + DensityCalculator(const BlackoilPropertiesInterface& props, + const int c) + : props_(props) + , c_(1, c) + { + } + + std::vector + operator()(const double p, + const std::vector& z) const + { + const int np = props_.numPhases(); + std::vector A(np * np, 0); + + assert (z.size() == std::vector::size_type(np)); + + double* dAdp = 0; + props_.matrix(1, &p, &z[0], &c_[0], &A[0], dAdp); + + std::vector rho(np, 0.0); + props_.density(1, &A[0], &rho[0]); + + return rho; + } + + private: + const BlackoilPropertiesInterface& props_; + const std::vector c_; + }; + + namespace miscibility { + struct NoMixing { + double + operator()(const double /* depth */, + const double /* press */) const + { + return 0.0; + } + }; + + class RsVD { + public: + RsVD(const std::vector& depth, + const std::vector& rs) + : depth_(depth) + , rs_(rs) + { + } + + double + operator()(const double depth, + const double /* press */) const + { + return linearInterpolation(depth_, rs_, depth); + } + + private: + std::vector depth_; + std::vector rs_; + }; + } // namespace miscibility + + struct EquilRecord { + struct { + double depth; + double press; + } main, woc, goc; + }; + + template + class EquilReg { + public: + EquilReg(const EquilRecord& rec, + const DensCalc& density, + const RS& rs, + const RV& rv, + const PhaseUsage& pu) + : rec_ (rec) + , density_(density) + , rs_ (rs) + , rv_ (rv) + , pu_ (pu) + { + } + + typedef DensCalc CalcDensity; + typedef RS CalcDissolution; + typedef RV CalcEvaporation; + + double datum() const { return this->rec_.main.depth; } + double pressure() const { return this->rec_.main.press; } + + double zwoc() const { return this->rec_.woc .depth; } + double pcow_woc() const { return this->rec_.woc .press; } + + double zgoc() const { return this->rec_.goc .depth; } + double pcgo_goc() const { return this->rec_.goc .press; } + + const CalcDensity& + densityCalculator() const { return this->density_; } + + const CalcDissolution& + dissolutionCalculator() const { return this->rs_; } + + const CalcEvaporation& + evaporationCalculator() const { return this->rv_; } + + const PhaseUsage& + phaseUsage() const { return this->pu_; } + + private: + EquilRecord rec_; + DensCalc density_; + RS rs_; + RV rv_; + PhaseUsage pu_; + }; + + template + std::vector< std::vector > + phasePressures(const UnstructuredGrid& G, + const Region& reg, + const double grav = unit::gravity); + } // namespace equil +} // namespace Opm + +#include + +#endif // OPM_INITSTATEEQUIL_HEADER_INCLUDED diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp new file mode 100644 index 000000000..cb19d0205 --- /dev/null +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -0,0 +1,513 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED +#define OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED + +#include +#include + +#include +#include +#include +#include + +namespace Opm +{ + namespace Details { + template + class RK4IVP : public std::binary_function { + public: + RK4IVP(const RHS& f , + const std::array& span, + const double y0 , + const int N ) + : N_(N) + , span_(span) + { + const double h = stepsize(); + const double h2 = h / 2; + const double h6 = h / 6; + + y_.reserve(N + 1); + f_.reserve(N + 1); + + y_.push_back(y0); + f_.push_back(f(span_[0], y0)); + + for (int i = 0; i < N; ++i) { + const double x = span_[0] + i*h; + const double y = y_.back(); + + const double k1 = f_[i]; + const double k2 = f(x + h2, y + h2*k1); + const double k3 = f(x + h2, y + h2*k2); + const double k4 = f(x + h , y + h*k3); + + y_.push_back(y + h6*(k1 + 2*(k2 + k3) + k4)); + f_.push_back(f(x + h, y_.back())); + } + + assert (y_.size() == std::vector::size_type(N + 1)); + } + + double + operator()(const double x) const + { + // Dense output (O(h**3)) according to Shampine + // (Hermite interpolation) + const double h = stepsize(); + const int i = (x - span_[0]) / h; + const double t = (x - (span_[0] + i*h)) / h; + + const double y0 = y_[i], y1 = y_[i + 1]; + const double f0 = f_[i], f1 = f_[i + 1]; + + double u = (1 - 2*t) * (y1 - y0); + u += h * ((t - 1)*f0 + t*f1); + u *= t * (t - 1); + u += (1 - t)*y0 + t*y1; + + return u; + } + + private: + int N_; + std::array span_; + std::vector y_; + std::vector f_; + + double + stepsize() const { return (span_[1] - span_[0]) / N_; } + }; + + namespace PhasePressODE { + template + class Water { + public: + Water(const Density& rho, + const int np, + const int ix, + const double norm_grav) + : rho_(rho) + , svol_(np, 0) + , ix_(ix) + , g_(norm_grav) + { + svol_[ix_] = 1.0; + } + + double + operator()(const double /* depth */, + const double press) const + { + return this->density(press) * g_; + } + + private: + const Density& rho_; + std::vector svol_; + const int ix_; + const double g_; + + double + density(const double press) const + { + const std::vector& rho = rho_(press, svol_); + + return rho[ix_]; + } + }; + + template + class Oil { + public: + Oil(const Density& rho, + const RS& rs, + const int np, + const int oix, + const int gix, + const double norm_grav) + : rho_(rho) + , rs_(rs) + , svol_(np, 0) + , oix_(oix) + , gix_(gix) + , g_(norm_grav) + { + svol_[oix_] = 1.0; + } + + double + operator()(const double depth, + const double press) const + { + return this->density(depth, press) * g_; + } + + private: + const Density& rho_; + const RS& rs_; + mutable std::vector svol_; + const int oix_; + const int gix_; + const double g_; + + double + density(const double depth, + const double press) const + { + if (gix_ >= 0) { + svol_[gix_] = rs_(depth, press); + } + + const std::vector& rho = rho_(press, svol_); + return rho[oix_]; + } + }; + + template + class Gas { + public: + Gas(const Density& rho, + const RV& rv, + const int np, + const int gix, + const int oix, + const double norm_grav) + : rho_(rho) + , rv_(rv) + , svol_(np, 0) + , gix_(gix) + , oix_(oix) + , g_(norm_grav) + { + svol_[gix_] = 1.0; + } + + double + operator()(const double depth, + const double press) const + { + return this->density(depth, press) * g_; + } + + private: + const Density& rho_; + const RV& rv_; + mutable std::vector svol_; + const int gix_; + const int oix_; + const double g_; + + double + density(const double depth, + const double press) const + { + if (oix_ >= 0) { + svol_[oix_] = rv_(depth, press); + } + + const std::vector& rho = rho_(press, svol_); + return rho[gix_]; + } + }; + } // namespace PhasePressODE + + namespace PhaseUsed { + inline bool + water(const PhaseUsage& pu) + { + return bool(pu.phase_used[ Opm::BlackoilPhases::Aqua ]); + } + + inline bool + oil(const PhaseUsage& pu) + { + return bool(pu.phase_used[ Opm::BlackoilPhases::Liquid ]); + } + + inline bool + gas(const PhaseUsage& pu) + { + return bool(pu.phase_used[ Opm::BlackoilPhases::Vapour ]); + } + } // namespace PhaseUsed + + namespace PhaseIndex { + inline int + water(const PhaseUsage& pu) + { + int i = -1; + if (PhaseUsed::water(pu)) { + i = pu.phase_pos[ Opm::BlackoilPhases::Aqua ]; + } + + return i; + } + + inline int + oil(const PhaseUsage& pu) + { + int i = -1; + if (PhaseUsed::oil(pu)) { + i = pu.phase_pos[ Opm::BlackoilPhases::Liquid ]; + } + + return i; + } + + inline int + gas(const PhaseUsage& pu) + { + int i = -1; + if (PhaseUsed::gas(pu)) { + i = pu.phase_pos[ Opm::BlackoilPhases::Vapour ]; + } + + return i; + } + } // namespace PhaseIndex + + namespace PhasePressure { + template + void + assign(const UnstructuredGrid& G , + const std::array& f , + const double split, + std::vector& p ) + { + const int nd = G.dimensions, nc = G.number_of_cells; + const double* depth = & G.cell_centroids[0*nd + (nd - 1)]; + + enum { up = 0, down = 1 }; + + for (int c = 0; c < nc; ++c, depth += nd) { + const double z = *depth; + p[c] = (z < split) ? f[up](z) : f[down](z); + } + } + + template + void + water(const UnstructuredGrid& G , + const Region& reg , + const std::array& span , + const double grav , + const double po_woc, + std::vector& press ) + { + using PhasePressODE::Water; + typedef Water ODE; + + const PhaseUsage& pu = reg.phaseUsage(); + + const int wix = PhaseIndex::water(pu); + ODE drho(reg.densityCalculator(), pu.num_phases, wix, grav); + + const double z0 = reg.zwoc(); + const double p0 = po_woc - reg.pcow_woc(); // Pcow = Po - Pw + + std::array up = {{ z0, span[0] }}; + std::array down = {{ z0, span[1] }}; + + typedef Details::RK4IVP WPress; + std::array wpress = { + { + WPress(drho, up , p0, 100) + , + WPress(drho, down, p0, 100) + } + }; + + assign(G, wpress, z0, press); + } + + template + void + oil(const UnstructuredGrid& G , + const Region& reg , + const std::array& span , + const double grav , + std::vector& press , + double& po_woc, + double& po_goc) + { + using PhasePressODE::Oil; + typedef Oil ODE; + + const PhaseUsage& pu = reg.phaseUsage(); + + const int oix = PhaseIndex::oil(pu); + const int gix = PhaseIndex::gas(pu); + ODE drho(reg.densityCalculator(), + reg.dissolutionCalculator(), + pu.num_phases, oix, gix, grav); + + const double z0 = reg.datum(); + const double p0 = reg.pressure(); + + std::array up = {{ z0, span[0] }}; + std::array down = {{ z0, span[1] }}; + + typedef Details::RK4IVP OPress; + std::array opress = { + { + OPress(drho, up , p0, 100) + , + OPress(drho, down, p0, 100) + } + }; + + assign(G, opress, z0, press); + + po_woc = -std::numeric_limits::max(); + po_goc = -std::numeric_limits::max(); + + const double woc = reg.zwoc(); + // Compute Oil pressure at WOC + if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum + else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum + else { po_woc = p0; } // WOC *at* datum + + const double goc = reg.zgoc(); + // Compute Oil pressure at GOC + if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum + else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum + else { po_goc = p0; } // GOC *at* datum + } + + template + void + gas(const UnstructuredGrid& G , + const Region& reg , + const std::array& span , + const double grav , + const double po_goc, + std::vector& press ) + { + using PhasePressODE::Gas; + typedef Gas ODE; + + const PhaseUsage& pu = reg.phaseUsage(); + + const int gix = PhaseIndex::gas(pu); + const int oix = PhaseIndex::oil(pu); + + ODE drho(reg.densityCalculator(), + reg.evaporationCalculator(), + pu.num_phases, gix, oix, grav); + + const double z0 = reg.zgoc(); + const double p0 = po_goc + reg.pcgo_goc(); // Pcog = Pg - Po + + std::array up = {{ z0, span[0] }}; + std::array down = {{ z0, span[1] }}; + + typedef Details::RK4IVP GPress; + std::array gpress = { + { + GPress(drho, up , p0, 100) + , + GPress(drho, down, p0, 100) + } + }; + + assign(G, gpress, z0, press); + } + } // namespace PhasePressure + + template + void + equilibrateOWG(const UnstructuredGrid& G, + const Region& reg, + const double grav, + const std::array& span, + std::vector< std::vector >& press) + { + const PhaseUsage& pu = reg.phaseUsage(); + + double po_woc = -1, po_goc = -1; + if (PhaseUsed::oil(pu)) { + const int oix = PhaseIndex::oil(pu); + PhasePressure::oil(G, reg, span, grav, + press[ oix ], po_woc, po_goc); + } + + if (PhaseUsed::water(pu)) { + const int wix = PhaseIndex::water(pu); + PhasePressure::water(G, reg, span, grav, + po_woc, press[ wix ]); + } + + if (PhaseUsed::gas(pu)) { + const int gix = PhaseIndex::gas(pu); + PhasePressure::gas(G, reg, span, grav, + po_goc, press[ gix ]); + } + } + } // namespace Details + + namespace equil { + template + std::vector< std::vector > + phasePressures(const UnstructuredGrid& G, + const Region& reg, + const double grav) + { + std::array span = + {{ std::numeric_limits::max() , + -std::numeric_limits::max() }}; // Symm. about 0. + { + // This code is only supported in three space dimensions + assert (G.dimensions == 3); + + const int nd = G.dimensions; + const double* depth = & G.node_coordinates[0*nd + (nd - 1)]; + + for (int n = 0; n < G.number_of_nodes; ++n, depth += nd) { + const double z = *depth; + + if (z < span[0]) { span[0] = z; } + if (z > span[1]) { span[1] = z; } + } + } + + const int np = reg.phaseUsage().num_phases; + + typedef std::vector pval; + std::vector press(np, pval(G.number_of_cells, 0.0)); + + const double z0 = reg.datum(); + const double zwoc = reg.zwoc (); + const double zgoc = reg.zgoc (); + + if (! ((zgoc > z0) || (z0 > zwoc))) { + // Datum depth in oil zone (zgoc <= z0 <= zwoc) + Details::equilibrateOWG(G, reg, grav, span, press); + } + + return press; + } + } // namespace equil +} // namespace Opm + +#endif // OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp new file mode 100644 index 000000000..4d7cbe836 --- /dev/null +++ b/tests/test_equil.cpp @@ -0,0 +1,89 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. +*/ + +#include "config.h" + +/* --- Boost.Test boilerplate --- */ +#if HAVE_DYNAMIC_BOOST_TEST +#define BOOST_TEST_DYN_LINK +#endif + +#define NVERBOSE // Suppress own messages when throw()ing + +#define BOOST_TEST_MODULE UnitsTest +#include +#include + +/* --- our own headers --- */ + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +BOOST_AUTO_TEST_SUITE () + +BOOST_AUTO_TEST_CASE (PhasePressure) +{ + typedef std::vector PVal; + typedef std::vector PPress; + + std::shared_ptr + G(create_grid_cart3d(10, 1, 10), destroy_grid); + + Opm::parameter::ParameterGroup param; + { + using Opm::unit::kilogram; + using Opm::unit::meter; + using Opm::unit::cubic; + + std::stringstream dens; dens << 700*kilogram/cubic(meter); + param.insertParameter("rho2", dens.str()); + } + + typedef Opm::BlackoilPropertiesBasic Props; + Props props(param, G->dimensions, G->number_of_cells); + + typedef Opm::equil::DensityCalculator RhoCalc; + RhoCalc calc(props, 0); + + Opm::equil::EquilRecord record = + { + { 0 , 1e5 } , // Datum depth, pressure + { 5 , 0 } , // Zwoc , Pcow_woc + { 0 , 0 } // Zgoc , Pcgo_goc + }; + + Opm::equil::EquilReg + region(record, calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()); + + const double grav = 10; + const PPress ppress = Opm::equil::phasePressures(*G, region, grav); + + const int first = 0, last = G->number_of_cells - 1; + const double reltol = 1.0e-8; + BOOST_CHECK_CLOSE(ppress[0][first] , 90e3 , reltol); + BOOST_CHECK_CLOSE(ppress[0][last ] , 180e3 , reltol); + BOOST_CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); + BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); +} + +BOOST_AUTO_TEST_SUITE_END() From d9766b0f6d888f80604bb96d850ee45b0b104980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 17 Jan 2014 17:43:27 +0100 Subject: [PATCH 002/158] Compute phase pressures in subset of cells This commit adds support for assigning the initial phase pressure distribution to a subset of the total grid cells. This is needed in order to fully support equilibration regions. The existing region support (template parameter 'Region' in function 'phasePressures()') was only used/needed to define PVT property (specifically, the fluid phase density) calculator pertaining to a particular equilibration region. --- opm/core/simulator/initStateEquil.hpp | 3 +- opm/core/simulator/initStateEquil_impl.hpp | 107 ++++++++++++++++----- tests/test_equil.cpp | 5 +- 3 files changed, 87 insertions(+), 28 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 61f7debc9..b81183cfe 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -160,10 +160,11 @@ namespace Opm PhaseUsage pu_; }; - template + template std::vector< std::vector > phasePressures(const UnstructuredGrid& G, const Region& reg, + const CellRange& cells, const double grav = unit::gravity); } // namespace equil } // namespace Opm diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index cb19d0205..befbf2757 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -286,31 +286,40 @@ namespace Opm } // namespace PhaseIndex namespace PhasePressure { - template + template void assign(const UnstructuredGrid& G , const std::array& f , const double split, + const CellRange& cells, std::vector& p ) { - const int nd = G.dimensions, nc = G.number_of_cells; - const double* depth = & G.cell_centroids[0*nd + (nd - 1)]; + const int nd = G.dimensions; enum { up = 0, down = 1 }; - for (int c = 0; c < nc; ++c, depth += nd) { - const double z = *depth; + std::vector::size_type c = 0; + for (typename CellRange::const_iterator + ci = cells.begin(), ce = cells.end(); + ci != ce; ++ci, ++c) + { + assert (c < p.size()); + + const double z = G.cell_centroids[(*ci)*nd + (nd - 1)]; p[c] = (z < split) ? f[up](z) : f[down](z); } } - template + template void water(const UnstructuredGrid& G , const Region& reg , const std::array& span , const double grav , const double po_woc, + const CellRange& cells , std::vector& press ) { using PhasePressODE::Water; @@ -336,15 +345,17 @@ namespace Opm } }; - assign(G, wpress, z0, press); + assign(G, wpress, z0, cells, press); } - template + template void oil(const UnstructuredGrid& G , const Region& reg , const std::array& span , const double grav , + const CellRange& cells , std::vector& press , double& po_woc, double& po_goc) @@ -376,7 +387,7 @@ namespace Opm } }; - assign(G, opress, z0, press); + assign(G, opress, z0, cells, press); po_woc = -std::numeric_limits::max(); po_goc = -std::numeric_limits::max(); @@ -394,13 +405,15 @@ namespace Opm else { po_goc = p0; } // GOC *at* datum } - template + template void gas(const UnstructuredGrid& G , const Region& reg , const std::array& span , const double grav , const double po_goc, + const CellRange& cells , std::vector& press ) { using PhasePressODE::Gas; @@ -431,16 +444,18 @@ namespace Opm } }; - assign(G, gpress, z0, press); + assign(G, gpress, z0, cells, press); } } // namespace PhasePressure - template + template void equilibrateOWG(const UnstructuredGrid& G, const Region& reg, const double grav, const std::array& span, + const CellRange& cells, std::vector< std::vector >& press) { const PhaseUsage& pu = reg.phaseUsage(); @@ -448,53 +463,93 @@ namespace Opm double po_woc = -1, po_goc = -1; if (PhaseUsed::oil(pu)) { const int oix = PhaseIndex::oil(pu); - PhasePressure::oil(G, reg, span, grav, + PhasePressure::oil(G, reg, span, grav, cells, press[ oix ], po_woc, po_goc); } if (PhaseUsed::water(pu)) { const int wix = PhaseIndex::water(pu); - PhasePressure::water(G, reg, span, grav, - po_woc, press[ wix ]); + PhasePressure::water(G, reg, span, grav, po_woc, + cells, press[ wix ]); } if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - PhasePressure::gas(G, reg, span, grav, - po_goc, press[ gix ]); + PhasePressure::gas(G, reg, span, grav, po_goc, + cells, press[ gix ]); } } } // namespace Details namespace equil { - template + template std::vector< std::vector > phasePressures(const UnstructuredGrid& G, const Region& reg, + const CellRange& cells, const double grav) { std::array span = {{ std::numeric_limits::max() , -std::numeric_limits::max() }}; // Symm. about 0. + + int ncell = 0; { // This code is only supported in three space dimensions assert (G.dimensions == 3); - const int nd = G.dimensions; - const double* depth = & G.node_coordinates[0*nd + (nd - 1)]; + const int nd = G.dimensions; - for (int n = 0; n < G.number_of_nodes; ++n, depth += nd) { - const double z = *depth; + // Define short-name aliases to reduce visual clutter. + const double* const nc = & G.node_coordinates[0]; - if (z < span[0]) { span[0] = z; } - if (z > span[1]) { span[1] = z; } + const int* const cfp = & G.cell_facepos[0]; + const int* const cf = & G.cell_faces[0]; + + const int* const fnp = & G.face_nodepos[0]; + const int* const fn = & G.face_nodes[0]; + + // Define vertical span as + // + // [minimum(node depth(cells)), maximum(node depth(cells))] + // + // Note: We use a sledgehammer approach--looping all + // the nodes of all the faces of all the 'cells'--to + // compute those bounds. This necessarily entails + // visiting some nodes (and faces) multiple times. + // + // Note: The implementation of 'RK4IVP<>' implicitly + // imposes the requirement that cell centroids are all + // within this vertical span. That requirement is not + // checked. + for (typename CellRange::const_iterator + ci = cells.begin(), ce = cells.end(); + ci != ce; ++ci, ++ncell) + { + for (const int + *fi = & cf[ cfp[*ci + 0] ], + *fe = & cf[ cfp[*ci + 1] ]; + fi != fe; ++fi) + { + for (const int + *i = & fn[ fnp[*fi + 0] ], + *e = & fn[ fnp[*fi + 1] ]; + i != e; ++i) + { + const double z = nc[(*i)*nd + (nd - 1)]; + + if (z < span[0]) { span[0] = z; } + if (z > span[1]) { span[1] = z; } + } + } } } const int np = reg.phaseUsage().num_phases; typedef std::vector pval; - std::vector press(np, pval(G.number_of_cells, 0.0)); + std::vector press(np, pval(ncell, 0.0)); const double z0 = reg.datum(); const double zwoc = reg.zwoc (); @@ -502,7 +557,7 @@ namespace Opm if (! ((zgoc > z0) || (z0 > zwoc))) { // Datum depth in oil zone (zgoc <= z0 <= zwoc) - Details::equilibrateOWG(G, reg, grav, span, press); + Details::equilibrateOWG(G, reg, grav, span, cells, press); } return press; diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 4d7cbe836..5a97c74ce 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -75,8 +75,11 @@ BOOST_AUTO_TEST_CASE (PhasePressure) Opm::equil::miscibility::NoMixing(), props.phaseUsage()); + std::vector cells(G->number_of_cells); + std::iota(cells.begin(), cells.end(), 0); + const double grav = 10; - const PPress ppress = Opm::equil::phasePressures(*G, region, grav); + const PPress ppress = Opm::equil::phasePressures(*G, region, cells, grav); const int first = 0, last = G->number_of_cells - 1; const double reltol = 1.0e-8; From 9bd0a58b354f6c5f33f01e0bad07ef40957fe8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 17 Jan 2014 19:41:22 +0100 Subject: [PATCH 003/158] Test cell subset phase pressure assignment. --- tests/test_equil.cpp | 112 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 5a97c74ce..36d1d4527 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -89,4 +89,116 @@ BOOST_AUTO_TEST_CASE (PhasePressure) BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } +BOOST_AUTO_TEST_CASE (CellSubset) +{ + typedef std::vector PVal; + typedef std::vector PPress; + + std::shared_ptr + G(create_grid_cart3d(10, 1, 10), destroy_grid); + + Opm::parameter::ParameterGroup param; + { + using Opm::unit::kilogram; + using Opm::unit::meter; + using Opm::unit::cubic; + + std::stringstream dens; dens << 700*kilogram/cubic(meter); + param.insertParameter("rho2", dens.str()); + } + + typedef Opm::BlackoilPropertiesBasic Props; + Props props(param, G->dimensions, G->number_of_cells); + + typedef Opm::equil::DensityCalculator RhoCalc; + RhoCalc calc(props, 0); + + Opm::equil::EquilRecord record[] = + { + { + { 0 , 1e5 } , // Datum depth, pressure + { 2.5 , -0.075e5 } , // Zwoc , Pcow_woc + { 0 , 0 } // Zgoc , Pcgo_goc + } + , + { + { 5 , 1.35e5 } , // Datum depth, pressure + { 7.5 , -0.225e5 } , // Zwoc , Pcow_woc + { 5 , 0 } // Zgoc , Pcgo_goc + } + }; + + Opm::equil::EquilReg region[] = + { + Opm::equil::EquilReg(record[0], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + , + Opm::equil::EquilReg(record[0], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + , + Opm::equil::EquilReg(record[1], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + , + Opm::equil::EquilReg(record[1], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + }; + + const int cdim[] = { 2, 1, 2 }; + int ncoarse = cdim[0]; + for (std::size_t d = 1; d < 3; ++d) { ncoarse *= cdim[d]; } + + std::vector< std::vector > cells(ncoarse); + for (int c = 0; c < G->number_of_cells; ++c) { + int ci = c; + const int i = ci % G->cartdims[0]; ci /= G->cartdims[0]; + const int j = ci % G->cartdims[1]; + const int k = ci / G->cartdims[1]; + + const int ic = (i / (G->cartdims[0] / cdim[0])); + const int jc = (j / (G->cartdims[1] / cdim[1])); + const int kc = (k / (G->cartdims[2] / cdim[2])); + const int ix = ic + cdim[0]*(jc + cdim[1]*kc); + + assert ((0 <= ix) && (ix < ncoarse)); + cells[ix].push_back(c); + } + + PPress ppress(2, PVal(G->number_of_cells, 0)); + for (std::vector< std::vector >::const_iterator + r = cells.begin(), e = cells.end(); + r != e; ++r) + { + const int rno = int(r - cells.begin()); + const double grav = 10; + const PPress p = + Opm::equil::phasePressures(*G, region[rno], *r, grav); + + PVal::size_type i = 0; + for (std::vector::const_iterator + c = r->begin(), ce = r->end(); + c != ce; ++c, ++i) + { + assert (i < p[0].size()); + + ppress[0][*c] = p[0][i]; + ppress[1][*c] = p[1][i]; + } + } + + const int first = 0, last = G->number_of_cells - 1; + const double reltol = 1.0e-8; + BOOST_CHECK_CLOSE(ppress[0][first] , 105e3 , reltol); + BOOST_CHECK_CLOSE(ppress[0][last ] , 195e3 , reltol); + BOOST_CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); + BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); +} + BOOST_AUTO_TEST_SUITE_END() From 9ddca948ff0b91d068487b279354f0f0625deca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 17 Jan 2014 20:07:51 +0100 Subject: [PATCH 004/158] Add reverse look-up mapping for region vectors Class RegionMapping<> provides an easy way of extracting the cells that belong to any identified region (e.g., as defined by EQLNUM) of the deck. --- opm/core/simulator/initStateEquil.hpp | 91 +++++++++++++++++++++ tests/test_equil.cpp | 110 ++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index b81183cfe..5df47a0c2 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -27,6 +27,7 @@ #include #include +#include #include struct UnstructuredGrid; @@ -102,6 +103,96 @@ namespace Opm }; } // namespace miscibility + template < class Region = std::vector > + class RegionMapping { + public: + explicit + RegionMapping(const Region& reg) + : reg_(reg) + { + rev_.init(reg_); + } + + typedef typename Region::value_type RegionId; + typedef typename Region::size_type CellId; + typedef typename std::vector::const_iterator CellIter; + + class CellRange { + public: + CellRange(const CellIter b, + const CellIter e) + : b_(b), e_(e) + {} + + typedef CellIter iterator; + typedef CellIter const_iterator; + + iterator begin() const { return b_; } + iterator end() const { return e_; } + + private: + iterator b_; + iterator e_; + }; + + RegionId + numRegions() const { return RegionId(rev_.p.size()) - 1; } + + RegionId + region(const CellId c) const { return reg_[c]; } + + CellRange + cells(const RegionId r) const { + const RegionId i = r - rev_.low; + return CellRange(rev_.c.begin() + rev_.p[i + 0], + rev_.c.begin() + rev_.p[i + 1]); + } + + private: + Region reg_; + + struct { + typedef typename std::vector::size_type Pos; + std::vector p; + std::vector c; + RegionId low; + + void + init(const Region& reg) + { + typedef typename Region::const_iterator CI; + const std::pair + m = std::minmax_element(reg.begin(), reg.end()); + + low = *m.first; + + const typename Region::size_type + n = *m.second - low + 1; + + p.resize(n + 1); std::fill(p.begin(), p.end(), Pos(0)); + for (CellId i = 0, nc = reg.size(); i < nc; ++i) { + p[ reg[i] - low + 1 ] += 1; + } + + for (typename std::vector::size_type + i = 1, sz = p.size(); i < sz; ++i) { + p[0] += p[i]; + p[i] = p[0] - p[i]; + } + + assert (p[0] == + static_cast(reg.size())); + + c.resize(reg.size()); + for (CellId i = 0, nc = reg.size(); i < nc; ++i) { + c[ p[ reg[i] - low + 1 ] ++ ] = i; + } + + p[0] = 0; + } + } rev_; + }; + struct EquilRecord { struct { double depth; diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 36d1d4527..80ae26529 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include #include @@ -201,4 +203,112 @@ BOOST_AUTO_TEST_CASE (CellSubset) BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } +BOOST_AUTO_TEST_CASE (RegMapping) +{ + typedef std::vector PVal; + typedef std::vector PPress; + + std::shared_ptr + G(create_grid_cart3d(10, 1, 10), destroy_grid); + + Opm::parameter::ParameterGroup param; + { + using Opm::unit::kilogram; + using Opm::unit::meter; + using Opm::unit::cubic; + + std::stringstream dens; dens << 700*kilogram/cubic(meter); + param.insertParameter("rho2", dens.str()); + } + + typedef Opm::BlackoilPropertiesBasic Props; + Props props(param, G->dimensions, G->number_of_cells); + + typedef Opm::equil::DensityCalculator RhoCalc; + RhoCalc calc(props, 0); + + Opm::equil::EquilRecord record[] = + { + { + { 0 , 1e5 } , // Datum depth, pressure + { 2.5 , -0.075e5 } , // Zwoc , Pcow_woc + { 0 , 0 } // Zgoc , Pcgo_goc + } + , + { + { 5 , 1.35e5 } , // Datum depth, pressure + { 7.5 , -0.225e5 } , // Zwoc , Pcow_woc + { 5 , 0 } // Zgoc , Pcgo_goc + } + }; + + Opm::equil::EquilReg region[] = + { + Opm::equil::EquilReg(record[0], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + , + Opm::equil::EquilReg(record[0], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + , + Opm::equil::EquilReg(record[1], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + , + Opm::equil::EquilReg(record[1], calc, + Opm::equil::miscibility::NoMixing(), + Opm::equil::miscibility::NoMixing(), + props.phaseUsage()) + }; + + std::vector eqlnum(G->number_of_cells); + { + std::vector cells(G->number_of_cells); + std::iota(cells.begin(), cells.end(), 0); + + const int cdim[] = { 2, 1, 2 }; + int ncoarse = cdim[0]; + for (std::size_t d = 1; d < 3; ++d) { ncoarse *= cdim[d]; } + + partition_unif_idx(G->dimensions, G->number_of_cells, + G->cartdims, cdim, + &cells[0], &eqlnum[0]); + } + Opm::equil::RegionMapping<> eqlmap(eqlnum); + + PPress ppress(2, PVal(G->number_of_cells, 0)); + for (int r = 0, e = eqlmap.numRegions(); r != e; ++r) + { + const Opm::equil::RegionMapping<>::CellRange& + rng = eqlmap.cells(r); + + const int rno = r; + const double grav = 10; + const PPress p = + Opm::equil::phasePressures(*G, region[rno], rng, grav); + + PVal::size_type i = 0; + for (Opm::equil::RegionMapping<>::CellRange::const_iterator + c = rng.begin(), ce = rng.end(); + c != ce; ++c, ++i) + { + assert (i < p[0].size()); + + ppress[0][*c] = p[0][i]; + ppress[1][*c] = p[1][i]; + } + } + + const int first = 0, last = G->number_of_cells - 1; + const double reltol = 1.0e-8; + BOOST_CHECK_CLOSE(ppress[0][first] , 105e3 , reltol); + BOOST_CHECK_CLOSE(ppress[0][last ] , 195e3 , reltol); + BOOST_CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); + BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); +} + BOOST_AUTO_TEST_SUITE_END() From 5cdcd77820f6aa9e68f37e3d8d879fcc093fe1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Mon, 20 Jan 2014 01:25:33 +0100 Subject: [PATCH 005/158] Document public interface of phasePressures(). --- opm/core/simulator/initStateEquil.hpp | 356 ++++++++++++++++++++++++-- 1 file changed, 336 insertions(+), 20 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 5df47a0c2..43f77aac4 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -30,17 +30,45 @@ #include #include +/** + * \file + * Facilities for an ECLIPSE-style equilibration-based + * initialisation scheme (keyword 'EQUIL'). + */ struct UnstructuredGrid; namespace Opm { + /** + * Types and routines that collectively implement a basic + * ECLIPSE-style equilibration-based initialisation scheme. + * + * This namespace is intentionally nested to avoid name clashes + * with other parts of OPM. + */ namespace equil { template class DensityCalculator; + /** + * Facility for calculating phase densities based on the + * BlackoilPropertiesInterface. + * + * Implements the crucial operator()(p,svol) + * function that is expected by class EquilReg. + */ template <> class DensityCalculator< BlackoilPropertiesInterface > { public: + /** + * Constructor. + * + * \param[in] props Implementation of the + * BlackoilPropertiesInterface. + * + * \param[in] c Single cell used as a representative cell + * in a PVT region. + */ DensityCalculator(const BlackoilPropertiesInterface& props, const int c) : props_(props) @@ -48,6 +76,16 @@ namespace Opm { } + /** + * Compute phase densities of all phases at phase point + * given by (pressure, surface volume) tuple. + * + * \param[in] p Fluid pressure. + * + * \param[in] z Surface volumes of all phases. + * + * \return Phase densities at phase point. + */ std::vector operator()(const double p, const std::vector& z) const @@ -71,8 +109,28 @@ namespace Opm const std::vector c_; }; + /** + * Types and routines relating to phase mixing in + * equilibration calculations. + */ namespace miscibility { + /** + * Type that implements "no phase mixing" policy. + */ struct NoMixing { + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. In "no mixing + * policy", this is identically zero. + */ double operator()(const double /* depth */, const double /* press */) const @@ -81,8 +139,19 @@ namespace Opm } }; + /** + * Type that implements "dissolved gas-oil ratio" + * tabulated as a function of depth policy. Data + * typically taken from keyword 'RSVD'. + */ class RsVD { public: + /** + * Constructor. + * + * \param[in] depth Depth nodes. + * \param[in] rs Dissolved gas-oil ratio at @c depth. + */ RsVD(const std::vector& depth, const std::vector& rs) : depth_(depth) @@ -90,6 +159,18 @@ namespace Opm { } + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. + */ double operator()(const double depth, const double /* press */) const @@ -98,14 +179,31 @@ namespace Opm } private: - std::vector depth_; - std::vector rs_; + std::vector depth_; /**< Depth nodes */ + std::vector rs_; /**< Dissolved gas-oil ratio */ }; } // namespace miscibility + /** + * Forward and reverse mappings between cells and + * regions/partitions (e.g., the ECLIPSE-style 'SATNUM', + * 'PVTNUM', or 'EQUILNUM' arrays). + * + * \tparam Region Type of a forward region mapping. Expected + * to provide indexed access through + * operator[]() as well as inner types + * 'value_type', 'size_type', and + * 'const_iterator'. + */ template < class Region = std::vector > class RegionMapping { public: + /** + * Constructor. + * + * \param[in] reg Forward region mapping, restricted to + * active cells only. + */ explicit RegionMapping(const Region& reg) : reg_(reg) @@ -113,34 +211,82 @@ namespace Opm rev_.init(reg_); } - typedef typename Region::value_type RegionId; - typedef typename Region::size_type CellId; + /** + * Type of forward (cell-to-region) mapping result. + * Expected to be an integer. + */ + typedef typename Region::value_type RegionId; + + /** + * Type of reverse (region-to-cell) mapping (element) + * result. + */ + typedef typename Region::size_type CellId; + + /** + * Type of reverse region-to-cell range bounds and + * iterators. + */ typedef typename std::vector::const_iterator CellIter; + /** + * Range of cells. Result from reverse (region-to-cell) + * mapping. + */ class CellRange { public: + /** + * Constructor. + * + * \param[in] b Beginning of range. + * \param[in] e One past end of range. + */ CellRange(const CellIter b, const CellIter e) : b_(b), e_(e) {} - typedef CellIter iterator; + /** + * Read-only iterator on cell ranges. + */ typedef CellIter const_iterator; - iterator begin() const { return b_; } - iterator end() const { return e_; } + /** + * Beginning of cell range. + */ + const_iterator begin() const { return b_; } + + /** + * One past end of cell range. + */ + const_iterator end() const { return e_; } private: - iterator b_; - iterator e_; + const_iterator b_; + const_iterator e_; }; + /** + * Number of declared regions in cell-to-region mapping. + */ RegionId numRegions() const { return RegionId(rev_.p.size()) - 1; } + /** + * Compute region number of given active cell. + * + * \param[in] c Active cell + * \return Region to which @c c belongs. + */ RegionId region(const CellId c) const { return reg_[c]; } + /** + * Extract active cells in particular region. + * + * \param[in] r Region number + * \returns Range of active cells in region @c r. + */ CellRange cells(const RegionId r) const { const RegionId i = r - rev_.low; @@ -149,14 +295,24 @@ namespace Opm } private: + /** + * Copy of forward region mapping (cell-to-region). + */ Region reg_; + /** + * Reverse mapping (region-to-cell). + */ struct { typedef typename std::vector::size_type Pos; - std::vector p; - std::vector c; - RegionId low; + std::vector p; /**< Region start pointers */ + std::vector c; /**< Region cells */ + RegionId low; /**< Smallest region number */ + /** + * Compute reverse mapping. Standard linear insertion + * sort algorithm. + */ void init(const Region& reg) { @@ -190,9 +346,32 @@ namespace Opm p[0] = 0; } - } rev_; + } rev_; /**< Reverse mapping instance */ }; + /** + * Equilibration record. + * + * Layout and contents inspired by first six items of + * ECLIPSE's 'EQUIL' records. This is the minimum amount of + * input data needed to define phase pressures in an + * equilibration region. + * + * Data consists of three pairs of depth and pressure values: + * 1. main + * - @c depth Main datum depth. + * - @c press Pressure at datum depth. + * + * 2. woc + * - @c depth Depth of water-oil contact + * - @c press water-oil capillary pressure at water-oil contact. + * Capillary pressure defined as "P_oil - P_water". + * + * 3. goc + * - @c depth Depth of gas-oil contact + * - @c press Gas-oil capillary pressure at gas-oil contact. + * Capillary pressure defined as "P_gas - P_oil". + */ struct EquilRecord { struct { double depth; @@ -200,11 +379,63 @@ namespace Opm } main, woc, goc; }; + /** + * Aggregate information base of an equilibration region. + * + * Provides inquiry methods for retrieving depths of contacs + * and pressure values as well as a means of calculating fluid + * densities, dissolved gas-oil ratio and vapourised oil-gas + * ratios. + * + * \tparam DensCalc Type that provides access to a phase + * density calculation facility. Must implement an operator() + * declared as + * + * std::vector + * operator()(const double press, + * const std::vector& svol ) + * + * that calculates the phase densities of all phases in @c + * svol at fluid pressure @c press. + * + * \tparam RS Type that provides access to a calculator for + * (initial) dissolved gas-oil ratios as a function of depth + * and (oil) pressure. Must implement an operator() declared + * as + * + * double + * operator()(const double depth, + * const double press) + * + * that calculates the dissolved gas-oil ratio at depth @c + * depth and (oil) pressure @c press. + * + * \tparam RV Type that provides access to a calculator for + * (initial) vapourised oil-gas ratios as a function of depth + * and (gas) pressure. Must implement an operator() declared + * as + * + * double + * operator()(const double depth, + * const double press) + * + * that calculates the vapourised oil-gas ratio at depth @c + * depth and (gas) pressure @c press. + */ template class EquilReg { public: + /** + * Constructor. + * + * \param[in] rec Equilibration data of current region. + * \param[in] density Density calculator of current region. + * \param[in] rs Calculator of dissolved gas-oil ratio. + * \param[in] rv Calculator of vapourised oil-gas ratio. + * \param[in] pu Summary of current active phases. + */ EquilReg(const EquilRecord& rec, const DensCalc& density, const RS& rs, @@ -218,39 +449,124 @@ namespace Opm { } + /** + * Type of density calculator. + */ typedef DensCalc CalcDensity; - typedef RS CalcDissolution; - typedef RV CalcEvaporation; + /** + * Type of dissolved gas-oil ratio calculator. + */ + typedef RS CalcDissolution; + + /** + * Type of vapourised oil-gas ratio calculator. + */ + typedef RV CalcEvaporation; + + /** + * Datum depth in current region + */ double datum() const { return this->rec_.main.depth; } + + /** + * Pressure at datum depth in current region. + */ double pressure() const { return this->rec_.main.press; } + /** + * Depth of water-oil contact. + */ double zwoc() const { return this->rec_.woc .depth; } + + /** + * water-oil capillary pressure at water-oil contact. + * + * \return P_o - P_w at WOC. + */ double pcow_woc() const { return this->rec_.woc .press; } + /** + * Depth of gas-oil contact. + */ double zgoc() const { return this->rec_.goc .depth; } + + /** + * Gas-oil capillary pressure at gas-oil contact. + * + * \return P_g - P_o at GOC. + */ double pcgo_goc() const { return this->rec_.goc .press; } + /** + * Retrieve phase density calculator of current region. + */ const CalcDensity& densityCalculator() const { return this->density_; } + /** + * Retrieve dissolved gas-oil ratio calculator of current + * region. + */ const CalcDissolution& dissolutionCalculator() const { return this->rs_; } + /** + * Retrieve vapourised oil-gas ratio calculator of current + * region. + */ const CalcEvaporation& evaporationCalculator() const { return this->rv_; } + /** + * Retrieve active fluid phase summary. + */ const PhaseUsage& phaseUsage() const { return this->pu_; } private: - EquilRecord rec_; - DensCalc density_; - RS rs_; - RV rv_; - PhaseUsage pu_; + EquilRecord rec_; /**< Equilibration data */ + DensCalc density_; /**< Density calculator */ + RS rs_; /**< RS calculator */ + RV rv_; /**< RV calculator */ + PhaseUsage pu_; /**< Active phase summary */ }; + /** + * Compute initial phase pressures by means of equilibration. + * + * This function uses the information contained in an + * equilibration record (i.e., depths and pressurs) as well as + * a density calculator and related data to vertically + * integrate the phase pressure ODE + * \f[ + * \frac{\mathrm{d}p_{\alpha}}{\mathrm{d}z} = + * \rho_{\alpha}(z,p_{\alpha})\cdot g + * \f] + * in which \f$\rho_{\alpha}$ denotes the fluid density of + * fluid phase \f$\alpha\f$, \f$p_{\alpha}\f$ is the + * corresponding phase pressure, \f$z\f$ is the depth and + * \f$g\f$ is the acceleration due to gravity (assumed + * directed downwords, in the positive \f$z\f$ direction). + * + * \tparam Region Type of an equilibration region information + * base. Typically an instance of the EquilReg + * class template. + * + * \tparam CellRange Type of cell range that demarcates the + * cells pertaining to the current + * equilibration region. + * + * \param[in] G Grid. + * \param[in] reg Current equilibration region. + * \param[in] cells Range that spans the cells of the current + * equilibration region. + * \param[in] grav Acceleration of gravity. + * + * \return Phase pressures, one vector for each active phase, + * of pressure values in each cell in the current + * equilibration region. + */ template std::vector< std::vector > phasePressures(const UnstructuredGrid& G, From 693612c0e2c7a0267743b6571950bbcc94c34ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Mon, 20 Jan 2014 10:33:42 +0100 Subject: [PATCH 006/158] Document requirements of CellRange. --- opm/core/simulator/initStateEquil.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 43f77aac4..4d7a6f0ff 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -555,7 +555,10 @@ namespace Opm * * \tparam CellRange Type of cell range that demarcates the * cells pertaining to the current - * equilibration region. + * equilibration region. Must implement + * methods begin() and end() to bound the range + * as well as provide an inner type, + * const_iterator, to traverse the range. * * \param[in] G Grid. * \param[in] reg Current equilibration region. From 4779b43e888e04c84c26c2eeb24bd976ef1eae7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 21 Jan 2014 13:49:06 +0100 Subject: [PATCH 007/158] Include for std::iota() Header was missing in earlier revision. --- tests/test_equil.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 80ae26529..27b46b559 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include From 30ba1b0f867ee19e42718063a296354f69aa47f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 21 Jan 2014 17:49:02 +0100 Subject: [PATCH 008/158] Install crude handling of data point outside vertical span The initial implementation of RK4IVP<>::operator() failed to take into account the possibility that we might need to evaluate the function outside the vertical span for which it was initially defined. This situation occurs, for instance, in the not uncommon cases of the GOC being above or the WOC being below the model. This commit installs a crude Hermitian extrapolation procedure to handle these cases. Refinements are likely. --- opm/core/simulator/initStateEquil_impl.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index befbf2757..ffc566be3 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -73,9 +73,13 @@ namespace Opm // Dense output (O(h**3)) according to Shampine // (Hermite interpolation) const double h = stepsize(); - const int i = (x - span_[0]) / h; + int i = (x - span_[0]) / h; const double t = (x - (span_[0] + i*h)) / h; + // Crude handling of evaluation point outside "span_"; + if (i < 0) { i = 0; } + if (N_ <= i) { i = N_ - 1; } + const double y0 = y_[i], y1 = y_[i + 1]; const double f0 = f_[i], f1 = f_[i + 1]; From ba82e3fa5e9aff381b4a3d59ab9c490cc72d6986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Thu, 23 Jan 2014 10:16:49 +0100 Subject: [PATCH 009/158] Add a layer of glue to extract data from deck This is a work in progress. --- opm/core/simulator/initStateEquil.hpp | 126 ++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 4d7a6f0ff..f9b5a65af 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -20,6 +20,7 @@ #ifndef OPM_INITSTATEEQUIL_HEADER_INCLUDED #define OPM_INITSTATEEQUIL_HEADER_INCLUDED +#include #include #include #include @@ -576,6 +577,131 @@ namespace Opm const Region& reg, const CellRange& cells, const double grav = unit::gravity); + + namespace DeckDependent { + inline + std::vector + getEquil(const EclipseGridParser& deck) + { + if (deck.hasField("EQUIL")) { + const EQUIL& eql = deck.getEQUIL(); + + typedef std::vector::size_type sz_t; + const sz_t nrec = eql.equil.size(); + + std::vector ret; + ret.reserve(nrec); + for (sz_t r = 0; r < nrec; ++r) { + const EquilLine& rec = eql.equil[r]; + + EquilRecord record = + { + { rec.datum_depth_ , + rec.datum_depth_pressure_ } + , + { rec.water_oil_contact_depth_ , + rec.oil_water_cap_pressure_ } + , + { rec.gas_oil_contact_depth_ , + rec.gas_oil_cap_pressure_ } + }; + + ret.push_back(record); + } + + return ret; + } + else { + OPM_THROW(std::domain_error, + "Deck does not provide equilibration data."); + } + } + + inline + std::vector + equilnum(const EclipseGridParser& deck, + const UnstructuredGrid& G ) + { + std::vector eqlnum; + if (deck.hasField("EQLNUM")) { + eqlnum = deck.getIntegerValue("EQLNUM"); + } + else { + // No explicit equilibration region. + // All cells in region zero. + eqlnum.assign(G.number_of_cells, 0); + } + + return eqlnum; + } + + template + class PhasePressureComputer; + + template <> + class PhasePressureComputer { + public: + PhasePressureComputer(const BlackoilPropertiesInterface& props, + const EclipseGridParser& deck , + const UnstructuredGrid& G ) + : pp_(props.numPhases(), + std::vector(G.number_of_cells)) + { + const std::vector rec = getEquil(deck); + const RegionMapping<> eqlmap(equilnum(deck, G)); + + calcII(eqlmap, rec, props, G); + } + + typedef std::vector PVal; + typedef std::vector PPress; + + const PPress& press() const { return pp_; } + + private: + typedef DensityCalculator RhoCalc; + typedef EquilReg EqReg; + + PPress pp_; + + template + void + calcII(const RMap& reg , + const std::vector< EquilRecord >& rec , + const Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G ) + { + typedef miscibility::NoMixing NoMix; + + for (typename RMap::RegionId + r = 0, nr = reg.numRegions(); + r < nr; ++r) + { + const typename RMap::CellRange cells = reg.cells(r); + + const int repcell = *cells.begin(); + const RhoCalc calc(props, repcell); + + const EqReg eqreg(rec[r], calc, NoMix(), NoMix(), + props.phaseUsage()); + + const PPress& res = phasePressures(G, eqreg, cells); + + for (int p = 0, np = props.numPhases(); p < np; ++p) { + PVal& d = pp_[p]; + PVal::const_iterator s = res[p].begin(); + for (typename RMap::CellRange::const_iterator + c = cells.begin(), + e = cells.end(); + c != e; ++c, ++s) + { + d[*c] = *s; + } + } + } + } + }; + } // namespace DeckDependent } // namespace equil } // namespace Opm From 97014713ce7fb2620cbe8653f314380223d2c429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Feb 2014 11:32:46 +0100 Subject: [PATCH 010/158] Removed RK4IVP's inheritance from binary_function. Three reasons: - class is a unary functor, - the typedefs obtained were not used, - binary_function is deprecated in C++11. --- opm/core/simulator/initStateEquil_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index ffc566be3..381a3f51c 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -32,7 +32,7 @@ namespace Opm { namespace Details { template - class RK4IVP : public std::binary_function { + class RK4IVP { public: RK4IVP(const RHS& f , const std::array& span, From 7997917c075f3d07e71f5d204168161b2aa5c782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Feb 2014 15:36:20 +0100 Subject: [PATCH 011/158] Add (unfinished) test case. --- tests/deadfluids.DATA | 9 +++++++++ tests/test_equil.cpp | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/deadfluids.DATA diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA new file mode 100644 index 000000000..37b3c6ee4 --- /dev/null +++ b/tests/deadfluids.DATA @@ -0,0 +1,9 @@ +WATER +OIL +GAS + +PVDO +100 1.0 1.0 +200 0.9 1.0 +/ + diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 27b46b559..7060c501c 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -92,6 +93,9 @@ BOOST_AUTO_TEST_CASE (PhasePressure) BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } + + + BOOST_AUTO_TEST_CASE (CellSubset) { typedef std::vector PVal; @@ -204,6 +208,9 @@ BOOST_AUTO_TEST_CASE (CellSubset) BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } + + + BOOST_AUTO_TEST_CASE (RegMapping) { typedef std::vector PVal; @@ -312,4 +319,17 @@ BOOST_AUTO_TEST_CASE (RegMapping) BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } + + +BOOST_AUTO_TEST_CASE (DeckAllDead) +{ + std::shared_ptr + grid(create_grid_cart3d(10, 1, 10), destroy_grid); + Opm::EclipseGridParser deck("deadfluids.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); + Opm::equil::DeckDependent::PhasePressureComputer comp(props, deck, *grid); +} + + + BOOST_AUTO_TEST_SUITE_END() From 6362621c13658f6f9f75fafc0ee639f812fdeb78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Feb 2014 09:38:47 +0100 Subject: [PATCH 012/158] Created simple data for init testing. --- tests/deadfluids.DATA | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA index 37b3c6ee4..190d5d975 100644 --- a/tests/deadfluids.DATA +++ b/tests/deadfluids.DATA @@ -7,3 +7,25 @@ PVDO 200 0.9 1.0 / +PVDG +100 0.05 0.1 +200 0.02 0.2 +/ + +SWOF +0 0 1 0 +1 1 0 0 +/ + +SGOF +0 0 1 0 +1 1 0 0 +/ + +DENSITY +700 1000 10 +/ + +EQUIL +5 150 2 0 8 0 +/ From ba4461a26c0497b30813fc12bc84df9b55647f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Feb 2014 10:56:09 +0100 Subject: [PATCH 013/158] Throw exception if datum not in oil zone. We are not capable of handling this, and must abort. --- opm/core/simulator/initStateEquil_impl.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 381a3f51c..a713e3b34 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -562,6 +562,8 @@ namespace Opm if (! ((zgoc > z0) || (z0 > zwoc))) { // Datum depth in oil zone (zgoc <= z0 <= zwoc) Details::equilibrateOWG(G, reg, grav, span, cells, press); + } else { + OPM_THROW(std::runtime_error, "Cannot initialise: the datum depth must be in the oil zone."); } return press; From b9589097fc689ae0c2fe26800ade79071d5a1045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Feb 2014 10:57:23 +0100 Subject: [PATCH 014/158] Fix contact depths in test deck. --- tests/deadfluids.DATA | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA index 190d5d975..8c368ff88 100644 --- a/tests/deadfluids.DATA +++ b/tests/deadfluids.DATA @@ -27,5 +27,5 @@ DENSITY / EQUIL -5 150 2 0 8 0 +5 150 8 0 2 0 / From 33a20301704f7e96bc8c54553c042945d43c0b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 5 Feb 2014 11:26:29 +0100 Subject: [PATCH 015/158] Still working on test_equil.cpp. --- tests/test_equil.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 7060c501c..844cf6ad2 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -324,10 +324,19 @@ BOOST_AUTO_TEST_CASE (RegMapping) BOOST_AUTO_TEST_CASE (DeckAllDead) { std::shared_ptr - grid(create_grid_cart3d(10, 1, 10), destroy_grid); + grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::EclipseGridParser deck("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); Opm::equil::DeckDependent::PhasePressureComputer comp(props, deck, *grid); + const auto& pressures = comp.press(); + BOOST_REQUIRE(pressures.size() == 3); + BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); + for (auto pp : pressures) { + for (auto p : pp){ + std::cout << p << ' '; + } + std::cout << std::endl; + } } From 55fcdec7347ffe93144b1fc9626c57e004a47a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 19 Feb 2014 13:38:21 +0100 Subject: [PATCH 016/158] Add (defaulted) gravity argument in some places. This is done to facilitate testing, using gravity = 10 m/s^2 for example. --- opm/core/simulator/initStateEquil.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index f9b5a65af..cde37352b 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -643,14 +643,15 @@ namespace Opm public: PhasePressureComputer(const BlackoilPropertiesInterface& props, const EclipseGridParser& deck , - const UnstructuredGrid& G ) + const UnstructuredGrid& G , + const double grav = unit::gravity) : pp_(props.numPhases(), std::vector(G.number_of_cells)) { const std::vector rec = getEquil(deck); const RegionMapping<> eqlmap(equilnum(deck, G)); - calcII(eqlmap, rec, props, G); + calcII(eqlmap, rec, props, G, grav); } typedef std::vector PVal; @@ -669,7 +670,8 @@ namespace Opm calcII(const RMap& reg , const std::vector< EquilRecord >& rec , const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G ) + const UnstructuredGrid& G , + const double grav) { typedef miscibility::NoMixing NoMix; @@ -685,7 +687,7 @@ namespace Opm const EqReg eqreg(rec[r], calc, NoMix(), NoMix(), props.phaseUsage()); - const PPress& res = phasePressures(G, eqreg, cells); + const PPress& res = phasePressures(G, eqreg, cells, grav); for (int p = 0, np = props.numPhases(); p < np; ++p) { PVal& d = pp_[p]; From 95ce3c4657e88102416334f03471b1a0a8de6593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 19 Feb 2014 13:40:02 +0100 Subject: [PATCH 017/158] Modify test data. --- tests/deadfluids.DATA | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA index 8c368ff88..ffaebc7ff 100644 --- a/tests/deadfluids.DATA +++ b/tests/deadfluids.DATA @@ -4,7 +4,7 @@ GAS PVDO 100 1.0 1.0 -200 0.9 1.0 +200 0.5 1.0 / PVDG @@ -27,5 +27,5 @@ DENSITY / EQUIL -5 150 8 0 2 0 +5 150 5 0 2 0 / From 2056623044b1e08cf5577f77ec477b5dda65f858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 19 Feb 2014 13:41:20 +0100 Subject: [PATCH 018/158] Complete pressure test for dead-oil deck. --- tests/test_equil.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 844cf6ad2..ff48cbc1a 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -327,16 +327,20 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::EclipseGridParser deck("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); - Opm::equil::DeckDependent::PhasePressureComputer comp(props, deck, *grid); + Opm::equil::DeckDependent::PhasePressureComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); - for (auto pp : pressures) { - for (auto p : pp){ - std::cout << p << ' '; - } - std::cout << std::endl; - } + + const int first = 0, last = grid->number_of_cells - 1; + // The relative tolerance is too loose to be very useful, + // but the answer we are checking is the result of an ODE + // solver, and it is unclear if we should check it against + // the true answer or something else. + const double reltol = 1.0e-3; + BOOST_CHECK_CLOSE(pressures[0][first] , 14955e3 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 15045e3 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.50473e7 , reltol); } From 50c6fa88635886c9ac59d6aceee62864bf90d9a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 19 Feb 2014 13:42:07 +0100 Subject: [PATCH 019/158] Add saturation init facilities. This adds the function phaseSaturations() and some helpers: satFromPc() and satFromSumOfPcs(). --- opm/core/simulator/initStateEquil.hpp | 223 ++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index cde37352b..6613d550a 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -533,6 +534,143 @@ namespace Opm PhaseUsage pu_; /**< Active phase summary */ }; + + + /// Functor for inverting capillary pressure function. + /// Function represented is + /// f(s) = pc(s) - target_pc + struct PcEq + { + PcEq(const BlackoilPropertiesInterface& props, + const int phase, + const int cell, + const double target_pc) + : props_(props), + phase_(phase), + cell_(cell), + target_pc_(target_pc) + { + std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); + std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + } + double operator()(double s) const + { + s_[phase_] = s; + props_.capPress(1, s_, &cell_, pc_, 0); + return pc_[phase_] - target_pc_; + } + private: + const BlackoilPropertiesInterface& props_; + const int phase_; + const int cell_; + const int target_pc_; + mutable double s_[BlackoilPhases::MaxNumPhases]; + mutable double pc_[BlackoilPhases::MaxNumPhases]; + }; + + + + /// Compute saturation of some phase corresponding to a given + /// capillary pressure. + inline double satFromPc(const BlackoilPropertiesInterface& props, + const int phase, + const int cell, + const double target_pc, + const bool increasing = false) + { + // Find minimum and maximum saturations. + double sminarr[BlackoilPhases::MaxNumPhases]; + double smaxarr[BlackoilPhases::MaxNumPhases]; + props.satRange(1, &cell, sminarr, smaxarr); + const double s0 = increasing ? smaxarr[phase] : sminarr[phase]; + const double s1 = increasing ? sminarr[phase] : smaxarr[phase]; + + // Create the equation f(s) = pc(s) - target_pc + const PcEq f(props, phase, cell, target_pc); + const double f0 = f(s0); + const double f1 = f(s1); + if (f0 <= 0.0) { + return s0; + } else if (f1 > 0.0) { + return s1; + } else { + const int max_iter = 30; + const double tol = 1e-6; + int iter_used = -1; + typedef RegulaFalsi ScalarSolver; + const double sol = ScalarSolver::solve(f, std::min(s0, s1), std::max(s0, s1), max_iter, tol, iter_used); + return sol; + } + } + + + /// Functor for inverting a sum of capillary pressure functions. + /// Function represented is + /// f(s) = pc1(s) + pc2(1 - s) - target_pc + struct PcEqSum + { + PcEqSum(const BlackoilPropertiesInterface& props, + const int phase1, + const int phase2, + const int cell, + const double target_pc) + : props_(props), + phase1_(phase1), + phase2_(phase2), + cell_(cell), + target_pc_(target_pc) + { + std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); + std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + } + double operator()(double s) const + { + s_[phase1_] = s; + s_[phase2_] = 1.0 - s; + props_.capPress(1, s_, &cell_, pc_, 0); + return pc_[phase1_] + pc_[phase2_] - target_pc_; + } + private: + const BlackoilPropertiesInterface& props_; + const int phase1_; + const int phase2_; + const int cell_; + const int target_pc_; + mutable double s_[BlackoilPhases::MaxNumPhases]; + mutable double pc_[BlackoilPhases::MaxNumPhases]; + }; + + + + + /// Compute saturation of some phase corresponding to a given + /// capillary pressure, where the capillary pressure function + /// is given as a sum of two other functions. + inline double satFromSumOfPcs(const BlackoilPropertiesInterface& props, + const int phase1, + const int phase2, + const int cell, + const double target_pc) + { + // Find minimum and maximum saturations. + double sminarr[BlackoilPhases::MaxNumPhases]; + double smaxarr[BlackoilPhases::MaxNumPhases]; + props.satRange(1, &cell, sminarr, smaxarr); + const double smin = sminarr[phase1]; + const double smax = smaxarr[phase1]; + + // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc + const PcEqSum f(props, phase1, phase2, cell, target_pc); + const int max_iter = 30; + const double tol = 1e-6; + int iter_used = -1; + typedef RegulaFalsi ScalarSolver; + const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used); + return sol; + } + + + /** * Compute initial phase pressures by means of equilibration. * @@ -578,6 +716,91 @@ namespace Opm const CellRange& cells, const double grav = unit::gravity); + + + /** + * Compute initial phase saturations by means of equilibration. + * + * \tparam Region Type of an equilibration region information + * base. Typically an instance of the EquilReg + * class template. + * + * \tparam CellRange Type of cell range that demarcates the + * cells pertaining to the current + * equilibration region. Must implement + * methods begin() and end() to bound the range + * as well as provide an inner type, + * const_iterator, to traverse the range. + * + * \param[in] reg Current equilibration region. + * \param[in] cells Range that spans the cells of the current + * equilibration region. + * \param[in] props Property object, needed for capillary functions. + * \param[in] phase_pressures Phase pressures, one vector for each active phase, + * of pressure values in each cell in the current + * equilibration region. + * \return Phase saturations, one vector for each phase, each containing + * one saturation value per cell in the region. + */ + template + std::vector< std::vector > + phaseSaturations(const Region& reg, + const CellRange& cells, + const BlackoilPropertiesInterface& props, + const std::vector< std::vector >& phase_pressures) + { + const double z0 = reg.datum(); + const double zwoc = reg.zwoc (); + const double zgoc = reg.zgoc (); + if ((zgoc > z0) || (z0 > zwoc)) { + OPM_THROW(std::runtime_error, "Cannot initialise: the datum depth must be in the oil zone."); + } + if (!reg.phaseUsage().phase_used[BlackoilPhases::Liquid]) { + OPM_THROW(std::runtime_error, "Cannot initialise: not handling water-gas cases."); + } + + std::vector< std::vector > phase_saturations = phase_pressures; // Just to get the right size. + + const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + std::vector::size_type local_index = 0; + for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { + const int cell = *ci; + // Find saturations from pressure differences by + // inverting capillary pressure functions. + double sw = 0.0; + if (reg.phaseUsage().phase_used[BlackoilPhases::Aqua]) { + const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; + const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; + sw = satFromPc(props, waterpos, cell, pcov); + phase_saturations[waterpos][local_index] = sw; + } + double sg = 0.0; + if (reg.phaseUsage().phase_used[BlackoilPhases::Vapour]) { + const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + // Note that pcog is defined to be (pg - po), not (po - pg). + const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; + const double increasing = true; // pcog(sg) expected to be increasing function + sg = satFromPc(props, gaspos, cell, pcog, increasing); + phase_saturations[gaspos][local_index] = sg; + } + if (sg > 0.0 && sw > 0.0) { + // Overlapping gas-oil and oil-water transition + // zones. Must recalculate using gas-water + // capillary pressure. + const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; + const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; + sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); + sg = 1.0 - sw; + phase_saturations[waterpos][local_index] = sw; + phase_saturations[gaspos][local_index] = sg; + } + phase_saturations[oilpos][local_index] = 1.0 - sw - sg; + } + } + + + namespace DeckDependent { inline std::vector From 2ec3a80cfb5dc9fa25257260ae46fdab3374fe8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 20 Feb 2014 15:24:27 +0100 Subject: [PATCH 020/158] Fix bugs in saturation initialisation and helpers. --- opm/core/simulator/initStateEquil.hpp | 38 ++++++++++++++++++--------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 6613d550a..723776c14 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -661,12 +661,20 @@ namespace Opm // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc const PcEqSum f(props, phase1, phase2, cell, target_pc); - const int max_iter = 30; - const double tol = 1e-6; - int iter_used = -1; - typedef RegulaFalsi ScalarSolver; - const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used); - return sol; + const double f0 = f(smin); + const double f1 = f(smax); + if (f0 <= 0.0) { + return smin; + } else if (f1 > 0.0) { + return smax; + } else { + const int max_iter = 30; + const double tol = 1e-6; + int iter_used = -1; + typedef RegulaFalsi ScalarSolver; + const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used); + return sol; + } } @@ -760,35 +768,38 @@ namespace Opm } std::vector< std::vector > phase_saturations = phase_pressures; // Just to get the right size. + double smin[BlackoilPhases::MaxNumPhases] = { 0.0 }; + double smax[BlackoilPhases::MaxNumPhases] = { 0.0 }; + const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; + const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; + const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; std::vector::size_type local_index = 0; for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { const int cell = *ci; + props.satRange(1, &cell, smin, smax); // Find saturations from pressure differences by // inverting capillary pressure functions. double sw = 0.0; - if (reg.phaseUsage().phase_used[BlackoilPhases::Aqua]) { - const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; + if (water) { const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; sw = satFromPc(props, waterpos, cell, pcov); phase_saturations[waterpos][local_index] = sw; } double sg = 0.0; - if (reg.phaseUsage().phase_used[BlackoilPhases::Vapour]) { - const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + if (gas) { // Note that pcog is defined to be (pg - po), not (po - pg). const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; const double increasing = true; // pcog(sg) expected to be increasing function sg = satFromPc(props, gaspos, cell, pcog, increasing); phase_saturations[gaspos][local_index] = sg; } - if (sg > 0.0 && sw > 0.0) { + if (gas && water && sg > smin[gaspos] && sw > smin[waterpos]) { // Overlapping gas-oil and oil-water transition // zones. Must recalculate using gas-water // capillary pressure. - const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; - const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); sg = 1.0 - sw; @@ -797,6 +808,7 @@ namespace Opm } phase_saturations[oilpos][local_index] = 1.0 - sw - sg; } + return phase_saturations; } From 5b0534c372139b9fe3181d9158e88a5549c06400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 20 Feb 2014 15:39:15 +0100 Subject: [PATCH 021/158] Add another test deck for initialisation. This deck includes capillary functions. --- tests/capillary.DATA | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/capillary.DATA diff --git a/tests/capillary.DATA b/tests/capillary.DATA new file mode 100644 index 000000000..d8d163fcd --- /dev/null +++ b/tests/capillary.DATA @@ -0,0 +1,31 @@ +WATER +OIL +GAS + +PVDO +100 1.0 1.0 +200 0.9 1.0 +/ + +PVDG +100 0.010 0.1 +200 0.005 0.2 +/ + +SWOF +0.2 0 1 0.4 +1 1 0 0.1 +/ + +SGOF +0 0 1 0.2 +0.8 1 0 0.5 +/ + +DENSITY +700 1000 1 +/ + +EQUIL +50 150 50 0.25 20 0.35 +/ From cc50cb94c105c3d7ed7aa97a4c957b4c1229f52a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 21 Feb 2014 08:32:15 +0100 Subject: [PATCH 022/158] Add test case for capillary inversion. --- tests/test_equil.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index ff48cbc1a..712ee31c4 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -345,4 +346,58 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) +BOOST_AUTO_TEST_CASE (CapillaryInversion) +{ + // Test setup. + Opm::GridManager gm(1, 1, 40, 1.0, 1.0, 2.5); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::EclipseGridParser deck("capillary.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + + // Test the capillary inversion for oil-water. + const int cell = 0; + const double reltol = 1.0e-7; + { + const int phase = 0; + const bool increasing = false; + const std::vector pc = { 10.0e5, 0.5e5, 0.4e5, 0.3e5, 0.2e5, 0.1e5, 0.099e5, 0.0e5, -10.0e5 }; + const std::vector s = { 0.2, 0.2, 0.2, 0.466666666666, 0.733333333333, 1.0, 1.0, 1.0, 1.0 }; + BOOST_REQUIRE(pc.size() == s.size()); + for (size_t i = 0; i < pc.size(); ++i) { + const double s_computed = Opm::equil::satFromPc(props, phase, cell, pc[i], increasing); + BOOST_CHECK_CLOSE(s_computed, s[i], reltol); + } + } + + // Test the capillary inversion for gas-oil. + { + const int phase = 2; + const bool increasing = true; + const std::vector pc = { 10.0e5, 0.6e5, 0.5e5, 0.4e5, 0.3e5, 0.2e5, 0.1e5, 0.0e5, -10.0e5 }; + const std::vector s = { 0.8, 0.8, 0.8, 0.533333333333, 0.266666666666, 0.0, 0.0, 0.0, 0.0 }; + BOOST_REQUIRE(pc.size() == s.size()); + for (size_t i = 0; i < pc.size(); ++i) { + const double s_computed = Opm::equil::satFromPc(props, phase, cell, pc[i], increasing); + BOOST_CHECK_CLOSE(s_computed, s[i], reltol); + } + } + + // Test the capillary inversion for gas-water. + { + const int water = 0; + const int gas = 2; + const std::vector pc = { 0.9e5, 0.8e5, 0.6e5, 0.4e5, 0.3e5 }; + const std::vector s = { 0.2, 0.333333333333, 0.6, 0.866666666666, 1.0 }; + BOOST_REQUIRE(pc.size() == s.size()); + for (size_t i = 0; i < pc.size(); ++i) { + const double s_computed = Opm::equil::satFromSumOfPcs(props, water, gas, cell, pc[i]); + BOOST_CHECK_CLOSE(s_computed, s[i], reltol); + } + } +} + + + + + BOOST_AUTO_TEST_SUITE_END() From 9712b617473f3e0471b4db172aad33f74e3dd843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 21 Feb 2014 08:52:25 +0100 Subject: [PATCH 023/158] Add saturation computation to and rename computer class. Opm::equil::DeckDependent::PhasePressureComputer -> Opm::equil::DeckDependent::PhasePressureSaturationComputer --- opm/core/simulator/initStateEquil.hpp | 81 +++++++++++++++++++++++---- tests/test_equil.cpp | 4 +- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 723776c14..e3460bc97 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -871,42 +871,47 @@ namespace Opm } template - class PhasePressureComputer; + class PhasePressureSaturationComputer; template <> - class PhasePressureComputer { + class PhasePressureSaturationComputer { public: - PhasePressureComputer(const BlackoilPropertiesInterface& props, - const EclipseGridParser& deck , - const UnstructuredGrid& G , - const double grav = unit::gravity) + PhasePressureSaturationComputer(const BlackoilPropertiesInterface& props, + const EclipseGridParser& deck , + const UnstructuredGrid& G , + const double grav = unit::gravity) : pp_(props.numPhases(), + std::vector(G.number_of_cells)), + sat_(props.numPhases(), std::vector(G.number_of_cells)) { const std::vector rec = getEquil(deck); const RegionMapping<> eqlmap(equilnum(deck, G)); - calcII(eqlmap, rec, props, G, grav); + calcPressII(eqlmap, rec, props, G, grav); + calcSat(eqlmap, rec, props, G, grav); } typedef std::vector PVal; typedef std::vector PPress; const PPress& press() const { return pp_; } + const PPress& saturation() const { return sat_; } private: typedef DensityCalculator RhoCalc; typedef EquilReg EqReg; PPress pp_; + PPress sat_; template void - calcII(const RMap& reg , - const std::vector< EquilRecord >& rec , - const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , - const double grav) + calcPressII(const RMap& reg , + const std::vector< EquilRecord >& rec , + const Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G , + const double grav) { typedef miscibility::NoMixing NoMix; @@ -937,6 +942,58 @@ namespace Opm } } } + + template + void + calcSat(const RMap& reg , + const std::vector< EquilRecord >& rec , + const Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G , + const double grav) + { + typedef miscibility::NoMixing NoMix; + + for (typename RMap::RegionId + r = 0, nr = reg.numRegions(); + r < nr; ++r) + { + const typename RMap::CellRange cells = reg.cells(r); + + const int repcell = *cells.begin(); + const RhoCalc calc(props, repcell); + + const EqReg eqreg(rec[r], calc, NoMix(), NoMix(), + props.phaseUsage()); + + const PPress press = phasePressures(G, eqreg, cells, grav); + const PPress sat = phaseSaturations(eqreg, cells, props, press); + + for (int p = 0, np = props.numPhases(); p < np; ++p) { + PVal& d = pp_[p]; + PVal::const_iterator s = press[p].begin(); + for (typename RMap::CellRange::const_iterator + c = cells.begin(), + e = cells.end(); + c != e; ++c, ++s) + { + d[*c] = *s; + } + } + for (int p = 0, np = props.numPhases(); p < np; ++p) { + PVal& d = sat_[p]; + PVal::const_iterator s = sat[p].begin(); + for (typename RMap::CellRange::const_iterator + c = cells.begin(), + e = cells.end(); + c != e; ++c, ++s) + { + d[*c] = *s; + } + } + } + } + + }; } // namespace DeckDependent } // namespace equil diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 712ee31c4..831482185 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::EclipseGridParser deck("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); - Opm::equil::DeckDependent::PhasePressureComputer comp(props, deck, *grid, 10.0); + Opm::equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -398,6 +398,4 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) - - BOOST_AUTO_TEST_SUITE_END() From e51b161c890c46e52c7f02d774ed880793b97cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 21 Feb 2014 08:55:15 +0100 Subject: [PATCH 024/158] Add test case with capillary transition region. --- tests/test_equil.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 831482185..d62aa5f1c 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -398,4 +398,42 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) +BOOST_AUTO_TEST_CASE (DeckWithCapillary) +{ + Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::EclipseGridParser deck("capillary.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + + Opm::equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + const auto& pressures = comp.press(); + BOOST_REQUIRE(pressures.size() == 3); + BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + + const int first = 0, last = grid.number_of_cells - 1; + // The relative tolerance is too loose to be very useful, + // but the answer we are checking is the result of an ODE + // solver, and it is unclear if we should check it against + // the true answer or something else. + const double reltol = 1.0e-6; + BOOST_CHECK_CLOSE(pressures[0][first] , 1.45e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.5351621345e7 , reltol); + + const auto& sats = comp.saturation(); + const std::vector s[3]{ + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.425893333333, 0.774026666666, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.00736, 0.792746666666, 0.8, 0.8, 0.8, 0.8, 0.574106666666, 0.225973333333, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + for (int phase = 0; phase < 3; ++phase) { + BOOST_REQUIRE(sats[phase].size() == s[phase].size()); + for (size_t i = 0; i < s[phase].size(); ++i) { + BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); + } + } + +} + + BOOST_AUTO_TEST_SUITE_END() From 734046e16ea47e1ee6ecf36c545a013b7e5c3858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 21 Feb 2014 14:47:14 +0100 Subject: [PATCH 025/158] Fix bug in saturation initialisation. We shall only use gas-water capillary to initialise when we would get unphysical saturations otherwise. --- opm/core/simulator/initStateEquil.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index e3460bc97..8e2b561ff 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -796,9 +796,10 @@ namespace Opm sg = satFromPc(props, gaspos, cell, pcog, increasing); phase_saturations[gaspos][local_index] = sg; } - if (gas && water && sg > smin[gaspos] && sw > smin[waterpos]) { + if (gas && water && (sg + sw > 1.0)) { // Overlapping gas-oil and oil-water transition - // zones. Must recalculate using gas-water + // zones can lead to unphysical saturations when + // treated as above. Must recalculate using gas-water // capillary pressure. const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); From 652283d87de5b14e1c86d166a3f196e83e1991b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 21 Feb 2014 14:50:45 +0100 Subject: [PATCH 026/158] Add test case with overlapping transitions. Capillary pressure functions and contact depths have been modified to ensure a large overlap. --- tests/capillary_overlap.DATA | 31 +++++++++++++++++++++++++ tests/test_equil.cpp | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/capillary_overlap.DATA diff --git a/tests/capillary_overlap.DATA b/tests/capillary_overlap.DATA new file mode 100644 index 000000000..185784eee --- /dev/null +++ b/tests/capillary_overlap.DATA @@ -0,0 +1,31 @@ +WATER +OIL +GAS + +PVDO +100 1.0 1.0 +200 0.9 1.0 +/ + +PVDG +100 0.010 0.1 +200 0.005 0.2 +/ + +SWOF +0.2 0 1 0.9 +1 1 0 0.1 +/ + +SGOF +0 0 1 0.2 +0.8 1 0 0.5 +/ + +DENSITY +700 1000 1 +/ + +EQUIL +50 150 50 0.25 45 0.35 +/ diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index d62aa5f1c..c4db1786a 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -432,7 +432,51 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); } } +} + + +BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) +{ + Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::EclipseGridParser deck("capillary_overlap.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + + Opm::equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + const auto& pressures = comp.press(); + BOOST_REQUIRE(pressures.size() == 3); + BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + + const int first = 0, last = grid.number_of_cells - 1; + // The relative tolerance is too loose to be very useful, + // but the answer we are checking is the result of an ODE + // solver, and it is unclear if we should check it against + // the true answer or something else. + const double reltol = 1.0e-6; + BOOST_CHECK_CLOSE(pressures[0][first] , 1.45e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.5351621345e7 , reltol); + + const auto& sats = comp.saturation(); + // std::cout << "Saturations:\n"; + // for (const auto& sat : sats) { + // for (const double s : sat) { + // std::cout << s << ' '; + // } + // std::cout << std::endl; + // } + const std::vector s[3]{ + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.223141818182, 0.532269090909, 0.78471, 0.91526, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.207743333333, 0.08474, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.776858181818, 0.467730909091, 0.0075466666666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + for (int phase = 0; phase < 3; ++phase) { + BOOST_REQUIRE(sats[phase].size() == s[phase].size()); + for (size_t i = 0; i < s[phase].size(); ++i) { + BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); + } + } } From 6c75579c67912ff4dd4696e3012288d92255eca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 24 Feb 2014 13:47:03 +0100 Subject: [PATCH 027/158] Added class RsSatAtContact (not tested). --- opm/core/simulator/initStateEquil.hpp | 74 +++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 8e2b561ff..4ed2b6190 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -184,8 +184,82 @@ namespace Opm std::vector depth_; /**< Depth nodes */ std::vector rs_; /**< Dissolved gas-oil ratio */ }; + + + /** + * Class that implements "dissolved gas-oil ratio" (Rs) + * as function of depth and pressure as follows: + * + * 1. The Rs at the gas-oil contact is equal to the + * saturated Rs value, Rs_sat_contact. + * + * 2. The Rs elsewhere is equal to Rs_sat_contact, but + * constrained to the saturated value as given by the + * local pressure. + * + * This should yield Rs-values that are constant below the + * contact, and decreasing above the contact. + */ + class RsSatAtContact { + public: + /** + * Constructor. + * + * \param[in] props property object + * \param[in] cell any cell in the pvt region + * \param[in] p_contact oil pressure at the contact + */ + RsSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact) + : props_(props), cell_(cell) + { + auto pu = props_.phaseUsage(); + std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); + z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; + z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; + rs_sat_contact_ = satRs(p_contact); + } + + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. + */ + double + operator()(const double /* depth */, + const double press) const + { + return std::max(satRs(press), rs_sat_contact_); + } + + private: + const BlackoilPropertiesInterface& props_; + const int cell_; + double z_[BlackoilPhases::MaxNumPhases]; + double rs_sat_contact_; + mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; + + double satRs(const double press) const + { + props_.matrix(1, &press, z_, &cell_, A_, 0); + // Rs/Bo is in the gas row and oil column of A_. + // 1/Bo is in the oil row and column. + // Recall also that it is stored in column-major order. + const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const int np = props_.numPhases(); + return A_[np*opos + gpos] / A_[np*opos + opos]; + } + }; } // namespace miscibility + /** * Forward and reverse mappings between cells and * regions/partitions (e.g., the ECLIPSE-style 'SATNUM', From 07ca74800aa6420dbe0b9c89018f243c719e2041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 24 Feb 2014 15:19:04 +0100 Subject: [PATCH 028/158] Move RegionMapping class to its own header, add test. Class now resides in opm/core/utility/RegionMapping.hpp. --- opm/core/simulator/initStateEquil.hpp | 165 +--------------------- opm/core/utility/RegionMapping.hpp | 195 ++++++++++++++++++++++++++ tests/test_equil.cpp | 6 +- tests/test_regionmapping.cpp | 64 +++++++++ 4 files changed, 263 insertions(+), 167 deletions(-) create mode 100644 opm/core/utility/RegionMapping.hpp create mode 100644 tests/test_regionmapping.cpp diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 4ed2b6190..fd1c6721a 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -260,170 +261,6 @@ namespace Opm } // namespace miscibility - /** - * Forward and reverse mappings between cells and - * regions/partitions (e.g., the ECLIPSE-style 'SATNUM', - * 'PVTNUM', or 'EQUILNUM' arrays). - * - * \tparam Region Type of a forward region mapping. Expected - * to provide indexed access through - * operator[]() as well as inner types - * 'value_type', 'size_type', and - * 'const_iterator'. - */ - template < class Region = std::vector > - class RegionMapping { - public: - /** - * Constructor. - * - * \param[in] reg Forward region mapping, restricted to - * active cells only. - */ - explicit - RegionMapping(const Region& reg) - : reg_(reg) - { - rev_.init(reg_); - } - - /** - * Type of forward (cell-to-region) mapping result. - * Expected to be an integer. - */ - typedef typename Region::value_type RegionId; - - /** - * Type of reverse (region-to-cell) mapping (element) - * result. - */ - typedef typename Region::size_type CellId; - - /** - * Type of reverse region-to-cell range bounds and - * iterators. - */ - typedef typename std::vector::const_iterator CellIter; - - /** - * Range of cells. Result from reverse (region-to-cell) - * mapping. - */ - class CellRange { - public: - /** - * Constructor. - * - * \param[in] b Beginning of range. - * \param[in] e One past end of range. - */ - CellRange(const CellIter b, - const CellIter e) - : b_(b), e_(e) - {} - - /** - * Read-only iterator on cell ranges. - */ - typedef CellIter const_iterator; - - /** - * Beginning of cell range. - */ - const_iterator begin() const { return b_; } - - /** - * One past end of cell range. - */ - const_iterator end() const { return e_; } - - private: - const_iterator b_; - const_iterator e_; - }; - - /** - * Number of declared regions in cell-to-region mapping. - */ - RegionId - numRegions() const { return RegionId(rev_.p.size()) - 1; } - - /** - * Compute region number of given active cell. - * - * \param[in] c Active cell - * \return Region to which @c c belongs. - */ - RegionId - region(const CellId c) const { return reg_[c]; } - - /** - * Extract active cells in particular region. - * - * \param[in] r Region number - * \returns Range of active cells in region @c r. - */ - CellRange - cells(const RegionId r) const { - const RegionId i = r - rev_.low; - return CellRange(rev_.c.begin() + rev_.p[i + 0], - rev_.c.begin() + rev_.p[i + 1]); - } - - private: - /** - * Copy of forward region mapping (cell-to-region). - */ - Region reg_; - - /** - * Reverse mapping (region-to-cell). - */ - struct { - typedef typename std::vector::size_type Pos; - std::vector p; /**< Region start pointers */ - std::vector c; /**< Region cells */ - RegionId low; /**< Smallest region number */ - - /** - * Compute reverse mapping. Standard linear insertion - * sort algorithm. - */ - void - init(const Region& reg) - { - typedef typename Region::const_iterator CI; - const std::pair - m = std::minmax_element(reg.begin(), reg.end()); - - low = *m.first; - - const typename Region::size_type - n = *m.second - low + 1; - - p.resize(n + 1); std::fill(p.begin(), p.end(), Pos(0)); - for (CellId i = 0, nc = reg.size(); i < nc; ++i) { - p[ reg[i] - low + 1 ] += 1; - } - - for (typename std::vector::size_type - i = 1, sz = p.size(); i < sz; ++i) { - p[0] += p[i]; - p[i] = p[0] - p[i]; - } - - assert (p[0] == - static_cast(reg.size())); - - c.resize(reg.size()); - for (CellId i = 0, nc = reg.size(); i < nc; ++i) { - c[ p[ reg[i] - low + 1 ] ++ ] = i; - } - - p[0] = 0; - } - } rev_; /**< Reverse mapping instance */ - }; /** * Equilibration record. diff --git a/opm/core/utility/RegionMapping.hpp b/opm/core/utility/RegionMapping.hpp new file mode 100644 index 000000000..9845919ff --- /dev/null +++ b/opm/core/utility/RegionMapping.hpp @@ -0,0 +1,195 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_REGIONMAPPING_HEADER_INCLUDED +#define OPM_REGIONMAPPING_HEADER_INCLUDED + +#include + +namespace Opm +{ + + /** + * Forward and reverse mappings between cells and + * regions/partitions (e.g., the ECLIPSE-style 'SATNUM', + * 'PVTNUM', or 'EQUILNUM' arrays). + * + * \tparam Region Type of a forward region mapping. Expected + * to provide indexed access through + * operator[]() as well as inner types + * 'value_type', 'size_type', and + * 'const_iterator'. + */ + template < class Region = std::vector > + class RegionMapping { + public: + /** + * Constructor. + * + * \param[in] reg Forward region mapping, restricted to + * active cells only. + */ + explicit + RegionMapping(const Region& reg) + : reg_(reg) + { + rev_.init(reg_); + } + + /** + * Type of forward (cell-to-region) mapping result. + * Expected to be an integer. + */ + typedef typename Region::value_type RegionId; + + /** + * Type of reverse (region-to-cell) mapping (element) + * result. + */ + typedef typename Region::size_type CellId; + + /** + * Type of reverse region-to-cell range bounds and + * iterators. + */ + typedef typename std::vector::const_iterator CellIter; + + /** + * Range of cells. Result from reverse (region-to-cell) + * mapping. + */ + class CellRange { + public: + /** + * Constructor. + * + * \param[in] b Beginning of range. + * \param[in] e One past end of range. + */ + CellRange(const CellIter b, + const CellIter e) + : b_(b), e_(e) + {} + + /** + * Read-only iterator on cell ranges. + */ + typedef CellIter const_iterator; + + /** + * Beginning of cell range. + */ + const_iterator begin() const { return b_; } + + /** + * One past end of cell range. + */ + const_iterator end() const { return e_; } + + private: + const_iterator b_; + const_iterator e_; + }; + + /** + * Number of declared regions in cell-to-region mapping. + */ + RegionId + numRegions() const { return RegionId(rev_.p.size()) - 1; } + + /** + * Compute region number of given active cell. + * + * \param[in] c Active cell + * \return Region to which @c c belongs. + */ + RegionId + region(const CellId c) const { return reg_[c]; } + + /** + * Extract active cells in particular region. + * + * \param[in] r Region number + * \returns Range of active cells in region @c r. + */ + CellRange + cells(const RegionId r) const { + const RegionId i = r - rev_.low; + return CellRange(rev_.c.begin() + rev_.p[i + 0], + rev_.c.begin() + rev_.p[i + 1]); + } + + private: + /** + * Copy of forward region mapping (cell-to-region). + */ + Region reg_; + + /** + * Reverse mapping (region-to-cell). + */ + struct { + typedef typename std::vector::size_type Pos; + std::vector p; /**< Region start pointers */ + std::vector c; /**< Region cells */ + RegionId low; /**< Smallest region number */ + + /** + * Compute reverse mapping. Standard linear insertion + * sort algorithm. + */ + void + init(const Region& reg) + { + typedef typename Region::const_iterator CI; + const std::pair + m = std::minmax_element(reg.begin(), reg.end()); + + low = *m.first; + + const typename Region::size_type + n = *m.second - low + 1; + + p.resize(n + 1); std::fill(p.begin(), p.end(), Pos(0)); + for (CellId i = 0, nc = reg.size(); i < nc; ++i) { + p[ reg[i] - low + 1 ] += 1; + } + + for (typename std::vector::size_type + i = 1, sz = p.size(); i < sz; ++i) { + p[0] += p[i]; + p[i] = p[0] - p[i]; + } + + assert (p[0] == + static_cast(reg.size())); + + c.resize(reg.size()); + for (CellId i = 0, nc = reg.size(); i < nc; ++i) { + c[ p[ reg[i] - low + 1 ] ++ ] = i; + } + + p[0] = 0; + } + } rev_; /**< Reverse mapping instance */ + }; + +} // namespace Opm + +#endif // OPM_REGIONMAPPING_HEADER_INCLUDED diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index c4db1786a..4519f5f58 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -287,12 +287,12 @@ BOOST_AUTO_TEST_CASE (RegMapping) G->cartdims, cdim, &cells[0], &eqlnum[0]); } - Opm::equil::RegionMapping<> eqlmap(eqlnum); + Opm::RegionMapping<> eqlmap(eqlnum); PPress ppress(2, PVal(G->number_of_cells, 0)); for (int r = 0, e = eqlmap.numRegions(); r != e; ++r) { - const Opm::equil::RegionMapping<>::CellRange& + const Opm::RegionMapping<>::CellRange& rng = eqlmap.cells(r); const int rno = r; @@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE (RegMapping) Opm::equil::phasePressures(*G, region[rno], rng, grav); PVal::size_type i = 0; - for (Opm::equil::RegionMapping<>::CellRange::const_iterator + for (Opm::RegionMapping<>::CellRange::const_iterator c = rng.begin(), ce = rng.end(); c != ce; ++c, ++i) { diff --git a/tests/test_regionmapping.cpp b/tests/test_regionmapping.cpp new file mode 100644 index 000000000..ca2ad4eab --- /dev/null +++ b/tests/test_regionmapping.cpp @@ -0,0 +1,64 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#include "config.h" + +/* --- Boost.Test boilerplate --- */ +#if HAVE_DYNAMIC_BOOST_TEST +#define BOOST_TEST_DYN_LINK +#endif + +#define NVERBOSE // Suppress own messages when throw()ing + +#define BOOST_TEST_MODULE UnitsTest +#include +#include + +/* --- our own headers --- */ + +#include + + +BOOST_AUTO_TEST_SUITE () + + +BOOST_AUTO_TEST_CASE (RegionMapping) +{ + // 0 1 2 3 4 5 6 7 8 + std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; + Opm::RegionMapping<> rm(regions); + for (size_t i = 0; i < regions.size(); ++i) { + BOOST_CHECK_EQUAL(rm.region(i), regions[i]); + } + std::vector region_ids = { 2, 3, 4, 5, 6, 7 }; + std::vector< std::vector > region_cells = { { 0, 2, 4 }, { 7 }, { 3 }, { 1 }, { 6, 8 }, { 5 } }; + BOOST_REQUIRE_EQUAL(rm.numRegions(), region_ids.size()); + for (size_t i = 0; i < region_ids.size(); ++i) { + auto cells = rm.cells(region_ids[i]); + BOOST_REQUIRE_EQUAL(std::distance(cells.begin(), cells.end()), region_cells[i].size()); + size_t count = 0; + for (auto iter = cells.begin(); iter != cells.end(); ++iter, ++count) { + BOOST_CHECK_EQUAL(*iter, region_cells[i][count]); + } + } +} + + + +BOOST_AUTO_TEST_SUITE_END() From 50a7bae23ebc08480ec0b901aa220505d3672fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 24 Feb 2014 15:55:14 +0100 Subject: [PATCH 029/158] Capitalize nested namespace names. equil -> Equil miscibility -> Miscibility --- opm/core/simulator/initStateEquil.hpp | 16 ++-- opm/core/simulator/initStateEquil_impl.hpp | 4 +- tests/test_equil.cpp | 88 +++++++++++----------- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index fd1c6721a..1f6f11c5d 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -49,7 +49,7 @@ namespace Opm * This namespace is intentionally nested to avoid name clashes * with other parts of OPM. */ - namespace equil { + namespace Equil { template class DensityCalculator; @@ -116,7 +116,7 @@ namespace Opm * Types and routines relating to phase mixing in * equilibration calculations. */ - namespace miscibility { + namespace Miscibility { /** * Type that implements "no phase mixing" policy. */ @@ -258,7 +258,7 @@ namespace Opm return A_[np*opos + gpos] / A_[np*opos + opos]; } }; - } // namespace miscibility + } // namespace Miscibility @@ -336,8 +336,8 @@ namespace Opm * depth and (gas) pressure @c press. */ template + class RS = Miscibility::NoMixing, + class RV = Miscibility::NoMixing> class EquilReg { public: /** @@ -825,7 +825,7 @@ namespace Opm const UnstructuredGrid& G , const double grav) { - typedef miscibility::NoMixing NoMix; + typedef Miscibility::NoMixing NoMix; for (typename RMap::RegionId r = 0, nr = reg.numRegions(); @@ -863,7 +863,7 @@ namespace Opm const UnstructuredGrid& G , const double grav) { - typedef miscibility::NoMixing NoMix; + typedef Miscibility::NoMixing NoMix; for (typename RMap::RegionId r = 0, nr = reg.numRegions(); @@ -908,7 +908,7 @@ namespace Opm }; } // namespace DeckDependent - } // namespace equil + } // namespace Equil } // namespace Opm #include diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index a713e3b34..29ab6ac1d 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -485,7 +485,7 @@ namespace Opm } } // namespace Details - namespace equil { + namespace Equil { template std::vector< std::vector > @@ -568,7 +568,7 @@ namespace Opm return press; } - } // namespace equil + } // namespace Equil } // namespace Opm #endif // OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 4519f5f58..88bec0729 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -64,27 +64,27 @@ BOOST_AUTO_TEST_CASE (PhasePressure) typedef Opm::BlackoilPropertiesBasic Props; Props props(param, G->dimensions, G->number_of_cells); - typedef Opm::equil::DensityCalculator RhoCalc; + typedef Opm::Equil::DensityCalculator RhoCalc; RhoCalc calc(props, 0); - Opm::equil::EquilRecord record = + Opm::Equil::EquilRecord record = { { 0 , 1e5 } , // Datum depth, pressure { 5 , 0 } , // Zwoc , Pcow_woc { 0 , 0 } // Zgoc , Pcgo_goc }; - Opm::equil::EquilReg + Opm::Equil::EquilReg region(record, calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()); std::vector cells(G->number_of_cells); std::iota(cells.begin(), cells.end(), 0); const double grav = 10; - const PPress ppress = Opm::equil::phasePressures(*G, region, cells, grav); + const PPress ppress = Opm::Equil::phasePressures(*G, region, cells, grav); const int first = 0, last = G->number_of_cells - 1; const double reltol = 1.0e-8; @@ -118,10 +118,10 @@ BOOST_AUTO_TEST_CASE (CellSubset) typedef Opm::BlackoilPropertiesBasic Props; Props props(param, G->dimensions, G->number_of_cells); - typedef Opm::equil::DensityCalculator RhoCalc; + typedef Opm::Equil::DensityCalculator RhoCalc; RhoCalc calc(props, 0); - Opm::equil::EquilRecord record[] = + Opm::Equil::EquilRecord record[] = { { { 0 , 1e5 } , // Datum depth, pressure @@ -136,26 +136,26 @@ BOOST_AUTO_TEST_CASE (CellSubset) } }; - Opm::equil::EquilReg region[] = + Opm::Equil::EquilReg region[] = { - Opm::equil::EquilReg(record[0], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[0], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) , - Opm::equil::EquilReg(record[0], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[0], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) , - Opm::equil::EquilReg(record[1], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[1], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) , - Opm::equil::EquilReg(record[1], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[1], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) }; @@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE (CellSubset) const int rno = int(r - cells.begin()); const double grav = 10; const PPress p = - Opm::equil::phasePressures(*G, region[rno], *r, grav); + Opm::Equil::phasePressures(*G, region[rno], *r, grav); PVal::size_type i = 0; for (std::vector::const_iterator @@ -233,10 +233,10 @@ BOOST_AUTO_TEST_CASE (RegMapping) typedef Opm::BlackoilPropertiesBasic Props; Props props(param, G->dimensions, G->number_of_cells); - typedef Opm::equil::DensityCalculator RhoCalc; + typedef Opm::Equil::DensityCalculator RhoCalc; RhoCalc calc(props, 0); - Opm::equil::EquilRecord record[] = + Opm::Equil::EquilRecord record[] = { { { 0 , 1e5 } , // Datum depth, pressure @@ -251,26 +251,26 @@ BOOST_AUTO_TEST_CASE (RegMapping) } }; - Opm::equil::EquilReg region[] = + Opm::Equil::EquilReg region[] = { - Opm::equil::EquilReg(record[0], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[0], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) , - Opm::equil::EquilReg(record[0], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[0], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) , - Opm::equil::EquilReg(record[1], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[1], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) , - Opm::equil::EquilReg(record[1], calc, - Opm::equil::miscibility::NoMixing(), - Opm::equil::miscibility::NoMixing(), + Opm::Equil::EquilReg(record[1], calc, + Opm::Equil::Miscibility::NoMixing(), + Opm::Equil::Miscibility::NoMixing(), props.phaseUsage()) }; @@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE (RegMapping) const int rno = r; const double grav = 10; const PPress p = - Opm::equil::phasePressures(*G, region[rno], rng, grav); + Opm::Equil::phasePressures(*G, region[rno], rng, grav); PVal::size_type i = 0; for (Opm::RegionMapping<>::CellRange::const_iterator @@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::EclipseGridParser deck("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); - Opm::equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, *grid, 10.0); + Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -364,7 +364,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.2, 0.2, 0.2, 0.466666666666, 0.733333333333, 1.0, 1.0, 1.0, 1.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::equil::satFromPc(props, phase, cell, pc[i], increasing); + const double s_computed = Opm::Equil::satFromPc(props, phase, cell, pc[i], increasing); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -377,7 +377,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.8, 0.8, 0.8, 0.533333333333, 0.266666666666, 0.0, 0.0, 0.0, 0.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::equil::satFromPc(props, phase, cell, pc[i], increasing); + const double s_computed = Opm::Equil::satFromPc(props, phase, cell, pc[i], increasing); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -390,7 +390,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.2, 0.333333333333, 0.6, 0.866666666666, 1.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::equil::satFromSumOfPcs(props, water, gas, cell, pc[i]); + const double s_computed = Opm::Equil::satFromSumOfPcs(props, water, gas, cell, pc[i]); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -405,7 +405,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::EclipseGridParser deck("capillary.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::EclipseGridParser deck("capillary_overlap.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); From 7035e37737906ff1c7b8b32a82210fc35a8b8731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 24 Feb 2014 16:09:04 +0100 Subject: [PATCH 030/158] Moved equilibration utilities to separate file. --- opm/core/simulator/EquilibrationHelpers.hpp | 631 ++++++++++++++++++++ opm/core/simulator/initStateEquil.hpp | 540 +---------------- 2 files changed, 632 insertions(+), 539 deletions(-) create mode 100644 opm/core/simulator/EquilibrationHelpers.hpp diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp new file mode 100644 index 000000000..442702d6c --- /dev/null +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -0,0 +1,631 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED +#define OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED + +#include +#include +#include +#include +#include + + +/* +---- synopsis of EquilibrationHelpers.hpp ---- + +namespace Opm +{ + namespace Equil { + + template + class DensityCalculator; + + template <> + class DensityCalculator< BlackoilPropertiesInterface >; + + namespace Miscibility { + struct NoMixing; + class RsVD; + class RsSatAtContact; + } + + struct EquilRecord; + + template + class EquilReg; + + + struct PcEq; + + inline double satFromPc(const BlackoilPropertiesInterface& props, + const int phase, + const int cell, + const double target_pc, + const bool increasing = false); + struct PcEqSum + inline double satFromSumOfPcs(const BlackoilPropertiesInterface& props, + const int phase1, + const int phase2, + const int cell, + const double target_pc); + } // namespace Equil +} // namespace Opm + +---- end of synopsis of EquilibrationHelpers.hpp ---- +*/ + + +namespace Opm +{ + /** + * Types and routines that collectively implement a basic + * ECLIPSE-style equilibration-based initialisation scheme. + * + * This namespace is intentionally nested to avoid name clashes + * with other parts of OPM. + */ + namespace Equil { + + + template + class DensityCalculator; + + /** + * Facility for calculating phase densities based on the + * BlackoilPropertiesInterface. + * + * Implements the crucial operator()(p,svol) + * function that is expected by class EquilReg. + */ + template <> + class DensityCalculator< BlackoilPropertiesInterface > { + public: + /** + * Constructor. + * + * \param[in] props Implementation of the + * BlackoilPropertiesInterface. + * + * \param[in] c Single cell used as a representative cell + * in a PVT region. + */ + DensityCalculator(const BlackoilPropertiesInterface& props, + const int c) + : props_(props) + , c_(1, c) + { + } + + /** + * Compute phase densities of all phases at phase point + * given by (pressure, surface volume) tuple. + * + * \param[in] p Fluid pressure. + * + * \param[in] z Surface volumes of all phases. + * + * \return Phase densities at phase point. + */ + std::vector + operator()(const double p, + const std::vector& z) const + { + const int np = props_.numPhases(); + std::vector A(np * np, 0); + + assert (z.size() == std::vector::size_type(np)); + + double* dAdp = 0; + props_.matrix(1, &p, &z[0], &c_[0], &A[0], dAdp); + + std::vector rho(np, 0.0); + props_.density(1, &A[0], &rho[0]); + + return rho; + } + + private: + const BlackoilPropertiesInterface& props_; + const std::vector c_; + }; + + /** + * Types and routines relating to phase mixing in + * equilibration calculations. + */ + namespace Miscibility { + /** + * Type that implements "no phase mixing" policy. + */ + struct NoMixing { + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. In "no mixing + * policy", this is identically zero. + */ + double + operator()(const double /* depth */, + const double /* press */) const + { + return 0.0; + } + }; + + /** + * Type that implements "dissolved gas-oil ratio" + * tabulated as a function of depth policy. Data + * typically taken from keyword 'RSVD'. + */ + class RsVD { + public: + /** + * Constructor. + * + * \param[in] depth Depth nodes. + * \param[in] rs Dissolved gas-oil ratio at @c depth. + */ + RsVD(const std::vector& depth, + const std::vector& rs) + : depth_(depth) + , rs_(rs) + { + } + + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. + */ + double + operator()(const double depth, + const double /* press */) const + { + return linearInterpolation(depth_, rs_, depth); + } + + private: + std::vector depth_; /**< Depth nodes */ + std::vector rs_; /**< Dissolved gas-oil ratio */ + }; + + + /** + * Class that implements "dissolved gas-oil ratio" (Rs) + * as function of depth and pressure as follows: + * + * 1. The Rs at the gas-oil contact is equal to the + * saturated Rs value, Rs_sat_contact. + * + * 2. The Rs elsewhere is equal to Rs_sat_contact, but + * constrained to the saturated value as given by the + * local pressure. + * + * This should yield Rs-values that are constant below the + * contact, and decreasing above the contact. + */ + class RsSatAtContact { + public: + /** + * Constructor. + * + * \param[in] props property object + * \param[in] cell any cell in the pvt region + * \param[in] p_contact oil pressure at the contact + */ + RsSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact) + : props_(props), cell_(cell) + { + auto pu = props_.phaseUsage(); + std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); + z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; + z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; + rs_sat_contact_ = satRs(p_contact); + } + + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. + */ + double + operator()(const double /* depth */, + const double press) const + { + return std::max(satRs(press), rs_sat_contact_); + } + + private: + const BlackoilPropertiesInterface& props_; + const int cell_; + double z_[BlackoilPhases::MaxNumPhases]; + double rs_sat_contact_; + mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; + + double satRs(const double press) const + { + props_.matrix(1, &press, z_, &cell_, A_, 0); + // Rs/Bo is in the gas row and oil column of A_. + // 1/Bo is in the oil row and column. + // Recall also that it is stored in column-major order. + const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const int np = props_.numPhases(); + return A_[np*opos + gpos] / A_[np*opos + opos]; + } + }; + } // namespace Miscibility + + + + /** + * Equilibration record. + * + * Layout and contents inspired by first six items of + * ECLIPSE's 'EQUIL' records. This is the minimum amount of + * input data needed to define phase pressures in an + * equilibration region. + * + * Data consists of three pairs of depth and pressure values: + * 1. main + * - @c depth Main datum depth. + * - @c press Pressure at datum depth. + * + * 2. woc + * - @c depth Depth of water-oil contact + * - @c press water-oil capillary pressure at water-oil contact. + * Capillary pressure defined as "P_oil - P_water". + * + * 3. goc + * - @c depth Depth of gas-oil contact + * - @c press Gas-oil capillary pressure at gas-oil contact. + * Capillary pressure defined as "P_gas - P_oil". + */ + struct EquilRecord { + struct { + double depth; + double press; + } main, woc, goc; + }; + + /** + * Aggregate information base of an equilibration region. + * + * Provides inquiry methods for retrieving depths of contacs + * and pressure values as well as a means of calculating fluid + * densities, dissolved gas-oil ratio and vapourised oil-gas + * ratios. + * + * \tparam DensCalc Type that provides access to a phase + * density calculation facility. Must implement an operator() + * declared as + * + * std::vector + * operator()(const double press, + * const std::vector& svol ) + * + * that calculates the phase densities of all phases in @c + * svol at fluid pressure @c press. + * + * \tparam RS Type that provides access to a calculator for + * (initial) dissolved gas-oil ratios as a function of depth + * and (oil) pressure. Must implement an operator() declared + * as + * + * double + * operator()(const double depth, + * const double press) + * + * that calculates the dissolved gas-oil ratio at depth @c + * depth and (oil) pressure @c press. + * + * \tparam RV Type that provides access to a calculator for + * (initial) vapourised oil-gas ratios as a function of depth + * and (gas) pressure. Must implement an operator() declared + * as + * + * double + * operator()(const double depth, + * const double press) + * + * that calculates the vapourised oil-gas ratio at depth @c + * depth and (gas) pressure @c press. + */ + template + class EquilReg { + public: + /** + * Constructor. + * + * \param[in] rec Equilibration data of current region. + * \param[in] density Density calculator of current region. + * \param[in] rs Calculator of dissolved gas-oil ratio. + * \param[in] rv Calculator of vapourised oil-gas ratio. + * \param[in] pu Summary of current active phases. + */ + EquilReg(const EquilRecord& rec, + const DensCalc& density, + const RS& rs, + const RV& rv, + const PhaseUsage& pu) + : rec_ (rec) + , density_(density) + , rs_ (rs) + , rv_ (rv) + , pu_ (pu) + { + } + + /** + * Type of density calculator. + */ + typedef DensCalc CalcDensity; + + /** + * Type of dissolved gas-oil ratio calculator. + */ + typedef RS CalcDissolution; + + /** + * Type of vapourised oil-gas ratio calculator. + */ + typedef RV CalcEvaporation; + + /** + * Datum depth in current region + */ + double datum() const { return this->rec_.main.depth; } + + /** + * Pressure at datum depth in current region. + */ + double pressure() const { return this->rec_.main.press; } + + /** + * Depth of water-oil contact. + */ + double zwoc() const { return this->rec_.woc .depth; } + + /** + * water-oil capillary pressure at water-oil contact. + * + * \return P_o - P_w at WOC. + */ + double pcow_woc() const { return this->rec_.woc .press; } + + /** + * Depth of gas-oil contact. + */ + double zgoc() const { return this->rec_.goc .depth; } + + /** + * Gas-oil capillary pressure at gas-oil contact. + * + * \return P_g - P_o at GOC. + */ + double pcgo_goc() const { return this->rec_.goc .press; } + + /** + * Retrieve phase density calculator of current region. + */ + const CalcDensity& + densityCalculator() const { return this->density_; } + + /** + * Retrieve dissolved gas-oil ratio calculator of current + * region. + */ + const CalcDissolution& + dissolutionCalculator() const { return this->rs_; } + + /** + * Retrieve vapourised oil-gas ratio calculator of current + * region. + */ + const CalcEvaporation& + evaporationCalculator() const { return this->rv_; } + + /** + * Retrieve active fluid phase summary. + */ + const PhaseUsage& + phaseUsage() const { return this->pu_; } + + private: + EquilRecord rec_; /**< Equilibration data */ + DensCalc density_; /**< Density calculator */ + RS rs_; /**< RS calculator */ + RV rv_; /**< RV calculator */ + PhaseUsage pu_; /**< Active phase summary */ + }; + + + + /// Functor for inverting capillary pressure function. + /// Function represented is + /// f(s) = pc(s) - target_pc + struct PcEq + { + PcEq(const BlackoilPropertiesInterface& props, + const int phase, + const int cell, + const double target_pc) + : props_(props), + phase_(phase), + cell_(cell), + target_pc_(target_pc) + { + std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); + std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + } + double operator()(double s) const + { + s_[phase_] = s; + props_.capPress(1, s_, &cell_, pc_, 0); + return pc_[phase_] - target_pc_; + } + private: + const BlackoilPropertiesInterface& props_; + const int phase_; + const int cell_; + const int target_pc_; + mutable double s_[BlackoilPhases::MaxNumPhases]; + mutable double pc_[BlackoilPhases::MaxNumPhases]; + }; + + + + /// Compute saturation of some phase corresponding to a given + /// capillary pressure. + inline double satFromPc(const BlackoilPropertiesInterface& props, + const int phase, + const int cell, + const double target_pc, + const bool increasing = false) + { + // Find minimum and maximum saturations. + double sminarr[BlackoilPhases::MaxNumPhases]; + double smaxarr[BlackoilPhases::MaxNumPhases]; + props.satRange(1, &cell, sminarr, smaxarr); + const double s0 = increasing ? smaxarr[phase] : sminarr[phase]; + const double s1 = increasing ? sminarr[phase] : smaxarr[phase]; + + // Create the equation f(s) = pc(s) - target_pc + const PcEq f(props, phase, cell, target_pc); + const double f0 = f(s0); + const double f1 = f(s1); + if (f0 <= 0.0) { + return s0; + } else if (f1 > 0.0) { + return s1; + } else { + const int max_iter = 30; + const double tol = 1e-6; + int iter_used = -1; + typedef RegulaFalsi ScalarSolver; + const double sol = ScalarSolver::solve(f, std::min(s0, s1), std::max(s0, s1), max_iter, tol, iter_used); + return sol; + } + } + + + /// Functor for inverting a sum of capillary pressure functions. + /// Function represented is + /// f(s) = pc1(s) + pc2(1 - s) - target_pc + struct PcEqSum + { + PcEqSum(const BlackoilPropertiesInterface& props, + const int phase1, + const int phase2, + const int cell, + const double target_pc) + : props_(props), + phase1_(phase1), + phase2_(phase2), + cell_(cell), + target_pc_(target_pc) + { + std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); + std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + } + double operator()(double s) const + { + s_[phase1_] = s; + s_[phase2_] = 1.0 - s; + props_.capPress(1, s_, &cell_, pc_, 0); + return pc_[phase1_] + pc_[phase2_] - target_pc_; + } + private: + const BlackoilPropertiesInterface& props_; + const int phase1_; + const int phase2_; + const int cell_; + const int target_pc_; + mutable double s_[BlackoilPhases::MaxNumPhases]; + mutable double pc_[BlackoilPhases::MaxNumPhases]; + }; + + + + + /// Compute saturation of some phase corresponding to a given + /// capillary pressure, where the capillary pressure function + /// is given as a sum of two other functions. + inline double satFromSumOfPcs(const BlackoilPropertiesInterface& props, + const int phase1, + const int phase2, + const int cell, + const double target_pc) + { + // Find minimum and maximum saturations. + double sminarr[BlackoilPhases::MaxNumPhases]; + double smaxarr[BlackoilPhases::MaxNumPhases]; + props.satRange(1, &cell, sminarr, smaxarr); + const double smin = sminarr[phase1]; + const double smax = smaxarr[phase1]; + + // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc + const PcEqSum f(props, phase1, phase2, cell, target_pc); + const double f0 = f(smin); + const double f1 = f(smax); + if (f0 <= 0.0) { + return smin; + } else if (f1 > 0.0) { + return smax; + } else { + const int max_iter = 30; + const double tol = 1e-6; + int iter_used = -1; + typedef RegulaFalsi ScalarSolver; + const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used); + return sol; + } + } + + } // namespace Equil +} // namespace Opm + + +#endif // OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 1f6f11c5d..8e0490175 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -20,6 +20,7 @@ #ifndef OPM_INITSTATEEQUIL_HEADER_INCLUDED #define OPM_INITSTATEEQUIL_HEADER_INCLUDED +#include #include #include #include @@ -50,545 +51,6 @@ namespace Opm * with other parts of OPM. */ namespace Equil { - template - class DensityCalculator; - - /** - * Facility for calculating phase densities based on the - * BlackoilPropertiesInterface. - * - * Implements the crucial operator()(p,svol) - * function that is expected by class EquilReg. - */ - template <> - class DensityCalculator< BlackoilPropertiesInterface > { - public: - /** - * Constructor. - * - * \param[in] props Implementation of the - * BlackoilPropertiesInterface. - * - * \param[in] c Single cell used as a representative cell - * in a PVT region. - */ - DensityCalculator(const BlackoilPropertiesInterface& props, - const int c) - : props_(props) - , c_(1, c) - { - } - - /** - * Compute phase densities of all phases at phase point - * given by (pressure, surface volume) tuple. - * - * \param[in] p Fluid pressure. - * - * \param[in] z Surface volumes of all phases. - * - * \return Phase densities at phase point. - */ - std::vector - operator()(const double p, - const std::vector& z) const - { - const int np = props_.numPhases(); - std::vector A(np * np, 0); - - assert (z.size() == std::vector::size_type(np)); - - double* dAdp = 0; - props_.matrix(1, &p, &z[0], &c_[0], &A[0], dAdp); - - std::vector rho(np, 0.0); - props_.density(1, &A[0], &rho[0]); - - return rho; - } - - private: - const BlackoilPropertiesInterface& props_; - const std::vector c_; - }; - - /** - * Types and routines relating to phase mixing in - * equilibration calculations. - */ - namespace Miscibility { - /** - * Type that implements "no phase mixing" policy. - */ - struct NoMixing { - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. In "no mixing - * policy", this is identically zero. - */ - double - operator()(const double /* depth */, - const double /* press */) const - { - return 0.0; - } - }; - - /** - * Type that implements "dissolved gas-oil ratio" - * tabulated as a function of depth policy. Data - * typically taken from keyword 'RSVD'. - */ - class RsVD { - public: - /** - * Constructor. - * - * \param[in] depth Depth nodes. - * \param[in] rs Dissolved gas-oil ratio at @c depth. - */ - RsVD(const std::vector& depth, - const std::vector& rs) - : depth_(depth) - , rs_(rs) - { - } - - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. - */ - double - operator()(const double depth, - const double /* press */) const - { - return linearInterpolation(depth_, rs_, depth); - } - - private: - std::vector depth_; /**< Depth nodes */ - std::vector rs_; /**< Dissolved gas-oil ratio */ - }; - - - /** - * Class that implements "dissolved gas-oil ratio" (Rs) - * as function of depth and pressure as follows: - * - * 1. The Rs at the gas-oil contact is equal to the - * saturated Rs value, Rs_sat_contact. - * - * 2. The Rs elsewhere is equal to Rs_sat_contact, but - * constrained to the saturated value as given by the - * local pressure. - * - * This should yield Rs-values that are constant below the - * contact, and decreasing above the contact. - */ - class RsSatAtContact { - public: - /** - * Constructor. - * - * \param[in] props property object - * \param[in] cell any cell in the pvt region - * \param[in] p_contact oil pressure at the contact - */ - RsSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact) - : props_(props), cell_(cell) - { - auto pu = props_.phaseUsage(); - std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); - z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; - z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; - rs_sat_contact_ = satRs(p_contact); - } - - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. - */ - double - operator()(const double /* depth */, - const double press) const - { - return std::max(satRs(press), rs_sat_contact_); - } - - private: - const BlackoilPropertiesInterface& props_; - const int cell_; - double z_[BlackoilPhases::MaxNumPhases]; - double rs_sat_contact_; - mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; - - double satRs(const double press) const - { - props_.matrix(1, &press, z_, &cell_, A_, 0); - // Rs/Bo is in the gas row and oil column of A_. - // 1/Bo is in the oil row and column. - // Recall also that it is stored in column-major order. - const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const int np = props_.numPhases(); - return A_[np*opos + gpos] / A_[np*opos + opos]; - } - }; - } // namespace Miscibility - - - - /** - * Equilibration record. - * - * Layout and contents inspired by first six items of - * ECLIPSE's 'EQUIL' records. This is the minimum amount of - * input data needed to define phase pressures in an - * equilibration region. - * - * Data consists of three pairs of depth and pressure values: - * 1. main - * - @c depth Main datum depth. - * - @c press Pressure at datum depth. - * - * 2. woc - * - @c depth Depth of water-oil contact - * - @c press water-oil capillary pressure at water-oil contact. - * Capillary pressure defined as "P_oil - P_water". - * - * 3. goc - * - @c depth Depth of gas-oil contact - * - @c press Gas-oil capillary pressure at gas-oil contact. - * Capillary pressure defined as "P_gas - P_oil". - */ - struct EquilRecord { - struct { - double depth; - double press; - } main, woc, goc; - }; - - /** - * Aggregate information base of an equilibration region. - * - * Provides inquiry methods for retrieving depths of contacs - * and pressure values as well as a means of calculating fluid - * densities, dissolved gas-oil ratio and vapourised oil-gas - * ratios. - * - * \tparam DensCalc Type that provides access to a phase - * density calculation facility. Must implement an operator() - * declared as - * - * std::vector - * operator()(const double press, - * const std::vector& svol ) - * - * that calculates the phase densities of all phases in @c - * svol at fluid pressure @c press. - * - * \tparam RS Type that provides access to a calculator for - * (initial) dissolved gas-oil ratios as a function of depth - * and (oil) pressure. Must implement an operator() declared - * as - * - * double - * operator()(const double depth, - * const double press) - * - * that calculates the dissolved gas-oil ratio at depth @c - * depth and (oil) pressure @c press. - * - * \tparam RV Type that provides access to a calculator for - * (initial) vapourised oil-gas ratios as a function of depth - * and (gas) pressure. Must implement an operator() declared - * as - * - * double - * operator()(const double depth, - * const double press) - * - * that calculates the vapourised oil-gas ratio at depth @c - * depth and (gas) pressure @c press. - */ - template - class EquilReg { - public: - /** - * Constructor. - * - * \param[in] rec Equilibration data of current region. - * \param[in] density Density calculator of current region. - * \param[in] rs Calculator of dissolved gas-oil ratio. - * \param[in] rv Calculator of vapourised oil-gas ratio. - * \param[in] pu Summary of current active phases. - */ - EquilReg(const EquilRecord& rec, - const DensCalc& density, - const RS& rs, - const RV& rv, - const PhaseUsage& pu) - : rec_ (rec) - , density_(density) - , rs_ (rs) - , rv_ (rv) - , pu_ (pu) - { - } - - /** - * Type of density calculator. - */ - typedef DensCalc CalcDensity; - - /** - * Type of dissolved gas-oil ratio calculator. - */ - typedef RS CalcDissolution; - - /** - * Type of vapourised oil-gas ratio calculator. - */ - typedef RV CalcEvaporation; - - /** - * Datum depth in current region - */ - double datum() const { return this->rec_.main.depth; } - - /** - * Pressure at datum depth in current region. - */ - double pressure() const { return this->rec_.main.press; } - - /** - * Depth of water-oil contact. - */ - double zwoc() const { return this->rec_.woc .depth; } - - /** - * water-oil capillary pressure at water-oil contact. - * - * \return P_o - P_w at WOC. - */ - double pcow_woc() const { return this->rec_.woc .press; } - - /** - * Depth of gas-oil contact. - */ - double zgoc() const { return this->rec_.goc .depth; } - - /** - * Gas-oil capillary pressure at gas-oil contact. - * - * \return P_g - P_o at GOC. - */ - double pcgo_goc() const { return this->rec_.goc .press; } - - /** - * Retrieve phase density calculator of current region. - */ - const CalcDensity& - densityCalculator() const { return this->density_; } - - /** - * Retrieve dissolved gas-oil ratio calculator of current - * region. - */ - const CalcDissolution& - dissolutionCalculator() const { return this->rs_; } - - /** - * Retrieve vapourised oil-gas ratio calculator of current - * region. - */ - const CalcEvaporation& - evaporationCalculator() const { return this->rv_; } - - /** - * Retrieve active fluid phase summary. - */ - const PhaseUsage& - phaseUsage() const { return this->pu_; } - - private: - EquilRecord rec_; /**< Equilibration data */ - DensCalc density_; /**< Density calculator */ - RS rs_; /**< RS calculator */ - RV rv_; /**< RV calculator */ - PhaseUsage pu_; /**< Active phase summary */ - }; - - - - /// Functor for inverting capillary pressure function. - /// Function represented is - /// f(s) = pc(s) - target_pc - struct PcEq - { - PcEq(const BlackoilPropertiesInterface& props, - const int phase, - const int cell, - const double target_pc) - : props_(props), - phase_(phase), - cell_(cell), - target_pc_(target_pc) - { - std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); - std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); - } - double operator()(double s) const - { - s_[phase_] = s; - props_.capPress(1, s_, &cell_, pc_, 0); - return pc_[phase_] - target_pc_; - } - private: - const BlackoilPropertiesInterface& props_; - const int phase_; - const int cell_; - const int target_pc_; - mutable double s_[BlackoilPhases::MaxNumPhases]; - mutable double pc_[BlackoilPhases::MaxNumPhases]; - }; - - - - /// Compute saturation of some phase corresponding to a given - /// capillary pressure. - inline double satFromPc(const BlackoilPropertiesInterface& props, - const int phase, - const int cell, - const double target_pc, - const bool increasing = false) - { - // Find minimum and maximum saturations. - double sminarr[BlackoilPhases::MaxNumPhases]; - double smaxarr[BlackoilPhases::MaxNumPhases]; - props.satRange(1, &cell, sminarr, smaxarr); - const double s0 = increasing ? smaxarr[phase] : sminarr[phase]; - const double s1 = increasing ? sminarr[phase] : smaxarr[phase]; - - // Create the equation f(s) = pc(s) - target_pc - const PcEq f(props, phase, cell, target_pc); - const double f0 = f(s0); - const double f1 = f(s1); - if (f0 <= 0.0) { - return s0; - } else if (f1 > 0.0) { - return s1; - } else { - const int max_iter = 30; - const double tol = 1e-6; - int iter_used = -1; - typedef RegulaFalsi ScalarSolver; - const double sol = ScalarSolver::solve(f, std::min(s0, s1), std::max(s0, s1), max_iter, tol, iter_used); - return sol; - } - } - - - /// Functor for inverting a sum of capillary pressure functions. - /// Function represented is - /// f(s) = pc1(s) + pc2(1 - s) - target_pc - struct PcEqSum - { - PcEqSum(const BlackoilPropertiesInterface& props, - const int phase1, - const int phase2, - const int cell, - const double target_pc) - : props_(props), - phase1_(phase1), - phase2_(phase2), - cell_(cell), - target_pc_(target_pc) - { - std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); - std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); - } - double operator()(double s) const - { - s_[phase1_] = s; - s_[phase2_] = 1.0 - s; - props_.capPress(1, s_, &cell_, pc_, 0); - return pc_[phase1_] + pc_[phase2_] - target_pc_; - } - private: - const BlackoilPropertiesInterface& props_; - const int phase1_; - const int phase2_; - const int cell_; - const int target_pc_; - mutable double s_[BlackoilPhases::MaxNumPhases]; - mutable double pc_[BlackoilPhases::MaxNumPhases]; - }; - - - - - /// Compute saturation of some phase corresponding to a given - /// capillary pressure, where the capillary pressure function - /// is given as a sum of two other functions. - inline double satFromSumOfPcs(const BlackoilPropertiesInterface& props, - const int phase1, - const int phase2, - const int cell, - const double target_pc) - { - // Find minimum and maximum saturations. - double sminarr[BlackoilPhases::MaxNumPhases]; - double smaxarr[BlackoilPhases::MaxNumPhases]; - props.satRange(1, &cell, sminarr, smaxarr); - const double smin = sminarr[phase1]; - const double smax = smaxarr[phase1]; - - // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc - const PcEqSum f(props, phase1, phase2, cell, target_pc); - const double f0 = f(smin); - const double f1 = f(smax); - if (f0 <= 0.0) { - return smin; - } else if (f1 > 0.0) { - return smax; - } else { - const int max_iter = 30; - const double tol = 1e-6; - int iter_used = -1; - typedef RegulaFalsi ScalarSolver; - const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used); - return sol; - } - } - - /** * Compute initial phase pressures by means of equilibration. From 37635c9b582f5c12e65d0f128996ee2497a3e003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 24 Feb 2014 16:11:50 +0100 Subject: [PATCH 031/158] Prune includes. --- opm/core/simulator/initStateEquil.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 8e0490175..9be77685d 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -24,9 +24,7 @@ #include #include #include -#include #include -#include #include #include From 865469129fb48276cfb26668d7c59482c7caebaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 26 Feb 2014 14:16:51 +0100 Subject: [PATCH 032/158] Made NoMixing a class. For uniformity with its sibling classes. --- opm/core/simulator/EquilibrationHelpers.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 442702d6c..316b435be 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -41,7 +41,7 @@ namespace Opm class DensityCalculator< BlackoilPropertiesInterface >; namespace Miscibility { - struct NoMixing; + class NoMixing; class RsVD; class RsSatAtContact; } @@ -156,7 +156,8 @@ namespace Opm /** * Type that implements "no phase mixing" policy. */ - struct NoMixing { + class NoMixing { + public: /** * Function call. * From 0d25ad9ec488367df571807400abdda358a41985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 26 Feb 2014 14:47:24 +0100 Subject: [PATCH 033/158] Made phase mixing functors a class hierarchy. In summary: - added RsFunction (base class), - made NoMixing, RsVD, RsSatAtContact inherit RsFunction, - RS and RV are no longer template arguments for EquilReg class, - EquilReg constructor now takes two shared_ptr, - use of constructor updated, mostly using make_shared. --- opm/core/simulator/EquilibrationHelpers.hpp | 84 +++++++++++---------- opm/core/simulator/initStateEquil.hpp | 6 +- tests/test_equil.cpp | 36 ++++----- 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 316b435be..0588f3464 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -26,6 +26,8 @@ #include #include +#include + /* ---- synopsis of EquilibrationHelpers.hpp ---- @@ -41,6 +43,7 @@ namespace Opm class DensityCalculator< BlackoilPropertiesInterface >; namespace Miscibility { + class RsFunction; class NoMixing; class RsVD; class RsSatAtContact; @@ -48,9 +51,7 @@ namespace Opm struct EquilRecord; - template + template class EquilReg; @@ -148,15 +149,40 @@ namespace Opm const std::vector c_; }; + /** * Types and routines relating to phase mixing in * equilibration calculations. */ namespace Miscibility { + + /** + * Base class for phase mixing functions. + */ + class RsFunction + { + public: + /** + * Function call operator. + * + * \param[in] depth Depth at which to calculate RS + * value. + * + * \param[in] press Pressure at which to calculate RS + * value. + * + * \return Dissolved gas-oil ratio (RS) at depth @c + * depth and pressure @c press. + */ + virtual double operator()(const double depth, + const double press) const = 0; + }; + + /** * Type that implements "no phase mixing" policy. */ - class NoMixing { + class NoMixing : public RsFunction { public: /** * Function call. @@ -179,12 +205,13 @@ namespace Opm } }; + /** * Type that implements "dissolved gas-oil ratio" * tabulated as a function of depth policy. Data * typically taken from keyword 'RSVD'. */ - class RsVD { + class RsVD : public RsFunction { public: /** * Constructor. @@ -238,7 +265,7 @@ namespace Opm * This should yield Rs-values that are constant below the * contact, and decreasing above the contact. */ - class RsSatAtContact { + class RsSatAtContact : public RsFunction { public: /** * Constructor. @@ -295,6 +322,7 @@ namespace Opm return A_[np*opos + gpos] / A_[np*opos + opos]; } }; + } // namespace Miscibility @@ -347,34 +375,8 @@ namespace Opm * * that calculates the phase densities of all phases in @c * svol at fluid pressure @c press. - * - * \tparam RS Type that provides access to a calculator for - * (initial) dissolved gas-oil ratios as a function of depth - * and (oil) pressure. Must implement an operator() declared - * as - * - * double - * operator()(const double depth, - * const double press) - * - * that calculates the dissolved gas-oil ratio at depth @c - * depth and (oil) pressure @c press. - * - * \tparam RV Type that provides access to a calculator for - * (initial) vapourised oil-gas ratios as a function of depth - * and (gas) pressure. Must implement an operator() declared - * as - * - * double - * operator()(const double depth, - * const double press) - * - * that calculates the vapourised oil-gas ratio at depth @c - * depth and (gas) pressure @c press. */ - template + template class EquilReg { public: /** @@ -388,8 +390,8 @@ namespace Opm */ EquilReg(const EquilRecord& rec, const DensCalc& density, - const RS& rs, - const RV& rv, + std::shared_ptr rs, + std::shared_ptr rv, const PhaseUsage& pu) : rec_ (rec) , density_(density) @@ -407,12 +409,12 @@ namespace Opm /** * Type of dissolved gas-oil ratio calculator. */ - typedef RS CalcDissolution; + typedef Miscibility::RsFunction CalcDissolution; /** * Type of vapourised oil-gas ratio calculator. */ - typedef RV CalcEvaporation; + typedef Miscibility::RsFunction CalcEvaporation; /** * Datum depth in current region @@ -459,14 +461,14 @@ namespace Opm * region. */ const CalcDissolution& - dissolutionCalculator() const { return this->rs_; } + dissolutionCalculator() const { return *this->rs_; } /** * Retrieve vapourised oil-gas ratio calculator of current * region. */ const CalcEvaporation& - evaporationCalculator() const { return this->rv_; } + evaporationCalculator() const { return *this->rv_; } /** * Retrieve active fluid phase summary. @@ -477,8 +479,8 @@ namespace Opm private: EquilRecord rec_; /**< Equilibration data */ DensCalc density_; /**< Density calculator */ - RS rs_; /**< RS calculator */ - RV rv_; /**< RV calculator */ + std::shared_ptr rs_; /**< RS calculator */ + std::shared_ptr rv_; /**< RV calculator */ PhaseUsage pu_; /**< Active phase summary */ }; diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 9be77685d..aa9f78625 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -296,7 +296,8 @@ namespace Opm const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); - const EqReg eqreg(rec[r], calc, NoMix(), NoMix(), + const EqReg eqreg(rec[r], calc, + std::make_shared(), std::make_shared(), props.phaseUsage()); const PPress& res = phasePressures(G, eqreg, cells, grav); @@ -334,7 +335,8 @@ namespace Opm const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); - const EqReg eqreg(rec[r], calc, NoMix(), NoMix(), + const EqReg eqreg(rec[r], calc, + std::make_shared(), std::make_shared(), props.phaseUsage()); const PPress press = phasePressures(G, eqreg, cells, grav); diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 88bec0729..5a5e9019b 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -76,8 +76,8 @@ BOOST_AUTO_TEST_CASE (PhasePressure) Opm::Equil::EquilReg region(record, calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()); std::vector cells(G->number_of_cells); @@ -139,23 +139,23 @@ BOOST_AUTO_TEST_CASE (CellSubset) Opm::Equil::EquilReg region[] = { Opm::Equil::EquilReg(record[0], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) , Opm::Equil::EquilReg(record[0], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) , Opm::Equil::EquilReg(record[1], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) , Opm::Equil::EquilReg(record[1], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) }; @@ -254,23 +254,23 @@ BOOST_AUTO_TEST_CASE (RegMapping) Opm::Equil::EquilReg region[] = { Opm::Equil::EquilReg(record[0], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) , Opm::Equil::EquilReg(record[0], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) , Opm::Equil::EquilReg(record[1], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) , Opm::Equil::EquilReg(record[1], calc, - Opm::Equil::Miscibility::NoMixing(), - Opm::Equil::Miscibility::NoMixing(), + std::make_shared(), + std::make_shared(), props.phaseUsage()) }; From b6315cabd6b5d00116be698cf4d6e7693068c031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 26 Feb 2014 14:49:06 +0100 Subject: [PATCH 034/158] Removed redundant calcPressII() method. Pressure is also calculated in the calcPressSat() method. --- opm/core/simulator/initStateEquil.hpp | 53 +++------------------------ 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index aa9f78625..9ba625244 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -259,9 +259,7 @@ namespace Opm { const std::vector rec = getEquil(deck); const RegionMapping<> eqlmap(equilnum(deck, G)); - - calcPressII(eqlmap, rec, props, G, grav); - calcSat(eqlmap, rec, props, G, grav); + calcPressSat(eqlmap, rec, props, G, grav); } typedef std::vector PVal; @@ -279,50 +277,11 @@ namespace Opm template void - calcPressII(const RMap& reg , - const std::vector< EquilRecord >& rec , - const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , - const double grav) - { - typedef Miscibility::NoMixing NoMix; - - for (typename RMap::RegionId - r = 0, nr = reg.numRegions(); - r < nr; ++r) - { - const typename RMap::CellRange cells = reg.cells(r); - - const int repcell = *cells.begin(); - const RhoCalc calc(props, repcell); - - const EqReg eqreg(rec[r], calc, - std::make_shared(), std::make_shared(), - props.phaseUsage()); - - const PPress& res = phasePressures(G, eqreg, cells, grav); - - for (int p = 0, np = props.numPhases(); p < np; ++p) { - PVal& d = pp_[p]; - PVal::const_iterator s = res[p].begin(); - for (typename RMap::CellRange::const_iterator - c = cells.begin(), - e = cells.end(); - c != e; ++c, ++s) - { - d[*c] = *s; - } - } - } - } - - template - void - calcSat(const RMap& reg , - const std::vector< EquilRecord >& rec , - const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , - const double grav) + calcPressSat(const RMap& reg , + const std::vector< EquilRecord >& rec , + const Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G , + const double grav) { typedef Miscibility::NoMixing NoMix; From 843517e5178eeff4367c06a031470f60a5a65c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 08:31:03 +0100 Subject: [PATCH 035/158] Enable live oil in initialisation. --- opm/core/simulator/initStateEquil.hpp | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 9ba625244..d2ebae79f 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -257,8 +257,33 @@ namespace Opm sat_(props.numPhases(), std::vector(G.number_of_cells)) { + // Get the equilibration records. const std::vector rec = getEquil(deck); + + // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(deck, G)); + + // Create Rs functions. + rs_func_.reserve(rec.size()); + if (deck.hasField("DISGAS")) { + if (deck.hasField("RSVD")) { + // Rs has been specified as a function of depth. + OPM_THROW(std::runtime_error, "Cannot initialise: RSVD field not read by EclipseGridParser class."); + } else { + // Default initialisation: constant Rs below contact, saturated above. + for (size_t i = 0; i < rec.size(); ++i) { + const int cell = *(eqlmap.cells(i + 1).begin()); + const double p_contact = rec[i].goc.press; + rs_func_.push_back(std::make_shared(props, cell, p_contact)); + } + } + } else { + for (size_t i = 0; i < rec.size(); ++i) { + rs_func_.push_back(std::make_shared()); + } + } + + // Compute phase pressures and saturations. calcPressSat(eqlmap, rec, props, G, grav); } @@ -272,6 +297,8 @@ namespace Opm typedef DensityCalculator RhoCalc; typedef EquilReg EqReg; + std::vector< std::shared_ptr > rs_func_; + PPress pp_; PPress sat_; @@ -295,7 +322,7 @@ namespace Opm const RhoCalc calc(props, repcell); const EqReg eqreg(rec[r], calc, - std::make_shared(), std::make_shared(), + rs_func_[r], std::make_shared(), props.phaseUsage()); const PPress press = phasePressures(G, eqreg, cells, grav); From 9c047f453364f6208ecae7db2a13a5b3d9720e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 08:31:51 +0100 Subject: [PATCH 036/158] Add test for live oil initialisation. The test is not finished or verified yet. --- tests/equil_liveoil.DATA | 46 +++++++++++++++++++++++++++++++++++++++ tests/test_equil.cpp | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 tests/equil_liveoil.DATA diff --git a/tests/equil_liveoil.DATA b/tests/equil_liveoil.DATA new file mode 100644 index 000000000..5b2766915 --- /dev/null +++ b/tests/equil_liveoil.DATA @@ -0,0 +1,46 @@ +WATER +OIL +GAS +DISGAS + + + +PVTO +-- Rs Pbub Bo Vo + 0 1. 1.0000 1.20 / + 100 40. 1.0120 1.17 / + 200 80. 1.0255 1.14 / + 300 120. 1.0380 1.11 / + 400 160. 1.0510 1.08 / + 500 200. 1.0630 1.06 / + 600 240. 1.0750 1.03 / + 700 280. 1.0870 1.00 / + 800 320. 1.0985 .98 / + 900 360. 1.1100 .95 / + 1000 400. 1.1200 .94 + 500. 1.1189 .94 / + / + + +PVDG +100 0.010 0.1 +200 0.005 0.2 +/ + +SWOF +0.2 0 1 0.9 +1 1 0 0.1 +/ + +SGOF +0 0 1 0.2 +0.8 1 0 0.5 +/ + +DENSITY +700 1000 1 +/ + +EQUIL +50 150 50 0.25 45 0.35 +/ diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 5a5e9019b..3e1866772 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -480,4 +480,51 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) } + +BOOST_AUTO_TEST_CASE (DeckWithLiveOil) +{ + Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::EclipseGridParser deck("equil_liveoil.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + + Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + const auto& pressures = comp.press(); + BOOST_REQUIRE(pressures.size() == 3); + BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + + const int first = 0, last = grid.number_of_cells - 1; + // The relative tolerance is too loose to be very useful, + // but the answer we are checking is the result of an ODE + // solver, and it is unclear if we should check it against + // the true answer or something else. + const double reltol = 1.0e-6; + BOOST_CHECK_CLOSE(pressures[0][first] , 1.45e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.5489764605846416e7 , reltol); + + const auto& sats = comp.saturation(); + // std::cout << "Saturations:\n"; + // for (const auto& sat : sats) { + // for (const double s : sat) { + // std::cout << s << ' '; + // } + // std::cout << std::endl; + // } + const std::vector s[3]{ + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.223141818182, 0.532269090909, 0.78471, 0.91526, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.207743333333, 0.08474, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.776858181818, 0.467730909091, 0.0075466666666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + for (int phase = 0; phase < 3; ++phase) { + BOOST_REQUIRE(sats[phase].size() == s[phase].size()); + for (size_t i = 0; i < s[phase].size(); ++i) { + std::cout << sats[phase][i] << '\n'; + //BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); + } + std::cout << std::endl; + } +} + + BOOST_AUTO_TEST_SUITE_END() From a0d3bf6dd731d8248c0c34eadd28b1a4160e5220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 08:58:38 +0100 Subject: [PATCH 037/158] Added size() method to CellRange inner class. --- opm/core/utility/RegionMapping.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/opm/core/utility/RegionMapping.hpp b/opm/core/utility/RegionMapping.hpp index 9845919ff..151ad07b2 100644 --- a/opm/core/utility/RegionMapping.hpp +++ b/opm/core/utility/RegionMapping.hpp @@ -92,6 +92,11 @@ namespace Opm */ typedef CellIter const_iterator; + /** + * Size type for this range. + */ + typedef typename std::vector::size_type size_type; + /** * Beginning of cell range. */ @@ -102,6 +107,11 @@ namespace Opm */ const_iterator end() const { return e_; } + /** + * Number of elements in the range. + */ + size_type size() const { return e_ - b_; } + private: const_iterator b_; const_iterator e_; From 5ee2c0cbc90ee59de64ba48854ac3b0da845c2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 09:08:39 +0100 Subject: [PATCH 038/158] Rename PhasePressureSaturationComputer -> InitialStateComputer. Also add (unused so far) rs_ field to class. --- opm/core/simulator/initStateEquil.hpp | 51 +++++++++++++++++---------- tests/test_equil.cpp | 8 ++--- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index d2ebae79f..ee8bf7ac6 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -243,19 +243,20 @@ namespace Opm } template - class PhasePressureSaturationComputer; + class InitialStateComputer; template <> - class PhasePressureSaturationComputer { + class InitialStateComputer { public: - PhasePressureSaturationComputer(const BlackoilPropertiesInterface& props, - const EclipseGridParser& deck , - const UnstructuredGrid& G , - const double grav = unit::gravity) + InitialStateComputer(const BlackoilPropertiesInterface& props, + const EclipseGridParser& deck , + const UnstructuredGrid& G , + const double grav = unit::gravity) : pp_(props.numPhases(), std::vector(G.number_of_cells)), sat_(props.numPhases(), - std::vector(G.number_of_cells)) + std::vector(G.number_of_cells)), + rs_(G.number_of_cells) { // Get the equilibration records. const std::vector rec = getEquil(deck); @@ -287,11 +288,11 @@ namespace Opm calcPressSat(eqlmap, rec, props, G, grav); } - typedef std::vector PVal; - typedef std::vector PPress; + typedef std::vector Vec; + typedef std::vector PVec; // One per phase. - const PPress& press() const { return pp_; } - const PPress& saturation() const { return sat_; } + const PVec& press() const { return pp_; } + const PVec& saturation() const { return sat_; } private: typedef DensityCalculator RhoCalc; @@ -299,8 +300,9 @@ namespace Opm std::vector< std::shared_ptr > rs_func_; - PPress pp_; - PPress sat_; + PVec pp_; + PVec sat_; + Vec rs_; template void @@ -325,12 +327,13 @@ namespace Opm rs_func_[r], std::make_shared(), props.phaseUsage()); - const PPress press = phasePressures(G, eqreg, cells, grav); - const PPress sat = phaseSaturations(eqreg, cells, props, press); + const PVec press = phasePressures(G, eqreg, cells, grav); + const PVec sat = phaseSaturations(eqreg, cells, props, press); + const Vec rs(cells.size());// = gasOilRatio(); for (int p = 0, np = props.numPhases(); p < np; ++p) { - PVal& d = pp_[p]; - PVal::const_iterator s = press[p].begin(); + Vec& d = pp_[p]; + Vec::const_iterator s = press[p].begin(); for (typename RMap::CellRange::const_iterator c = cells.begin(), e = cells.end(); @@ -340,8 +343,8 @@ namespace Opm } } for (int p = 0, np = props.numPhases(); p < np; ++p) { - PVal& d = sat_[p]; - PVal::const_iterator s = sat[p].begin(); + Vec& d = sat_[p]; + Vec::const_iterator s = sat[p].begin(); for (typename RMap::CellRange::const_iterator c = cells.begin(), e = cells.end(); @@ -350,6 +353,16 @@ namespace Opm d[*c] = *s; } } + Vec::const_iterator s = rs.begin(); + Vec& d = rs_; + for (typename RMap::CellRange::const_iterator + c = cells.begin(), + e = cells.end(); + c != e; ++c, ++s) + { + d[*c] = *s; + } + } } diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 3e1866772..38bdff80d 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::EclipseGridParser deck("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); - Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, *grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -405,7 +405,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::EclipseGridParser deck("capillary.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::EclipseGridParser deck("capillary_overlap.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -488,7 +488,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::EclipseGridParser deck("equil_liveoil.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::PhasePressureSaturationComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); From 6144730b47e8a41c956bda8840d38724a6f5a260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 09:31:48 +0100 Subject: [PATCH 039/158] Refactor copying of region to global data. --- opm/core/simulator/initStateEquil.hpp | 48 ++++++++++----------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index ee8bf7ac6..6ddb80ef8 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -331,41 +331,27 @@ namespace Opm const PVec sat = phaseSaturations(eqreg, cells, props, press); const Vec rs(cells.size());// = gasOilRatio(); - for (int p = 0, np = props.numPhases(); p < np; ++p) { - Vec& d = pp_[p]; - Vec::const_iterator s = press[p].begin(); - for (typename RMap::CellRange::const_iterator - c = cells.begin(), - e = cells.end(); - c != e; ++c, ++s) - { - d[*c] = *s; - } + const int np = props.numPhases(); + for (int p = 0; p < np; ++p) { + copyFromRegion(press[p], cells, pp_[p]); + copyFromRegion(sat[p], cells, sat_[p]); } - for (int p = 0, np = props.numPhases(); p < np; ++p) { - Vec& d = sat_[p]; - Vec::const_iterator s = sat[p].begin(); - for (typename RMap::CellRange::const_iterator - c = cells.begin(), - e = cells.end(); - c != e; ++c, ++s) - { - d[*c] = *s; - } - } - Vec::const_iterator s = rs.begin(); - Vec& d = rs_; - for (typename RMap::CellRange::const_iterator - c = cells.begin(), - e = cells.end(); - c != e; ++c, ++s) - { - d[*c] = *s; - } - + copyFromRegion(rs, cells, rs_); } } + template + void copyFromRegion(const Vec& source, + const CellRangeType& cells, + Vec& destination) + { + auto s = source.begin(); + auto c = cells.begin(); + const auto e = cells.end(); + for (; c != e; ++c, ++s) { + destination[*c] = *s; + } + } }; } // namespace DeckDependent From b53944f30a1ef675fe61ca758812cf3ccf890ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 09:37:48 +0100 Subject: [PATCH 040/158] Moved implementation of phaseSaturations() to _impl file. --- opm/core/simulator/initStateEquil.hpp | 58 +----------------- opm/core/simulator/initStateEquil_impl.hpp | 70 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 57 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 6ddb80ef8..296e67747 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -126,63 +126,7 @@ namespace Opm phaseSaturations(const Region& reg, const CellRange& cells, const BlackoilPropertiesInterface& props, - const std::vector< std::vector >& phase_pressures) - { - const double z0 = reg.datum(); - const double zwoc = reg.zwoc (); - const double zgoc = reg.zgoc (); - if ((zgoc > z0) || (z0 > zwoc)) { - OPM_THROW(std::runtime_error, "Cannot initialise: the datum depth must be in the oil zone."); - } - if (!reg.phaseUsage().phase_used[BlackoilPhases::Liquid]) { - OPM_THROW(std::runtime_error, "Cannot initialise: not handling water-gas cases."); - } - - std::vector< std::vector > phase_saturations = phase_pressures; // Just to get the right size. - double smin[BlackoilPhases::MaxNumPhases] = { 0.0 }; - double smax[BlackoilPhases::MaxNumPhases] = { 0.0 }; - - const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; - const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; - const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; - const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - std::vector::size_type local_index = 0; - for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { - const int cell = *ci; - props.satRange(1, &cell, smin, smax); - // Find saturations from pressure differences by - // inverting capillary pressure functions. - double sw = 0.0; - if (water) { - const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; - sw = satFromPc(props, waterpos, cell, pcov); - phase_saturations[waterpos][local_index] = sw; - } - double sg = 0.0; - if (gas) { - // Note that pcog is defined to be (pg - po), not (po - pg). - const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; - const double increasing = true; // pcog(sg) expected to be increasing function - sg = satFromPc(props, gaspos, cell, pcog, increasing); - phase_saturations[gaspos][local_index] = sg; - } - if (gas && water && (sg + sw > 1.0)) { - // Overlapping gas-oil and oil-water transition - // zones can lead to unphysical saturations when - // treated as above. Must recalculate using gas-water - // capillary pressure. - const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; - sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); - sg = 1.0 - sw; - phase_saturations[waterpos][local_index] = sw; - phase_saturations[gaspos][local_index] = sg; - } - phase_saturations[oilpos][local_index] = 1.0 - sw - sg; - } - return phase_saturations; - } - + const std::vector< std::vector >& phase_pressures); namespace DeckDependent { diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 29ab6ac1d..03c10b4a4 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -485,7 +485,10 @@ namespace Opm } } // namespace Details + namespace Equil { + + template std::vector< std::vector > @@ -568,6 +571,73 @@ namespace Opm return press; } + + + + + template + std::vector< std::vector > + phaseSaturations(const Region& reg, + const CellRange& cells, + const BlackoilPropertiesInterface& props, + const std::vector< std::vector >& phase_pressures) + { + const double z0 = reg.datum(); + const double zwoc = reg.zwoc (); + const double zgoc = reg.zgoc (); + if ((zgoc > z0) || (z0 > zwoc)) { + OPM_THROW(std::runtime_error, "Cannot initialise: the datum depth must be in the oil zone."); + } + if (!reg.phaseUsage().phase_used[BlackoilPhases::Liquid]) { + OPM_THROW(std::runtime_error, "Cannot initialise: not handling water-gas cases."); + } + + std::vector< std::vector > phase_saturations = phase_pressures; // Just to get the right size. + double smin[BlackoilPhases::MaxNumPhases] = { 0.0 }; + double smax[BlackoilPhases::MaxNumPhases] = { 0.0 }; + + const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; + const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; + const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; + const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + std::vector::size_type local_index = 0; + for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { + const int cell = *ci; + props.satRange(1, &cell, smin, smax); + // Find saturations from pressure differences by + // inverting capillary pressure functions. + double sw = 0.0; + if (water) { + const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; + sw = satFromPc(props, waterpos, cell, pcov); + phase_saturations[waterpos][local_index] = sw; + } + double sg = 0.0; + if (gas) { + // Note that pcog is defined to be (pg - po), not (po - pg). + const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; + const double increasing = true; // pcog(sg) expected to be increasing function + sg = satFromPc(props, gaspos, cell, pcog, increasing); + phase_saturations[gaspos][local_index] = sg; + } + if (gas && water && (sg + sw > 1.0)) { + // Overlapping gas-oil and oil-water transition + // zones can lead to unphysical saturations when + // treated as above. Must recalculate using gas-water + // capillary pressure. + const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; + sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); + sg = 1.0 - sw; + phase_saturations[waterpos][local_index] = sw; + phase_saturations[gaspos][local_index] = sg; + } + phase_saturations[oilpos][local_index] = 1.0 - sw - sg; + } + return phase_saturations; + } + + } // namespace Equil } // namespace Opm From 128829e7c81b20049e14f6ba9ed968c74b0ffc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 10:39:18 +0100 Subject: [PATCH 041/158] Added Rv field to InitialStateComputer. It is currently not computed, as for Rs. --- opm/core/simulator/initStateEquil.hpp | 37 ++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 296e67747..98842fb4b 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -129,7 +129,11 @@ namespace Opm const std::vector< std::vector >& phase_pressures); + + + namespace DeckDependent { + inline std::vector getEquil(const EclipseGridParser& deck) @@ -168,6 +172,9 @@ namespace Opm } } + + + inline std::vector equilnum(const EclipseGridParser& deck, @@ -186,6 +193,9 @@ namespace Opm return eqlnum; } + + + template class InitialStateComputer; @@ -200,7 +210,8 @@ namespace Opm std::vector(G.number_of_cells)), sat_(props.numPhases(), std::vector(G.number_of_cells)), - rs_(G.number_of_cells) + rs_(G.number_of_cells), + rv_(G.number_of_cells) { // Get the equilibration records. const std::vector rec = getEquil(deck); @@ -228,8 +239,11 @@ namespace Opm } } - // Compute phase pressures and saturations. - calcPressSat(eqlmap, rec, props, G, grav); + // Compute pressures, saturations, rs and rv factors. + calcPressSatRsRv(eqlmap, rec, props, G, grav); + + // Modify oil pressure in no-oil regions so that the pressures of present phases can + // be recovered from the oil pressure and capillary relations. } typedef std::vector Vec; @@ -237,6 +251,8 @@ namespace Opm const PVec& press() const { return pp_; } const PVec& saturation() const { return sat_; } + const Vec& rs() const { return rs_; } + const Vec& rv() const { return rv_; } private: typedef DensityCalculator RhoCalc; @@ -247,14 +263,15 @@ namespace Opm PVec pp_; PVec sat_; Vec rs_; + Vec rv_; template void - calcPressSat(const RMap& reg , - const std::vector< EquilRecord >& rec , - const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , - const double grav) + calcPressSatRsRv(const RMap& reg , + const std::vector< EquilRecord >& rec , + const Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G , + const double grav) { typedef Miscibility::NoMixing NoMix; @@ -273,7 +290,8 @@ namespace Opm const PVec press = phasePressures(G, eqreg, cells, grav); const PVec sat = phaseSaturations(eqreg, cells, props, press); - const Vec rs(cells.size());// = gasOilRatio(); + const Vec rs(cells.size()); + const Vec rv(cells.size()); const int np = props.numPhases(); for (int p = 0; p < np; ++p) { @@ -281,6 +299,7 @@ namespace Opm copyFromRegion(sat[p], cells, sat_[p]); } copyFromRegion(rs, cells, rs_); + copyFromRegion(rv, cells, rv_); } } From d2741a76be8cf4f39d685ba4d85bc12404692177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 10:40:14 +0100 Subject: [PATCH 042/158] Add initStateEquil() function. It is not quite complete yet for the following reasons: - it does not compute state.surfacevol(), - the InitialStateComputer class does not compute Rs or Rv, - it has not been verified. --- opm/core/simulator/initStateEquil.hpp | 24 +++++++++ opm/core/simulator/initStateEquil_impl.hpp | 58 ++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 98842fb4b..43b34d2c7 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -21,6 +21,7 @@ #define OPM_INITSTATEEQUIL_HEADER_INCLUDED #include +#include #include #include #include @@ -41,6 +42,29 @@ struct UnstructuredGrid; namespace Opm { + + /** + * Compute initial state by an equilibration procedure. + * + * The following state fields are modified: + * pressure(), + * saturation(), + * surfacevol(), + * gasoilratio(), + * rv(). + * + * \param[in] grid Grid. + * \param[in] props Property object, pvt and capillary properties are used. + * \param[in] deck Simulation deck, used to obtain EQUIL and related data. + * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. + */ + void initStateEquil(const UnstructuredGrid& grid, + const BlackoilPropertiesInterface& props, + const EclipseGridParser& deck, + const double gravity, + BlackoilState& state); + + /** * Types and routines that collectively implement a basic * ECLIPSE-style equilibration-based initialisation scheme. diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 03c10b4a4..2b2f99dba 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -639,6 +639,64 @@ namespace Opm } // namespace Equil + + + namespace + { + /// Convert saturations from a vector of individual phase saturation vectors + /// to an interleaved format where all values for a given cell come before all + /// values for the next cell, all in a single vector. + std::vector convertSats(const std::vector< std::vector >& sat) + { + const int np = sat.size(); + const int nc = sat[0].size(); + std::vector s(np * nc); + for (int c = 0; c < nc; ++c) { + for (int p = 0; p < np; ++p) { + s[np*c + p] = sat[p][c]; + } + } + return s; + } + } + + + /** + * Compute initial state by an equilibration procedure. + * + * The following state fields are modified: + * pressure(), + * saturation(), + * surfacevol(), + * gasoilratio(), + * rv(). + * + * \param[in] grid Grid. + * \param[in] props Property object, pvt and capillary properties are used. + * \param[in] deck Simulation deck, used to obtain EQUIL and related data. + * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. + */ + void initStateEquil(const UnstructuredGrid& grid, + const BlackoilPropertiesInterface& props, + const EclipseGridParser& deck, + const double gravity, + BlackoilState& state) + { + typedef Equil::DeckDependent::InitialStateComputer ISC; + ISC isc(props, deck, grid, gravity); + const auto pu = props.phaseUsage(); + const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] + ? pu.phase_pos[BlackoilPhases::Liquid] + : pu.phase_pos[BlackoilPhases::Aqua]; + state.pressure() = isc.press()[ref_phase]; + state.saturation() = convertSats(isc.saturation()); + state.gasoilratio() = isc.rs(); + state.rv() = isc.rv(); + // TODO: state.surfacevol() must be computed from s, rs, rv. + } + + + } // namespace Opm #endif // OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED From 8728e43722fbfa3fb701fb2a4b64476af5b695c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 13:14:48 +0100 Subject: [PATCH 043/158] Add computeRs() function and use from InitialStateComputer. --- opm/core/simulator/initStateEquil.hpp | 36 +++++++++++++++++++--- opm/core/simulator/initStateEquil_impl.hpp | 35 +++++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 43b34d2c7..cb4051e05 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -154,6 +154,28 @@ namespace Opm + /** + * Compute initial Rs values. + * + * \tparam CellRangeType Type of cell range that demarcates the + * cells pertaining to the current + * equilibration region. Must implement + * methods begin() and end() to bound the range + * as well as provide an inner type, + * const_iterator, to traverse the range. + * + * \param[in] grid Grid. + * \param[in] cells Range that spans the cells of the current + * equilibration region. + * \param[in] oil_pressure Oil pressure for each cell in range. + * \param[in] rs_func Rs as function of pressure and depth. + * \return Rs values, one for each cell in the 'cells' range. + */ + template + std::vector computeRs(const UnstructuredGrid& grid, + const CellRangeType& cells, + const std::vector oil_pressure, + const Miscibility::RsFunction& rs_func); namespace DeckDependent { @@ -314,16 +336,20 @@ namespace Opm const PVec press = phasePressures(G, eqreg, cells, grav); const PVec sat = phaseSaturations(eqreg, cells, props, press); - const Vec rs(cells.size()); - const Vec rv(cells.size()); - const int np = props.numPhases(); for (int p = 0; p < np; ++p) { copyFromRegion(press[p], cells, pp_[p]); copyFromRegion(sat[p], cells, sat_[p]); } - copyFromRegion(rs, cells, rs_); - copyFromRegion(rv, cells, rv_); + if (props.phaseUsage().phase_used[BlackoilPhases::Liquid] + && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { + const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r])); + const Vec rv(cells.size(), 0.0); + std::cout << "rs.size() = " << rs.size() << std::endl; + copyFromRegion(rs, cells, rs_); + copyFromRegion(rv, cells, rv_); + } } } diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 2b2f99dba..c075f4ecb 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -638,6 +638,41 @@ namespace Opm } + /** + * Compute initial Rs values. + * + * \tparam CellRangeType Type of cell range that demarcates the + * cells pertaining to the current + * equilibration region. Must implement + * methods begin() and end() to bound the range + * as well as provide an inner type, + * const_iterator, to traverse the range. + * + * \param[in] grid Grid. + * \param[in] cells Range that spans the cells of the current + * equilibration region. + * \param[in] oil_pressure Oil pressure for each cell in range. + * \param[in] rs_func Rs as function of pressure and depth. + * \return Rs values, one for each cell in the 'cells' range. + */ + template + std::vector computeRs(const UnstructuredGrid& grid, + const CellRangeType& cells, + const std::vector oil_pressure, + const Miscibility::RsFunction& rs_func) + { + assert(grid.dimensions == 3); + std::vector rs(cells.size()); + int count = 0; + for (auto it = cells.begin(); it != cells.end(); ++it, ++count) { + const double depth = grid.cell_centroids[3*(*it) + 2]; + rs[count] = rs_func(depth, oil_pressure[count]); + } + return rs; + } + + + } // namespace Equil From 6e607115fda46dd005b5e85aafa4bc80da073aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 13:27:07 +0100 Subject: [PATCH 044/158] Remove debugging output. --- opm/core/simulator/initStateEquil.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index cb4051e05..1b81b07bd 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -346,7 +346,6 @@ namespace Opm const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r])); const Vec rv(cells.size(), 0.0); - std::cout << "rs.size() = " << rs.size() << std::endl; copyFromRegion(rs, cells, rs_); copyFromRegion(rv, cells, rv_); } From 0bfa30de7b7494318b3223bf8c6d9d121fd8ea78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 13:55:15 +0100 Subject: [PATCH 045/158] Added simple program example for initialisation. --- examples/compute_initial_state.cpp | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 examples/compute_initial_state.cpp diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp new file mode 100644 index 000000000..0b11ecf1c --- /dev/null +++ b/examples/compute_initial_state.cpp @@ -0,0 +1,104 @@ +/* + Copyright 2014 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + + +#if HAVE_CONFIG_H +#include "config.h" +#endif // HAVE_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param) + { + if (param.anyUnused()) { + std::cout << "-------------------- Unused parameters: --------------------\n"; + param.displayUsage(); + std::cout << "----------------------------------------------------------------" << std::endl; + } + } + + void outputData(const std::string& output_dir, + const std::string& name, + const std::vector& data) + { + std::ostringstream fname; + fname << output_dir << "/" << name; + boost::filesystem::path fpath = fname.str(); + try { + create_directories(fpath); + } + catch (...) { + OPM_THROW(std::runtime_error, "Creating directories failed: " << fpath); + } + fname << "/" << "initial.txt"; + std::ofstream file(fname.str().c_str()); + if (!file) { + OPM_THROW(std::runtime_error, "Failed to open " << fname.str()); + } + std::copy(data.begin(), data.end(), std::ostream_iterator(file, "\n")); + } + + + +} // anon namespace + + + +// ----------------- Main program ----------------- +int +main(int argc, char** argv) +try +{ + using namespace Opm; + + // Setup. + parameter::ParameterGroup param(argc, argv, false); + std::cout << "--------------- Reading parameters ---------------" << std::endl; + const std::string deck_filename = param.get("deck_filename"); + const double grav = param.getDefault("gravity", unit::gravity); + EclipseGridParser deck(deck_filename); + GridManager gm(deck); + const UnstructuredGrid& grid = *gm.c_grid(); + BlackoilPropertiesFromDeck props(deck, grid, param); + warnIfUnusedParams(param); + + // Initialisation. + BlackoilState state; + initStateEquil(grid, props, deck, grav, state); + + // Output. + const std::string output_dir = param.getDefault("output_dir", "output"); + outputData(output_dir, "pressure", state.pressure()); + outputData(output_dir, "saturation", state.saturation()); + outputData(output_dir, "rs", state.gasoilratio()); + outputData(output_dir, "rv", state.rv()); +} +catch (const std::exception& e) { + std::cerr << "Program threw an exception: " << e.what() << "\n"; + throw; +} From 1923de2694d8bbee1d25bb202bf41e089aecf86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 14:48:14 +0100 Subject: [PATCH 046/158] Fix bug in RS initialisation. Also throw if default init is specified and datum != goc depth. --- opm/core/simulator/initStateEquil.hpp | 8 +++++++- tests/equil_liveoil.DATA | 2 +- tests/test_equil.cpp | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 1b81b07bd..3767563f3 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -275,7 +275,13 @@ namespace Opm // Default initialisation: constant Rs below contact, saturated above. for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i + 1).begin()); - const double p_contact = rec[i].goc.press; + if (rec[i].goc.depth != rec[i].main.depth) { + OPM_THROW(std::runtime_error, + "Cannot initialise: when no explicit RSVD table is given, \n" + "datum depth must be at the gas-oil-contact. " + "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); + } + const double p_contact = rec[i].main.press; rs_func_.push_back(std::make_shared(props, cell, p_contact)); } } diff --git a/tests/equil_liveoil.DATA b/tests/equil_liveoil.DATA index 5b2766915..955a09b7f 100644 --- a/tests/equil_liveoil.DATA +++ b/tests/equil_liveoil.DATA @@ -42,5 +42,5 @@ DENSITY / EQUIL -50 150 50 0.25 45 0.35 +45 150 50 0.25 45 0.35 / diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 38bdff80d..6a175acc2 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -499,9 +499,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-6; - BOOST_CHECK_CLOSE(pressures[0][first] , 1.45e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.5489764605846416e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][first] , 1.4551328443106037e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 1.5501328443106037e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.5541598197355453e7 , reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; From b8d48a5fc88724d6e0ad623faa74962ee4eadb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 27 Feb 2014 14:57:38 +0100 Subject: [PATCH 047/158] Bugfix in RsSatAtContact: use min(), not max(). Also modified test to match output. --- opm/core/simulator/EquilibrationHelpers.hpp | 2 +- tests/test_equil.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 0588f3464..0d4d08196 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -300,7 +300,7 @@ namespace Opm operator()(const double /* depth */, const double press) const { - return std::max(satRs(press), rs_sat_contact_); + return std::min(satRs(press), rs_sat_contact_); } private: diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 6a175acc2..b4df1fae8 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -499,9 +499,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-6; - BOOST_CHECK_CLOSE(pressures[0][first] , 1.4551328443106037e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 1.5501328443106037e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.5541598197355453e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][first], 1.4551302072306179e7, reltol); + BOOST_CHECK_CLOSE(pressures[0][last], 1.5501302072306179e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][last], 1.5538684664272346e7, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; From c5b07d962391531a6feaca6c06fc28fc60ad99d6 Mon Sep 17 00:00:00 2001 From: osae Date: Wed, 26 Mar 2014 14:08:39 +0100 Subject: [PATCH 048/158] Some adjustments to equil initialisation. - Saturations, phase pressures, and standard initialsation of RS and RV now agree to baseline. - Tables of RS and RV versus vertical depth (kw RSVD RVVD) have been hardcoded for testing (need new parser) and the calculations agree to baseline in the gas and oil zones. In the water zone there is some differences: Our code computes saturated RS and RV using the final phase pressures (these are modified to be consistent with saturations and capillary pressures) while the baseline uses unmodified phase pressures. --- opm/core/simulator/EquilibrationHelpers.hpp | 213 +++++++++++++++++++- opm/core/simulator/initStateEquil.hpp | 91 +++++++-- opm/core/simulator/initStateEquil_impl.hpp | 34 +++- 3 files changed, 306 insertions(+), 32 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 0d4d08196..d89dd8c3c 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -175,7 +175,8 @@ namespace Opm * depth and pressure @c press. */ virtual double operator()(const double depth, - const double press) const = 0; + const double press, + const double sat = 0.0) const = 0; }; @@ -199,7 +200,8 @@ namespace Opm */ double operator()(const double /* depth */, - const double /* press */) const + const double /* press */, + const double sat = 0.0) const { return 0.0; } @@ -216,14 +218,24 @@ namespace Opm /** * Constructor. * + * \param[in] props property object + * \param[in] cell any cell in the pvt region * \param[in] depth Depth nodes. * \param[in] rs Dissolved gas-oil ratio at @c depth. */ - RsVD(const std::vector& depth, + RsVD(const BlackoilPropertiesInterface& props, + const int cell, + const std::vector& depth, const std::vector& rs) - : depth_(depth) + : props_(props) + , cell_(cell) + , depth_(depth) , rs_(rs) { + auto pu = props_.phaseUsage(); + std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); + z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; + z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; } /** @@ -240,14 +252,111 @@ namespace Opm */ double operator()(const double depth, - const double /* press */) const + const double press, + const double sat_gas = 0.0) const { - return linearInterpolation(depth_, rs_, depth); + if (sat_gas > 0.0) { + return satRs(press); + } else { + return std::min(satRs(press), linearInterpolation(depth_, rs_, depth)); + } } private: + const BlackoilPropertiesInterface& props_; + const int cell_; std::vector depth_; /**< Depth nodes */ std::vector rs_; /**< Dissolved gas-oil ratio */ + double z_[BlackoilPhases::MaxNumPhases]; + mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; + + double satRs(const double press) const + { + props_.matrix(1, &press, z_, &cell_, A_, 0); + // Rs/Bo is in the gas row and oil column of A_. + // 1/Bo is in the oil row and column. + // Recall also that it is stored in column-major order. + const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const int np = props_.numPhases(); + return A_[np*opos + gpos] / A_[np*opos + opos]; + } + }; + + + /** + * Type that implements "vaporized oil-gas ratio" + * tabulated as a function of depth policy. Data + * typically taken from keyword 'RVVD'. + */ + class RvVD : public RsFunction { + public: + /** + * Constructor. + * + * \param[in] props property object + * \param[in] cell any cell in the pvt region + * \param[in] depth Depth nodes. + * \param[in] rv Dissolved gas-oil ratio at @c depth. + */ + RvVD(const BlackoilPropertiesInterface& props, + const int cell, + const std::vector& depth, + const std::vector& rv) + : props_(props) + , cell_(cell) + , depth_(depth) + , rv_(rv) + { + auto pu = props_.phaseUsage(); + std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); + z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0; + z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1e100; + } + + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RV + * value. + * + * \param[in] press Pressure at which to calculate RV + * value. + * + * \return Vaporized oil-gas ratio (RV) at depth @c + * depth and pressure @c press. + */ + double + operator()(const double depth, + const double press, + const double sat_oil = 0.0 ) const + { + if (sat_oil > 0.0) { + return satRv(press); + } else { + return std::min(satRv(press), linearInterpolation(depth_, rv_, depth)); + } + } + + private: + const BlackoilPropertiesInterface& props_; + const int cell_; + std::vector depth_; /**< Depth nodes */ + std::vector rv_; /**< Vaporized oil-gas ratio */ + double z_[BlackoilPhases::MaxNumPhases]; + mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; + + double satRv(const double press) const + { + props_.matrix(1, &press, z_, &cell_, A_, 0); + // Rv/Bg is in the oil row and gas column of A_. + // 1/Bg is in the gas row and column. + // Recall also that it is stored in column-major order. + const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const int np = props_.numPhases(); + return A_[np*gpos + opos] / A_[np*gpos + gpos]; + } }; @@ -298,9 +407,14 @@ namespace Opm */ double operator()(const double /* depth */, - const double press) const - { - return std::min(satRs(press), rs_sat_contact_); + const double press, + const double sat_gas = 0.0) const + { + if (sat_gas > 0.0) { + return satRs(press); + } else { + return std::min(satRs(press), rs_sat_contact_); + } } private: @@ -323,6 +437,84 @@ namespace Opm } }; + + /** + * Class that implements "vaporized oil-gas ratio" (Rv) + * as function of depth and pressure as follows: + * + * 1. The Rv at the gas-oil contact is equal to the + * saturated Rv value, Rv_sat_contact. + * + * 2. The Rv elsewhere is equal to Rv_sat_contact, but + * constrained to the saturated value as given by the + * local pressure. + * + * This should yield Rv-values that are constant below the + * contact, and decreasing above the contact. + */ + class RvSatAtContact : public RsFunction { + public: + /** + * Constructor. + * + * \param[in] props property object + * \param[in] cell any cell in the pvt region + * \param[in] p_contact oil pressure at the contact + */ + RvSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact) + : props_(props), cell_(cell) + { + auto pu = props_.phaseUsage(); + std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); + z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0; + z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1e100; + rv_sat_contact_ = satRv(p_contact); + } + + /** + * Function call. + * + * \param[in] depth Depth at which to calculate RV + * value. + * + * \param[in] press Pressure at which to calculate RV + * value. + * + * \return Dissolved oil-gas ratio (RV) at depth @c + * depth and pressure @c press. + */ + double + operator()(const double /*depth*/, + const double press, + const double sat_oil = 0.0) const + { + if (sat_oil > 0.0) { + return satRv(press); + } else { + return std::min(satRv(press), rv_sat_contact_); + } + } + + private: + const BlackoilPropertiesInterface& props_; + const int cell_; + double z_[BlackoilPhases::MaxNumPhases]; + double rv_sat_contact_; + mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; + + double satRv(const double press) const + { + props_.matrix(1, &press, z_, &cell_, A_, 0); + // Rv/Bg is in the oil row and gas column of A_. + // 1/Bg is in the gas row and column. + // Recall also that it is stored in column-major order. + const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const int np = props_.numPhases(); + return A_[np*gpos + opos] / A_[np*gpos + gpos]; + } + }; + } // namespace Miscibility @@ -355,6 +547,9 @@ namespace Opm double depth; double press; } main, woc, goc; + int live_oil_table_index; + int wet_gas_table_index; + int N; }; /** diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 3767563f3..566f2b00f 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -175,8 +175,8 @@ namespace Opm std::vector computeRs(const UnstructuredGrid& grid, const CellRangeType& cells, const std::vector oil_pressure, - const Miscibility::RsFunction& rs_func); - + const Miscibility::RsFunction& rs_func, + const std::vector gas_saturation); namespace DeckDependent { @@ -205,8 +205,17 @@ namespace Opm , { rec.gas_oil_contact_depth_ , rec.gas_oil_cap_pressure_ } + , + rec.live_oil_table_index_ + , + rec.wet_gas_table_index_ + , + rec.N_ }; - + if (record.N != 0) { + OPM_THROW(std::domain_error, + "kw EQUIL, item 9: Only N=0 supported."); + } ret.push_back(record); } @@ -267,14 +276,25 @@ namespace Opm // Create Rs functions. rs_func_.reserve(rec.size()); - if (deck.hasField("DISGAS")) { - if (deck.hasField("RSVD")) { - // Rs has been specified as a function of depth. - OPM_THROW(std::runtime_error, "Cannot initialise: RSVD field not read by EclipseGridParser class."); - } else { - // Default initialisation: constant Rs below contact, saturated above. - for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); + if (deck.hasField("DISGAS")) { + for (size_t i = 0; i < rec.size(); ++i) { + const int cell = *(eqlmap.cells(i + 1).begin()); + // TODO Check this ... + // The index is here picked as a representative for its equlibrium region, + // but is below used to identify PVT region. + // This assumes that an eq-region has uniform pvt properties, is this always ok? + // For Norne this is trivial, as there is only one active pvt-region (PVTNUM=1 for all cells): + if (rec[i].live_oil_table_index > 0) { + if (deck.hasField("RSVD")) { + // TODO When this kw is actually parsed, also check for proper number of available tables + // For now, just use dummy ... + std::vector depth; depth.push_back(0.0); depth.push_back(100.0); + std::vector rs; rs.push_back(0.0); rs.push_back(100.0); + rs_func_.push_back(std::make_shared(props, cell, depth, rs)); + } else { + OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); + } + } else { if (rec[i].goc.depth != rec[i].main.depth) { OPM_THROW(std::runtime_error, "Cannot initialise: when no explicit RSVD table is given, \n" @@ -289,8 +309,40 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { rs_func_.push_back(std::make_shared()); } - } + } + rv_func_.reserve(rec.size()); + if (deck.hasField("VAPOIL")) { + for (size_t i = 0; i < rec.size(); ++i) { + const int cell = *(eqlmap.cells(i + 1).begin()); + // TODO Similar as above: eq-region vs pvt-region ... + if (rec[i].wet_gas_table_index > 0) { + if (deck.hasField("RVVD")) { + // TODO When this kw is actually parsed, also check for proper number of available tables + // For now, just use dummy ... + std::vector depth; depth.push_back(0.0); depth.push_back(100.0); + std::vector rv; rv.push_back(0.0); rv.push_back(0.0001); + rv_func_.push_back(std::make_shared(props, cell, depth, rv)); + } else { + OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); + } + } else { + if (rec[i].goc.depth != rec[i].main.depth) { + OPM_THROW(std::runtime_error, + "Cannot initialise: when no explicit RVVD table is given, \n" + "datum depth must be at the gas-oil-contact. " + "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); + } + const double p_contact = rec[i].main.press + rec[i].goc.press; + rv_func_.push_back(std::make_shared(props, cell, p_contact)); + } + } + } else { + for (size_t i = 0; i < rec.size(); ++i) { + rv_func_.push_back(std::make_shared()); + } + } + // Compute pressures, saturations, rs and rv factors. calcPressSatRsRv(eqlmap, rec, props, G, grav); @@ -311,6 +363,7 @@ namespace Opm typedef EquilReg EqReg; std::vector< std::shared_ptr > rs_func_; + std::vector< std::shared_ptr > rv_func_; PVec pp_; PVec sat_; @@ -335,13 +388,14 @@ namespace Opm const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); - const EqReg eqreg(rec[r], calc, - rs_func_[r], std::make_shared(), + rs_func_[r], rv_func_[r], props.phaseUsage()); - - const PVec press = phasePressures(G, eqreg, cells, grav); + + PVec press = phasePressures(G, eqreg, cells, grav); + const PVec sat = phaseSaturations(eqreg, cells, props, press); + const int np = props.numPhases(); for (int p = 0; p < np; ++p) { copyFromRegion(press[p], cells, pp_[p]); @@ -350,8 +404,9 @@ namespace Opm if (props.phaseUsage().phase_used[BlackoilPhases::Liquid] && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r])); - const Vec rv(cells.size(), 0.0); + const int gaspos = props.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r]), sat[gaspos]); + const Vec rv = computeRs(G, cells, press[gaspos], *(rv_func_[r]), sat[oilpos]); copyFromRegion(rs, cells, rs_); copyFromRegion(rv, cells, rv_); } diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index c075f4ecb..6c9912151 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -580,7 +580,7 @@ namespace Opm phaseSaturations(const Region& reg, const CellRange& cells, const BlackoilPropertiesInterface& props, - const std::vector< std::vector >& phase_pressures) + std::vector< std::vector >& phase_pressures) { const double z0 = reg.datum(); const double zwoc = reg.zwoc (); @@ -621,6 +621,7 @@ namespace Opm sg = satFromPc(props, gaspos, cell, pcog, increasing); phase_saturations[gaspos][local_index] = sg; } + bool overlap = false; if (gas && water && (sg + sw > 1.0)) { // Overlapping gas-oil and oil-water transition // zones can lead to unphysical saturations when @@ -631,8 +632,32 @@ namespace Opm sg = 1.0 - sw; phase_saturations[waterpos][local_index] = sw; phase_saturations[gaspos][local_index] = sg; + overlap = true; } phase_saturations[oilpos][local_index] = 1.0 - sw - sg; + + // Adjust phase pressures for max and min saturation ... + double pc[BlackoilPhases::MaxNumPhases]; + double sat[BlackoilPhases::MaxNumPhases]; + if (sw > smax[waterpos]-1.0e-6) { + sat[waterpos] = smax[waterpos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pc[waterpos]; + } else if (overlap || sg > smax[gaspos]-1.0e-6) { + sat[gaspos] = smax[gaspos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; + } + if (sg < smin[gaspos]+1.0e-6) { + sat[gaspos] = smin[gaspos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pc[gaspos]; + } + if (sw < smin[waterpos]+1.0e-6) { + sat[waterpos] = smin[waterpos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pc[waterpos]; + } } return phase_saturations; } @@ -659,20 +684,19 @@ namespace Opm std::vector computeRs(const UnstructuredGrid& grid, const CellRangeType& cells, const std::vector oil_pressure, - const Miscibility::RsFunction& rs_func) + const Miscibility::RsFunction& rs_func, + const std::vector gas_saturation) { assert(grid.dimensions == 3); std::vector rs(cells.size()); int count = 0; for (auto it = cells.begin(); it != cells.end(); ++it, ++count) { const double depth = grid.cell_centroids[3*(*it) + 2]; - rs[count] = rs_func(depth, oil_pressure[count]); + rs[count] = rs_func(depth, oil_pressure[count], gas_saturation[count]); } return rs; } - - } // namespace Equil From b79455fea6421a5b69ef9e782af3c49bbfe77219 Mon Sep 17 00:00:00 2001 From: osae Date: Fri, 28 Mar 2014 17:18:50 +0100 Subject: [PATCH 049/158] Default equil region should be one not zero ... Otherwise problems when kw EQLNUM is used. --- opm/core/simulator/initStateEquil.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 566f2b00f..cfcb56bae 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -241,8 +241,8 @@ namespace Opm } else { // No explicit equilibration region. - // All cells in region zero. - eqlnum.assign(G.number_of_cells, 0); + // All cells in region one. + eqlnum.assign(G.number_of_cells, 1); } return eqlnum; @@ -384,7 +384,7 @@ namespace Opm r = 0, nr = reg.numRegions(); r < nr; ++r) { - const typename RMap::CellRange cells = reg.cells(r); + const typename RMap::CellRange cells = reg.cells(r+1); const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); From 27579736ddebc4cdf8944f52b80c97f0f3d54e0b Mon Sep 17 00:00:00 2001 From: osae Date: Fri, 28 Mar 2014 17:35:43 +0100 Subject: [PATCH 050/158] New parser included. --- examples/compute_initial_state.cpp | 8 +- opm/core/simulator/initStateEquil.hpp | 247 ++++++++++++++++++++- opm/core/simulator/initStateEquil_impl.hpp | 20 ++ 3 files changed, 266 insertions(+), 9 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 0b11ecf1c..3193c9fac 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -29,6 +29,10 @@ #include #include #include + +#include +#include + #include namespace @@ -80,8 +84,10 @@ try parameter::ParameterGroup param(argc, argv, false); std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get("deck_filename"); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile(deck_filename); const double grav = param.getDefault("gravity", unit::gravity); - EclipseGridParser deck(deck_filename); + //EclipseGridParser deck(deck_filename); GridManager gm(deck); const UnstructuredGrid& grid = *gm.c_grid(); BlackoilPropertiesFromDeck props(deck, grid, param); diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index cfcb56bae..c4608b804 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -63,6 +65,13 @@ namespace Opm const EclipseGridParser& deck, const double gravity, BlackoilState& state); + + + void initStateEquil(const UnstructuredGrid& grid, + const BlackoilPropertiesInterface& props, + const Opm::DeckConstPtr newParserDeck, + const double gravity, + BlackoilState& state); /** @@ -227,7 +236,51 @@ namespace Opm } } + inline + std::vector + getEquil(const Opm::DeckConstPtr newParserDeck) + { + if (newParserDeck->hasKeyword("EQUIL")) { + + Opm::EquilWrapper eql(newParserDeck->getKeyword("EQUIL")); + const int nrec = eql.numRegions(); + + std::vector ret; + ret.reserve(nrec); + for (int r = 0; r < nrec; ++r) { + + EquilRecord record = + { + { eql.datumDepth(r) , + eql.datumDepthPressure(r) } + , + { eql.waterOilContactDepth(r) , + eql.waterOilContactCapillaryPressure(r) } + , + { eql.gasOilContactDepth(r) , + eql.gasOilContactCapillaryPressure(r) } + , + eql.liveOilInitProceedure(r) + , + eql.wetGasInitProceedure(r) + , + eql.initializationTargetAccuracy(r) + }; + if (record.N != 0) { + OPM_THROW(std::domain_error, + "kw EQUIL, item 9: Only N=0 supported."); + } + ret.push_back(record); + } + + return ret; + } + else { + OPM_THROW(std::domain_error, + "Deck does not provide equilibration data."); + } + } inline @@ -249,6 +302,23 @@ namespace Opm } + inline + std::vector + equilnum(const Opm::DeckConstPtr newParserDeck, + const UnstructuredGrid& G ) + { + std::vector eqlnum; + if (newParserDeck->hasKeyword("EQLNUM")) { + eqlnum = newParserDeck->getKeyword("EQLNUM")->getIntData(); + } + else { + // No explicit equilibration region. + // All cells in region one. + eqlnum.assign(G.number_of_cells, 1); + } + + return eqlnum; + } template @@ -278,12 +348,7 @@ namespace Opm rs_func_.reserve(rec.size()); if (deck.hasField("DISGAS")) { for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); - // TODO Check this ... - // The index is here picked as a representative for its equlibrium region, - // but is below used to identify PVT region. - // This assumes that an eq-region has uniform pvt properties, is this always ok? - // For Norne this is trivial, as there is only one active pvt-region (PVTNUM=1 for all cells): + const int cell = *(eqlmap.cells(i + 1).begin()); if (rec[i].live_oil_table_index > 0) { if (deck.hasField("RSVD")) { // TODO When this kw is actually parsed, also check for proper number of available tables @@ -314,8 +379,7 @@ namespace Opm rv_func_.reserve(rec.size()); if (deck.hasField("VAPOIL")) { for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); - // TODO Similar as above: eq-region vs pvt-region ... + const int cell = *(eqlmap.cells(i + 1).begin()); if (rec[i].wet_gas_table_index > 0) { if (deck.hasField("RVVD")) { // TODO When this kw is actually parsed, also check for proper number of available tables @@ -427,6 +491,173 @@ namespace Opm } }; + + + template <> + class InitialStateComputer { + public: + InitialStateComputer(const BlackoilPropertiesInterface& props, + const Opm::DeckConstPtr newParserDeck, + const UnstructuredGrid& G , + const double grav = unit::gravity) + : pp_(props.numPhases(), + std::vector(G.number_of_cells)), + sat_(props.numPhases(), + std::vector(G.number_of_cells)), + rs_(G.number_of_cells), + rv_(G.number_of_cells) + { + // Get the equilibration records. + const std::vector rec = getEquil(newParserDeck); + + // Create (inverse) region mapping. + const RegionMapping<> eqlmap(equilnum(newParserDeck, G)); + + // Create Rs functions. + rs_func_.reserve(rec.size()); + if (newParserDeck->hasKeyword("DISGAS")) { + for (size_t i = 0; i < rec.size(); ++i) { + const int cell = *(eqlmap.cells(i + 1).begin()); + if (rec[i].live_oil_table_index > 0) { + if (newParserDeck->hasKeyword("RSVD") && rec[i].live_oil_table_index <= newParserDeck->getKeyword("RSVD")->size()) { + Opm::SimpleTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); + std::vector vd(rsvd.getColumn("vd")); + std::vector rs(rsvd.getColumn("rs")); + rs_func_.push_back(std::make_shared(props, cell, vd, rs)); + } else { + OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); + } + } else { + if (rec[i].goc.depth != rec[i].main.depth) { + OPM_THROW(std::runtime_error, + "Cannot initialise: when no explicit RSVD table is given, \n" + "datum depth must be at the gas-oil-contact. " + "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); + } + const double p_contact = rec[i].main.press; + rs_func_.push_back(std::make_shared(props, cell, p_contact)); + } + } + } else { + for (size_t i = 0; i < rec.size(); ++i) { + rs_func_.push_back(std::make_shared()); + } + } + + rv_func_.reserve(rec.size()); + if (newParserDeck->hasKeyword("VAPOIL")) { + for (size_t i = 0; i < rec.size(); ++i) { + const int cell = *(eqlmap.cells(i + 1).begin()); + if (rec[i].wet_gas_table_index > 0) { + if (newParserDeck->hasKeyword("RVVD") && rec[i].wet_gas_table_index <= newParserDeck->getKeyword("RVVD")->size()) { + Opm::SimpleTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); + std::vector vd(rvvd.getColumn("vd")); + std::vector rv(rvvd.getColumn("rv")); + rv_func_.push_back(std::make_shared(props, cell, vd, rv)); + } else { + OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); + } + } else { + if (rec[i].goc.depth != rec[i].main.depth) { + OPM_THROW(std::runtime_error, + "Cannot initialise: when no explicit RVVD table is given, \n" + "datum depth must be at the gas-oil-contact. " + "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); + } + const double p_contact = rec[i].main.press + rec[i].goc.press; + rv_func_.push_back(std::make_shared(props, cell, p_contact)); + } + } + } else { + for (size_t i = 0; i < rec.size(); ++i) { + rv_func_.push_back(std::make_shared()); + } + } + + // Compute pressures, saturations, rs and rv factors. + calcPressSatRsRv(eqlmap, rec, props, G, grav); + + // Modify oil pressure in no-oil regions so that the pressures of present phases can + // be recovered from the oil pressure and capillary relations. + } + + typedef std::vector Vec; + typedef std::vector PVec; // One per phase. + + const PVec& press() const { return pp_; } + const PVec& saturation() const { return sat_; } + const Vec& rs() const { return rs_; } + const Vec& rv() const { return rv_; } + + private: + typedef DensityCalculator RhoCalc; + typedef EquilReg EqReg; + + std::vector< std::shared_ptr > rs_func_; + std::vector< std::shared_ptr > rv_func_; + + PVec pp_; + PVec sat_; + Vec rs_; + Vec rv_; + + template + void + calcPressSatRsRv(const RMap& reg , + const std::vector< EquilRecord >& rec , + const Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G , + const double grav) + { + typedef Miscibility::NoMixing NoMix; + + for (typename RMap::RegionId + r = 0, nr = reg.numRegions(); + r < nr; ++r) + { + const typename RMap::CellRange cells = reg.cells(r+1); + + const int repcell = *cells.begin(); + const RhoCalc calc(props, repcell); + const EqReg eqreg(rec[r], calc, + rs_func_[r], rv_func_[r], + props.phaseUsage()); + + PVec press = phasePressures(G, eqreg, cells, grav); + + const PVec sat = phaseSaturations(eqreg, cells, props, press); + + const int np = props.numPhases(); + for (int p = 0; p < np; ++p) { + copyFromRegion(press[p], cells, pp_[p]); + copyFromRegion(sat[p], cells, sat_[p]); + } + if (props.phaseUsage().phase_used[BlackoilPhases::Liquid] + && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { + const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; + const int gaspos = props.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r]), sat[gaspos]); + const Vec rv = computeRs(G, cells, press[gaspos], *(rv_func_[r]), sat[oilpos]); + copyFromRegion(rs, cells, rs_); + copyFromRegion(rv, cells, rv_); + } + } + } + + template + void copyFromRegion(const Vec& source, + const CellRangeType& cells, + Vec& destination) + { + auto s = source.begin(); + auto c = cells.begin(); + const auto e = cells.end(); + for (; c != e; ++c, ++s) { + destination[*c] = *s; + } + } + + }; } // namespace DeckDependent } // namespace Equil } // namespace Opm diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 6c9912151..d227d54d1 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -753,6 +753,26 @@ namespace Opm state.rv() = isc.rv(); // TODO: state.surfacevol() must be computed from s, rs, rv. } + + + void initStateEquil(const UnstructuredGrid& grid, + const BlackoilPropertiesInterface& props, + const Opm::DeckConstPtr newParserDeck, + const double gravity, + BlackoilState& state) + { + typedef Equil::DeckDependent::InitialStateComputer ISC; + ISC isc(props, newParserDeck, grid, gravity); + const auto pu = props.phaseUsage(); + const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] + ? pu.phase_pos[BlackoilPhases::Liquid] + : pu.phase_pos[BlackoilPhases::Aqua]; + state.pressure() = isc.press()[ref_phase]; + state.saturation() = convertSats(isc.saturation()); + state.gasoilratio() = isc.rs(); + state.rv() = isc.rv(); + // TODO: state.surfacevol() must be computed from s, rs, rv. + } From ce054750108e70518fc32768b1cf6be093cb1565 Mon Sep 17 00:00:00 2001 From: osae Date: Mon, 31 Mar 2014 15:32:06 +0200 Subject: [PATCH 051/158] Update tests and provide some eclipse output. --- tests/capillary_overlap.DATA | 99 ++++++++++++++++++++++++++++- tests/equil_liveoil.DATA | 118 +++++++++++++++++++++++++++++++---- tests/test_equil.cpp | 93 ++++++++++++++++++--------- 3 files changed, 268 insertions(+), 42 deletions(-) diff --git a/tests/capillary_overlap.DATA b/tests/capillary_overlap.DATA index 185784eee..b59e42202 100644 --- a/tests/capillary_overlap.DATA +++ b/tests/capillary_overlap.DATA @@ -1,7 +1,77 @@ +NOECHO + +RUNSPEC ====== + WATER OIL GAS +TABDIMS + 1 1 40 20 1 20 / + +DIMENS +1 1 20 +/ + +WELLDIMS + 30 10 2 30 / + +START + 1 'JAN' 1990 / + +NSTACK + 25 / + +EQLDIMS +-- NTEQUL + 1 / + + +FMTOUT +FMTIN + +GRID ====== + +DXV +1.0 +/ + +DYV +1.0 +/ + +DZV +20*5.0 +/ + + +PORO +20*0.2 +/ + + +PERMZ + 20*1.0 +/ + +PERMY +20*100.0 +/ + +PERMX +20*100.0 +/ + +BOX + 1 1 1 1 1 1 / + +TOPS +0.0 +/ + +PROPS ====== + + PVDO 100 1.0 1.0 200 0.9 1.0 @@ -22,10 +92,37 @@ SGOF 0.8 1 0 0.5 / +PVTW +--RefPres Bw Comp Vw Cv + 1. 1.0 4.0E-5 0.96 0.0 / + + +ROCK +--RefPres Comp + 1. 5.0E-5 / + DENSITY 700 1000 1 / +SOLUTION ====== + EQUIL -50 150 50 0.25 45 0.35 +45 150 50 0.25 45 0.35 1* 1* 0 / + +RPTSOL +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RESTART=2' / + +SUMMARY ====== +RUNSUM + +SEPARATE + +SCHEDULE ====== + +RPTSCHED +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RESTART=3' 'NEWTON=2' / + + +END diff --git a/tests/equil_liveoil.DATA b/tests/equil_liveoil.DATA index 955a09b7f..e1b417c46 100644 --- a/tests/equil_liveoil.DATA +++ b/tests/equil_liveoil.DATA @@ -1,27 +1,94 @@ +NOECHO + +RUNSPEC ====== + WATER OIL GAS DISGAS +TABDIMS + 1 1 40 20 1 20 / + +DIMENS +1 1 20 +/ + +WELLDIMS + 30 10 2 30 / + +START + 1 'JAN' 1990 / + +NSTACK + 25 / + +EQLDIMS +-- NTEQUL + 1 / + + +FMTOUT +FMTIN + +GRID ====== + +DXV +1.0 +/ + +DYV +1.0 +/ + +DZV +20*5.0 +/ + + +PORO +20*0.2 +/ + + +PERMZ + 20*1.0 +/ + +PERMY +20*100.0 +/ + +PERMX +20*100.0 +/ + +BOX + 1 1 1 1 1 1 / + +TOPS +0.0 +/ + +PROPS ====== PVTO -- Rs Pbub Bo Vo 0 1. 1.0000 1.20 / - 100 40. 1.0120 1.17 / - 200 80. 1.0255 1.14 / - 300 120. 1.0380 1.11 / - 400 160. 1.0510 1.08 / - 500 200. 1.0630 1.06 / - 600 240. 1.0750 1.03 / - 700 280. 1.0870 1.00 / - 800 320. 1.0985 .98 / - 900 360. 1.1100 .95 / - 1000 400. 1.1200 .94 + 20 40. 1.0120 1.17 / + 40 80. 1.0255 1.14 / + 60 120. 1.0380 1.11 / + 80 160. 1.0510 1.08 / + 100 200. 1.0630 1.06 / + 120 240. 1.0750 1.03 / + 140 280. 1.0870 1.00 / + 160 320. 1.0985 .98 / + 180 360. 1.1100 .95 / + 200 400. 1.1200 .94 500. 1.1189 .94 / / - PVDG 100 0.010 0.1 200 0.005 0.2 @@ -37,10 +104,37 @@ SGOF 0.8 1 0 0.5 / +PVTW +--RefPres Bw Comp Vw Cv + 1. 1.0 4.0E-5 0.96 0.0 / + + +ROCK +--RefPres Comp + 1. 5.0E-5 / + DENSITY 700 1000 1 / +SOLUTION ====== + EQUIL -45 150 50 0.25 45 0.35 +45 150 50 0.25 45 0.35 1* 1* 0 / + +RPTSOL +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RS' 'RESTART=2' / + +SUMMARY ====== +RUNSUM + +SEPARATE + +SCHEDULE ====== + +RPTSCHED +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RS' 'RESTART=3' 'NEWTON=2' / + + +END diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index b4df1fae8..b1e6f6c0a 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include @@ -339,9 +342,9 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-3; - BOOST_CHECK_CLOSE(pressures[0][first] , 14955e3 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 15045e3 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.50473e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][first] , 1.496329839e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 1.50473245e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.50473245e7 , reltol); } @@ -416,9 +419,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-6; - BOOST_CHECK_CLOSE(pressures[0][first] , 1.45e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][first] , 1.469769063e7 , reltol); BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.5351621345e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.546e7 , reltol); const auto& sats = comp.saturation(); const std::vector s[3]{ @@ -443,7 +446,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::EclipseGridParser deck("capillary_overlap.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -454,9 +457,15 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-6; - BOOST_CHECK_CLOSE(pressures[0][first] , 1.45e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.5351621345e7 , reltol); + const double reltol_ecl = 1.0; + BOOST_CHECK_CLOSE(pressures[0][first], 1.48324e+07, reltol_ecl); // eclipse + BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][first], 1.49224e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); + + BOOST_CHECK_CLOSE(pressures[0][first] , 14832467.14, reltol); // opm + BOOST_CHECK_CLOSE(pressures[0][last ] , 15479883.47, reltol); + BOOST_CHECK_CLOSE(pressures[1][last ] , 15489883.47, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; @@ -466,15 +475,24 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) // } // std::cout << std::endl; // } - const std::vector s[3]{ - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.223141818182, 0.532269090909, 0.78471, 0.91526, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.207743333333, 0.08474, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.776858181818, 0.467730909091, 0.0075466666666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + + const std::vector s_ecl[3]{// eclipse + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22874042, 0.53397995, 0.78454906, 0.91542006, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20039, 0.08458, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77125955, 0.46602005, 0.015063271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + + const std::vector s_opm[3]{ // opm + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2289309090909091, 0.53406545454545451, 0.78458, 0.9154, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2002466666666666, 0.0846, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77106909090909093, 0.46593454545454549, 0.015173333333333336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s[phase].size()); - for (size_t i = 0; i < s[phase].size(); ++i) { - BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); + BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + for (size_t i = 0; i < s_opm[phase].size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); } } } @@ -485,10 +503,12 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::EclipseGridParser deck("equil_liveoil.DATA"); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA"); + //Opm::EclipseGridParser deck("equil_liveoil.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -499,9 +519,16 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-6; - BOOST_CHECK_CLOSE(pressures[0][first], 1.4551302072306179e7, reltol); - BOOST_CHECK_CLOSE(pressures[0][last], 1.5501302072306179e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][last], 1.5538684664272346e7, reltol); + const double reltol_ecl = 1.0; + BOOST_CHECK_CLOSE(pressures[0][first], 1.48324e+07, reltol_ecl); // eclipse + BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][first], 1.49224e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); + + BOOST_CHECK_CLOSE(pressures[0][first], 1.483246714e7, reltol); // opm + BOOST_CHECK_CLOSE(pressures[0][last], 1.547991652e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][first], 1.492246714e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][last], 1.548991652e7, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; @@ -511,16 +538,24 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) // } // std::cout << std::endl; // } - const std::vector s[3]{ - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.223141818182, 0.532269090909, 0.78471, 0.91526, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.207743333333, 0.08474, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.776858181818, 0.467730909091, 0.0075466666666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + const std::vector s_ecl[3]{ // eclipse + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22898, 0.53422, 0.78470, 0.91531, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20073, 0.08469, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77102, 0.46578, 0.01458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; + + const std::vector s_opm[3]{ // opm + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2291709091, 0.5343054545, 0.78472, 0.91529, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2005866667, 0.08471, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7708290909, 0.4656945455, 0.01469333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s[phase].size()); - for (size_t i = 0; i < s[phase].size(); ++i) { - std::cout << sats[phase][i] << '\n'; - //BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); + BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + for (size_t i = 0; i < s_opm[phase].size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); + BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } From 43839c7923256e900c6ea7052953c79b67ce3d90 Mon Sep 17 00:00:00 2001 From: osae Date: Mon, 31 Mar 2014 16:16:45 +0200 Subject: [PATCH 052/158] Equil regions now internally indexed 0..(NTEQUL-1) --- opm/core/simulator/initStateEquil.hpp | 34 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index c4608b804..c1f72b714 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -289,13 +289,16 @@ namespace Opm const UnstructuredGrid& G ) { std::vector eqlnum; - if (deck.hasField("EQLNUM")) { - eqlnum = deck.getIntegerValue("EQLNUM"); + if (deck.hasField("EQLNUM")) { + const std::vector& e = deck.getIntegerValue("EQLNUM"); + eqlnum.reserve(e.size()); + std::transform(e.begin(), e.end(), std::back_inserter(eqlnum), + std::bind2nd(std::minus(), 1)); } else { // No explicit equilibration region. - // All cells in region one. - eqlnum.assign(G.number_of_cells, 1); + // All cells in region zero. + eqlnum.assign(G.number_of_cells, 0); } return eqlnum; @@ -308,13 +311,16 @@ namespace Opm const UnstructuredGrid& G ) { std::vector eqlnum; - if (newParserDeck->hasKeyword("EQLNUM")) { - eqlnum = newParserDeck->getKeyword("EQLNUM")->getIntData(); + if (newParserDeck->hasKeyword("EQLNUM")) { + const std::vector& e = newParserDeck->getKeyword("EQLNUM")->getIntData(); + eqlnum.reserve(e.size()); + std::transform(e.begin(), e.end(), std::back_inserter(eqlnum), + std::bind2nd(std::minus(), 1)); } else { // No explicit equilibration region. - // All cells in region one. - eqlnum.assign(G.number_of_cells, 1); + // All cells in region zero. + eqlnum.assign(G.number_of_cells, 0); } return eqlnum; @@ -348,7 +354,7 @@ namespace Opm rs_func_.reserve(rec.size()); if (deck.hasField("DISGAS")) { for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); + const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { if (deck.hasField("RSVD")) { // TODO When this kw is actually parsed, also check for proper number of available tables @@ -379,7 +385,7 @@ namespace Opm rv_func_.reserve(rec.size()); if (deck.hasField("VAPOIL")) { for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); + const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { if (deck.hasField("RVVD")) { // TODO When this kw is actually parsed, also check for proper number of available tables @@ -448,7 +454,7 @@ namespace Opm r = 0, nr = reg.numRegions(); r < nr; ++r) { - const typename RMap::CellRange cells = reg.cells(r+1); + const typename RMap::CellRange cells = reg.cells(r); const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); @@ -517,7 +523,7 @@ namespace Opm rs_func_.reserve(rec.size()); if (newParserDeck->hasKeyword("DISGAS")) { for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); + const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { if (newParserDeck->hasKeyword("RSVD") && rec[i].live_oil_table_index <= newParserDeck->getKeyword("RSVD")->size()) { Opm::SimpleTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); @@ -547,7 +553,7 @@ namespace Opm rv_func_.reserve(rec.size()); if (newParserDeck->hasKeyword("VAPOIL")) { for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i + 1).begin()); + const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { if (newParserDeck->hasKeyword("RVVD") && rec[i].wet_gas_table_index <= newParserDeck->getKeyword("RVVD")->size()) { Opm::SimpleTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); @@ -615,7 +621,7 @@ namespace Opm r = 0, nr = reg.numRegions(); r < nr; ++r) { - const typename RMap::CellRange cells = reg.cells(r+1); + const typename RMap::CellRange cells = reg.cells(r); const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); From 977c2e71064805f82f16f9df6251c5300a6d007a Mon Sep 17 00:00:00 2001 From: osae Date: Thu, 3 Apr 2014 09:07:00 +0200 Subject: [PATCH 053/158] Some additional tests: live gas, RSVD and RVVD --- tests/capillary.DATA | 9 +- tests/deadfluids.DATA | 9 +- tests/equil_livegas.DATA | 131 ++++++++++++++++++++ tests/equil_rsvd_and_rvvd.DATA | 151 +++++++++++++++++++++++ tests/test_equil.cpp | 219 +++++++++++++++++++++++++++++++-- 5 files changed, 507 insertions(+), 12 deletions(-) create mode 100644 tests/equil_livegas.DATA create mode 100644 tests/equil_rsvd_and_rvvd.DATA diff --git a/tests/capillary.DATA b/tests/capillary.DATA index d8d163fcd..89c938999 100644 --- a/tests/capillary.DATA +++ b/tests/capillary.DATA @@ -2,6 +2,13 @@ WATER OIL GAS +TABDIMS + 1 1 40 20 1 20 / + +EQLDIMS +-- NTEQUL + 1 / + PVDO 100 1.0 1.0 200 0.9 1.0 @@ -27,5 +34,5 @@ DENSITY / EQUIL -50 150 50 0.25 20 0.35 +50 150 50 0.25 20 0.35 1* 1* 0 / diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA index ffaebc7ff..89232054b 100644 --- a/tests/deadfluids.DATA +++ b/tests/deadfluids.DATA @@ -2,6 +2,13 @@ WATER OIL GAS +TABDIMS + 1 1 40 20 1 20 / + +EQLDIMS +-- NTEQUL + 1 / + PVDO 100 1.0 1.0 200 0.5 1.0 @@ -27,5 +34,5 @@ DENSITY / EQUIL -5 150 5 0 2 0 +5 150 5 0 2 0 1* 1* 0 / diff --git a/tests/equil_livegas.DATA b/tests/equil_livegas.DATA new file mode 100644 index 000000000..a0676f52c --- /dev/null +++ b/tests/equil_livegas.DATA @@ -0,0 +1,131 @@ +NOECHO + +RUNSPEC ====== + +WATER +OIL +GAS +VAPOIL + +TABDIMS + 1 1 40 20 1 20 / + +DIMENS +1 1 20 +/ + +WELLDIMS + 30 10 2 30 / + +START + 1 'JAN' 1990 / + +NSTACK + 25 / + +EQLDIMS +-- NTEQUL + 1 / + + +FMTOUT +FMTIN + +GRID ====== + +DXV +1.0 +/ + +DYV +1.0 +/ + +DZV +20*5.0 +/ + + +PORO +20*0.2 +/ + + +PERMZ + 20*1.0 +/ + +PERMY +20*100.0 +/ + +PERMX +20*100.0 +/ + +BOX + 1 1 1 1 1 1 / + +TOPS +0.0 +/ + +PROPS ====== + +PVDO +100 1.0 1.0 +200 0.9 1.0 +/ + +PVTG +-- Pg Rv Bg Vg + 100 0.0001 0.010 0.1 + 0.0 0.0104 0.1 / + 200 0.0004 0.005 0.2 + 0.0 0.0054 0.2 / +/ + +SWOF +0.2 0 1 0.9 +1 1 0 0.1 +/ + +SGOF +0 0 1 0.2 +0.8 1 0 0.5 +/ + +PVTW +--RefPres Bw Comp Vw Cv + 1. 1.0 4.0E-5 0.96 0.0 / + + +ROCK +--RefPres Comp + 1. 5.0E-5 / + +DENSITY +700 1000 1 +/ + +SOLUTION ====== + +EQUIL +45 150 50 0.25 45 0.35 1* 1* 0 +/ + +RPTSOL +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RS' 'RESTART=2' / + +SUMMARY ====== +RUNSUM + +SEPARATE + +SCHEDULE ====== + +RPTSCHED +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RS' 'RESTART=3' 'NEWTON=2' / + + +END diff --git a/tests/equil_rsvd_and_rvvd.DATA b/tests/equil_rsvd_and_rvvd.DATA new file mode 100644 index 000000000..3076524e3 --- /dev/null +++ b/tests/equil_rsvd_and_rvvd.DATA @@ -0,0 +1,151 @@ +NOECHO + +RUNSPEC ====== + +WATER +OIL +GAS +DISGAS +VAPOIL + +TABDIMS + 1 1 40 20 1 20 / + +DIMENS +1 1 20 +/ + +WELLDIMS + 30 10 2 30 / + +START + 1 'JAN' 1990 / + +NSTACK + 25 / + +EQLDIMS +-- NTEQUL + 1 / + + +FMTOUT +FMTIN + +GRID ====== + +DXV +1.0 +/ + +DYV +1.0 +/ + +DZV +20*5.0 +/ + + +PORO +20*0.2 +/ + + +PERMZ + 20*1.0 +/ + +PERMY +20*100.0 +/ + +PERMX +20*100.0 +/ + +BOX + 1 1 1 1 1 1 / + +TOPS +0.0 +/ + +PROPS ====== + +PVTO +-- Rs Pbub Bo Vo + 0 1. 1.0000 1.20 / + 20 40. 1.0120 1.17 / + 40 80. 1.0255 1.14 / + 60 120. 1.0380 1.11 / + 80 160. 1.0510 1.08 / + 100 200. 1.0630 1.06 / + 120 240. 1.0750 1.03 / + 140 280. 1.0870 1.00 / + 160 320. 1.0985 .98 / + 180 360. 1.1100 .95 / + 200 400. 1.1200 .94 + 500. 1.1189 .94 / +/ + +PVTG +-- Pg Rv Bg Vg + 100 0.0001 0.010 0.1 + 0.0 0.0104 0.1 / + 200 0.0004 0.005 0.2 + 0.0 0.0054 0.2 / +/ + +SWOF +0.2 0 1 0.9 +1 1 0 0.1 +/ + +SGOF +0 0 1 0.2 +0.8 1 0 0.5 +/ + +PVTW +--RefPres Bw Comp Vw Cv + 1. 1.0 4.0E-5 0.96 0.0 / + + +ROCK +--RefPres Comp + 1. 5.0E-5 / + +DENSITY +700 1000 1 +/ + +SOLUTION ====== + +EQUIL +45 150 50 0.25 45 0.35 1 1 0 +/ + +RSVD + 0 0.0 + 100 100. / + +RVVD + 0. 0. + 100. 0.0001 / + +RPTSOL +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RS' 'RESTART=2' / + +SUMMARY ====== +RUNSUM + +SEPARATE + +SCHEDULE ====== + +RPTSCHED +'PRES' 'PGAS' 'PWAT' 'SOIL' 'SWAT' 'SGAS' 'RS' 'RESTART=3' 'NEWTON=2' / + + +END diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index b1e6f6c0a..d68470b08 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -329,9 +329,10 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) { std::shared_ptr grid(create_grid_cart3d(1, 1, 10), destroy_grid); - Opm::EclipseGridParser deck("deadfluids.DATA"); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -354,7 +355,8 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) // Test setup. Opm::GridManager gm(1, 1, 40, 1.0, 1.0, 2.5); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::EclipseGridParser deck("capillary.DATA"); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); // Test the capillary inversion for oil-water. @@ -405,10 +407,11 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::EclipseGridParser deck("capillary.DATA"); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -443,10 +446,11 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::EclipseGridParser deck("capillary_overlap.DATA"); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -505,7 +509,6 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA"); - //Opm::EclipseGridParser deck("equil_liveoil.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); @@ -543,13 +546,11 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20073, 0.08469, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77102, 0.46578, 0.01458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - const std::vector s_opm[3]{ // opm { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2291709091, 0.5343054545, 0.78472, 0.91529, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2005866667, 0.08471, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7708290909, 0.4656945455, 0.01469333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - for (int phase = 0; phase < 3; ++phase) { BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { @@ -559,7 +560,205 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) } std::cout << std::endl; } + + const auto& rs = comp.rs(); + const std::vector rs_opm {74.612335679539058, 74.649052116644228, 74.685786561426298, 74.722539022717172, // opm + 74.759309509353145, 74.796098030174733, 74.8329045940269, 74.869729209758916, + 74.906571886224327, 75.090675116639048, 75.0, 75.0, + 75.0, 75.0, 75.0, 75.0, + 75.0, 75.0, 75.0, 75.0}; + const std::vector rs_ecl {74.612228, 74.648956, 74.685707, 74.722473, // eclipse + 74.759254, 74.796051, 74.832870, 74.875145, + 74.969231, 75.090706, 75.000000, 75.000000, + 75.000000, 75.000000, 75.000000, 75.000000, + 75.000000, 75.000000, 75.000000, 75.000000}; + for (size_t i = 0; i < rs_opm.size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(rs[i], rs_opm[i], reltol); + BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); + } } + +BOOST_AUTO_TEST_CASE (DeckWithLiveGas) +{ + Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + const auto& pressures = comp.press(); + BOOST_REQUIRE(pressures.size() == 3); + BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + + const int first = 0, last = grid.number_of_cells - 1; + // The relative tolerance is too loose to be very useful, + // but the answer we are checking is the result of an ODE + // solver, and it is unclear if we should check it against + // the true answer or something else. + const double reltol = 1.0e-6; + const double reltol_ecl = 1.0; + BOOST_CHECK_CLOSE(pressures[0][first], 1.48215e+07, reltol_ecl); // eclipse + BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][first], 1.49115e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); + + BOOST_CHECK_CLOSE(pressures[0][first], 1.482150311e7, reltol); // opm + BOOST_CHECK_CLOSE(pressures[0][last], 1.547988347e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][first], 1.491150311e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][last], 1.548988347e7, reltol); + + const auto& sats = comp.saturation(); + // std::cout << "Saturations:\n"; + // for (const auto& sat : sats) { + // for (const double s : sat) { + // std::cout << s << ' '; + // } + // std::cout << std::endl; + // } + const std::vector s_ecl[3]{ // eclipse + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.24285614, 0.53869015, 0.78454906, 0.91542006, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.18311, 0.08458, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.75714386, 0.46130988, 0.032345835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + + const std::vector s_opm[3]{ // opm + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.24310545, 0.5388, 0.78458, 0.91540, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.18288667, 0.0846, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.75689455, 0.4612, 0.03253333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + for (int phase = 0; phase < 3; ++phase) { + BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + for (size_t i = 0; i < s_opm[phase].size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], 100.*reltol); + BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + } + std::cout << std::endl; + } + + const auto& rv = comp.rv(); + const std::vector rv_opm { // opm + 2.4884509e-4, 2.4910378e-4, 2.4936267e-4, 2.4962174e-4, + 2.4988100e-4, 2.5014044e-4, 2.5040008e-4, 2.5065990e-4, + 2.5091992e-4, 2.5118012e-4, 2.5223082e-4, 2.5105e-4, + 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4, + 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4}; + + const std::vector rv_ecl { // eclipse + 0.24884584E-03, 0.24910446E-03, 0.24936325E-03, 0.24962222E-03, + 0.24988138E-03, 0.25014076E-03, 0.25040031E-03, 0.25066003E-03, + 0.25091995E-03, 0.25118008E-03, 0.25223137E-03, 0.25104999E-03, + 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, + 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03}; + + for (size_t i = 0; i < rv_opm.size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(rv[i], rv_opm[i], 100.*reltol); + BOOST_CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); + } +} + +BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) +{ + Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::ParserPtr parser(new Opm::Parser() ); + Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA"); + Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + const auto& pressures = comp.press(); + BOOST_REQUIRE(pressures.size() == 3); + BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + + const int first = 0, last = grid.number_of_cells - 1; + // The relative tolerance is too loose to be very useful, + // but the answer we are checking is the result of an ODE + // solver, and it is unclear if we should check it against + // the true answer or something else. + const double reltol = 1.0e-6; + const double reltol_ecl = 1.0; + BOOST_CHECK_CLOSE(pressures[0][first], 1.48350e+07, reltol_ecl); // eclipse + BOOST_CHECK_CLOSE(pressures[0][last], 1.54794e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][first], 1.49250e+07, reltol_ecl); + BOOST_CHECK_CLOSE(pressures[1][last], 1.54894e+07, reltol_ecl); + + BOOST_CHECK_CLOSE(pressures[0][first], 1.483499660e7, reltol); // opm + BOOST_CHECK_CLOSE(pressures[0][last], 1.547924516e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][first], 1.492499660e7, reltol); + BOOST_CHECK_CLOSE(pressures[1][last], 1.548924516e7, reltol); + + const auto& sats = comp.saturation(); + // std::cout << "Saturations:\n"; + // for (const auto& sat : sats) { + // for (const double s : sat) { + // std::cout << s << ' '; + // } + // std::cout << std::endl; + // } + const std::vector s_ecl[3]{ // eclipse + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22206347, 0.52871972, 0.78150368, 0.91819441, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.19656529, 0.081805572, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77793652, 0.47128031, 0.021931054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + + const std::vector s_opm[3]{ // opm + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22232000, 0.52882909, 0.78153000, 0.91817000, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.19636333, 0.08183000, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77768000, 0.47117091, 0.02210667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + + for (int phase = 0; phase < 3; ++phase) { + BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + for (size_t i = 0; i < s_opm[phase].size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], 100.*reltol); + BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + } + std::cout << std::endl; + } + + const auto& rs = comp.rs(); + const std::vector rs_opm { // opm + 74.624983020822540, 74.659590408801634, 74.694380353364522, 74.729353362649505, + 74.764509945812975, 74.799850613032362, 74.835375875509555, 74.87108624547416, + 74.906982236186707, 75.088917653469309, 52.5, 57.5, + 62.5, 67.5, 72.5, 76.45954840804761, + 76.70621044909619, 76.952877357524045, 77.199549133522638, 77.446225777283587}; + + const std::vector rs_ecl { // eclipse + 74.625114, 74.659706, 74.694481, 74.729439, + 74.764580, 74.799904, 74.835419, 74.875252, + 74.968628, 75.088951, 52.500000, 57.500000, + 62.500000, 67.500000, 72.500000, 76.168388, + 76.349953, 76.531532, 76.713142, 76.894775,}; + + const auto& rv = comp.rv(); + const std::vector rv_opm { // opm + 2.50e-6, 7.50e-6, 1.25e-5, 1.75e-5, + 2.25e-5, 2.75e-5, 3.25e-5, 3.75e-5, + 4.25e-5, 2.51158386e-4, 2.52203372e-4, 5.75e-5, + 6.25e-5, 6.75e-5, 7.25e-5, 7.75e-5, + 8.25e-5, 8.75e-5, 9.25e-5, 9.75e-5}; + + const std::vector rv_ecl { // eclipse + 0.24999999E-05, 0.74999998E-05, 0.12500000E-04, 0.17500000E-04, + 0.22500000E-04, 0.27500000E-04, 0.32500000E-04, 0.37500002E-04, + 0.42500000E-04, 0.25115837E-03, 0.25220393E-03, 0.57500001E-04, + 0.62500003E-04, 0.67499997E-04, 0.72499999E-04, 0.77500001E-04, + 0.82500002E-04, 0.87499997E-04, 0.92499999E-04, 0.97500000E-04}; + + for (size_t i = 0; i < rv_opm.size(); ++i) { + //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + BOOST_CHECK_CLOSE(rs[i], rs_opm[i], 100*reltol); + BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); + BOOST_CHECK_CLOSE(rv[i], rv_opm[i], 100.*reltol); + BOOST_CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); + } +} + BOOST_AUTO_TEST_SUITE_END() From 7a60e971996374c54b16fea1634b2201a0a3014e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 15 Apr 2014 13:40:15 +0200 Subject: [PATCH 054/158] Comment out unused function argument. --- opm/core/simulator/EquilibrationHelpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index d89dd8c3c..9979c6c16 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -201,7 +201,7 @@ namespace Opm double operator()(const double /* depth */, const double /* press */, - const double sat = 0.0) const + const double /* sat */ = 0.0) const { return 0.0; } From ec3befafae87790a407960b0c99e05c966b8fc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 15 Apr 2014 13:40:50 +0200 Subject: [PATCH 055/158] Avoid signed/unsigned warning. --- opm/core/simulator/initStateEquil.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index c1f72b714..dc5215c26 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -525,7 +525,8 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { - if (newParserDeck->hasKeyword("RSVD") && rec[i].live_oil_table_index <= newParserDeck->getKeyword("RSVD")->size()) { + const int tab_size = newParserDeck->getKeyword("RSVD")->size(); + if (newParserDeck->hasKeyword("RSVD") && rec[i].live_oil_table_index <= tab_size) { Opm::SimpleTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); std::vector vd(rsvd.getColumn("vd")); std::vector rs(rsvd.getColumn("rs")); @@ -555,7 +556,8 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { - if (newParserDeck->hasKeyword("RVVD") && rec[i].wet_gas_table_index <= newParserDeck->getKeyword("RVVD")->size()) { + const int tab_size = newParserDeck->getKeyword("RVVD")->size(); + if (newParserDeck->hasKeyword("RVVD") && rec[i].wet_gas_table_index <= tab_size) { Opm::SimpleTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); std::vector vd(rvvd.getColumn("vd")); std::vector rv(rvvd.getColumn("rv")); From 7120bdf1cee1dc13829e6992ba7bacc9c36cf095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 15 Apr 2014 13:41:10 +0200 Subject: [PATCH 056/158] Add (all-zero) initialisation of new EquilRecord fields. --- tests/test_equil.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index d68470b08..05f8df8d7 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -74,7 +74,8 @@ BOOST_AUTO_TEST_CASE (PhasePressure) { { 0 , 1e5 } , // Datum depth, pressure { 5 , 0 } , // Zwoc , Pcow_woc - { 0 , 0 } // Zgoc , Pcgo_goc + { 0 , 0 } , // Zgoc , Pcgo_goc + 0, 0, 0 }; Opm::Equil::EquilReg @@ -129,13 +130,15 @@ BOOST_AUTO_TEST_CASE (CellSubset) { { 0 , 1e5 } , // Datum depth, pressure { 2.5 , -0.075e5 } , // Zwoc , Pcow_woc - { 0 , 0 } // Zgoc , Pcgo_goc + { 0 , 0 } , // Zgoc , Pcgo_goc + 0, 0, 0 } , { { 5 , 1.35e5 } , // Datum depth, pressure { 7.5 , -0.225e5 } , // Zwoc , Pcow_woc - { 5 , 0 } // Zgoc , Pcgo_goc + { 5 , 0 } , // Zgoc , Pcgo_goc + 0, 0, 0 } }; @@ -244,13 +247,15 @@ BOOST_AUTO_TEST_CASE (RegMapping) { { 0 , 1e5 } , // Datum depth, pressure { 2.5 , -0.075e5 } , // Zwoc , Pcow_woc - { 0 , 0 } // Zgoc , Pcgo_goc + { 0 , 0 } , // Zgoc , Pcgo_goc + 0, 0, 0 } , { { 5 , 1.35e5 } , // Datum depth, pressure { 7.5 , -0.225e5 } , // Zwoc , Pcow_woc - { 5 , 0 } // Zgoc , Pcgo_goc + { 5 , 0 } , // Zgoc , Pcgo_goc + 0, 0, 0 } }; From e8f059259981744b2a52882315c5519bb2f7fa48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 15 Apr 2014 14:52:21 +0200 Subject: [PATCH 057/158] Fix access to keywords, while still silencing warning. Previous fix was wrong because it called getKeyword() outside the hasKeyword() check. Current version (like original code) uses the short-circuiting behaviour of && to ensure this. --- opm/core/simulator/initStateEquil.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index dc5215c26..152431d79 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -525,8 +525,8 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { - const int tab_size = newParserDeck->getKeyword("RSVD")->size(); - if (newParserDeck->hasKeyword("RSVD") && rec[i].live_oil_table_index <= tab_size) { + if (newParserDeck->hasKeyword("RSVD") && + size_t(rec[i].live_oil_table_index) <= newParserDeck->getKeyword("RSVD")->size()) { Opm::SimpleTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); std::vector vd(rsvd.getColumn("vd")); std::vector rs(rsvd.getColumn("rs")); @@ -556,8 +556,8 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { - const int tab_size = newParserDeck->getKeyword("RVVD")->size(); - if (newParserDeck->hasKeyword("RVVD") && rec[i].wet_gas_table_index <= tab_size) { + if (newParserDeck->hasKeyword("RVVD") && + size_t(rec[i].wet_gas_table_index) <= newParserDeck->getKeyword("RVVD")->size()) { Opm::SimpleTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); std::vector vd(rvvd.getColumn("vd")); std::vector rv(rvvd.getColumn("rv")); From 7cf70894b0a43611cd49c736bed285a0606f3153 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 17 Apr 2014 11:47:50 +0200 Subject: [PATCH 058/158] convert the examples and the tests to opm-parser --- examples/compute_initial_state.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 3193c9fac..b59a9a404 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -87,7 +87,6 @@ try Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile(deck_filename); const double grav = param.getDefault("gravity", unit::gravity); - //EclipseGridParser deck(deck_filename); GridManager gm(deck); const UnstructuredGrid& grid = *gm.c_grid(); BlackoilPropertiesFromDeck props(deck, grid, param); From 0467bf8b8fdde7a5b4a733f4ad9527a68d50d648 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Mon, 28 Apr 2014 18:47:28 +0200 Subject: [PATCH 059/158] adapt to the renames of the table classes in opm-parser basically, "Opm::SimpleTable" becomes "Opm::SingleRecordTable". --- opm/core/simulator/initStateEquil.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 152431d79..79ab69686 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include @@ -527,7 +527,7 @@ namespace Opm if (rec[i].live_oil_table_index > 0) { if (newParserDeck->hasKeyword("RSVD") && size_t(rec[i].live_oil_table_index) <= newParserDeck->getKeyword("RSVD")->size()) { - Opm::SimpleTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); + Opm::SingleRecordTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); std::vector vd(rsvd.getColumn("vd")); std::vector rs(rsvd.getColumn("rs")); rs_func_.push_back(std::make_shared(props, cell, vd, rs)); @@ -558,7 +558,7 @@ namespace Opm if (rec[i].wet_gas_table_index > 0) { if (newParserDeck->hasKeyword("RVVD") && size_t(rec[i].wet_gas_table_index) <= newParserDeck->getKeyword("RVVD")->size()) { - Opm::SimpleTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); + Opm::SingleRecordTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); std::vector vd(rvvd.getColumn("vd")); std::vector rv(rvvd.getColumn("rv")); rv_func_.push_back(std::make_shared(props, cell, vd, rv)); From b28c7ed35eb98ef0e96829db2383a5fbba7e306a Mon Sep 17 00:00:00 2001 From: osae Date: Mon, 5 May 2014 11:23:43 +0200 Subject: [PATCH 060/158] Fix to make EQLNUM consistent with ACTNUM. This should eventually be integrated in the parser. --- opm/core/simulator/initStateEquil.hpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 79ab69686..0b2455417 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -314,8 +314,21 @@ namespace Opm if (newParserDeck->hasKeyword("EQLNUM")) { const std::vector& e = newParserDeck->getKeyword("EQLNUM")->getIntData(); eqlnum.reserve(e.size()); - std::transform(e.begin(), e.end(), std::back_inserter(eqlnum), - std::bind2nd(std::minus(), 1)); + if (newParserDeck->hasKeyword("ACTNUM")) { + std::vector::const_iterator actnum_begin = + newParserDeck->getKeyword("ACTNUM")->getIntData().begin(); + std::transform(e.begin(), e.end(), actnum_begin, std::back_inserter(eqlnum), + [](int eql, int act){ return (act == 0) ? -1 : eql-1;}); + eqlnum.erase(std::remove_if(eqlnum.begin(), eqlnum.end(), + std::bind2nd(std::less(), 0)), + eqlnum.end()); + } + else { + std::transform(e.begin(), e.end(), std::back_inserter(eqlnum), + std::bind2nd(std::minus(), 1)); + } + if (eqlnum.size() != G.number_of_cells) + OPM_THROW(std::runtime_error, "Keyword EQLNUM: inconsistent array size."); } else { // No explicit equilibration region. From 46cec82e0ef4593f8396f77648aaf725646cfec4 Mon Sep 17 00:00:00 2001 From: osae Date: Mon, 5 May 2014 11:27:10 +0200 Subject: [PATCH 061/158] Inserted some documentation. --- opm/core/simulator/EquilibrationHelpers.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 9979c6c16..dd90e3689 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -541,6 +541,17 @@ namespace Opm * - @c depth Depth of gas-oil contact * - @c press Gas-oil capillary pressure at gas-oil contact. * Capillary pressure defined as "P_gas - P_oil". + * + * For the time being, items 7-9 of ECLIPSE's 'EQUIL' records are also + * stored here, but might (should?) eventually be moved elsewhere. + * + * - @c live_oil_table_index Indicates type of initialisation for live oil. + * Positive value points to corresponding Rs vs. depth table. + * - @c wet_gas_table_index Indicates type of initialisation for wet gas. + * Positive value points to corresponding Rv vs. depth table. + * - @c N Defines accuracy of initialisation computations. Currently + * only @c N=0 is supported. + * */ struct EquilRecord { struct { From 8ec7f178dec7ea7ac94820a4f01312aa7d23009b Mon Sep 17 00:00:00 2001 From: osae Date: Tue, 6 May 2014 12:47:24 +0200 Subject: [PATCH 062/158] Initialisation of EGLNUM (analogous to e.g SATNUM) --- opm/core/simulator/initStateEquil.hpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 0b2455417..98ebadbb3 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -311,24 +311,15 @@ namespace Opm const UnstructuredGrid& G ) { std::vector eqlnum; - if (newParserDeck->hasKeyword("EQLNUM")) { - const std::vector& e = newParserDeck->getKeyword("EQLNUM")->getIntData(); - eqlnum.reserve(e.size()); - if (newParserDeck->hasKeyword("ACTNUM")) { - std::vector::const_iterator actnum_begin = - newParserDeck->getKeyword("ACTNUM")->getIntData().begin(); - std::transform(e.begin(), e.end(), actnum_begin, std::back_inserter(eqlnum), - [](int eql, int act){ return (act == 0) ? -1 : eql-1;}); - eqlnum.erase(std::remove_if(eqlnum.begin(), eqlnum.end(), - std::bind2nd(std::less(), 0)), - eqlnum.end()); + if (newParserDeck->hasKeyword("EQLNUM")) { + eqlnum.resize(G.number_of_cells); + const std::vector& e = + newParserDeck->getKeyword("EQLNUM")->getIntData(); + const int* gc = G.global_cell; + for (int cell = 0; cell < G.number_of_cells; ++cell) { + const int deck_pos = (gc == NULL) ? cell : gc[cell]; + eqlnum[cell] = e[deck_pos] - 1; } - else { - std::transform(e.begin(), e.end(), std::back_inserter(eqlnum), - std::bind2nd(std::minus(), 1)); - } - if (eqlnum.size() != G.number_of_cells) - OPM_THROW(std::runtime_error, "Keyword EQLNUM: inconsistent array size."); } else { // No explicit equilibration region. From 55927d68cff3fa567a907be3b769ad07d768c932 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 17 Apr 2014 12:04:31 +0200 Subject: [PATCH 063/158] remove EclipseGridParser compatibility methods from all classes --- opm/core/simulator/initStateEquil.hpp | 254 +-------------------- opm/core/simulator/initStateEquil_impl.hpp | 22 +- tests/test_equil.cpp | 12 +- 3 files changed, 8 insertions(+), 280 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 98ebadbb3..fd8c35a13 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -60,13 +59,6 @@ namespace Opm * \param[in] deck Simulation deck, used to obtain EQUIL and related data. * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. */ - void initStateEquil(const UnstructuredGrid& grid, - const BlackoilPropertiesInterface& props, - const EclipseGridParser& deck, - const double gravity, - BlackoilState& state); - - void initStateEquil(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, const Opm::DeckConstPtr newParserDeck, @@ -188,54 +180,6 @@ namespace Opm const std::vector gas_saturation); namespace DeckDependent { - - inline - std::vector - getEquil(const EclipseGridParser& deck) - { - if (deck.hasField("EQUIL")) { - const EQUIL& eql = deck.getEQUIL(); - - typedef std::vector::size_type sz_t; - const sz_t nrec = eql.equil.size(); - - std::vector ret; - ret.reserve(nrec); - for (sz_t r = 0; r < nrec; ++r) { - const EquilLine& rec = eql.equil[r]; - - EquilRecord record = - { - { rec.datum_depth_ , - rec.datum_depth_pressure_ } - , - { rec.water_oil_contact_depth_ , - rec.oil_water_cap_pressure_ } - , - { rec.gas_oil_contact_depth_ , - rec.gas_oil_cap_pressure_ } - , - rec.live_oil_table_index_ - , - rec.wet_gas_table_index_ - , - rec.N_ - }; - if (record.N != 0) { - OPM_THROW(std::domain_error, - "kw EQUIL, item 9: Only N=0 supported."); - } - ret.push_back(record); - } - - return ret; - } - else { - OPM_THROW(std::domain_error, - "Deck does not provide equilibration data."); - } - } - inline std::vector getEquil(const Opm::DeckConstPtr newParserDeck) @@ -282,29 +226,6 @@ namespace Opm } } - - inline - std::vector - equilnum(const EclipseGridParser& deck, - const UnstructuredGrid& G ) - { - std::vector eqlnum; - if (deck.hasField("EQLNUM")) { - const std::vector& e = deck.getIntegerValue("EQLNUM"); - eqlnum.reserve(e.size()); - std::transform(e.begin(), e.end(), std::back_inserter(eqlnum), - std::bind2nd(std::minus(), 1)); - } - else { - // No explicit equilibration region. - // All cells in region zero. - eqlnum.assign(G.number_of_cells, 0); - } - - return eqlnum; - } - - inline std::vector equilnum(const Opm::DeckConstPtr newParserDeck, @@ -331,180 +252,7 @@ namespace Opm } - template - class InitialStateComputer; - - template <> - class InitialStateComputer { - public: - InitialStateComputer(const BlackoilPropertiesInterface& props, - const EclipseGridParser& deck , - const UnstructuredGrid& G , - const double grav = unit::gravity) - : pp_(props.numPhases(), - std::vector(G.number_of_cells)), - sat_(props.numPhases(), - std::vector(G.number_of_cells)), - rs_(G.number_of_cells), - rv_(G.number_of_cells) - { - // Get the equilibration records. - const std::vector rec = getEquil(deck); - - // Create (inverse) region mapping. - const RegionMapping<> eqlmap(equilnum(deck, G)); - - // Create Rs functions. - rs_func_.reserve(rec.size()); - if (deck.hasField("DISGAS")) { - for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i).begin()); - if (rec[i].live_oil_table_index > 0) { - if (deck.hasField("RSVD")) { - // TODO When this kw is actually parsed, also check for proper number of available tables - // For now, just use dummy ... - std::vector depth; depth.push_back(0.0); depth.push_back(100.0); - std::vector rs; rs.push_back(0.0); rs.push_back(100.0); - rs_func_.push_back(std::make_shared(props, cell, depth, rs)); - } else { - OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); - } - } else { - if (rec[i].goc.depth != rec[i].main.depth) { - OPM_THROW(std::runtime_error, - "Cannot initialise: when no explicit RSVD table is given, \n" - "datum depth must be at the gas-oil-contact. " - "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); - } - const double p_contact = rec[i].main.press; - rs_func_.push_back(std::make_shared(props, cell, p_contact)); - } - } - } else { - for (size_t i = 0; i < rec.size(); ++i) { - rs_func_.push_back(std::make_shared()); - } - } - - rv_func_.reserve(rec.size()); - if (deck.hasField("VAPOIL")) { - for (size_t i = 0; i < rec.size(); ++i) { - const int cell = *(eqlmap.cells(i).begin()); - if (rec[i].wet_gas_table_index > 0) { - if (deck.hasField("RVVD")) { - // TODO When this kw is actually parsed, also check for proper number of available tables - // For now, just use dummy ... - std::vector depth; depth.push_back(0.0); depth.push_back(100.0); - std::vector rv; rv.push_back(0.0); rv.push_back(0.0001); - rv_func_.push_back(std::make_shared(props, cell, depth, rv)); - } else { - OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); - } - } else { - if (rec[i].goc.depth != rec[i].main.depth) { - OPM_THROW(std::runtime_error, - "Cannot initialise: when no explicit RVVD table is given, \n" - "datum depth must be at the gas-oil-contact. " - "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); - } - const double p_contact = rec[i].main.press + rec[i].goc.press; - rv_func_.push_back(std::make_shared(props, cell, p_contact)); - } - } - } else { - for (size_t i = 0; i < rec.size(); ++i) { - rv_func_.push_back(std::make_shared()); - } - } - - // Compute pressures, saturations, rs and rv factors. - calcPressSatRsRv(eqlmap, rec, props, G, grav); - - // Modify oil pressure in no-oil regions so that the pressures of present phases can - // be recovered from the oil pressure and capillary relations. - } - - typedef std::vector Vec; - typedef std::vector PVec; // One per phase. - - const PVec& press() const { return pp_; } - const PVec& saturation() const { return sat_; } - const Vec& rs() const { return rs_; } - const Vec& rv() const { return rv_; } - - private: - typedef DensityCalculator RhoCalc; - typedef EquilReg EqReg; - - std::vector< std::shared_ptr > rs_func_; - std::vector< std::shared_ptr > rv_func_; - - PVec pp_; - PVec sat_; - Vec rs_; - Vec rv_; - - template - void - calcPressSatRsRv(const RMap& reg , - const std::vector< EquilRecord >& rec , - const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , - const double grav) - { - typedef Miscibility::NoMixing NoMix; - - for (typename RMap::RegionId - r = 0, nr = reg.numRegions(); - r < nr; ++r) - { - const typename RMap::CellRange cells = reg.cells(r); - - const int repcell = *cells.begin(); - const RhoCalc calc(props, repcell); - const EqReg eqreg(rec[r], calc, - rs_func_[r], rv_func_[r], - props.phaseUsage()); - - PVec press = phasePressures(G, eqreg, cells, grav); - - const PVec sat = phaseSaturations(eqreg, cells, props, press); - - const int np = props.numPhases(); - for (int p = 0; p < np; ++p) { - copyFromRegion(press[p], cells, pp_[p]); - copyFromRegion(sat[p], cells, sat_[p]); - } - if (props.phaseUsage().phase_used[BlackoilPhases::Liquid] - && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { - const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gaspos = props.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r]), sat[gaspos]); - const Vec rv = computeRs(G, cells, press[gaspos], *(rv_func_[r]), sat[oilpos]); - copyFromRegion(rs, cells, rs_); - copyFromRegion(rv, cells, rv_); - } - } - } - - template - void copyFromRegion(const Vec& source, - const CellRangeType& cells, - Vec& destination) - { - auto s = source.begin(); - auto c = cells.begin(); - const auto e = cells.end(); - for (; c != e; ++c, ++s) { - destination[*c] = *s; - } - } - - }; - - - template <> - class InitialStateComputer { + class InitialStateComputer { public: InitialStateComputer(const BlackoilPropertiesInterface& props, const Opm::DeckConstPtr newParserDeck, diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index d227d54d1..cd08a98ec 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -735,33 +735,13 @@ namespace Opm * \param[in] deck Simulation deck, used to obtain EQUIL and related data. * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. */ - void initStateEquil(const UnstructuredGrid& grid, - const BlackoilPropertiesInterface& props, - const EclipseGridParser& deck, - const double gravity, - BlackoilState& state) - { - typedef Equil::DeckDependent::InitialStateComputer ISC; - ISC isc(props, deck, grid, gravity); - const auto pu = props.phaseUsage(); - const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] - ? pu.phase_pos[BlackoilPhases::Liquid] - : pu.phase_pos[BlackoilPhases::Aqua]; - state.pressure() = isc.press()[ref_phase]; - state.saturation() = convertSats(isc.saturation()); - state.gasoilratio() = isc.rs(); - state.rv() = isc.rv(); - // TODO: state.surfacevol() must be computed from s, rs, rv. - } - - void initStateEquil(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, const Opm::DeckConstPtr newParserDeck, const double gravity, BlackoilState& state) { - typedef Equil::DeckDependent::InitialStateComputer ISC; + typedef Equil::DeckDependent::InitialStateComputer ISC; ISC isc(props, newParserDeck, grid, gravity); const auto pu = props.phaseUsage(); const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 05f8df8d7..e94f5d267 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -337,7 +337,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -416,7 +416,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -455,7 +455,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -516,7 +516,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -594,7 +594,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -675,7 +675,7 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA"); Opm::BlackoilPropertiesFromDeck props(deck, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); From b5266db401639fa132e511878c7810944bc5f05d Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Sat, 26 Apr 2014 12:03:07 +0200 Subject: [PATCH 064/158] rename all "newParserDeck" objects to "deck" The "new" parser is now "the" parser... --- opm/core/simulator/initStateEquil.hpp | 36 +++++++++++----------- opm/core/simulator/initStateEquil_impl.hpp | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index fd8c35a13..1cf88ee48 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -61,7 +61,7 @@ namespace Opm */ void initStateEquil(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, - const Opm::DeckConstPtr newParserDeck, + const Opm::DeckConstPtr deck, const double gravity, BlackoilState& state); @@ -182,11 +182,11 @@ namespace Opm namespace DeckDependent { inline std::vector - getEquil(const Opm::DeckConstPtr newParserDeck) + getEquil(const Opm::DeckConstPtr deck) { - if (newParserDeck->hasKeyword("EQUIL")) { + if (deck->hasKeyword("EQUIL")) { - Opm::EquilWrapper eql(newParserDeck->getKeyword("EQUIL")); + Opm::EquilWrapper eql(deck->getKeyword("EQUIL")); const int nrec = eql.numRegions(); @@ -228,14 +228,14 @@ namespace Opm inline std::vector - equilnum(const Opm::DeckConstPtr newParserDeck, + equilnum(const Opm::DeckConstPtr deck, const UnstructuredGrid& G ) { std::vector eqlnum; - if (newParserDeck->hasKeyword("EQLNUM")) { + if (deck->hasKeyword("EQLNUM")) { eqlnum.resize(G.number_of_cells); const std::vector& e = - newParserDeck->getKeyword("EQLNUM")->getIntData(); + deck->getKeyword("EQLNUM")->getIntData(); const int* gc = G.global_cell; for (int cell = 0; cell < G.number_of_cells; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; @@ -255,7 +255,7 @@ namespace Opm class InitialStateComputer { public: InitialStateComputer(const BlackoilPropertiesInterface& props, - const Opm::DeckConstPtr newParserDeck, + const Opm::DeckConstPtr deck, const UnstructuredGrid& G , const double grav = unit::gravity) : pp_(props.numPhases(), @@ -266,20 +266,20 @@ namespace Opm rv_(G.number_of_cells) { // Get the equilibration records. - const std::vector rec = getEquil(newParserDeck); + const std::vector rec = getEquil(deck); // Create (inverse) region mapping. - const RegionMapping<> eqlmap(equilnum(newParserDeck, G)); + const RegionMapping<> eqlmap(equilnum(deck, G)); // Create Rs functions. rs_func_.reserve(rec.size()); - if (newParserDeck->hasKeyword("DISGAS")) { + if (deck->hasKeyword("DISGAS")) { for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { - if (newParserDeck->hasKeyword("RSVD") && - size_t(rec[i].live_oil_table_index) <= newParserDeck->getKeyword("RSVD")->size()) { - Opm::SingleRecordTable rsvd(newParserDeck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); + if (deck->hasKeyword("RSVD") && + size_t(rec[i].live_oil_table_index) <= deck->getKeyword("RSVD")->size()) { + Opm::SingleRecordTable rsvd(deck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); std::vector vd(rsvd.getColumn("vd")); std::vector rs(rsvd.getColumn("rs")); rs_func_.push_back(std::make_shared(props, cell, vd, rs)); @@ -304,13 +304,13 @@ namespace Opm } rv_func_.reserve(rec.size()); - if (newParserDeck->hasKeyword("VAPOIL")) { + if (deck->hasKeyword("VAPOIL")) { for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { - if (newParserDeck->hasKeyword("RVVD") && - size_t(rec[i].wet_gas_table_index) <= newParserDeck->getKeyword("RVVD")->size()) { - Opm::SingleRecordTable rvvd(newParserDeck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); + if (deck->hasKeyword("RVVD") && + size_t(rec[i].wet_gas_table_index) <= deck->getKeyword("RVVD")->size()) { + Opm::SingleRecordTable rvvd(deck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); std::vector vd(rvvd.getColumn("vd")); std::vector rv(rvvd.getColumn("rv")); rv_func_.push_back(std::make_shared(props, cell, vd, rv)); diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index cd08a98ec..ba2df1ed4 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -737,12 +737,12 @@ namespace Opm */ void initStateEquil(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, - const Opm::DeckConstPtr newParserDeck, + const Opm::DeckConstPtr deck, const double gravity, BlackoilState& state) { typedef Equil::DeckDependent::InitialStateComputer ISC; - ISC isc(props, newParserDeck, grid, gravity); + ISC isc(props, deck, grid, gravity); const auto pu = props.phaseUsage(); const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] ? pu.phase_pos[BlackoilPhases::Liquid] From beed4544ded28a5fbc44d14ebe756a152477b9a9 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 24 Apr 2014 17:07:41 +0200 Subject: [PATCH 065/158] Implement multi-region PVT for all property classes since they are not using a single PVT table anymore, their "Single" prefix has been removed... --- opm/core/simulator/initStateEquil.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 1cf88ee48..e5f8c8ec2 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -279,7 +279,7 @@ namespace Opm if (rec[i].live_oil_table_index > 0) { if (deck->hasKeyword("RSVD") && size_t(rec[i].live_oil_table_index) <= deck->getKeyword("RSVD")->size()) { - Opm::SingleRecordTable rsvd(deck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); + Opm::SingleRecordTable rsvd(deck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); std::vector vd(rsvd.getColumn("vd")); std::vector rs(rsvd.getColumn("rs")); rs_func_.push_back(std::make_shared(props, cell, vd, rs)); From 8c8ed13c162738b87a2f19a4c53a9bfca21917a3 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Tue, 13 May 2014 12:59:11 +0200 Subject: [PATCH 066/158] incorperate the review comments/decisions for multi-region PVT the largest change is that all classes below opm/core/props/pvt take the PVT region index as an argument, the higher-level ones (i.e., BlackoilProps*) take cell indices. --- opm/core/simulator/EquilibrationHelpers.hpp | 2 +- opm/core/simulator/initStateEquil.hpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index dd90e3689..e97d5077f 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -139,7 +139,7 @@ namespace Opm props_.matrix(1, &p, &z[0], &c_[0], &A[0], dAdp); std::vector rho(np, 0.0); - props_.density(1, &A[0], &rho[0]); + props_.density(1, &A[0], &c_[0], &rho[0]); return rho; } diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index e5f8c8ec2..a4ec1ee4f 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -369,8 +369,6 @@ namespace Opm const UnstructuredGrid& G , const double grav) { - typedef Miscibility::NoMixing NoMix; - for (typename RMap::RegionId r = 0, nr = reg.numRegions(); r < nr; ++r) From 0fc8fee4ccb6f24570681d0a2d15b31ecfa665b6 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Wed, 4 Jun 2014 11:35:24 +0200 Subject: [PATCH 067/158] add missing PVTW keywords to the decks used by the equil test the test still fails, but the errors seem to be due to differences in the saturation functions... --- tests/capillary.DATA | 4 ++++ tests/deadfluids.DATA | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tests/capillary.DATA b/tests/capillary.DATA index 89c938999..64429cf0c 100644 --- a/tests/capillary.DATA +++ b/tests/capillary.DATA @@ -19,6 +19,10 @@ PVDG 200 0.005 0.2 / +PVTW +1.0 1.0 4.0E-5 0.96 0.0 +/ + SWOF 0.2 0 1 0.4 1 1 0 0.1 diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA index 89232054b..bc88ccb59 100644 --- a/tests/deadfluids.DATA +++ b/tests/deadfluids.DATA @@ -19,6 +19,10 @@ PVDG 200 0.02 0.2 / +PVTW +1.0 1.0 4.0E-5 0.96 0.0 +/ + SWOF 0 0 1 0 1 1 0 0 From dcd79e787e6574a19d263876f41c783eedc73726 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Wed, 4 Jun 2014 13:26:37 +0200 Subject: [PATCH 068/158] fix the equilibration test by using new values thanks to @bska for the hints. --- tests/test_equil.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index e94f5d267..ffe3f7366 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -428,13 +428,13 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) // the true answer or something else. const double reltol = 1.0e-6; BOOST_CHECK_CLOSE(pressures[0][first] , 1.469769063e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 1.545e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.546e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 15452880.328284413 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 15462880.328284413 , reltol); const auto& sats = comp.saturation(); const std::vector s[3]{ - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.425893333333, 0.774026666666, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0.00736, 0.792746666666, 0.8, 0.8, 0.8, 0.8, 0.574106666666, 0.225973333333, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42192000000000002, 0.77802666666666664, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.00736, 0.792746666666, 0.8, 0.8, 0.8, 0.8, 0.57807999999999993, 0.22197333333333336, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { From 9731539f6a6c478323f9b58a729343f6d2731de7 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 6 Jun 2014 14:07:14 +0200 Subject: [PATCH 069/158] Glue in support for the grid property modifier keywords this basically means using Opm::EclipseState instead of the raw deck for these keywords. with this, property modifiers like ADD, MULT, COPY and friends are supported for at least the PERM* keywords. If additional keywords are required these can be added relatively easily as well. no ctest regressions have been observed with this patch on my machine. --- examples/compute_initial_state.cpp | 3 ++- tests/capillary.DATA | 39 ++++++++++++++++++++++++++++++ tests/deadfluids.DATA | 39 ++++++++++++++++++++++++++++++ tests/test_equil.cpp | 21 ++++++++++------ 4 files changed, 94 insertions(+), 8 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index b59a9a404..387c1feff 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -86,10 +86,11 @@ try const std::string deck_filename = param.get("deck_filename"); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile(deck_filename); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); const double grav = param.getDefault("gravity", unit::gravity); GridManager gm(deck); const UnstructuredGrid& grid = *gm.c_grid(); - BlackoilPropertiesFromDeck props(deck, grid, param); + BlackoilPropertiesFromDeck props(deck, eclipseState, grid, param); warnIfUnusedParams(param); // Initialisation. diff --git a/tests/capillary.DATA b/tests/capillary.DATA index 64429cf0c..3fbf71ac2 100644 --- a/tests/capillary.DATA +++ b/tests/capillary.DATA @@ -1,7 +1,18 @@ +-- Most of the following sections are not actually needed by the test, +-- but it is required by the Eclipse reference manual that they are +-- present. Also, the higher level opm-parser classes +-- (i.e. Opm::EclipseState et al.) assume that they are present. + +------------------------------------- +RUNSPEC + WATER OIL GAS +DIMENS +3 3 3 / + TABDIMS 1 1 40 20 1 20 / @@ -9,6 +20,27 @@ EQLDIMS -- NTEQUL 1 / +------------------------------------- +GRID + +-- Opm::EclipseState assumes that _some_ grid gets defined, so let's +-- specify a fake one... + +DXV +1 2 3 / + +DYV +4 5 6 / + +DZV +7 8 9 / + +DEPTHZ +16*123.456 / + +------------------------------------- +PROPS + PVDO 100 1.0 1.0 200 0.9 1.0 @@ -37,6 +69,13 @@ DENSITY 700 1000 1 / +------------------------------------- +SOLUTION + EQUIL 50 150 50 0.25 20 0.35 1* 1* 0 / + +------------------------------------- +SCHEDULE +-- empty section diff --git a/tests/deadfluids.DATA b/tests/deadfluids.DATA index bc88ccb59..04264774e 100644 --- a/tests/deadfluids.DATA +++ b/tests/deadfluids.DATA @@ -1,7 +1,18 @@ +-- Most of the following sections are not actually needed by the test, +-- but it is required by the Eclipse reference manual that they are +-- present. Also, the higher level opm-parser classes +-- (i.e. Opm::EclipseState et al.) assume that they are present. + +------------------------------------- +RUNSPEC + WATER OIL GAS +DIMENS +3 3 3 / + TABDIMS 1 1 40 20 1 20 / @@ -9,6 +20,27 @@ EQLDIMS -- NTEQUL 1 / +------------------------------------- +GRID + +-- Opm::EclipseState assumes that _some_ grid gets defined, so let's +-- specify a fake one... + +DXV +1 2 3 / + +DYV +4 5 6 / + +DZV +7 8 9 / + +DEPTHZ +16*123.456 / + +------------------------------------- +PROPS + PVDO 100 1.0 1.0 200 0.5 1.0 @@ -37,6 +69,13 @@ DENSITY 700 1000 10 / +------------------------------------- +SOLUTION + EQUIL 5 150 5 0 2 0 1* 1* 0 / + +------------------------------------- +SCHEDULE +-- empty section diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index ffe3f7366..7084b80fc 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -336,7 +336,8 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, *grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); @@ -362,7 +363,8 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); // Test the capillary inversion for oil-water. const int cell = 0; @@ -414,7 +416,8 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); const auto& pressures = comp.press(); @@ -453,7 +456,8 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); @@ -514,7 +518,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); @@ -592,7 +597,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); @@ -673,7 +679,8 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA"); - Opm::BlackoilPropertiesFromDeck props(deck, grid, false); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); const auto& pressures = comp.press(); From 05b7347b1a88e06c64d129ba0f8cff94809f423f Mon Sep 17 00:00:00 2001 From: osae Date: Tue, 10 Jun 2014 14:02:22 +0200 Subject: [PATCH 070/158] SWATINIT: Initialisation and capillary pressure scaling. --- opm/core/simulator/initStateEquil.hpp | 33 ++++++++++++++++------ opm/core/simulator/initStateEquil_impl.hpp | 15 +++++++--- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index a4ec1ee4f..273271f2d 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -150,8 +150,9 @@ namespace Opm std::vector< std::vector > phaseSaturations(const Region& reg, const CellRange& cells, - const BlackoilPropertiesInterface& props, - const std::vector< std::vector >& phase_pressures); + BlackoilPropertiesInterface& props, + const std::vector swat_init, + std::vector< std::vector >& phase_pressures); @@ -254,7 +255,7 @@ namespace Opm class InitialStateComputer { public: - InitialStateComputer(const BlackoilPropertiesInterface& props, + InitialStateComputer(BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, const UnstructuredGrid& G , const double grav = unit::gravity) @@ -333,6 +334,19 @@ namespace Opm rv_func_.push_back(std::make_shared()); } } + + + // Check for presence of kw SWATINIT + if (deck->hasKeyword("SWATINIT")) { + const std::vector& swat_init = deck->getKeyword("SWATINIT")->getSIDoubleData(); + swat_init_.resize(G.number_of_cells); + const int* gc = G.global_cell; + for (int c = 0; c < G.number_of_cells; ++c) { + const int deck_pos = (gc == NULL) ? c : gc[c]; + swat_init_[c] = swat_init[deck_pos]; + } + + } // Compute pressures, saturations, rs and rv factors. calcPressSatRsRv(eqlmap, rec, props, G, grav); @@ -360,15 +374,18 @@ namespace Opm PVec sat_; Vec rs_; Vec rv_; + Vec swat_init_; template void - calcPressSatRsRv(const RMap& reg , - const std::vector< EquilRecord >& rec , - const Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , + calcPressSatRsRv(const RMap& reg , + const std::vector< EquilRecord >& rec , + Opm::BlackoilPropertiesInterface& props, + const UnstructuredGrid& G , const double grav) { + typedef Miscibility::NoMixing NoMix; + for (typename RMap::RegionId r = 0, nr = reg.numRegions(); r < nr; ++r) @@ -383,7 +400,7 @@ namespace Opm PVec press = phasePressures(G, eqreg, cells, grav); - const PVec sat = phaseSaturations(eqreg, cells, props, press); + const PVec sat = phaseSaturations(eqreg, cells, props, swat_init_, press); const int np = props.numPhases(); for (int p = 0; p < np; ++p) { diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index ba2df1ed4..31215de58 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -579,7 +579,8 @@ namespace Opm std::vector< std::vector > phaseSaturations(const Region& reg, const CellRange& cells, - const BlackoilPropertiesInterface& props, + BlackoilPropertiesInterface& props, + const std::vector swat_init, std::vector< std::vector >& phase_pressures) { const double z0 = reg.datum(); @@ -610,8 +611,14 @@ namespace Opm double sw = 0.0; if (water) { const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; - sw = satFromPc(props, waterpos, cell, pcov); - phase_saturations[waterpos][local_index] = sw; + if (swat_init.empty()) { // Invert Pc to find sw + sw = satFromPc(props, waterpos, cell, pcov); + phase_saturations[waterpos][local_index] = sw; + } else { // Scale Pc to reflect imposed sw + sw = swat_init[cell]; + props.swatInitScaling(cell, pcov, sw); + phase_saturations[waterpos][local_index] = sw; + } } double sg = 0.0; if (gas) { @@ -736,7 +743,7 @@ namespace Opm * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. */ void initStateEquil(const UnstructuredGrid& grid, - const BlackoilPropertiesInterface& props, + BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, const double gravity, BlackoilState& state) From beffa1424ca10273eff2fdebbb9a301251be2261 Mon Sep 17 00:00:00 2001 From: osae Date: Wed, 25 Jun 2014 17:59:02 +0200 Subject: [PATCH 071/158] Adjustments for vanishing oil phase. --- opm/core/simulator/initStateEquil_impl.hpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 31215de58..74dbba1f7 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -628,18 +628,28 @@ namespace Opm sg = satFromPc(props, gaspos, cell, pcog, increasing); phase_saturations[gaspos][local_index] = sg; } - bool overlap = false; if (gas && water && (sg + sw > 1.0)) { // Overlapping gas-oil and oil-water transition // zones can lead to unphysical saturations when // treated as above. Must recalculate using gas-water // capillary pressure. const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; + if (! swat_init.empty()) { + // Re-scale Pc to reflect imposed sw for vanishing oil phase. + // This seems consistent with ecl, and fails to honour + // swat_init in case of non-trivial gas-oil cap pressure. + props.swatInitScaling(cell, pcgw, sw); + } sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); sg = 1.0 - sw; phase_saturations[waterpos][local_index] = sw; phase_saturations[gaspos][local_index] = sg; - overlap = true; + // Adjust oil pressure according to gas saturation and cap pressure + double pc[BlackoilPhases::MaxNumPhases]; + double sat[BlackoilPhases::MaxNumPhases]; + sat[gaspos] = sg; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; } phase_saturations[oilpos][local_index] = 1.0 - sw - sg; @@ -650,7 +660,7 @@ namespace Opm sat[waterpos] = smax[waterpos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pc[waterpos]; - } else if (overlap || sg > smax[gaspos]-1.0e-6) { + } else if (sg > smax[gaspos]-1.0e-6) { sat[gaspos] = smax[gaspos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; From 9d9f5f003b69273687237ddd0bedeb6b28fd16ee Mon Sep 17 00:00:00 2001 From: osae Date: Thu, 26 Jun 2014 14:46:57 +0200 Subject: [PATCH 072/158] Make use of EclipseState for EQLNUM and SWATINIT. --- examples/compute_initial_state.cpp | 2 +- opm/core/simulator/initStateEquil.hpp | 11 +++++++---- opm/core/simulator/initStateEquil_impl.hpp | 3 ++- tests/test_equil.cpp | 12 ++++++------ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 387c1feff..3b118c153 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -95,7 +95,7 @@ try // Initialisation. BlackoilState state; - initStateEquil(grid, props, deck, grav, state); + initStateEquil(grid, props, deck, eclipseState, grav, state); // Output. const std::string output_dir = param.getDefault("output_dir", "output"); diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 273271f2d..b869aa977 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,7 @@ namespace Opm void initStateEquil(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, + const Opm::EclipseStateConstPtr eclipseState, const double gravity, BlackoilState& state); @@ -230,13 +232,14 @@ namespace Opm inline std::vector equilnum(const Opm::DeckConstPtr deck, + const Opm::EclipseStateConstPtr eclipseState, const UnstructuredGrid& G ) { std::vector eqlnum; if (deck->hasKeyword("EQLNUM")) { eqlnum.resize(G.number_of_cells); const std::vector& e = - deck->getKeyword("EQLNUM")->getIntData(); + eclipseState->getIntGridProperty("EQLNUM")->getData(); const int* gc = G.global_cell; for (int cell = 0; cell < G.number_of_cells; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; @@ -257,6 +260,7 @@ namespace Opm public: InitialStateComputer(BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, + const Opm::EclipseStateConstPtr eclipseState, const UnstructuredGrid& G , const double grav = unit::gravity) : pp_(props.numPhases(), @@ -270,7 +274,7 @@ namespace Opm const std::vector rec = getEquil(deck); // Create (inverse) region mapping. - const RegionMapping<> eqlmap(equilnum(deck, G)); + const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); // Create Rs functions. rs_func_.reserve(rec.size()); @@ -338,14 +342,13 @@ namespace Opm // Check for presence of kw SWATINIT if (deck->hasKeyword("SWATINIT")) { - const std::vector& swat_init = deck->getKeyword("SWATINIT")->getSIDoubleData(); + const std::vector& swat_init = eclipseState->getDoubleGridProperty("SWATINIT")->getData(); swat_init_.resize(G.number_of_cells); const int* gc = G.global_cell; for (int c = 0; c < G.number_of_cells; ++c) { const int deck_pos = (gc == NULL) ? c : gc[c]; swat_init_[c] = swat_init[deck_pos]; } - } // Compute pressures, saturations, rs and rv factors. diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 74dbba1f7..553b35969 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -755,11 +755,12 @@ namespace Opm void initStateEquil(const UnstructuredGrid& grid, BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, + const Opm::EclipseStateConstPtr eclipseState, const double gravity, BlackoilState& state) { typedef Equil::DeckDependent::InitialStateComputer ISC; - ISC isc(props, deck, grid, gravity); + ISC isc(props, deck, eclipseState, grid, gravity); const auto pu = props.phaseUsage(); const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] ? pu.phase_pos[BlackoilPhases::Liquid] diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 7084b80fc..839478559 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA"); Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, *grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -419,7 +419,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 10.0); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -459,7 +459,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -521,7 +521,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -600,7 +600,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -682,7 +682,7 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, grid, 9.80665); + Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); From 5be2c46aa85b7d8d53fbbe3742d65d01f6f87283 Mon Sep 17 00:00:00 2001 From: osae Date: Thu, 26 Jun 2014 15:06:47 +0200 Subject: [PATCH 073/158] Included inititalisation of surface volumes. --- opm/core/simulator/initStateEquil_impl.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 553b35969..611c5cd46 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -769,7 +770,7 @@ namespace Opm state.saturation() = convertSats(isc.saturation()); state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); - // TODO: state.surfacevol() must be computed from s, rs, rv. + initBlackoilSurfvolUsingRSorRV(grid, props, state); } From e4f3516fd3808abbf1ee3aa1f73f55e1d4927606 Mon Sep 17 00:00:00 2001 From: osae Date: Mon, 11 Aug 2014 13:19:17 +0200 Subject: [PATCH 074/158] Correcting the equil test. --- tests/test_equil.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 839478559..febc4316f 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -572,18 +572,18 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) } const auto& rs = comp.rs(); - const std::vector rs_opm {74.612335679539058, 74.649052116644228, 74.685786561426298, 74.722539022717172, // opm - 74.759309509353145, 74.796098030174733, 74.8329045940269, 74.869729209758916, - 74.906571886224327, 75.090675116639048, 75.0, 75.0, - 75.0, 75.0, 75.0, 75.0, - 75.0, 75.0, 75.0, 75.0}; + const std::vector rs_opm {74.61233568, 74.64905212, 74.68578656, 74.72253902, // opm + 74.75930951, 74.79609803, 74.83290459, 74.87519876, + 74.96925416, 75.09067512, 75.0, 75.0, + 75.0, 75.0, 75.0, 75.0, + 75.0, 75.0, 75.0, 75.0}; const std::vector rs_ecl {74.612228, 74.648956, 74.685707, 74.722473, // eclipse 74.759254, 74.796051, 74.832870, 74.875145, 74.969231, 75.090706, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000}; for (size_t i = 0; i < rs_opm.size(); ++i) { - //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + //std::cout << std::setprecision(10) << rs[i] << '\n'; BOOST_CHECK_CLOSE(rs[i], rs_opm[i], reltol); BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); } @@ -736,11 +736,11 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) const auto& rs = comp.rs(); const std::vector rs_opm { // opm - 74.624983020822540, 74.659590408801634, 74.694380353364522, 74.729353362649505, - 74.764509945812975, 74.799850613032362, 74.835375875509555, 74.87108624547416, - 74.906982236186707, 75.088917653469309, 52.5, 57.5, - 62.5, 67.5, 72.5, 76.45954840804761, - 76.70621044909619, 76.952877357524045, 77.199549133522638, 77.446225777283587}; + 74.62498302, 74.65959041, 74.69438035, 74.72935336, + 74.76450995, 74.79985061, 74.83537588, 74.87527125, + 74.96863769, 75.08891765, 52.5, 57.5, + 62.5, 67.5, 72.5, 76.45954841, + 76.70621045, 76.95287736, 77.19954913, 77.44622578}; const std::vector rs_ecl { // eclipse 74.625114, 74.659706, 74.694481, 74.729439, @@ -765,7 +765,7 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) 0.82500002E-04, 0.87499997E-04, 0.92499999E-04, 0.97500000E-04}; for (size_t i = 0; i < rv_opm.size(); ++i) { - //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; + //std::cout << std::setprecision(10) << rs[i] << '\n'; BOOST_CHECK_CLOSE(rs[i], rs_opm[i], 100*reltol); BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); BOOST_CHECK_CLOSE(rv[i], rv_opm[i], 100.*reltol); From fe19d25bd6ea2a644b9b660ab7d307984faf54bf Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 11 Aug 2014 11:21:44 +0200 Subject: [PATCH 075/158] Computes saturations based on depths For constant capillar pressure function the saturation is determined by cell depths: Sg_max, Sw_min ----- goc ---- Sg_min, Sw_min ----- woc ---- Sg_min, Sw_max --- opm/core/simulator/EquilibrationHelpers.hpp | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index e97d5077f..9b0626646 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -745,6 +745,7 @@ namespace Opm const PcEq f(props, phase, cell, target_pc); const double f0 = f(s0); const double f1 = f(s1); + if (f0 <= 0.0) { return s0; } else if (f1 > 0.0) { @@ -833,6 +834,46 @@ namespace Opm } } + /// Compute saturation from depth. Used for constant capillary pressure function + inline double satFromDepth(const BlackoilPropertiesInterface& props, + const double cellDepth, + const double contactDepth, + const int phase, + const int cell, + const bool increasing = false) + { + // Find minimum and maximum saturations. + double sminarr[BlackoilPhases::MaxNumPhases]; + double smaxarr[BlackoilPhases::MaxNumPhases]; + props.satRange(1, &cell, sminarr, smaxarr); + const double s0 = increasing ? smaxarr[phase] : sminarr[phase]; + const double s1 = increasing ? sminarr[phase] : smaxarr[phase]; + + if (cellDepth < contactDepth){ + return s0; + } else { + return s1; + } + + } + + /// Return true if capillary pressure function is constant + bool isConstPc(const BlackoilPropertiesInterface& props, + const int phase, + const int cell) + { + // Find minimum and maximum saturations. + double sminarr[BlackoilPhases::MaxNumPhases]; + double smaxarr[BlackoilPhases::MaxNumPhases]; + props.satRange(1, &cell, sminarr, smaxarr); + + // Create the equation f(s) = pc(s); + const PcEq f(props, phase, cell, 0); + const double f0 = f(sminarr[phase]); + const double f1 = f(smaxarr[phase]); + return std::abs(f0 - f1 < std::numeric_limits::epsilon()); + } + } // namespace Equil } // namespace Opm From eb25a7bf5e80433b99fdfa629ced12bd224a4a34 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 11 Aug 2014 11:23:15 +0200 Subject: [PATCH 076/158] Implements initialization for constant capillary pressure functions --- opm/core/simulator/initStateEquil.hpp | 2 +- opm/core/simulator/initStateEquil_impl.hpp | 45 +++++++++++++++------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index b869aa977..bcee71452 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -403,7 +403,7 @@ namespace Opm PVec press = phasePressures(G, eqreg, cells, grav); - const PVec sat = phaseSaturations(eqreg, cells, props, swat_init_, press); + const PVec sat = phaseSaturations(G, eqreg, cells, props, swat_init_, press); const int np = props.numPhases(); for (int p = 0; p < np; ++p) { diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 611c5cd46..5e68a1762 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -578,7 +578,8 @@ namespace Opm template std::vector< std::vector > - phaseSaturations(const Region& reg, + phaseSaturations(const UnstructuredGrid& G, + const Region& reg, const CellRange& cells, BlackoilPropertiesInterface& props, const std::vector swat_init, @@ -598,6 +599,8 @@ namespace Opm double smin[BlackoilPhases::MaxNumPhases] = { 0.0 }; double smax[BlackoilPhases::MaxNumPhases] = { 0.0 }; + const double* const cc = & G.cell_centroids[0]; + const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; @@ -611,23 +614,39 @@ namespace Opm // inverting capillary pressure functions. double sw = 0.0; if (water) { - const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; - if (swat_init.empty()) { // Invert Pc to find sw - sw = satFromPc(props, waterpos, cell, pcov); - phase_saturations[waterpos][local_index] = sw; - } else { // Scale Pc to reflect imposed sw - sw = swat_init[cell]; - props.swatInitScaling(cell, pcov, sw); + if (isConstPc(props,waterpos,cell)){ + const int nd = G.dimensions; + const double cellDepth = cc[nd * cell + nd-1]; + sw = satFromDepth(props,cellDepth,zwoc,waterpos,cell,false); phase_saturations[waterpos][local_index] = sw; } + else{ + const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; + if (swat_init.empty()) { // Invert Pc to find sw + sw = satFromPc(props, waterpos, cell, pcov); + phase_saturations[waterpos][local_index] = sw; + } else { // Scale Pc to reflect imposed sw + sw = swat_init[cell]; + props.swatInitScaling(cell, pcov, sw); + phase_saturations[waterpos][local_index] = sw; + } + } } double sg = 0.0; if (gas) { - // Note that pcog is defined to be (pg - po), not (po - pg). - const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; - const double increasing = true; // pcog(sg) expected to be increasing function - sg = satFromPc(props, gaspos, cell, pcog, increasing); - phase_saturations[gaspos][local_index] = sg; + if (isConstPc(props,gaspos,cell)){ + const int nd = G.dimensions; + const double cellDepth = cc[nd * cell + nd-1]; + sg = satFromDepth(props,cellDepth,zgoc,gaspos,cell,true); + phase_saturations[gaspos][local_index] = sg; + } + else{ + // Note that pcog is defined to be (pg - po), not (po - pg). + const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; + const double increasing = true; // pcog(sg) expected to be increasing function + sg = satFromPc(props, gaspos, cell, pcog, increasing); + phase_saturations[gaspos][local_index] = sg; + } } if (gas && water && (sg + sw > 1.0)) { // Overlapping gas-oil and oil-water transition From 3c7d481c8c01cbae53015157c5c2a61033d7c236 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 11 Aug 2014 12:45:52 +0200 Subject: [PATCH 077/158] BUGFIX Wrong placement of parentes --- opm/core/simulator/EquilibrationHelpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 9b0626646..f7c764355 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -871,7 +871,7 @@ namespace Opm const PcEq f(props, phase, cell, 0); const double f0 = f(sminarr[phase]); const double f1 = f(smaxarr[phase]); - return std::abs(f0 - f1 < std::numeric_limits::epsilon()); + return std::abs(f0 - f1) < std::numeric_limits::epsilon(); } } // namespace Equil From 6038b4bb789d5675f3dd42639f679981521b45c1 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 12 Aug 2014 07:08:57 +0200 Subject: [PATCH 078/158] Changes in the ref. solution in the DeakAllDead test --- tests/test_equil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index febc4316f..78b3d10d8 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -350,8 +350,8 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) // the true answer or something else. const double reltol = 1.0e-3; BOOST_CHECK_CLOSE(pressures[0][first] , 1.496329839e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 1.50473245e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.50473245e7 , reltol); + BOOST_CHECK_CLOSE(pressures[0][last ] , 1.504526940e7 , reltol); + BOOST_CHECK_CLOSE(pressures[1][last] , 1.504526940e7 , reltol); } From 151f967f4da8ed746ba9abb65c919ec8183bd9b0 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Fri, 15 Aug 2014 08:56:35 +0200 Subject: [PATCH 079/158] The water/gas pressures are only calculated if woc and goc lies within the reservoar The water/gas pressure is set to -inf when woc and goc is above or below the reservoar. --- opm/core/simulator/initStateEquil_impl.hpp | 61 +++++++++++++++++----- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 5e68a1762..01db93997 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -394,20 +394,28 @@ namespace Opm assign(G, opress, z0, cells, press); + // Default pressure at WOC and GOC to -inf po_woc = -std::numeric_limits::max(); po_goc = -std::numeric_limits::max(); const double woc = reg.zwoc(); - // Compute Oil pressure at WOC - if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum - else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum - else { po_woc = p0; } // WOC *at* datum + // Compute Oil pressure at WOC, + // if WOC is within the reservoir. + if ( ( woc > span[0] ) & ( woc < span[1] ) ){ + if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum + else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum + else { po_woc = p0; } // WOC *at* datum + } const double goc = reg.zgoc(); - // Compute Oil pressure at GOC - if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum - else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum - else { po_goc = p0; } // GOC *at* datum + // Compute Oil pressure at GOC, + // if GOC is within the reservoir. + if ( ( goc > span[0] ) & ( goc < span[1] ) ){ + if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum + else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum + else { po_goc = p0; } // GOC *at* datum + } + } template 0 ){ + + PhasePressure::water(G, reg, span, grav, po_woc, + cells, press[ wix ]); + } else { + std::vector::size_type local_index = 0; + for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { + const int cell = *ci; + press[wix][cell] = po_woc; + } + } + + } if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gix ]); + + // If woc is above or below the reservoar, + // po_woc is -inf and the water pressure + // is set to -inf. + if (po_goc > 0){ + + PhasePressure::gas(G, reg, span, grav, po_goc, + cells, press[ gix ]); + } else { + std::vector::size_type local_index = 0; + for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { + const int cell = *ci; + press[gix][cell] = po_goc; + } + } + } } } // namespace Details From a6b85d28a4d6fbadff9cd17b807c678d6dc0b3f2 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 18 Aug 2014 08:57:23 +0200 Subject: [PATCH 080/158] Fixes issues pointed out in the PR comments --- opm/core/simulator/initStateEquil_impl.hpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 01db93997..84e146673 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -401,7 +401,7 @@ namespace Opm const double woc = reg.zwoc(); // Compute Oil pressure at WOC, // if WOC is within the reservoir. - if ( ( woc > span[0] ) & ( woc < span[1] ) ){ + if ( ( woc > span[0] ) && ( woc < span[1] ) ){ if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum else { po_woc = p0; } // WOC *at* datum @@ -410,7 +410,7 @@ namespace Opm const double goc = reg.zgoc(); // Compute Oil pressure at GOC, // if GOC is within the reservoir. - if ( ( goc > span[0] ) & ( goc < span[1] ) ){ + if ( ( goc > span[0] ) && ( goc < span[1] ) ){ if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum else { po_goc = p0; } // GOC *at* datum @@ -487,18 +487,12 @@ namespace Opm // po_woc is -inf and the water pressure // is set to -inf. if ( po_woc > 0 ){ - PhasePressure::water(G, reg, span, grav, po_woc, cells, press[ wix ]); } else { - std::vector::size_type local_index = 0; - for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { - const int cell = *ci; - press[wix][cell] = po_woc; - } + press[wix].assign(cells.size(),po_woc); } - } if (PhaseUsed::gas(pu)) { @@ -508,15 +502,10 @@ namespace Opm // po_woc is -inf and the water pressure // is set to -inf. if (po_goc > 0){ - PhasePressure::gas(G, reg, span, grav, po_goc, cells, press[ gix ]); } else { - std::vector::size_type local_index = 0; - for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { - const int cell = *ci; - press[gix][cell] = po_goc; - } + press[gix].assign(cells.size(),po_goc); } } From 11ac3d1ccd6a545413ce48bc204663ad58921d79 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 27 Aug 2014 09:46:14 +0200 Subject: [PATCH 081/158] Currectly handling GOC below and WOC above the reservoir The phase pressure of water and gas is set to inf when WOC and GOC is above and below the reservoir. This make sure the minimum saturation values are picked for these cases. --- opm/core/simulator/initStateEquil_impl.hpp | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 84e146673..f8092bbde 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -394,14 +394,12 @@ namespace Opm assign(G, opress, z0, cells, press); - // Default pressure at WOC and GOC to -inf - po_woc = -std::numeric_limits::max(); - po_goc = -std::numeric_limits::max(); - const double woc = reg.zwoc(); // Compute Oil pressure at WOC, - // if WOC is within the reservoir. - if ( ( woc > span[0] ) && ( woc < span[1] ) ){ + if ( woc > span[1] ) { po_woc = std::numeric_limits::max(); } // WOC above reservoir (model is entirely water filled) + else if ( woc < span[0] ) { po_woc = -std::numeric_limits::max(); } // WOC below reservoir + else{ + // if WOC is within the reservoir. if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum else { po_woc = p0; } // WOC *at* datum @@ -409,8 +407,10 @@ namespace Opm const double goc = reg.zgoc(); // Compute Oil pressure at GOC, - // if GOC is within the reservoir. - if ( ( goc > span[0] ) && ( goc < span[1] ) ){ + if ( goc > span[1] ) { po_goc = -std::numeric_limits::max(); } // GOC above reservoir + else if ( goc < span[0] ) { po_goc = std::numeric_limits::max(); } // GOC below reservoir (model is entirely gas filled) + else{ + // if GOC is within the reservoir. if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum else { po_goc = p0; } // GOC *at* datum @@ -484,9 +484,9 @@ namespace Opm const int wix = PhaseIndex::water(pu); // If woc is above or below the reservoar, - // po_woc is -inf and the water pressure - // is set to -inf. - if ( po_woc > 0 ){ + // po_woc is set to inf and -inf, respectivly + // and so is the water pressure + if ( std::abs(po_woc) < std::numeric_limits::max() ){ PhasePressure::water(G, reg, span, grav, po_woc, cells, press[ wix ]); } else { @@ -498,10 +498,11 @@ namespace Opm if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - // If woc is above or below the reservoar, - // po_woc is -inf and the water pressure - // is set to -inf. - if (po_goc > 0){ + // If goc is above or below the reservoar, + // po_goc is set to -inf and inf, respectivly + // and so is the gas pressure + + if ( std::abs(po_goc) < std::numeric_limits::max()){ PhasePressure::gas(G, reg, span, grav, po_goc, cells, press[ gix ]); } else { From efffb8c385ce27c62b5edc1c6d1459b8b8104fc2 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 27 Aug 2014 14:35:01 +0200 Subject: [PATCH 082/158] Fix sign error in the specified oil pressures at at WOC and GOC The oil pressure at the contact for the special cases: contact location po(contact) GOC above -inf GOC below +inf WOC above -inf WOC below +inf --- opm/core/simulator/initStateEquil_impl.hpp | 33 ++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index f8092bbde..fb5de4fa1 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -394,11 +394,20 @@ namespace Opm assign(G, opress, z0, cells, press); + + const double inf = std::numeric_limits::max(); const double woc = reg.zwoc(); - // Compute Oil pressure at WOC, - if ( woc > span[1] ) { po_woc = std::numeric_limits::max(); } // WOC above reservoir (model is entirely water filled) - else if ( woc < span[0] ) { po_woc = -std::numeric_limits::max(); } // WOC below reservoir - else{ + + // Oil pressure at WOC, Pc_ow = Po - Pw, dPc_ow/dSw <= 0 + if ( woc < span[0] ) { + // WOC above reservoir (model entirely water filled) + po_woc = - inf; + } + else if ( woc > span[1] ) { + // WOC below reservoir (no mobile water) + po_woc = inf; + } + else { // if WOC is within the reservoir. if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum @@ -406,10 +415,18 @@ namespace Opm } const double goc = reg.zgoc(); - // Compute Oil pressure at GOC, - if ( goc > span[1] ) { po_goc = -std::numeric_limits::max(); } // GOC above reservoir - else if ( goc < span[0] ) { po_goc = std::numeric_limits::max(); } // GOC below reservoir (model is entirely gas filled) - else{ + + // Oil pressure at GOC, Pc_go = Pg - Po, dPc_go/dSg >= 0 + if ( goc < span[0] ) { + // GOC above reservoir (no gas phase) + po_goc = -inf; + } + + else if ( goc > span[1] ) { + // GOC below reservoir (model entirely gas filled) + po_goc = inf; + } + else { // if GOC is within the reservoir. if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum From 02f6d8f8eb394deb78ec4f3e41e8ed1776898e88 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 2 Sep 2014 14:42:18 +0200 Subject: [PATCH 083/158] Remove fix for GOC and WOC above/below reservoir --- opm/core/simulator/initStateEquil_impl.hpp | 78 +++++----------------- 1 file changed, 16 insertions(+), 62 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index fb5de4fa1..575c1208f 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -394,44 +394,15 @@ namespace Opm assign(G, opress, z0, cells, press); - - const double inf = std::numeric_limits::max(); const double woc = reg.zwoc(); - - // Oil pressure at WOC, Pc_ow = Po - Pw, dPc_ow/dSw <= 0 - if ( woc < span[0] ) { - // WOC above reservoir (model entirely water filled) - po_woc = - inf; - } - else if ( woc > span[1] ) { - // WOC below reservoir (no mobile water) - po_woc = inf; - } - else { - // if WOC is within the reservoir. - if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum - else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum - else { po_woc = p0; } // WOC *at* datum - } + if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum + else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum + else { po_woc = p0; } // WOC *at* datum const double goc = reg.zgoc(); - - // Oil pressure at GOC, Pc_go = Pg - Po, dPc_go/dSg >= 0 - if ( goc < span[0] ) { - // GOC above reservoir (no gas phase) - po_goc = -inf; - } - - else if ( goc > span[1] ) { - // GOC below reservoir (model entirely gas filled) - po_goc = inf; - } - else { - // if GOC is within the reservoir. - if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum - else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum - else { po_goc = p0; } // GOC *at* datum - } + if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum + else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum + else { po_goc = p0; } // GOC *at* datum } @@ -499,33 +470,14 @@ namespace Opm if (PhaseUsed::water(pu)) { const int wix = PhaseIndex::water(pu); - - // If woc is above or below the reservoar, - // po_woc is set to inf and -inf, respectivly - // and so is the water pressure - if ( std::abs(po_woc) < std::numeric_limits::max() ){ - PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ wix ]); - } else { - press[wix].assign(cells.size(),po_woc); - } - + PhasePressure::water(G, reg, span, grav, po_woc, + cells, press[ wix ]); } if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - - // If goc is above or below the reservoar, - // po_goc is set to -inf and inf, respectivly - // and so is the gas pressure - - if ( std::abs(po_goc) < std::numeric_limits::max()){ - PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gix ]); - } else { - press[gix].assign(cells.size(),po_goc); - } - + PhasePressure::gas(G, reg, span, grav, po_goc, + cells, press[ gix ]); } } } // namespace Details @@ -720,21 +672,23 @@ namespace Opm // Adjust phase pressures for max and min saturation ... double pc[BlackoilPhases::MaxNumPhases]; double sat[BlackoilPhases::MaxNumPhases]; - if (sw > smax[waterpos]-1.0e-6) { + double threshold_sat = 1.0e-6; + + if (sw > smax[waterpos]-threshold_sat ) { sat[waterpos] = smax[waterpos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pc[waterpos]; - } else if (sg > smax[gaspos]-1.0e-6) { + } else if (sg > smax[gaspos]-threshold_sat) { sat[gaspos] = smax[gaspos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; } - if (sg < smin[gaspos]+1.0e-6) { + if (sg < smin[gaspos]+threshold_sat) { sat[gaspos] = smin[gaspos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pc[gaspos]; } - if (sw < smin[waterpos]+1.0e-6) { + if (sw < smin[waterpos]+threshold_sat) { sat[waterpos] = smin[waterpos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pc[waterpos]; From 18dd2c6e3939ef926b0c17569e564ec3a40c5b2e Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 2 Sep 2014 14:46:10 +0200 Subject: [PATCH 084/158] Include goc and woc in the span for the phase pressure calculation --- opm/core/simulator/initStateEquil_impl.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 575c1208f..9656d13c0 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -559,6 +559,10 @@ namespace Opm const double zwoc = reg.zwoc (); const double zgoc = reg.zgoc (); + // make sure goc and woc is within the span for the phase pressure calculation + span[0] = std::min(span[0],zgoc); + span[1] = std::max(span[1],zwoc); + if (! ((zgoc > z0) || (z0 > zwoc))) { // Datum depth in oil zone (zgoc <= z0 <= zwoc) Details::equilibrateOWG(G, reg, grav, span, cells, press); From 87adfef01829b24ec55e049416cc8a69f82586c2 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Wed, 17 Sep 2014 12:44:40 +0200 Subject: [PATCH 085/158] adapt the the table related API changes of opm-parser --- opm/core/simulator/initStateEquil.hpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index bcee71452..bb69a424d 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -279,15 +278,15 @@ namespace Opm // Create Rs functions. rs_func_.reserve(rec.size()); if (deck->hasKeyword("DISGAS")) { + const std::vector& rsvdTables = eclipseState->getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { - if (deck->hasKeyword("RSVD") && - size_t(rec[i].live_oil_table_index) <= deck->getKeyword("RSVD")->size()) { - Opm::SingleRecordTable rsvd(deck->getKeyword("RSVD"),std::vector{"vd", "rs"},rec[i].live_oil_table_index-1); - std::vector vd(rsvd.getColumn("vd")); - std::vector rs(rsvd.getColumn("rs")); - rs_func_.push_back(std::make_shared(props, cell, vd, rs)); + if (rsvdTables.size() > 0 && size_t(rec[i].live_oil_table_index) <= rsvdTables.size()) { + rs_func_.push_back(std::make_shared(props, + cell, + rsvdTables[i].getDepthColumn(), + rsvdTables[i].getRsColumn())); } else { OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); } @@ -310,15 +309,15 @@ namespace Opm rv_func_.reserve(rec.size()); if (deck->hasKeyword("VAPOIL")) { + const std::vector& rvvdTables = eclipseState->getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { - if (deck->hasKeyword("RVVD") && - size_t(rec[i].wet_gas_table_index) <= deck->getKeyword("RVVD")->size()) { - Opm::SingleRecordTable rvvd(deck->getKeyword("RVVD"),std::vector{"vd", "rv"},rec[i].wet_gas_table_index-1); - std::vector vd(rvvd.getColumn("vd")); - std::vector rv(rvvd.getColumn("rv")); - rv_func_.push_back(std::make_shared(props, cell, vd, rv)); + if (rvvdTables.size() > 0 && size_t(rec[i].wet_gas_table_index) <= rvvdTables.size()) { + rv_func_.push_back(std::make_shared(props, + cell, + rvvdTables[i].getDepthColumn(), + rvvdTables[i].getRvColumn())); } else { OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); } From ab75ba3ee5965c3e7ab49230b3a2ccd06cfdc095 Mon Sep 17 00:00:00 2001 From: Robert K Date: Fri, 24 Oct 2014 12:51:57 +0200 Subject: [PATCH 086/158] remove unused typedef to avoid compiler warning and keep code clean. --- opm/core/simulator/initStateEquil.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index bb69a424d..07c341298 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -386,8 +386,6 @@ namespace Opm const UnstructuredGrid& G , const double grav) { - typedef Miscibility::NoMixing NoMix; - for (typename RMap::RegionId r = 0, nr = reg.numRegions(); r < nr; ++r) From baee24ecde04d9d7b88cb63cc3155c6213bc89bd Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 20 Nov 2014 12:15:01 +0100 Subject: [PATCH 087/158] PVT properties: allow them to be temperature dependent Note that this patch does not introduce any real temperature dependence but only changes the APIs for the viscosity and for the density related methods. Note that I also don't like the fact that this requires so many changes to so many files, but with the current design of the property classes I cannot see a way to avoid this... --- opm/core/simulator/EquilibrationHelpers.hpp | 71 +++++++++++++++------ opm/core/simulator/initStateEquil.hpp | 13 ++-- opm/core/simulator/initStateEquil_impl.hpp | 58 ++++++++++++----- 3 files changed, 100 insertions(+), 42 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index f7c764355..16095f44a 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -122,12 +122,15 @@ namespace Opm * * \param[in] p Fluid pressure. * + * \param[in] T Temperature. + * * \param[in] z Surface volumes of all phases. * * \return Phase densities at phase point. */ std::vector operator()(const double p, + const double T, const std::vector& z) const { const int np = props_.numPhases(); @@ -136,7 +139,7 @@ namespace Opm assert (z.size() == std::vector::size_type(np)); double* dAdp = 0; - props_.matrix(1, &p, &z[0], &c_[0], &A[0], dAdp); + props_.matrix(1, &p, &T, &z[0], &c_[0], &A[0], dAdp); std::vector rho(np, 0.0); props_.density(1, &A[0], &c_[0], &rho[0]); @@ -171,11 +174,15 @@ namespace Opm * \param[in] press Pressure at which to calculate RS * value. * + * \param[in] temp Temperature at which to calculate RS + * value. + * * \return Dissolved gas-oil ratio (RS) at depth @c * depth and pressure @c press. */ virtual double operator()(const double depth, const double press, + const double temp, const double sat = 0.0) const = 0; }; @@ -194,6 +201,9 @@ namespace Opm * \param[in] press Pressure at which to calculate RS * value. * + * \param[in] temp Temperature at which to calculate RS + * value. + * * \return Dissolved gas-oil ratio (RS) at depth @c * depth and pressure @c press. In "no mixing * policy", this is identically zero. @@ -201,6 +211,7 @@ namespace Opm double operator()(const double /* depth */, const double /* press */, + const double /* temp */, const double /* sat */ = 0.0) const { return 0.0; @@ -247,18 +258,22 @@ namespace Opm * \param[in] press Pressure at which to calculate RS * value. * + * \param[in] temp Temperature at which to calculate RS + * value. + * * \return Dissolved gas-oil ratio (RS) at depth @c * depth and pressure @c press. */ double operator()(const double depth, const double press, + const double temp, const double sat_gas = 0.0) const { if (sat_gas > 0.0) { - return satRs(press); + return satRs(press, temp); } else { - return std::min(satRs(press), linearInterpolation(depth_, rs_, depth)); + return std::min(satRs(press, temp), linearInterpolation(depth_, rs_, depth)); } } @@ -270,9 +285,9 @@ namespace Opm double z_[BlackoilPhases::MaxNumPhases]; mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; - double satRs(const double press) const + double satRs(const double press, const double temp) const { - props_.matrix(1, &press, z_, &cell_, A_, 0); + props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); // Rs/Bo is in the gas row and oil column of A_. // 1/Bo is in the oil row and column. // Recall also that it is stored in column-major order. @@ -323,18 +338,22 @@ namespace Opm * \param[in] press Pressure at which to calculate RV * value. * + * \param[in] temp Temperature at which to calculate RV + * value. + * * \return Vaporized oil-gas ratio (RV) at depth @c * depth and pressure @c press. */ double operator()(const double depth, const double press, + const double temp, const double sat_oil = 0.0 ) const { if (sat_oil > 0.0) { - return satRv(press); + return satRv(press, temp); } else { - return std::min(satRv(press), linearInterpolation(depth_, rv_, depth)); + return std::min(satRv(press, temp), linearInterpolation(depth_, rv_, depth)); } } @@ -346,9 +365,9 @@ namespace Opm double z_[BlackoilPhases::MaxNumPhases]; mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; - double satRv(const double press) const + double satRv(const double press, const double temp) const { - props_.matrix(1, &press, z_, &cell_, A_, 0); + props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); // Rv/Bg is in the oil row and gas column of A_. // 1/Bg is in the gas row and column. // Recall also that it is stored in column-major order. @@ -382,15 +401,16 @@ namespace Opm * \param[in] props property object * \param[in] cell any cell in the pvt region * \param[in] p_contact oil pressure at the contact + * \param[in] T_contact temperature at the contact */ - RsSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact) + RsSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact, const double T_contact) : props_(props), cell_(cell) { auto pu = props_.phaseUsage(); std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; - rs_sat_contact_ = satRs(p_contact); + rs_sat_contact_ = satRs(p_contact, T_contact); } /** @@ -402,18 +422,22 @@ namespace Opm * \param[in] press Pressure at which to calculate RS * value. * + * \param[in] temp Temperature at which to calculate RS + * value. + * * \return Dissolved gas-oil ratio (RS) at depth @c * depth and pressure @c press. */ double operator()(const double /* depth */, const double press, + const double temp, const double sat_gas = 0.0) const { if (sat_gas > 0.0) { - return satRs(press); + return satRs(press, temp); } else { - return std::min(satRs(press), rs_sat_contact_); + return std::min(satRs(press, temp), rs_sat_contact_); } } @@ -424,9 +448,9 @@ namespace Opm double rs_sat_contact_; mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; - double satRs(const double press) const + double satRs(const double press, const double temp) const { - props_.matrix(1, &press, z_, &cell_, A_, 0); + props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); // Rs/Bo is in the gas row and oil column of A_. // 1/Bo is in the oil row and column. // Recall also that it is stored in column-major order. @@ -460,15 +484,16 @@ namespace Opm * \param[in] props property object * \param[in] cell any cell in the pvt region * \param[in] p_contact oil pressure at the contact + * \param[in] T_contact temperature at the contact */ - RvSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact) + RvSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact, const double T_contact) : props_(props), cell_(cell) { auto pu = props_.phaseUsage(); std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0; z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1e100; - rv_sat_contact_ = satRv(p_contact); + rv_sat_contact_ = satRv(p_contact, T_contact); } /** @@ -480,18 +505,22 @@ namespace Opm * \param[in] press Pressure at which to calculate RV * value. * + * \param[in] temp Temperature at which to calculate RV + * value. + * * \return Dissolved oil-gas ratio (RV) at depth @c * depth and pressure @c press. */ double operator()(const double /*depth*/, const double press, + const double temp, const double sat_oil = 0.0) const { if (sat_oil > 0.0) { - return satRv(press); + return satRv(press, temp); } else { - return std::min(satRv(press), rv_sat_contact_); + return std::min(satRv(press, temp), rv_sat_contact_); } } @@ -502,9 +531,9 @@ namespace Opm double rv_sat_contact_; mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; - double satRv(const double press) const + double satRv(const double press, const double temp) const { - props_.matrix(1, &press, z_, &cell_, A_, 0); + props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); // Rv/Bg is in the oil row and gas column of A_. // 1/Bg is in the gas row and column. // Recall also that it is stored in column-major order. diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 07c341298..8e86c4ef9 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -171,6 +171,7 @@ namespace Opm * \param[in] cells Range that spans the cells of the current * equilibration region. * \param[in] oil_pressure Oil pressure for each cell in range. + * \param[in] temperature Temperature for each cell in range. * \param[in] rs_func Rs as function of pressure and depth. * \return Rs values, one for each cell in the 'cells' range. */ @@ -178,6 +179,7 @@ namespace Opm std::vector computeRs(const UnstructuredGrid& grid, const CellRangeType& cells, const std::vector oil_pressure, + const std::vector& temperature, const Miscibility::RsFunction& rs_func, const std::vector gas_saturation); @@ -298,7 +300,8 @@ namespace Opm "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); } const double p_contact = rec[i].main.press; - rs_func_.push_back(std::make_shared(props, cell, p_contact)); + const double T_contact = 273.15 + 20; // standard temperature for now + rs_func_.push_back(std::make_shared(props, cell, p_contact, T_contact)); } } } else { @@ -329,7 +332,8 @@ namespace Opm "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); } const double p_contact = rec[i].main.press + rec[i].goc.press; - rv_func_.push_back(std::make_shared(props, cell, p_contact)); + const double T_contact = 273.15 + 20; // standard temperature for now + rv_func_.push_back(std::make_shared(props, cell, p_contact, T_contact)); } } } else { @@ -399,6 +403,7 @@ namespace Opm props.phaseUsage()); PVec press = phasePressures(G, eqreg, cells, grav); + const std::vector& temp = temperature(G, eqreg, cells); const PVec sat = phaseSaturations(G, eqreg, cells, props, swat_init_, press); @@ -411,8 +416,8 @@ namespace Opm && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; const int gaspos = props.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const Vec rs = computeRs(G, cells, press[oilpos], *(rs_func_[r]), sat[gaspos]); - const Vec rv = computeRs(G, cells, press[gaspos], *(rv_func_[r]), sat[oilpos]); + const Vec rs = computeRs(G, cells, press[oilpos], temp, *(rs_func_[r]), sat[gaspos]); + const Vec rv = computeRs(G, cells, press[gaspos], temp, *(rv_func_[r]), sat[oilpos]); copyFromRegion(rs, cells, rs_); copyFromRegion(rv, cells, rv_); } diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 9656d13c0..b31297b8d 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -106,11 +106,13 @@ namespace Opm template class Water { public: - Water(const Density& rho, + Water(const double temp, + const Density& rho, const int np, const int ix, const double norm_grav) - : rho_(rho) + : temp_(temp) + , rho_(rho) , svol_(np, 0) , ix_(ix) , g_(norm_grav) @@ -126,6 +128,7 @@ namespace Opm } private: + const double temp_; const Density& rho_; std::vector svol_; const int ix_; @@ -134,7 +137,7 @@ namespace Opm double density(const double press) const { - const std::vector& rho = rho_(press, svol_); + const std::vector& rho = rho_(press, temp_, svol_); return rho[ix_]; } @@ -143,13 +146,15 @@ namespace Opm template class Oil { public: - Oil(const Density& rho, + Oil(const double temp, + const Density& rho, const RS& rs, const int np, const int oix, const int gix, const double norm_grav) - : rho_(rho) + : temp_(temp) + , rho_(rho) , rs_(rs) , svol_(np, 0) , oix_(oix) @@ -167,6 +172,7 @@ namespace Opm } private: + const double temp_; const Density& rho_; const RS& rs_; mutable std::vector svol_; @@ -179,10 +185,10 @@ namespace Opm const double press) const { if (gix_ >= 0) { - svol_[gix_] = rs_(depth, press); + svol_[gix_] = rs_(depth, press, temp_); } - const std::vector& rho = rho_(press, svol_); + const std::vector& rho = rho_(press, temp_, svol_); return rho[oix_]; } }; @@ -190,13 +196,15 @@ namespace Opm template class Gas { public: - Gas(const Density& rho, + Gas(const double temp, + const Density& rho, const RV& rv, const int np, const int gix, const int oix, const double norm_grav) - : rho_(rho) + : temp_(temp) + , rho_(rho) , rv_(rv) , svol_(np, 0) , gix_(gix) @@ -214,6 +222,7 @@ namespace Opm } private: + const double temp_; const Density& rho_; const RV& rv_; mutable std::vector svol_; @@ -226,10 +235,10 @@ namespace Opm const double press) const { if (oix_ >= 0) { - svol_[oix_] = rv_(depth, press); + svol_[oix_] = rv_(depth, press, temp_); } - const std::vector& rho = rho_(press, svol_); + const std::vector& rho = rho_(press, temp_, svol_); return rho[gix_]; } }; @@ -333,7 +342,8 @@ namespace Opm const PhaseUsage& pu = reg.phaseUsage(); const int wix = PhaseIndex::water(pu); - ODE drho(reg.densityCalculator(), pu.num_phases, wix, grav); + const double T = 273.15 + 20; // standard temperature for now + ODE drho(T, reg.densityCalculator(), pu.num_phases, wix, grav); const double z0 = reg.zwoc(); const double p0 = po_woc - reg.pcow_woc(); // Pcow = Po - Pw @@ -373,7 +383,9 @@ namespace Opm const int oix = PhaseIndex::oil(pu); const int gix = PhaseIndex::gas(pu); - ODE drho(reg.densityCalculator(), + const double T = 273.15 + 20; // standard temperature for now + ODE drho(T, + reg.densityCalculator(), reg.dissolutionCalculator(), pu.num_phases, oix, gix, grav); @@ -426,7 +438,9 @@ namespace Opm const int gix = PhaseIndex::gas(pu); const int oix = PhaseIndex::oil(pu); - ODE drho(reg.densityCalculator(), + const double T = 273.15 + 20; // standard temperature for now + ODE drho(T, + reg.densityCalculator(), reg.evaporationCalculator(), pu.num_phases, gix, oix, grav); @@ -573,8 +587,16 @@ namespace Opm return press; } - - + template + std::vector + temperature(const UnstructuredGrid& G, + const Region& reg, + const CellRange& cells) + { + // use the standard temperature for everything for now + return std::vector(cells.size(), 273.15 + 20.0); + } template std::vector< std::vector > @@ -716,6 +738,7 @@ namespace Opm * \param[in] cells Range that spans the cells of the current * equilibration region. * \param[in] oil_pressure Oil pressure for each cell in range. + * \param[in] temperature Temperature for each cell in range. * \param[in] rs_func Rs as function of pressure and depth. * \return Rs values, one for each cell in the 'cells' range. */ @@ -723,6 +746,7 @@ namespace Opm std::vector computeRs(const UnstructuredGrid& grid, const CellRangeType& cells, const std::vector oil_pressure, + const std::vector& temperature, const Miscibility::RsFunction& rs_func, const std::vector gas_saturation) { @@ -731,7 +755,7 @@ namespace Opm int count = 0; for (auto it = cells.begin(); it != cells.end(); ++it, ++count) { const double depth = grid.cell_centroids[3*(*it) + 2]; - rs[count] = rs_func(depth, oil_pressure[count], gas_saturation[count]); + rs[count] = rs_func(depth, oil_pressure[count], temperature[count], gas_saturation[count]); } return rs; } From 2770843d6f79b1b286ff0a8c2fbb214d68a966c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 2 Dec 2014 09:17:11 +0100 Subject: [PATCH 088/158] Silence unused argument warning. --- opm/core/simulator/initStateEquil_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index b31297b8d..e85a67042 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -590,8 +590,8 @@ namespace Opm template std::vector - temperature(const UnstructuredGrid& G, - const Region& reg, + temperature(const UnstructuredGrid& /* G */, + const Region& /* reg */, const CellRange& cells) { // use the standard temperature for everything for now From b942633b3ce2d92069d489ec8e6c541865a5e736 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Fri, 20 Feb 2015 09:26:03 +0100 Subject: [PATCH 089/158] Ported initStateEquil to using the GridHelpers. Currently the keyword EQUIL is not supported by the fully implicit blackoil simulator when using CpGrid. This commit is a first step towards this as it makes the implementation of initStateEquil generic. --- opm/core/simulator/initStateEquil.hpp | 53 ++++++----- opm/core/simulator/initStateEquil_impl.hpp | 105 +++++++++++---------- 2 files changed, 87 insertions(+), 71 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 8e86c4ef9..14deaf677 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -1,5 +1,7 @@ /* Copyright 2014 SINTEF ICT, Applied Mathematics. + Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services + Copyright 2015 NTNU This file is part of the Open Porous Media project (OPM). @@ -20,6 +22,7 @@ #ifndef OPM_INITSTATEEQUIL_HEADER_INCLUDED #define OPM_INITSTATEEQUIL_HEADER_INCLUDED +#include #include #include #include @@ -59,7 +62,8 @@ namespace Opm * \param[in] deck Simulation deck, used to obtain EQUIL and related data. * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. */ - void initStateEquil(const UnstructuredGrid& grid, + template + void initStateEquil(const Grid& grid, const BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, const Opm::EclipseStateConstPtr eclipseState, @@ -114,9 +118,9 @@ namespace Opm * of pressure values in each cell in the current * equilibration region. */ - template + template std::vector< std::vector > - phasePressures(const UnstructuredGrid& G, + phasePressures(const Grid& G, const Region& reg, const CellRange& cells, const double grav = unit::gravity); @@ -147,9 +151,10 @@ namespace Opm * \return Phase saturations, one vector for each phase, each containing * one saturation value per cell in the region. */ - template + template std::vector< std::vector > - phaseSaturations(const Region& reg, + phaseSaturations(const Grid& grid, + const Region& reg, const CellRange& cells, BlackoilPropertiesInterface& props, const std::vector swat_init, @@ -175,8 +180,8 @@ namespace Opm * \param[in] rs_func Rs as function of pressure and depth. * \return Rs values, one for each cell in the 'cells' range. */ - template - std::vector computeRs(const UnstructuredGrid& grid, + template + std::vector computeRs(const Grid& grid, const CellRangeType& cells, const std::vector oil_pressure, const std::vector& temperature, @@ -230,19 +235,21 @@ namespace Opm } } + template inline std::vector equilnum(const Opm::DeckConstPtr deck, const Opm::EclipseStateConstPtr eclipseState, - const UnstructuredGrid& G ) + const Grid& G ) { std::vector eqlnum; if (deck->hasKeyword("EQLNUM")) { - eqlnum.resize(G.number_of_cells); + const int nc = UgGridHelpers::numCells(G); + eqlnum.resize(nc); const std::vector& e = eclipseState->getIntGridProperty("EQLNUM")->getData(); - const int* gc = G.global_cell; - for (int cell = 0; cell < G.number_of_cells; ++cell) { + const int* gc = UgGridHelpers::globalCell(G); + for (int cell = 0; cell < nc; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; eqlnum[cell] = e[deck_pos] - 1; } @@ -250,7 +257,7 @@ namespace Opm else { // No explicit equilibration region. // All cells in region zero. - eqlnum.assign(G.number_of_cells, 0); + eqlnum.assign(UgGridHelpers::numCells(G), 0); } return eqlnum; @@ -259,17 +266,18 @@ namespace Opm class InitialStateComputer { public: + template InitialStateComputer(BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, const Opm::EclipseStateConstPtr eclipseState, - const UnstructuredGrid& G , + const Grid& G , const double grav = unit::gravity) : pp_(props.numPhases(), - std::vector(G.number_of_cells)), + std::vector(UgGridHelpers::numCells(G))), sat_(props.numPhases(), - std::vector(G.number_of_cells)), - rs_(G.number_of_cells), - rv_(G.number_of_cells) + std::vector(UgGridHelpers::numCells(G))), + rs_(UgGridHelpers::numCells(G)), + rv_(UgGridHelpers::numCells(G)) { // Get the equilibration records. const std::vector rec = getEquil(deck); @@ -346,9 +354,10 @@ namespace Opm // Check for presence of kw SWATINIT if (deck->hasKeyword("SWATINIT")) { const std::vector& swat_init = eclipseState->getDoubleGridProperty("SWATINIT")->getData(); - swat_init_.resize(G.number_of_cells); - const int* gc = G.global_cell; - for (int c = 0; c < G.number_of_cells; ++c) { + const int nc = UgGridHelpers::numCells(G); + swat_init_.resize(nc); + const int* gc = UgGridHelpers::globalCell(G); + for (int c = 0; c < nc; ++c) { const int deck_pos = (gc == NULL) ? c : gc[c]; swat_init_[c] = swat_init[deck_pos]; } @@ -382,12 +391,12 @@ namespace Opm Vec rv_; Vec swat_init_; - template + template void calcPressSatRsRv(const RMap& reg , const std::vector< EquilRecord >& rec , Opm::BlackoilPropertiesInterface& props, - const UnstructuredGrid& G , + const Grid& G , const double grav) { for (typename RMap::RegionId diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index e85a67042..9d0c6e7dd 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -1,5 +1,7 @@ /* Copyright 2014 SINTEF ICT, Applied Mathematics. + Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services + Copyright 2015 NTNU This file is part of the Open Porous Media project (OPM). @@ -21,6 +23,7 @@ #define OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED #include +#include #include #include @@ -300,16 +303,17 @@ namespace Opm } // namespace PhaseIndex namespace PhasePressure { - template void - assign(const UnstructuredGrid& G , + assign(const Grid& G , const std::array& f , const double split, const CellRange& cells, std::vector& p ) { - const int nd = G.dimensions; + const int nd = UgGridHelpers::dimensions(G); enum { up = 0, down = 1 }; @@ -320,15 +324,16 @@ namespace Opm { assert (c < p.size()); - const double z = G.cell_centroids[(*ci)*nd + (nd - 1)]; + const double z = UgGridHelpers::cellCentroidCoordinate(G, *ci, nd-1); p[c] = (z < split) ? f[up](z) : f[down](z); } } - template void - water(const UnstructuredGrid& G , + water(const Grid& G , const Region& reg , const std::array& span , const double grav , @@ -363,10 +368,11 @@ namespace Opm assign(G, wpress, z0, cells, press); } - template void - oil(const UnstructuredGrid& G , + oil(const Grid& G , const Region& reg , const std::array& span , const double grav , @@ -418,10 +424,11 @@ namespace Opm } - template void - gas(const UnstructuredGrid& G , + gas(const Grid& G , const Region& reg , const std::array& span , const double grav , @@ -463,10 +470,11 @@ namespace Opm } } // namespace PhasePressure - template void - equilibrateOWG(const UnstructuredGrid& G, + equilibrateOWG(const Grid& G, const Region& reg, const double grav, const std::array& span, @@ -500,10 +508,11 @@ namespace Opm namespace Equil { - template std::vector< std::vector > - phasePressures(const UnstructuredGrid& G, + phasePressures(const Grid& G, const Region& reg, const CellRange& cells, const double grav) @@ -515,18 +524,9 @@ namespace Opm int ncell = 0; { // This code is only supported in three space dimensions - assert (G.dimensions == 3); + assert (UgGridHelpers::dimensions(G) == 3); - const int nd = G.dimensions; - - // Define short-name aliases to reduce visual clutter. - const double* const nc = & G.node_coordinates[0]; - - const int* const cfp = & G.cell_facepos[0]; - const int* const cf = & G.cell_faces[0]; - - const int* const fnp = & G.face_nodepos[0]; - const int* const fn = & G.face_nodes[0]; + const int nd = UgGridHelpers::dimensions(G); // Define vertical span as // @@ -541,21 +541,24 @@ namespace Opm // imposes the requirement that cell centroids are all // within this vertical span. That requirement is not // checked. + typename UgGridHelpers::Cell2FacesTraits::Type + cell2Faces = UgGridHelpers::cell2Faces(G); + typename UgGridHelpers::Face2VerticesTraits::Type + faceVertices = UgGridHelpers::face2Vertices(G); + for (typename CellRange::const_iterator ci = cells.begin(), ce = cells.end(); ci != ce; ++ci, ++ncell) { - for (const int - *fi = & cf[ cfp[*ci + 0] ], - *fe = & cf[ cfp[*ci + 1] ]; - fi != fe; ++fi) + for (auto fi=cell2Faces[*ci].begin(), + fe=cell2Faces[*ci].end(); + fi != fe; + ++fi) { - for (const int - *i = & fn[ fnp[*fi + 0] ], - *e = & fn[ fnp[*fi + 1] ]; + for (auto i = faceVertices[*fi].begin(), e=faceVertices[*fi].end(); i != e; ++i) { - const double z = nc[(*i)*nd + (nd - 1)]; + const double z = UgGridHelpers::vertexCoordinates(G, *i)[nd-1]; if (z < span[0]) { span[0] = z; } if (z > span[1]) { span[1] = z; } @@ -587,10 +590,11 @@ namespace Opm return press; } - template std::vector - temperature(const UnstructuredGrid& /* G */, + temperature(const Grid& /* G */, const Region& /* reg */, const CellRange& cells) { @@ -598,9 +602,9 @@ namespace Opm return std::vector(cells.size(), 273.15 + 20.0); } - template + template std::vector< std::vector > - phaseSaturations(const UnstructuredGrid& G, + phaseSaturations(const Grid& G, const Region& reg, const CellRange& cells, BlackoilPropertiesInterface& props, @@ -621,8 +625,6 @@ namespace Opm double smin[BlackoilPhases::MaxNumPhases] = { 0.0 }; double smax[BlackoilPhases::MaxNumPhases] = { 0.0 }; - const double* const cc = & G.cell_centroids[0]; - const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; @@ -637,8 +639,10 @@ namespace Opm double sw = 0.0; if (water) { if (isConstPc(props,waterpos,cell)){ - const int nd = G.dimensions; - const double cellDepth = cc[nd * cell + nd-1]; + const int nd = UgGridHelpers::dimensions(G); + const double cellDepth = UgGridHelpers::cellCentroidCoordinate(G, + cell, + nd-1); sw = satFromDepth(props,cellDepth,zwoc,waterpos,cell,false); phase_saturations[waterpos][local_index] = sw; } @@ -657,8 +661,10 @@ namespace Opm double sg = 0.0; if (gas) { if (isConstPc(props,gaspos,cell)){ - const int nd = G.dimensions; - const double cellDepth = cc[nd * cell + nd-1]; + const int nd = UgGridHelpers::dimensions(G); + const double cellDepth = UgGridHelpers::cellCentroidCoordinate(G, + cell, + nd-1); sg = satFromDepth(props,cellDepth,zgoc,gaspos,cell,true); phase_saturations[gaspos][local_index] = sg; } @@ -742,19 +748,19 @@ namespace Opm * \param[in] rs_func Rs as function of pressure and depth. * \return Rs values, one for each cell in the 'cells' range. */ - template - std::vector computeRs(const UnstructuredGrid& grid, + template + std::vector computeRs(const Grid& grid, const CellRangeType& cells, const std::vector oil_pressure, const std::vector& temperature, const Miscibility::RsFunction& rs_func, const std::vector gas_saturation) { - assert(grid.dimensions == 3); + assert(UgGridHelpers::dimensions(grid) == 3); std::vector rs(cells.size()); int count = 0; for (auto it = cells.begin(); it != cells.end(); ++it, ++count) { - const double depth = grid.cell_centroids[3*(*it) + 2]; + const double depth = UgGridHelpers::cellCentroidCoordinate(grid, *it, 2); rs[count] = rs_func(depth, oil_pressure[count], temperature[count], gas_saturation[count]); } return rs; @@ -798,7 +804,8 @@ namespace Opm * \param[in] deck Simulation deck, used to obtain EQUIL and related data. * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. */ - void initStateEquil(const UnstructuredGrid& grid, + template + void initStateEquil(const Grid& grid, BlackoilPropertiesInterface& props, const Opm::DeckConstPtr deck, const Opm::EclipseStateConstPtr eclipseState, @@ -815,7 +822,7 @@ namespace Opm state.saturation() = convertSats(isc.saturation()); state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); - initBlackoilSurfvolUsingRSorRV(grid, props, state); + initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); } From b4b9557b850630088a10b8b6de7433a8d4ace090 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Fri, 20 Feb 2015 14:29:05 +0100 Subject: [PATCH 090/158] Rely on auto instead of querying the explicit type via e.g. typename UgGridHelpers::Face2VerticesTraits::Type --- opm/core/simulator/initStateEquil_impl.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 9d0c6e7dd..1e58e02ef 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -541,10 +541,8 @@ namespace Opm // imposes the requirement that cell centroids are all // within this vertical span. That requirement is not // checked. - typename UgGridHelpers::Cell2FacesTraits::Type - cell2Faces = UgGridHelpers::cell2Faces(G); - typename UgGridHelpers::Face2VerticesTraits::Type - faceVertices = UgGridHelpers::face2Vertices(G); + auto cell2Faces = UgGridHelpers::cell2Faces(G); + auto faceVertices = UgGridHelpers::face2Vertices(G); for (typename CellRange::const_iterator ci = cells.begin(), ce = cells.end(); From a8ac4f053d93c7e72b47c77a1fd2b77644f83499 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Fri, 20 Feb 2015 14:30:06 +0100 Subject: [PATCH 091/158] Put spaces around operators. --- opm/core/simulator/initStateEquil_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 1e58e02ef..915fc4ba0 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -553,7 +553,7 @@ namespace Opm fi != fe; ++fi) { - for (auto i = faceVertices[*fi].begin(), e=faceVertices[*fi].end(); + for (auto i = faceVertices[*fi].begin(), e = faceVertices[*fi].end(); i != e; ++i) { const double z = UgGridHelpers::vertexCoordinates(G, *i)[nd-1]; From fedc92d1b4e7839f86480e91c3395dfd225e55c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 2 Mar 2015 10:28:55 +0100 Subject: [PATCH 092/158] Fix unneeded-internal-declaration warning. Again related to anonymous namespace function only being used in template functions. --- opm/core/simulator/initStateEquil_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 915fc4ba0..642fc5695 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -767,7 +767,7 @@ namespace Opm } // namespace Equil - namespace + namespace Details { /// Convert saturations from a vector of individual phase saturation vectors /// to an interleaved format where all values for a given cell come before all @@ -784,7 +784,7 @@ namespace Opm } return s; } - } + } // namespace Details /** @@ -817,7 +817,7 @@ namespace Opm ? pu.phase_pos[BlackoilPhases::Liquid] : pu.phase_pos[BlackoilPhases::Aqua]; state.pressure() = isc.press()[ref_phase]; - state.saturation() = convertSats(isc.saturation()); + state.saturation() = Details::convertSats(isc.saturation()); state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); From fa53925642eaed1ee9839629d0fefb42d0e23f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 14 Apr 2015 15:32:19 +0200 Subject: [PATCH 093/158] Make some programs stricter about parameter parsing. This applies to programs which always require at least one parameter. --- examples/compute_initial_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 3b118c153..4eeec0b25 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -81,7 +81,7 @@ try using namespace Opm; // Setup. - parameter::ParameterGroup param(argc, argv, false); + parameter::ParameterGroup param(argc, argv); std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get("deck_filename"); Opm::ParserPtr parser(new Opm::Parser() ); From 9290cfe32ed8cccea4db5890ae33c214946f6769 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Fri, 24 Apr 2015 10:48:32 +0200 Subject: [PATCH 094/158] fix tests - cannot use BOOST_CHECK_CLOSE around 0 due to a relative test - slacken a tolerance significantly --- tests/test_equil.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 78b3d10d8..5a8eb6f85 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -44,6 +44,14 @@ #include #include +#define CHECK(value, expected, reltol) \ +{ \ + if (std::fabs((expected)) < 1.e-14) \ + BOOST_CHECK_SMALL((value), (reltol)); \ + else \ + BOOST_CHECK_CLOSE((value), (expected), (reltol)); \ +} + BOOST_AUTO_TEST_SUITE () BOOST_AUTO_TEST_CASE (PhasePressure) @@ -443,7 +451,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) for (int phase = 0; phase < 3; ++phase) { BOOST_REQUIRE(sats[phase].size() == s[phase].size()); for (size_t i = 0; i < s[phase].size(); ++i) { - BOOST_CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); + CHECK(sats[phase][i], s[phase][i], reltol); } } } @@ -504,8 +512,8 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); - BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); + CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK(sats[phase][i], s_opm[phase][i], reltol); } } } @@ -565,8 +573,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); - BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK(sats[phase][i], s_opm[phase][i], reltol); + CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } @@ -610,7 +618,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) // but the answer we are checking is the result of an ODE // solver, and it is unclear if we should check it against // the true answer or something else. - const double reltol = 1.0e-6; + const double reltol = 5.0e-3; const double reltol_ecl = 1.0; BOOST_CHECK_CLOSE(pressures[0][first], 1.48215e+07, reltol_ecl); // eclipse BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); @@ -645,8 +653,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], 100.*reltol); - BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK(sats[phase][i], s_opm[phase][i], 100.*reltol); + CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } @@ -668,8 +676,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) for (size_t i = 0; i < rv_opm.size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - BOOST_CHECK_CLOSE(rv[i], rv_opm[i], 100.*reltol); - BOOST_CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); + CHECK(rv[i], rv_opm[i], 100.*reltol); + CHECK(rv[i], rv_ecl[i], reltol_ecl); } } @@ -728,8 +736,8 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - BOOST_CHECK_CLOSE(sats[phase][i], s_opm[phase][i], 100.*reltol); - BOOST_CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK(sats[phase][i], s_opm[phase][i], 100.*reltol); + CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } From 94ea28a2a0f158107d5d70a43990b1a9cb418f06 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 27 Jul 2015 13:07:02 +0200 Subject: [PATCH 095/158] Updated to use ParseMode. --- examples/compute_initial_state.cpp | 6 +++-- tests/test_equil.cpp | 36 ++++++++++++++++++------------ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 4eeec0b25..6093b694b 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -84,9 +85,10 @@ try parameter::ParameterGroup param(argc, argv); std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get("deck_filename"); + Opm::ParseMode parseMode; Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile(deck_filename); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseMode)); const double grav = param.getDefault("gravity", unit::gravity); GridManager gm(deck); const UnstructuredGrid& grid = *gm.c_grid(); diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 5a8eb6f85..b029f5276 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -342,9 +343,10 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) { std::shared_ptr grid(create_grid_cart3d(1, 1, 10), destroy_grid); + Opm::ParseMode parseMode; Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA" , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); @@ -370,8 +372,9 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) Opm::GridManager gm(1, 1, 40, 1.0, 1.0, 2.5); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::ParseMode parseMode; + Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); // Test the capillary inversion for oil-water. @@ -423,8 +426,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::ParseMode parseMode; + Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); @@ -463,8 +467,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::ParseMode parseMode; + Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA" , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -525,8 +530,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::ParseMode parseMode; + Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA" , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -604,8 +610,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::ParseMode parseMode; + Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA" , parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -686,8 +693,9 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA"); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck)); + Opm::ParseMode parseMode; + Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA", parseMode); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); From 1375968541e14005d1c8a57e1a2753ba038009c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 10 Aug 2015 16:07:45 +0200 Subject: [PATCH 096/158] Suppress warnings. --- tests/test_regionmapping.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_regionmapping.cpp b/tests/test_regionmapping.cpp index ca2ad4eab..7b22c5017 100644 --- a/tests/test_regionmapping.cpp +++ b/tests/test_regionmapping.cpp @@ -27,8 +27,11 @@ #define NVERBOSE // Suppress own messages when throw()ing #define BOOST_TEST_MODULE UnitsTest + +#include #include #include +#include /* --- our own headers --- */ From fd3a0ad1365d3f81a348b8a4e5f6a022e0063550 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Tue, 1 Sep 2015 12:58:09 +0200 Subject: [PATCH 097/158] Using TableManager to get tables. --- opm/core/simulator/initStateEquil.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 14deaf677..aa518f3d6 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -281,14 +281,14 @@ namespace Opm { // Get the equilibration records. const std::vector rec = getEquil(deck); - + std::shared_ptr tables = eclipseState->getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); // Create Rs functions. rs_func_.reserve(rec.size()); if (deck->hasKeyword("DISGAS")) { - const std::vector& rsvdTables = eclipseState->getRsvdTables(); + const std::vector& rsvdTables = tables->getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { @@ -320,7 +320,7 @@ namespace Opm rv_func_.reserve(rec.size()); if (deck->hasKeyword("VAPOIL")) { - const std::vector& rvvdTables = eclipseState->getRvvdTables(); + const std::vector& rvvdTables = tables->getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { From 973e89d4a4c08b770fde0de2e8648b2c4e6c3b2c Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Mon, 3 Aug 2015 15:16:15 +0200 Subject: [PATCH 098/158] InitStateEquil: fix valgrind complaint about uninitialized values it seems that it was pure luck that this worked so far! --- opm/core/simulator/initStateEquil_impl.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 642fc5695..aa138126d 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -693,7 +693,9 @@ namespace Opm // Adjust oil pressure according to gas saturation and cap pressure double pc[BlackoilPhases::MaxNumPhases]; double sat[BlackoilPhases::MaxNumPhases]; + sat[waterpos] = sw; sat[gaspos] = sg; + sat[oilpos] = 1.0 - sat[waterpos] - sat[gaspos]; props.capPress(1, sat, &cell, pc, 0); phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; } @@ -704,6 +706,9 @@ namespace Opm double sat[BlackoilPhases::MaxNumPhases]; double threshold_sat = 1.0e-6; + sat[waterpos] = smax[waterpos]; + sat[gaspos] = smax[gaspos]; + sat[oilpos] = 1.0 - sat[waterpos] - sat[gaspos]; if (sw > smax[waterpos]-threshold_sat ) { sat[waterpos] = smax[waterpos]; props.capPress(1, sat, &cell, pc, 0); From f1e102a54ef5992d6cf075d1b9427a1edcdac4e0 Mon Sep 17 00:00:00 2001 From: babrodtk Date: Wed, 2 Sep 2015 13:23:54 +0200 Subject: [PATCH 099/158] Fixed several warnings --- opm/core/simulator/initStateEquil.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index aa518f3d6..ac398b1a9 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -411,24 +411,24 @@ namespace Opm rs_func_[r], rv_func_[r], props.phaseUsage()); - PVec press = phasePressures(G, eqreg, cells, grav); + PVec pressures = phasePressures(G, eqreg, cells, grav); const std::vector& temp = temperature(G, eqreg, cells); - const PVec sat = phaseSaturations(G, eqreg, cells, props, swat_init_, press); + const PVec sat = phaseSaturations(G, eqreg, cells, props, swat_init_, pressures); const int np = props.numPhases(); for (int p = 0; p < np; ++p) { - copyFromRegion(press[p], cells, pp_[p]); + copyFromRegion(pressures[p], cells, pp_[p]); copyFromRegion(sat[p], cells, sat_[p]); } if (props.phaseUsage().phase_used[BlackoilPhases::Liquid] && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; const int gaspos = props.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const Vec rs = computeRs(G, cells, press[oilpos], temp, *(rs_func_[r]), sat[gaspos]); - const Vec rv = computeRs(G, cells, press[gaspos], temp, *(rv_func_[r]), sat[oilpos]); - copyFromRegion(rs, cells, rs_); - copyFromRegion(rv, cells, rv_); + const Vec rs_vals = computeRs(G, cells, pressures[oilpos], temp, *(rs_func_[r]), sat[gaspos]); + const Vec rv_vals = computeRs(G, cells, pressures[gaspos], temp, *(rv_func_[r]), sat[oilpos]); + copyFromRegion(rs_vals, cells, rs_); + copyFromRegion(rv_vals, cells, rv_); } } } From 2cbf99fcde709e143b290e64e90d51a935bdceb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 4 Sep 2015 15:04:13 +0200 Subject: [PATCH 100/158] Mark non-template functions in headers as 'inline' --- opm/core/simulator/EquilibrationHelpers.hpp | 6 +++--- opm/core/simulator/initStateEquil_impl.hpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 16095f44a..2ea49e59e 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -887,9 +887,9 @@ namespace Opm } /// Return true if capillary pressure function is constant - bool isConstPc(const BlackoilPropertiesInterface& props, - const int phase, - const int cell) + inline bool isConstPc(const BlackoilPropertiesInterface& props, + const int phase, + const int cell) { // Find minimum and maximum saturations. double sminarr[BlackoilPhases::MaxNumPhases]; diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index aa138126d..af25b15a6 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -777,7 +777,8 @@ namespace Opm /// Convert saturations from a vector of individual phase saturation vectors /// to an interleaved format where all values for a given cell come before all /// values for the next cell, all in a single vector. - std::vector convertSats(const std::vector< std::vector >& sat) + inline std::vector + convertSats(const std::vector< std::vector >& sat) { const int np = sat.size(); const int nc = sat[0].size(); From b08f89e68ade22c5236f23dc6b2b0b701339cd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 4 Sep 2015 15:08:05 +0200 Subject: [PATCH 101/158] convertSats(): Transpose loop nest for locality of data --- opm/core/simulator/initStateEquil_impl.hpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index af25b15a6..a8344a24f 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -780,14 +780,22 @@ namespace Opm inline std::vector convertSats(const std::vector< std::vector >& sat) { - const int np = sat.size(); - const int nc = sat[0].size(); + const auto np = sat.size(); + const auto nc = sat[0].size(); + std::vector s(np * nc); - for (int c = 0; c < nc; ++c) { - for (int p = 0; p < np; ++p) { - s[np*c + p] = sat[p][c]; + + for (decltype(sat.size()) p = 0; p < np; ++p) { + const auto& sat_p = sat[p]; + double* sp = & s[0*nc + p]; + + for (decltype(sat[0].size()) c = 0; + c < nc; ++c, sp += np) + { + *sp = sat_p[c]; } } + return s; } } // namespace Details From b337714d4d61a72b950e86502a0d1bab592c8b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Wed, 2 Sep 2015 10:36:07 +0200 Subject: [PATCH 102/158] RegionMapping<>: Support arbitrary region IDs This commit introduces a new public method, activeRegions(), that retrieves those region IDs that contain at least one active cell. We furthermore extend the cells() method to support lookup of arbitrary region IDs. Non-active region IDs produce empty cell ranges. Intended use case is for (const auto& reg : rmap.activeRegions()) { const auto& c = rmap.cells(reg); // use c } --- opm/core/simulator/initStateEquil.hpp | 9 +- opm/core/utility/RegionMapping.hpp | 130 +++++++++++--------------- tests/test_equil.cpp | 17 ++-- tests/test_regionmapping.cpp | 120 ++++++++++++++++++++---- 4 files changed, 167 insertions(+), 109 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index ac398b1a9..dc0071003 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -399,13 +399,10 @@ namespace Opm const Grid& G , const double grav) { - for (typename RMap::RegionId - r = 0, nr = reg.numRegions(); - r < nr; ++r) - { - const typename RMap::CellRange cells = reg.cells(r); - + for (const auto& r : reg.activeRegions()) { + const auto& cells = reg.cells(r); const int repcell = *cells.begin(); + const RhoCalc calc(props, repcell); const EqReg eqreg(rec[r], calc, rs_func_[r], rv_func_[r], diff --git a/opm/core/utility/RegionMapping.hpp b/opm/core/utility/RegionMapping.hpp index 151ad07b2..63d412b0f 100644 --- a/opm/core/utility/RegionMapping.hpp +++ b/opm/core/utility/RegionMapping.hpp @@ -20,6 +20,9 @@ #ifndef OPM_REGIONMAPPING_HEADER_INCLUDED #define OPM_REGIONMAPPING_HEADER_INCLUDED +#include + +#include #include namespace Opm @@ -47,7 +50,7 @@ namespace Opm */ explicit RegionMapping(const Region& reg) - : reg_(reg) + : reg_(reg) { rev_.init(reg_); } @@ -70,58 +73,7 @@ namespace Opm */ typedef typename std::vector::const_iterator CellIter; - /** - * Range of cells. Result from reverse (region-to-cell) - * mapping. - */ - class CellRange { - public: - /** - * Constructor. - * - * \param[in] b Beginning of range. - * \param[in] e One past end of range. - */ - CellRange(const CellIter b, - const CellIter e) - : b_(b), e_(e) - {} - - /** - * Read-only iterator on cell ranges. - */ - typedef CellIter const_iterator; - - /** - * Size type for this range. - */ - typedef typename std::vector::size_type size_type; - - /** - * Beginning of cell range. - */ - const_iterator begin() const { return b_; } - - /** - * One past end of cell range. - */ - const_iterator end() const { return e_; } - - /** - * Number of elements in the range. - */ - size_type size() const { return e_ - b_; } - - private: - const_iterator b_; - const_iterator e_; - }; - - /** - * Number of declared regions in cell-to-region mapping. - */ - RegionId - numRegions() const { return RegionId(rev_.p.size()) - 1; } + typedef boost::iterator_range Range; /** * Compute region number of given active cell. @@ -132,17 +84,33 @@ namespace Opm RegionId region(const CellId c) const { return reg_[c]; } + const std::vector& + activeRegions() const + { + return rev_.active; + } + /** * Extract active cells in particular region. * * \param[in] r Region number - * \returns Range of active cells in region @c r. + * + * \return Range of active cells in region @c r. Empty if @c r is + * not an active region. */ - CellRange + Range cells(const RegionId r) const { - const RegionId i = r - rev_.low; - return CellRange(rev_.c.begin() + rev_.p[i + 0], - rev_.c.begin() + rev_.p[i + 1]); + const auto id = rev_.binid.find(r); + + if (id == rev_.binid.end()) { + // Region 'r' not an active region. Return empty. + return Range(rev_.c.end(), rev_.c.end()); + } + + const auto i = id->second; + + return Range(rev_.c.begin() + rev_.p[i + 0], + rev_.c.begin() + rev_.p[i + 1]); } private: @@ -156,9 +124,12 @@ namespace Opm */ struct { typedef typename std::vector::size_type Pos; + + std::unordered_map binid; + std::vector active; + std::vector p; /**< Region start pointers */ std::vector c; /**< Region cells */ - RegionId low; /**< Smallest region number */ /** * Compute reverse mapping. Standard linear insertion @@ -167,32 +138,37 @@ namespace Opm void init(const Region& reg) { - typedef typename Region::const_iterator CI; - const std::pair - m = std::minmax_element(reg.begin(), reg.end()); - - low = *m.first; - - const typename Region::size_type - n = *m.second - low + 1; - - p.resize(n + 1); std::fill(p.begin(), p.end(), Pos(0)); - for (CellId i = 0, nc = reg.size(); i < nc; ++i) { - p[ reg[i] - low + 1 ] += 1; + binid.clear(); + for (const auto& r : reg) { + ++binid[r]; } - for (typename std::vector::size_type - i = 1, sz = p.size(); i < sz; ++i) { + p .clear(); p.emplace_back(0); + active.clear(); + { + Pos n = 0; + for (auto& id : binid) { + active.push_back(id.first); + p .push_back(id.second); + + id.second = n++; + } + } + + for (decltype(p.size()) i = 1, sz = p.size(); i < sz; ++i) { p[0] += p[i]; p[i] = p[0] - p[i]; } - assert (p[0] == - static_cast(reg.size())); + assert (p[0] == static_cast(reg.size())); c.resize(reg.size()); - for (CellId i = 0, nc = reg.size(); i < nc; ++i) { - c[ p[ reg[i] - low + 1 ] ++ ] = i; + { + CellId i = 0; + for (const auto& r : reg) { + auto& pos = p[ binid[r] + 1 ]; + c[ pos++ ] = i++; + } } p[0] = 0; diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index b029f5276..d7436195a 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -307,10 +307,8 @@ BOOST_AUTO_TEST_CASE (RegMapping) Opm::RegionMapping<> eqlmap(eqlnum); PPress ppress(2, PVal(G->number_of_cells, 0)); - for (int r = 0, e = eqlmap.numRegions(); r != e; ++r) - { - const Opm::RegionMapping<>::CellRange& - rng = eqlmap.cells(r); + for (const auto& r : eqlmap.activeRegions()) { + const auto& rng = eqlmap.cells(r); const int rno = r; const double grav = 10; @@ -318,14 +316,13 @@ BOOST_AUTO_TEST_CASE (RegMapping) Opm::Equil::phasePressures(*G, region[rno], rng, grav); PVal::size_type i = 0; - for (Opm::RegionMapping<>::CellRange::const_iterator - c = rng.begin(), ce = rng.end(); - c != ce; ++c, ++i) - { + for (const auto& c : rng) { assert (i < p[0].size()); - ppress[0][*c] = p[0][i]; - ppress[1][*c] = p[1][i]; + ppress[0][c] = p[0][i]; + ppress[1][c] = p[1][i]; + + ++i; } } diff --git a/tests/test_regionmapping.cpp b/tests/test_regionmapping.cpp index 7b22c5017..75eb0318d 100644 --- a/tests/test_regionmapping.cpp +++ b/tests/test_regionmapping.cpp @@ -26,42 +26,130 @@ #define NVERBOSE // Suppress own messages when throw()ing -#define BOOST_TEST_MODULE UnitsTest +#define BOOST_TEST_MODULE RegionMapping #include #include -#include #include /* --- our own headers --- */ #include +#include +#include BOOST_AUTO_TEST_SUITE () -BOOST_AUTO_TEST_CASE (RegionMapping) +BOOST_AUTO_TEST_CASE (Forward) { - // 0 1 2 3 4 5 6 7 8 std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; + Opm::RegionMapping<> rm(regions); - for (size_t i = 0; i < regions.size(); ++i) { + + for (decltype(regions.size()) i = 0, n = regions.size(); i < n; ++i) { BOOST_CHECK_EQUAL(rm.region(i), regions[i]); } - std::vector region_ids = { 2, 3, 4, 5, 6, 7 }; - std::vector< std::vector > region_cells = { { 0, 2, 4 }, { 7 }, { 3 }, { 1 }, { 6, 8 }, { 5 } }; - BOOST_REQUIRE_EQUAL(rm.numRegions(), region_ids.size()); - for (size_t i = 0; i < region_ids.size(); ++i) { - auto cells = rm.cells(region_ids[i]); - BOOST_REQUIRE_EQUAL(std::distance(cells.begin(), cells.end()), region_cells[i].size()); - size_t count = 0; - for (auto iter = cells.begin(); iter != cells.end(); ++iter, ++count) { - BOOST_CHECK_EQUAL(*iter, region_cells[i][count]); - } - } } +BOOST_AUTO_TEST_CASE (ActiveRegions) +{ + // 0 1 2 3 4 5 6 7 8 + std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; + + Opm::RegionMapping<> rm(regions); + + std::vector region_ids = { 2, 3, 4, 5, 6, 7 }; + + auto active = [®ion_ids](const int reg) + { + auto b = region_ids.begin(); + auto e = region_ids.end(); + + return std::find(b, e, reg) != e; + }; + + BOOST_CHECK_EQUAL(rm.activeRegions().size(), region_ids.size()); + + for (const auto& reg : rm.activeRegions()) { + BOOST_CHECK(active(reg)); + } +} + + +BOOST_AUTO_TEST_CASE (Consecutive) +{ + using RegionCells = std::map>; + + // 0 1 2 3 4 5 6 7 8 + std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; + + Opm::RegionMapping<> rm(regions); + + std::vector region_ids = { 2, 3, 4, 5, 6, 7 }; + RegionCells region_cells; + { + using VT = RegionCells::value_type; + + region_cells.insert(VT(2, { 0, 2, 4 })); + region_cells.insert(VT(3, { 7 })); + region_cells.insert(VT(4, { 3 })); + region_cells.insert(VT(5, { 1 })); + region_cells.insert(VT(6, { 6, 8 })); + region_cells.insert(VT(7, { 5 })); + } + + for (const auto& reg : region_ids) { + const auto& cells = rm.cells(reg); + const auto& expect = region_cells[reg]; + + BOOST_CHECK_EQUAL_COLLECTIONS(cells .begin(), cells .end(), + expect.begin(), expect.end()); + } + + // Verify that there are no cells in unused regions 0 and 1. + for (const auto& r : { 0, 1 }) { + BOOST_CHECK(rm.cells(r).empty()); + } +} + + +BOOST_AUTO_TEST_CASE (NonConsecutive) +{ + using RegionCells = std::map>; + + // 0 1 2 3 4 5 6 7 8 + std::vector regions = { 2, 4, 2, 4, 2, 7, 6, 3, 6 }; + + Opm::RegionMapping<> rm(regions); + + std::vector region_ids = { 2, 3, 4, 6, 7 }; + RegionCells region_cells; + { + using VT = RegionCells::value_type; + + region_cells.insert(VT(2, { 0, 2, 4 })); + region_cells.insert(VT(3, { 7 })); + region_cells.insert(VT(4, { 1, 3 })); + region_cells.insert(VT(6, { 6, 8 })); + region_cells.insert(VT(7, { 5 })); + } + + for (const auto& reg : region_ids) { + const auto& cells = rm.cells(reg); + const auto& expect = region_cells[reg]; + + BOOST_CHECK_EQUAL_COLLECTIONS(cells .begin(), cells .end(), + expect.begin(), expect.end()); + } + + // Verify that there are no cells in unused regions 0, 1, and 5. + for (const auto& r : { 0, 1, 5 }) { + BOOST_CHECK(rm.cells(r).empty()); + } +} + BOOST_AUTO_TEST_SUITE_END() From ecb7dec7523c27bc36c6015fedd1887a67b32da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 1 Oct 2015 15:20:08 +0200 Subject: [PATCH 103/158] Make grid in deck have larger number of cells. This makes some tests succeed that use this deck only for its properties and not its grid: if the grid in the deck has fewer cells than the grid that is used for the test we will fail in the SATNUM mapping. --- tests/capillary.DATA | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/capillary.DATA b/tests/capillary.DATA index 3fbf71ac2..063db39fe 100644 --- a/tests/capillary.DATA +++ b/tests/capillary.DATA @@ -11,7 +11,7 @@ OIL GAS DIMENS -3 3 3 / +40 40 40 / TABDIMS 1 1 40 20 1 20 / @@ -27,16 +27,16 @@ GRID -- specify a fake one... DXV -1 2 3 / +40*1 / DYV -4 5 6 / +40*1 / DZV -7 8 9 / +40*1 / DEPTHZ -16*123.456 / +1681*123.456 / ------------------------------------- PROPS From cb9d8709f92cab08dcdeda4f7ca675203f313484 Mon Sep 17 00:00:00 2001 From: osae Date: Mon, 21 Sep 2015 18:22:11 +0200 Subject: [PATCH 104/158] Support for equil-initialisation for datum depth outside oil zone. --- opm/core/simulator/initStateEquil_impl.hpp | 146 +++++++++++++++------ 1 file changed, 106 insertions(+), 40 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index a8344a24f..20ca1f40c 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -337,7 +337,7 @@ namespace Opm const Region& reg , const std::array& span , const double grav , - const double po_woc, + double& po_woc, const CellRange& cells , std::vector& press ) { @@ -350,8 +350,15 @@ namespace Opm const double T = 273.15 + 20; // standard temperature for now ODE drho(T, reg.densityCalculator(), pu.num_phases, wix, grav); - const double z0 = reg.zwoc(); - const double p0 = po_woc - reg.pcow_woc(); // Pcow = Po - Pw + double z0; + double p0; + if (reg.datum() > reg.zwoc()) {//Datum in water zone + z0 = reg.datum(); + p0 = reg.pressure(); + } else { + z0 = reg.zwoc(); + p0 = po_woc - reg.pcow_woc(); // Water pressure at contact + } std::array up = {{ z0, span[0] }}; std::array down = {{ z0, span[1] }}; @@ -366,6 +373,11 @@ namespace Opm }; assign(G, wpress, z0, cells, press); + + if (reg.datum() > reg.zwoc()) { + // Return oil pressure at contact + po_woc = wpress[0](reg.zwoc()) + reg.pcow_woc(); + } } template reg.zwoc()) {//Datum in water zone, po_woc given + z0 = reg.zwoc(); + p0 = po_woc; + } else if (reg.datum() < reg.zgoc()) {//Datum in gas zone, po_goc given + z0 = reg.zgoc(); + p0 = po_goc; + } else { //Datum in oil zone + z0 = reg.datum(); + p0 = reg.pressure(); + } std::array up = {{ z0, span[0] }}; std::array down = {{ z0, span[1] }}; @@ -421,7 +443,6 @@ namespace Opm if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum else { po_goc = p0; } // GOC *at* datum - } template & span , const double grav , - const double po_goc, + double& po_goc, const CellRange& cells , std::vector& press ) { @@ -451,8 +472,15 @@ namespace Opm reg.evaporationCalculator(), pu.num_phases, gix, oix, grav); - const double z0 = reg.zgoc(); - const double p0 = po_goc + reg.pcgo_goc(); // Pcog = Pg - Po + double z0; + double p0; + if (reg.datum() < reg.zgoc()) {//Datum in gas zone + z0 = reg.datum(); + p0 = reg.pressure(); + } else { + z0 = reg.zgoc(); + p0 = po_goc + reg.pcgo_goc(); // Gas pressure at contact + } std::array up = {{ z0, span[0] }}; std::array down = {{ z0, span[1] }}; @@ -467,6 +495,11 @@ namespace Opm }; assign(G, gpress, z0, cells, press); + + if (reg.datum() < reg.zgoc()) { + // Return oil pressure at contact + po_goc = gpress[1](reg.zgoc()) - reg.pcgo_goc(); + } } } // namespace PhasePressure @@ -483,23 +516,69 @@ namespace Opm { const PhaseUsage& pu = reg.phaseUsage(); - double po_woc = -1, po_goc = -1; - if (PhaseUsed::oil(pu)) { - const int oix = PhaseIndex::oil(pu); - PhasePressure::oil(G, reg, span, grav, cells, - press[ oix ], po_woc, po_goc); - } + if (reg.datum() > reg.zwoc()) { // Datum in water zone + double po_woc = -1; + double po_goc = -1; - if (PhaseUsed::water(pu)) { - const int wix = PhaseIndex::water(pu); - PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ wix ]); - } + if (PhaseUsed::water(pu)) { + const int wix = PhaseIndex::water(pu); + PhasePressure::water(G, reg, span, grav, po_woc, + cells, press[ wix ]); + } - if (PhaseUsed::gas(pu)) { - const int gix = PhaseIndex::gas(pu); - PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gix ]); + if (PhaseUsed::oil(pu)) { + const int oix = PhaseIndex::oil(pu); + PhasePressure::oil(G, reg, span, grav, cells, + press[ oix ], po_woc, po_goc); + } + + if (PhaseUsed::gas(pu)) { + const int gix = PhaseIndex::gas(pu); + PhasePressure::gas(G, reg, span, grav, po_goc, + cells, press[ gix ]); + } + } else if (reg.datum() < reg.zgoc()) { // Datum in gas zone + double po_woc = -1; + double po_goc = -1; + + if (PhaseUsed::gas(pu)) { + const int gix = PhaseIndex::gas(pu); + PhasePressure::gas(G, reg, span, grav, po_goc, + cells, press[ gix ]); + } + + if (PhaseUsed::oil(pu)) { + const int oix = PhaseIndex::oil(pu); + PhasePressure::oil(G, reg, span, grav, cells, + press[ oix ], po_woc, po_goc); + } + + if (PhaseUsed::water(pu)) { + const int wix = PhaseIndex::water(pu); + PhasePressure::water(G, reg, span, grav, po_woc, + cells, press[ wix ]); + } + } else { // Datum in oil zone + double po_woc = -1; + double po_goc = -1; + + if (PhaseUsed::oil(pu)) { + const int oix = PhaseIndex::oil(pu); + PhasePressure::oil(G, reg, span, grav, cells, + press[ oix ], po_woc, po_goc); + } + + if (PhaseUsed::water(pu)) { + const int wix = PhaseIndex::water(pu); + PhasePressure::water(G, reg, span, grav, po_woc, + cells, press[ wix ]); + } + + if (PhaseUsed::gas(pu)) { + const int gix = PhaseIndex::gas(pu); + PhasePressure::gas(G, reg, span, grav, po_goc, + cells, press[ gix ]); + } } } } // namespace Details @@ -564,13 +643,11 @@ namespace Opm } } } - const int np = reg.phaseUsage().num_phases; typedef std::vector pval; std::vector press(np, pval(ncell, 0.0)); - const double z0 = reg.datum(); const double zwoc = reg.zwoc (); const double zgoc = reg.zgoc (); @@ -578,12 +655,7 @@ namespace Opm span[0] = std::min(span[0],zgoc); span[1] = std::max(span[1],zwoc); - if (! ((zgoc > z0) || (z0 > zwoc))) { - // Datum depth in oil zone (zgoc <= z0 <= zwoc) - Details::equilibrateOWG(G, reg, grav, span, cells, press); - } else { - OPM_THROW(std::runtime_error, "Cannot initialise: the datum depth must be in the oil zone."); - } + Details::equilibrateOWG(G, reg, grav, span, cells, press); return press; } @@ -609,12 +681,6 @@ namespace Opm const std::vector swat_init, std::vector< std::vector >& phase_pressures) { - const double z0 = reg.datum(); - const double zwoc = reg.zwoc (); - const double zgoc = reg.zgoc (); - if ((zgoc > z0) || (z0 > zwoc)) { - OPM_THROW(std::runtime_error, "Cannot initialise: the datum depth must be in the oil zone."); - } if (!reg.phaseUsage().phase_used[BlackoilPhases::Liquid]) { OPM_THROW(std::runtime_error, "Cannot initialise: not handling water-gas cases."); } @@ -641,7 +707,7 @@ namespace Opm const double cellDepth = UgGridHelpers::cellCentroidCoordinate(G, cell, nd-1); - sw = satFromDepth(props,cellDepth,zwoc,waterpos,cell,false); + sw = satFromDepth(props,cellDepth,reg.zwoc(),waterpos,cell,false); phase_saturations[waterpos][local_index] = sw; } else{ @@ -663,7 +729,7 @@ namespace Opm const double cellDepth = UgGridHelpers::cellCentroidCoordinate(G, cell, nd-1); - sg = satFromDepth(props,cellDepth,zgoc,gaspos,cell,true); + sg = satFromDepth(props,cellDepth,reg.zgoc(),gaspos,cell,true); phase_saturations[gaspos][local_index] = sg; } else{ From 4e620e7eb6d57417b4a6229f13848581a590877b Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 21 Sep 2015 18:22:09 +0200 Subject: [PATCH 105/158] Changed Table code to use TableContainer --- opm/core/simulator/initStateEquil.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index dc0071003..707287405 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -288,15 +288,17 @@ namespace Opm // Create Rs functions. rs_func_.reserve(rec.size()); if (deck->hasKeyword("DISGAS")) { - const std::vector& rsvdTables = tables->getRsvdTables(); + const TableContainer& rsvdTables = tables->getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { + const RsvdTable& rsvdTable = rsvdTables.getTable(i); const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { if (rsvdTables.size() > 0 && size_t(rec[i].live_oil_table_index) <= rsvdTables.size()) { + rs_func_.push_back(std::make_shared(props, cell, - rsvdTables[i].getDepthColumn(), - rsvdTables[i].getRsColumn())); + rsvdTable.getDepthColumn(), + rsvdTable.getRsColumn())); } else { OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); } @@ -320,15 +322,16 @@ namespace Opm rv_func_.reserve(rec.size()); if (deck->hasKeyword("VAPOIL")) { - const std::vector& rvvdTables = tables->getRvvdTables(); + const TableContainer& rvvdTables = tables->getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (rec[i].wet_gas_table_index > 0) { if (rvvdTables.size() > 0 && size_t(rec[i].wet_gas_table_index) <= rvvdTables.size()) { + const RvvdTable& rvvdTable = rvvdTables.getTable(i); rv_func_.push_back(std::make_shared(props, cell, - rvvdTables[i].getDepthColumn(), - rvvdTables[i].getRvColumn())); + rvvdTable.getDepthColumn(), + rvvdTable.getRvColumn())); } else { OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); } From f7da1ca81cd845e5fbb099c813b34e60ef02e039 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 5 Oct 2015 15:59:08 +0200 Subject: [PATCH 106/158] Fxied bug in table-container use. --- opm/core/simulator/initStateEquil.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 707287405..6ce7f96bb 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -290,11 +290,10 @@ namespace Opm if (deck->hasKeyword("DISGAS")) { const TableContainer& rsvdTables = tables->getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { - const RsvdTable& rsvdTable = rsvdTables.getTable(i); const int cell = *(eqlmap.cells(i).begin()); if (rec[i].live_oil_table_index > 0) { if (rsvdTables.size() > 0 && size_t(rec[i].live_oil_table_index) <= rsvdTables.size()) { - + const RsvdTable& rsvdTable = rsvdTables.getTable(i); rs_func_.push_back(std::make_shared(props, cell, rsvdTable.getDepthColumn(), From cbc41cfbf755e679c7fe64097bcd611567fb9b78 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Tue, 6 Oct 2015 11:39:14 +0200 Subject: [PATCH 107/158] Relocated warning headers. --- tests/test_regionmapping.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_regionmapping.cpp b/tests/test_regionmapping.cpp index 75eb0318d..760a719f9 100644 --- a/tests/test_regionmapping.cpp +++ b/tests/test_regionmapping.cpp @@ -28,9 +28,9 @@ #define BOOST_TEST_MODULE RegionMapping -#include +#include #include -#include +#include /* --- our own headers --- */ From b04db90cfeecc756aec4178b081f104ec738464a Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 8 Oct 2015 11:42:15 +0200 Subject: [PATCH 108/158] use the error macros from opm-common --- examples/compute_initial_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 6093b694b..a8e3704d0 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include From e11257d8cef43ce270d8cffc20235587f38323f8 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Mon, 26 Oct 2015 11:21:26 +0100 Subject: [PATCH 109/158] fix Equilibration test by adding some fuzz Backports parts of a7b1e69a45c14ec88a82b92ee704424f1ea1b41c --- opm/core/simulator/EquilibrationHelpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 2ea49e59e..8619cf640 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -350,7 +350,7 @@ namespace Opm const double temp, const double sat_oil = 0.0 ) const { - if (sat_oil > 0.0) { + if (std::abs(sat_oil) > 1e-16) { return satRv(press, temp); } else { return std::min(satRv(press, temp), linearInterpolation(depth_, rv_, depth)); From ca902168ed6b5d85f140379c71a756e67c460abb Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Fri, 30 Oct 2015 08:14:10 +0100 Subject: [PATCH 110/158] Change the number of integration points in the initialization The number is changed from 100->2000 to increase accuracy. --- opm/core/simulator/initStateEquil_impl.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 20ca1f40c..b2c433e94 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -366,9 +366,9 @@ namespace Opm typedef Details::RK4IVP WPress; std::array wpress = { { - WPress(drho, up , p0, 100) + WPress(drho, up , p0, 2000) , - WPress(drho, down, p0, 100) + WPress(drho, down, p0, 2000) } }; @@ -426,9 +426,9 @@ namespace Opm typedef Details::RK4IVP OPress; std::array opress = { { - OPress(drho, up , p0, 100) + OPress(drho, up , p0, 2000) , - OPress(drho, down, p0, 100) + OPress(drho, down, p0, 2000) } }; @@ -488,9 +488,9 @@ namespace Opm typedef Details::RK4IVP GPress; std::array gpress = { { - GPress(drho, up , p0, 100) + GPress(drho, up , p0, 2000) , - GPress(drho, down, p0, 100) + GPress(drho, down, p0, 2000) } }; From d77e33b5dc213fccccd88369085c3f26c5b561b0 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 24 Nov 2015 10:17:12 +0100 Subject: [PATCH 111/158] Use cell depths based on averaging cell corners --- opm/core/simulator/initStateEquil_impl.hpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index b2c433e94..359666efe 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -313,7 +313,6 @@ namespace Opm const CellRange& cells, std::vector& p ) { - const int nd = UgGridHelpers::dimensions(G); enum { up = 0, down = 1 }; @@ -324,7 +323,7 @@ namespace Opm { assert (c < p.size()); - const double z = UgGridHelpers::cellCentroidCoordinate(G, *ci, nd-1); + const double z = UgGridHelpers::cellCenterDepth(G, *ci); p[c] = (z < split) ? f[up](z) : f[down](z); } } @@ -703,10 +702,8 @@ namespace Opm double sw = 0.0; if (water) { if (isConstPc(props,waterpos,cell)){ - const int nd = UgGridHelpers::dimensions(G); - const double cellDepth = UgGridHelpers::cellCentroidCoordinate(G, - cell, - nd-1); + const double cellDepth = UgGridHelpers::cellCenterDepth(G, + cell); sw = satFromDepth(props,cellDepth,reg.zwoc(),waterpos,cell,false); phase_saturations[waterpos][local_index] = sw; } @@ -725,10 +722,8 @@ namespace Opm double sg = 0.0; if (gas) { if (isConstPc(props,gaspos,cell)){ - const int nd = UgGridHelpers::dimensions(G); - const double cellDepth = UgGridHelpers::cellCentroidCoordinate(G, - cell, - nd-1); + const double cellDepth = UgGridHelpers::cellCenterDepth(G, + cell); sg = satFromDepth(props,cellDepth,reg.zgoc(),gaspos,cell,true); phase_saturations[gaspos][local_index] = sg; } @@ -829,7 +824,7 @@ namespace Opm std::vector rs(cells.size()); int count = 0; for (auto it = cells.begin(); it != cells.end(); ++it, ++count) { - const double depth = UgGridHelpers::cellCentroidCoordinate(grid, *it, 2); + const double depth = UgGridHelpers::cellCenterDepth(grid, *it); rs[count] = rs_func(depth, oil_pressure[count], temperature[count], gas_saturation[count]); } return rs; From 0cf00f240b39b805ffec1369ab79981b5ef3ad42 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Tue, 5 Jan 2016 12:12:29 +0100 Subject: [PATCH 112/158] Changed to use new table api from opm-parser. --- opm/core/simulator/initStateEquil.hpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 6ce7f96bb..e439d0805 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -294,10 +294,11 @@ namespace Opm if (rec[i].live_oil_table_index > 0) { if (rsvdTables.size() > 0 && size_t(rec[i].live_oil_table_index) <= rsvdTables.size()) { const RsvdTable& rsvdTable = rsvdTables.getTable(i); + std::vector depthColumn = rsvdTable.getColumn("DEPTH").vectorCopy(); + std::vector rsColumn = rsvdTable.getColumn("RS").vectorCopy(); rs_func_.push_back(std::make_shared(props, cell, - rsvdTable.getDepthColumn(), - rsvdTable.getRsColumn())); + depthColumn , rsColumn)); } else { OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); } @@ -327,10 +328,13 @@ namespace Opm if (rec[i].wet_gas_table_index > 0) { if (rvvdTables.size() > 0 && size_t(rec[i].wet_gas_table_index) <= rvvdTables.size()) { const RvvdTable& rvvdTable = rvvdTables.getTable(i); + std::vector depthColumn = rvvdTable.getColumn("DEPTH").vectorCopy(); + std::vector rvColumn = rvvdTable.getColumn("RV").vectorCopy(); + rv_func_.push_back(std::make_shared(props, cell, - rvvdTable.getDepthColumn(), - rvvdTable.getRvColumn())); + depthColumn , rvColumn)); + } else { OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); } From da411e49a50ec55d66c4badbd8914188d4ec5036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Wed, 20 Jan 2016 14:12:04 +0100 Subject: [PATCH 113/158] Fixes includes wrt opm-parser PR-656 Several files stopped compiling due to relying on opm-parser headers doing includes. From opm-parser PR-656 https://github.com/OPM/opm-parser/pull/656 this assumption is no longer valid. --- opm/core/simulator/initStateEquil.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index e439d0805..0a0c2f6ef 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include From 04a368cfc6b7e3150b9c737c1eb93a6bae0a46e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Fri, 26 Feb 2016 11:49:40 +0100 Subject: [PATCH 114/158] Add missing opm-parser headers opm-parser pull #695 https://github.com/OPM/opm-parser/pull/695 --- opm/core/simulator/initStateEquil.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 0a0c2f6ef..b8bdde42f 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include From 32c5b5e8624c340ceb5408297817493e1a83a9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Mon, 29 Feb 2016 15:41:08 +0100 Subject: [PATCH 115/158] Remove Equil + EquilWrapper, replace with upstream Upstream (opm-parser) now provides a better Equil + EquilRecord, and simultaneously deprecated EquilWrapper. This patch fixes the resulting breakage. One important note: The new Equil does not expose integers for live oil/wet gas initialization procedure methods, but rather booleans through constRs/constRv methods. This is how the variable behaves according to the Eclipse reference manual (EQUIL keyword section). Code has been updated to reflect this. --- opm/core/simulator/EquilibrationHelpers.hpp | 66 +------ opm/core/simulator/initStateEquil.hpp | 106 ++++------- opm/core/simulator/initStateEquil_impl.hpp | 4 +- tests/test_equil.cpp | 195 +++++++++++--------- 4 files changed, 158 insertions(+), 213 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 8619cf640..6d4a4e40e 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -26,6 +26,8 @@ #include #include +#include + #include @@ -34,7 +36,7 @@ namespace Opm { - namespace Equil { + namespace EQUIL { template class DensityCalculator; @@ -49,8 +51,6 @@ namespace Opm class RsSatAtContact; } - struct EquilRecord; - template class EquilReg; @@ -84,7 +84,7 @@ namespace Opm * This namespace is intentionally nested to avoid name clashes * with other parts of OPM. */ - namespace Equil { + namespace EQUIL { template @@ -546,52 +546,6 @@ namespace Opm } // namespace Miscibility - - - /** - * Equilibration record. - * - * Layout and contents inspired by first six items of - * ECLIPSE's 'EQUIL' records. This is the minimum amount of - * input data needed to define phase pressures in an - * equilibration region. - * - * Data consists of three pairs of depth and pressure values: - * 1. main - * - @c depth Main datum depth. - * - @c press Pressure at datum depth. - * - * 2. woc - * - @c depth Depth of water-oil contact - * - @c press water-oil capillary pressure at water-oil contact. - * Capillary pressure defined as "P_oil - P_water". - * - * 3. goc - * - @c depth Depth of gas-oil contact - * - @c press Gas-oil capillary pressure at gas-oil contact. - * Capillary pressure defined as "P_gas - P_oil". - * - * For the time being, items 7-9 of ECLIPSE's 'EQUIL' records are also - * stored here, but might (should?) eventually be moved elsewhere. - * - * - @c live_oil_table_index Indicates type of initialisation for live oil. - * Positive value points to corresponding Rs vs. depth table. - * - @c wet_gas_table_index Indicates type of initialisation for wet gas. - * Positive value points to corresponding Rv vs. depth table. - * - @c N Defines accuracy of initialisation computations. Currently - * only @c N=0 is supported. - * - */ - struct EquilRecord { - struct { - double depth; - double press; - } main, woc, goc; - int live_oil_table_index; - int wet_gas_table_index; - int N; - }; - /** * Aggregate information base of an equilibration region. * @@ -654,36 +608,36 @@ namespace Opm /** * Datum depth in current region */ - double datum() const { return this->rec_.main.depth; } + double datum() const { return this->rec_.datumDepth(); } /** * Pressure at datum depth in current region. */ - double pressure() const { return this->rec_.main.press; } + double pressure() const { return this->rec_.datumDepthPressure(); } /** * Depth of water-oil contact. */ - double zwoc() const { return this->rec_.woc .depth; } + double zwoc() const { return this->rec_.waterOilContactDepth(); } /** * water-oil capillary pressure at water-oil contact. * * \return P_o - P_w at WOC. */ - double pcow_woc() const { return this->rec_.woc .press; } + double pcow_woc() const { return this->rec_.waterOilContactCapillaryPressure(); } /** * Depth of gas-oil contact. */ - double zgoc() const { return this->rec_.goc .depth; } + double zgoc() const { return this->rec_.gasOilContactDepth(); } /** * Gas-oil capillary pressure at gas-oil contact. * * \return P_g - P_o at GOC. */ - double pcgo_goc() const { return this->rec_.goc .press; } + double pcgo_goc() const { return this->rec_.gasOilContactCapillaryPressure(); } /** * Retrieve phase density calculator of current region. diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index b8bdde42f..92932e88f 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -29,9 +29,10 @@ #include #include #include -#include #include #include +#include +#include #include #include #include @@ -83,7 +84,7 @@ namespace Opm * This namespace is intentionally nested to avoid name clashes * with other parts of OPM. */ - namespace Equil { + namespace EQUIL { /** * Compute initial phase pressures by means of equilibration. @@ -196,48 +197,16 @@ namespace Opm namespace DeckDependent { inline std::vector - getEquil(const Opm::DeckConstPtr deck) + getEquil(const Opm::EclipseState& state) { - if (deck->hasKeyword("EQUIL")) { - - Opm::EquilWrapper eql(deck->getKeyword("EQUIL")); + const auto& init = *state.getInitConfig(); - const int nrec = eql.numRegions(); - - std::vector ret; - ret.reserve(nrec); - for (int r = 0; r < nrec; ++r) { - - EquilRecord record = - { - { eql.datumDepth(r) , - eql.datumDepthPressure(r) } - , - { eql.waterOilContactDepth(r) , - eql.waterOilContactCapillaryPressure(r) } - , - { eql.gasOilContactDepth(r) , - eql.gasOilContactCapillaryPressure(r) } - , - eql.liveOilInitProceedure(r) - , - eql.wetGasInitProceedure(r) - , - eql.initializationTargetAccuracy(r) - }; - if (record.N != 0) { - OPM_THROW(std::domain_error, - "kw EQUIL, item 9: Only N=0 supported."); - } - ret.push_back(record); - } - - return ret; - } - else { - OPM_THROW(std::domain_error, - "Deck does not provide equilibration data."); + if( !init.hasEquil() ) { + OPM_THROW(std::domain_error, "Deck does not provide equilibration data."); } + + const auto& equil = init.getEquil(); + return { equil.begin(), equil.end() }; } template @@ -285,7 +254,7 @@ namespace Opm rv_(UgGridHelpers::numCells(G)) { // Get the equilibration records. - const std::vector rec = getEquil(deck); + const std::vector rec = getEquil(*eclipseState); std::shared_ptr tables = eclipseState->getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); @@ -296,25 +265,24 @@ namespace Opm const TableContainer& rsvdTables = tables->getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); - if (rec[i].live_oil_table_index > 0) { - if (rsvdTables.size() > 0 && size_t(rec[i].live_oil_table_index) <= rsvdTables.size()) { - const RsvdTable& rsvdTable = rsvdTables.getTable(i); - std::vector depthColumn = rsvdTable.getColumn("DEPTH").vectorCopy(); - std::vector rsColumn = rsvdTable.getColumn("RS").vectorCopy(); - rs_func_.push_back(std::make_shared(props, - cell, - depthColumn , rsColumn)); - } else { - OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table " << (rec[i].live_oil_table_index) << " not available."); + if (!rec[i].liveOilInitConstantRs()) { + if (rsvdTables.size() <= 0 ) { + OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table not available."); } + const RsvdTable& rsvdTable = rsvdTables.getTable(i); + std::vector depthColumn = rsvdTable.getColumn("DEPTH").vectorCopy(); + std::vector rsColumn = rsvdTable.getColumn("RS").vectorCopy(); + rs_func_.push_back(std::make_shared(props, + cell, + depthColumn , rsColumn)); } else { - if (rec[i].goc.depth != rec[i].main.depth) { + if (rec[i].gasOilContactDepth() != rec[i].datumDepth()) { OPM_THROW(std::runtime_error, "Cannot initialise: when no explicit RSVD table is given, \n" "datum depth must be at the gas-oil-contact. " "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); } - const double p_contact = rec[i].main.press; + const double p_contact = rec[i].datumDepthPressure(); const double T_contact = 273.15 + 20; // standard temperature for now rs_func_.push_back(std::make_shared(props, cell, p_contact, T_contact)); } @@ -330,27 +298,27 @@ namespace Opm const TableContainer& rvvdTables = tables->getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); - if (rec[i].wet_gas_table_index > 0) { - if (rvvdTables.size() > 0 && size_t(rec[i].wet_gas_table_index) <= rvvdTables.size()) { - const RvvdTable& rvvdTable = rvvdTables.getTable(i); - std::vector depthColumn = rvvdTable.getColumn("DEPTH").vectorCopy(); - std::vector rvColumn = rvvdTable.getColumn("RV").vectorCopy(); - - rv_func_.push_back(std::make_shared(props, - cell, - depthColumn , rvColumn)); - - } else { - OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table " << (rec[i].wet_gas_table_index) << " not available."); + if (!rec[i].wetGasInitConstantRv()) { + if (rvvdTables.size() <= 0) { + OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table not available."); } + + const RvvdTable& rvvdTable = rvvdTables.getTable(i); + std::vector depthColumn = rvvdTable.getColumn("DEPTH").vectorCopy(); + std::vector rvColumn = rvvdTable.getColumn("RV").vectorCopy(); + + rv_func_.push_back(std::make_shared(props, + cell, + depthColumn , rvColumn)); + } else { - if (rec[i].goc.depth != rec[i].main.depth) { + if (rec[i].gasOilContactDepth() != rec[i].datumDepth()) { OPM_THROW(std::runtime_error, "Cannot initialise: when no explicit RVVD table is given, \n" "datum depth must be at the gas-oil-contact. " "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); } - const double p_contact = rec[i].main.press + rec[i].goc.press; + const double p_contact = rec[i].datumDepthPressure() + rec[i].gasOilContactCapillaryPressure(); const double T_contact = 273.15 + 20; // standard temperature for now rv_func_.push_back(std::make_shared(props, cell, p_contact, T_contact)); } @@ -456,7 +424,7 @@ namespace Opm }; } // namespace DeckDependent - } // namespace Equil + } // namespace EQUIL } // namespace Opm #include diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 359666efe..b3d750c34 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -583,7 +583,7 @@ namespace Opm } // namespace Details - namespace Equil { + namespace EQUIL { template #include #include +#include +#include +#include +#include #include @@ -55,6 +59,62 @@ BOOST_AUTO_TEST_SUITE () +static Opm::EquilRecord mkEquilRecord( double datd, double datp, + double zwoc, double pcow_woc, + double zgoc, double pcgo_goc ) { + using namespace Opm; + + auto dd = DeckItem::make< double >( "datdep" ); + dd.push_back( datd ); + auto dd_dim = std::make_shared< Opm::Dimension >( "dddim", 1 ); + dd.push_backDimension( dd_dim, dd_dim ); + + auto dp = DeckItem::make< double >( "datps" ); + dp.push_back( datp ); + auto dp_dim = std::make_shared< Opm::Dimension >( "dpdim", 1 ); + dp.push_backDimension( dp_dim, dp_dim ); + + auto zw = DeckItem::make< double >( "zwoc" ); + zw.push_back( zwoc ); + auto zw_dim = std::make_shared< Opm::Dimension >( "zwdim", 1 ); + zw.push_backDimension( zw_dim, zw_dim ); + + auto pcow = DeckItem::make< double >( "pcow" ); + pcow.push_back( pcow_woc ); + auto pcow_dim = std::make_shared< Opm::Dimension >( "pcowdim", 1 ); + pcow.push_backDimension( pcow_dim, pcow_dim ); + + auto zg = DeckItem::make< double >( "zgoc" ); + zg.push_back( zgoc ); + auto zg_dim = std::make_shared< Opm::Dimension >( "zgdim", 1 ); + zg.push_backDimension( zg_dim, zg_dim ); + + auto pcgo = DeckItem::make< double >( "pcgo" ); + pcgo.push_back( pcgo_goc ); + auto pcgo_dim = std::make_shared< Opm::Dimension >( "pcgodim", 1 ); + pcgo.push_backDimension( pcgo_dim, pcgo_dim ); + + auto i1 = DeckItem::make< int >( "i1" ); + auto i2 = DeckItem::make< int >( "i2" ); + auto i3 = DeckItem::make< int >( "i3" ); + i1.push_back( 0 ); + i2.push_back( 0 ); + i3.push_back( 0 ); + + DeckRecord rec; + rec.addItem( std::move( dd ) ); + rec.addItem( std::move( dp ) ); + rec.addItem( std::move( zw ) ); + rec.addItem( std::move( pcow ) ); + rec.addItem( std::move( zg ) ); + rec.addItem( std::move( pcgo ) ); + rec.addItem( std::move( i1 ) ); + rec.addItem( std::move( i2 ) ); + rec.addItem( std::move( i3 ) ); + + return EquilRecord( rec ); +} + BOOST_AUTO_TEST_CASE (PhasePressure) { typedef std::vector PVal; @@ -76,28 +136,22 @@ BOOST_AUTO_TEST_CASE (PhasePressure) typedef Opm::BlackoilPropertiesBasic Props; Props props(param, G->dimensions, G->number_of_cells); - typedef Opm::Equil::DensityCalculator RhoCalc; + typedef Opm::EQUIL::DensityCalculator RhoCalc; RhoCalc calc(props, 0); - Opm::Equil::EquilRecord record = - { - { 0 , 1e5 } , // Datum depth, pressure - { 5 , 0 } , // Zwoc , Pcow_woc - { 0 , 0 } , // Zgoc , Pcgo_goc - 0, 0, 0 - }; + auto record = mkEquilRecord( 0, 1e5, 5, 0, 0, 0 ); - Opm::Equil::EquilReg + Opm::EQUIL::EquilReg region(record, calc, - std::make_shared(), - std::make_shared(), + std::make_shared(), + std::make_shared(), props.phaseUsage()); std::vector cells(G->number_of_cells); std::iota(cells.begin(), cells.end(), 0); const double grav = 10; - const PPress ppress = Opm::Equil::phasePressures(*G, region, cells, grav); + const PPress ppress = Opm::EQUIL::phasePressures(*G, region, cells, grav); const int first = 0, last = G->number_of_cells - 1; const double reltol = 1.0e-8; @@ -107,9 +161,6 @@ BOOST_AUTO_TEST_CASE (PhasePressure) BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } - - - BOOST_AUTO_TEST_CASE (CellSubset) { typedef std::vector PVal; @@ -131,46 +182,32 @@ BOOST_AUTO_TEST_CASE (CellSubset) typedef Opm::BlackoilPropertiesBasic Props; Props props(param, G->dimensions, G->number_of_cells); - typedef Opm::Equil::DensityCalculator RhoCalc; + typedef Opm::EQUIL::DensityCalculator RhoCalc; RhoCalc calc(props, 0); - Opm::Equil::EquilRecord record[] = - { - { - { 0 , 1e5 } , // Datum depth, pressure - { 2.5 , -0.075e5 } , // Zwoc , Pcow_woc - { 0 , 0 } , // Zgoc , Pcgo_goc - 0, 0, 0 - } - , - { - { 5 , 1.35e5 } , // Datum depth, pressure - { 7.5 , -0.225e5 } , // Zwoc , Pcow_woc - { 5 , 0 } , // Zgoc , Pcgo_goc - 0, 0, 0 - } - }; + Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), + mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - Opm::Equil::EquilReg region[] = + Opm::EQUIL::EquilReg region[] = { - Opm::Equil::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[0], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) , - Opm::Equil::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[0], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) , - Opm::Equil::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[1], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) , - Opm::Equil::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[1], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) }; @@ -202,7 +239,7 @@ BOOST_AUTO_TEST_CASE (CellSubset) const int rno = int(r - cells.begin()); const double grav = 10; const PPress p = - Opm::Equil::phasePressures(*G, region[rno], *r, grav); + Opm::EQUIL::phasePressures(*G, region[rno], *r, grav); PVal::size_type i = 0; for (std::vector::const_iterator @@ -248,46 +285,32 @@ BOOST_AUTO_TEST_CASE (RegMapping) typedef Opm::BlackoilPropertiesBasic Props; Props props(param, G->dimensions, G->number_of_cells); - typedef Opm::Equil::DensityCalculator RhoCalc; + typedef Opm::EQUIL::DensityCalculator RhoCalc; RhoCalc calc(props, 0); - Opm::Equil::EquilRecord record[] = - { - { - { 0 , 1e5 } , // Datum depth, pressure - { 2.5 , -0.075e5 } , // Zwoc , Pcow_woc - { 0 , 0 } , // Zgoc , Pcgo_goc - 0, 0, 0 - } - , - { - { 5 , 1.35e5 } , // Datum depth, pressure - { 7.5 , -0.225e5 } , // Zwoc , Pcow_woc - { 5 , 0 } , // Zgoc , Pcgo_goc - 0, 0, 0 - } - }; + Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), + mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - Opm::Equil::EquilReg region[] = + Opm::EQUIL::EquilReg region[] = { - Opm::Equil::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[0], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) , - Opm::Equil::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[0], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) , - Opm::Equil::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[1], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) , - Opm::Equil::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), + Opm::EQUIL::EquilReg(record[1], calc, + std::make_shared(), + std::make_shared(), props.phaseUsage()) }; @@ -313,7 +336,7 @@ BOOST_AUTO_TEST_CASE (RegMapping) const int rno = r; const double grav = 10; const PPress p = - Opm::Equil::phasePressures(*G, region[rno], rng, grav); + Opm::EQUIL::phasePressures(*G, region[rno], rng, grav); PVal::size_type i = 0; for (const auto& c : rng) { @@ -345,7 +368,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA" , parseMode); Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -384,7 +407,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.2, 0.2, 0.2, 0.466666666666, 0.733333333333, 1.0, 1.0, 1.0, 1.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::Equil::satFromPc(props, phase, cell, pc[i], increasing); + const double s_computed = Opm::EQUIL::satFromPc(props, phase, cell, pc[i], increasing); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -397,7 +420,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.8, 0.8, 0.8, 0.533333333333, 0.266666666666, 0.0, 0.0, 0.0, 0.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::Equil::satFromPc(props, phase, cell, pc[i], increasing); + const double s_computed = Opm::EQUIL::satFromPc(props, phase, cell, pc[i], increasing); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -410,7 +433,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.2, 0.333333333333, 0.6, 0.866666666666, 1.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::Equil::satFromSumOfPcs(props, water, gas, cell, pc[i]); + const double s_computed = Opm::EQUIL::satFromSumOfPcs(props, water, gas, cell, pc[i]); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -428,7 +451,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -469,7 +492,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -532,7 +555,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -612,7 +635,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -695,7 +718,7 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::Equil::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); From 7ce3151081e484c35a2794f7f413f6a8209c2a93 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Thu, 17 Mar 2016 09:46:12 +0800 Subject: [PATCH 116/158] rename ParseMode in examples folder. --- examples/compute_initial_state.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index a8e3704d0..adf85ab53 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include @@ -85,10 +85,10 @@ try parameter::ParameterGroup param(argc, argv); std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get("deck_filename"); - Opm::ParseMode parseMode; + Opm::ParseContext parseContext; Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseMode)); + Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseContext)); const double grav = param.getDefault("gravity", unit::gravity); GridManager gm(deck); const UnstructuredGrid& grid = *gm.c_grid(); From 6fb9db5dcf1c85b3e1090183ef03f2d61f20fe85 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Thu, 17 Mar 2016 09:57:59 +0800 Subject: [PATCH 117/158] rename ParseMode as ParseContext. --- tests/test_equil.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 863b384e4..ed7f74ffa 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -363,10 +363,10 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) { std::shared_ptr grid(create_grid_cart3d(1, 1, 10), destroy_grid); - Opm::ParseMode parseMode; + Opm::ParseContext parseContext; Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA" , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseMode)); + Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA" , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); @@ -392,9 +392,9 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) Opm::GridManager gm(1, 1, 40, 1.0, 1.0, 2.5); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::ParseMode parseMode; - Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); + Opm::ParseContext parseContext; + Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); // Test the capillary inversion for oil-water. @@ -446,9 +446,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::ParseMode parseMode; - Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); + Opm::ParseContext parseContext; + Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); @@ -487,9 +487,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::ParseMode parseMode; - Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA" , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); + Opm::ParseContext parseContext; + Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA" , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -550,9 +550,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::ParseMode parseMode; - Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA" , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); + Opm::ParseContext parseContext; + Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA" , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -630,9 +630,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::ParseMode parseMode; - Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA" , parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); + Opm::ParseContext parseContext; + Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA" , parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -713,9 +713,9 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); Opm::ParserPtr parser(new Opm::Parser() ); - Opm::ParseMode parseMode; - Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA", parseMode); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseMode)); + Opm::ParseContext parseContext; + Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA", parseContext); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); From 12991490bd3fb8105ef49e1970a497ed6561dac3 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Thu, 25 Feb 2016 21:47:47 +0100 Subject: [PATCH 118/158] Replaced SimulatorState -> SimulationDatacontainer Have removed the SimulatorState base class, and instead replaced with the SimulationDatacontainer class from opm-common. The SimulatorState objects were typcially created with a default constructor, and then explicitly initialized with a SimulatorState::init() method. For the SimulationDataContainer RAII is employed; the init( ) has been removed - and there is no default constructor. --- examples/compute_initial_state.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index adf85ab53..a88638f02 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -96,7 +96,8 @@ try warnIfUnusedParams(param); // Initialisation. - BlackoilState state; + //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); + BlackoilState state( UgGridHelpers::numCells(grid) , UgGridHelpers::numFaces(grid), 3); initStateEquil(grid, props, deck, eclipseState, grav, state); // Output. From de0aeac57040379ab7cac622613735fa7a6e0eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A5l=20Gr=C3=B8n=C3=A5s=20Drange?= Date: Fri, 8 Apr 2016 16:30:01 +0200 Subject: [PATCH 119/158] Updated opm-core to use new EclipseState API in opm-parser --- opm/core/simulator/initStateEquil.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 92932e88f..6b2b01736 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -221,7 +221,7 @@ namespace Opm const int nc = UgGridHelpers::numCells(G); eqlnum.resize(nc); const std::vector& e = - eclipseState->getIntGridProperty("EQLNUM")->getData(); + eclipseState->getEclipseProperties().getIntGridProperty("EQLNUM").getData(); const int* gc = UgGridHelpers::globalCell(G); for (int cell = 0; cell < nc; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; @@ -255,14 +255,14 @@ namespace Opm { // Get the equilibration records. const std::vector rec = getEquil(*eclipseState); - std::shared_ptr tables = eclipseState->getTableManager(); + const auto& tables = eclipseState->getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); // Create Rs functions. rs_func_.reserve(rec.size()); if (deck->hasKeyword("DISGAS")) { - const TableContainer& rsvdTables = tables->getRsvdTables(); + const TableContainer& rsvdTables = tables.getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (!rec[i].liveOilInitConstantRs()) { @@ -295,7 +295,7 @@ namespace Opm rv_func_.reserve(rec.size()); if (deck->hasKeyword("VAPOIL")) { - const TableContainer& rvvdTables = tables->getRvvdTables(); + const TableContainer& rvvdTables = tables.getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { const int cell = *(eqlmap.cells(i).begin()); if (!rec[i].wetGasInitConstantRv()) { @@ -332,7 +332,8 @@ namespace Opm // Check for presence of kw SWATINIT if (deck->hasKeyword("SWATINIT")) { - const std::vector& swat_init = eclipseState->getDoubleGridProperty("SWATINIT")->getData(); + const std::vector& swat_init = eclipseState-> + getEclipseProperties().getDoubleGridProperty("SWATINIT").getData(); const int nc = UgGridHelpers::numCells(G); swat_init_.resize(nc); const int* gc = UgGridHelpers::globalCell(G); From e6a4cda9a885a814351fd44836c3a7355013e5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A5l=20Gr=C3=B8n=C3=A5s=20Drange?= Date: Mon, 11 Apr 2016 15:13:38 +0200 Subject: [PATCH 120/158] Using API get3DProperties() --- opm/core/simulator/initStateEquil.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 6b2b01736..2e539ea49 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -221,7 +221,7 @@ namespace Opm const int nc = UgGridHelpers::numCells(G); eqlnum.resize(nc); const std::vector& e = - eclipseState->getEclipseProperties().getIntGridProperty("EQLNUM").getData(); + eclipseState->get3DProperties().getIntGridProperty("EQLNUM").getData(); const int* gc = UgGridHelpers::globalCell(G); for (int cell = 0; cell < nc; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; @@ -333,7 +333,7 @@ namespace Opm // Check for presence of kw SWATINIT if (deck->hasKeyword("SWATINIT")) { const std::vector& swat_init = eclipseState-> - getEclipseProperties().getDoubleGridProperty("SWATINIT").getData(); + get3DProperties().getDoubleGridProperty("SWATINIT").getData(); const int nc = UgGridHelpers::numCells(G); swat_init_.resize(nc); const int* gc = UgGridHelpers::globalCell(G); From fac5dd017d1117d4e9ba19579ed62a769fd0879f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A5l=20Gr=C3=B8n=C3=A5s=20Drange?= Date: Tue, 19 Apr 2016 17:00:01 +0200 Subject: [PATCH 121/158] Using getInputGrid API from Parser, changed GridManager to no longer accept Deck in constructor --- examples/compute_initial_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index a88638f02..a2b8c2ed8 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -90,7 +90,7 @@ try Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseContext); Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseContext)); const double grav = param.getDefault("gravity", unit::gravity); - GridManager gm(deck); + GridManager gm(eclipseState->getInputGrid()); const UnstructuredGrid& grid = *gm.c_grid(); BlackoilPropertiesFromDeck props(deck, eclipseState, grid, param); warnIfUnusedParams(param); From c32ff2b4044d8cf5bff231dd8949026d1aceef1f Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Fri, 6 May 2016 21:40:33 +0200 Subject: [PATCH 122/158] Prevent dereferencing the end iterator. This happened for empty regions and surfaced when compiling with "-D_GLIBCXX_DEBUG -DDEBUG -DGLIBCXX_FORCE_NEW". --- opm/core/simulator/initStateEquil.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 2e539ea49..2b4b02b1f 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -264,6 +264,11 @@ namespace Opm if (deck->hasKeyword("DISGAS")) { const TableContainer& rsvdTables = tables.getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { + if (eqlmap.cells(i).empty()) + { + rs_func_.push_back(std::shared_ptr()); + continue; + } const int cell = *(eqlmap.cells(i).begin()); if (!rec[i].liveOilInitConstantRs()) { if (rsvdTables.size() <= 0 ) { @@ -297,6 +302,11 @@ namespace Opm if (deck->hasKeyword("VAPOIL")) { const TableContainer& rvvdTables = tables.getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { + if (eqlmap.cells(i).empty()) + { + rv_func_.push_back(std::shared_ptr()); + continue; + } const int cell = *(eqlmap.cells(i).begin()); if (!rec[i].wetGasInitConstantRv()) { if (rvvdTables.size() <= 0) { @@ -381,6 +391,10 @@ namespace Opm { for (const auto& r : reg.activeRegions()) { const auto& cells = reg.cells(r); + if (cells.empty()) + { + continue; + } const int repcell = *cells.begin(); const RhoCalc calc(props, repcell); From 9e4af968db71485c8533b8541e97293c81f3bd2b Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Fri, 27 May 2016 08:59:00 +0000 Subject: [PATCH 123/158] Fix incomplete type error for std::ofstream in examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On my system I got ```c++ error: variable ‘std::ofstream file’ has initializer but incomplete type std::ofstream file(fname.str().c_str()); ``` This is fixed with this commit by including fstream. Previously, this include might have happened implicitely. --- examples/compute_initial_state.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index a2b8c2ed8..356f3f42d 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -36,6 +36,8 @@ #include +#include + namespace { void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param) From f089b00a30161dc26f81d1730cb04f25b0864b00 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Wed, 15 Jun 2016 15:40:38 +0800 Subject: [PATCH 124/158] Rise up a warning if equil region has no active cells. --- opm/core/simulator/initStateEquil.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 2b4b02b1f..bff1813ca 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -389,11 +390,14 @@ namespace Opm const Grid& G , const double grav) { + int regnum = 0; for (const auto& r : reg.activeRegions()) { + regnum++ ; const auto& cells = reg.cells(r); if (cells.empty()) { - continue; + OpmLog::warning("Equilibration region " + std::to_string(regnum) + + " has no active cells"); } const int repcell = *cells.begin(); From d3ea24f653e0fe1ae5ac7fcd68509c478ee47d29 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Wed, 15 Jun 2016 16:52:32 +0800 Subject: [PATCH 125/158] use correct region number. --- opm/core/simulator/initStateEquil.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index bff1813ca..7ed55cb56 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -390,14 +390,13 @@ namespace Opm const Grid& G , const double grav) { - int regnum = 0; for (const auto& r : reg.activeRegions()) { - regnum++ ; const auto& cells = reg.cells(r); if (cells.empty()) { - OpmLog::warning("Equilibration region " + std::to_string(regnum) + OpmLog::warning("Equilibration region " + std::to_string(r) + " has no active cells"); + continue; } const int repcell = *cells.begin(); From a9ae704a354696f3dd7fea2f2a8aa33e92528fe1 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Wed, 15 Jun 2016 16:53:51 +0800 Subject: [PATCH 126/158] it should be the same number in EQLNUM. --- opm/core/simulator/initStateEquil.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 7ed55cb56..b03d488a0 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -394,7 +394,7 @@ namespace Opm const auto& cells = reg.cells(r); if (cells.empty()) { - OpmLog::warning("Equilibration region " + std::to_string(r) + OpmLog::warning("Equilibration region " + std::to_string(r + 1) + " has no active cells"); continue; } From 57548be345dd71e4b8228fdbbfc9fa277b091326 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 7 Jun 2016 08:40:16 +0200 Subject: [PATCH 127/158] Fix two phase EQUIL initialization --- opm/core/simulator/initStateEquil_impl.hpp | 50 ++++++++++++---------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index b3d750c34..20f56c5a4 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -767,28 +767,34 @@ namespace Opm double sat[BlackoilPhases::MaxNumPhases]; double threshold_sat = 1.0e-6; - sat[waterpos] = smax[waterpos]; - sat[gaspos] = smax[gaspos]; - sat[oilpos] = 1.0 - sat[waterpos] - sat[gaspos]; - if (sw > smax[waterpos]-threshold_sat ) { - sat[waterpos] = smax[waterpos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pc[waterpos]; - } else if (sg > smax[gaspos]-threshold_sat) { - sat[gaspos] = smax[gaspos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; - } - if (sg < smin[gaspos]+threshold_sat) { - sat[gaspos] = smin[gaspos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pc[gaspos]; - } - if (sw < smin[waterpos]+threshold_sat) { - sat[waterpos] = smin[waterpos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pc[waterpos]; - } + sat[oilpos] = 1.0; + if (water) { + sat[waterpos] = smax[waterpos]; + sat[oilpos] -= sat[waterpos]; + } + if (gas) { + sat[gaspos] = smax[gaspos]; + sat[oilpos] -= sat[gaspos]; + } + if (water && sw > smax[waterpos]-threshold_sat ) { + sat[waterpos] = smax[waterpos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pc[waterpos]; + } else if (gas && sg > smax[gaspos]-threshold_sat) { + sat[gaspos] = smax[gaspos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; + } + if (gas && sg < smin[gaspos]+threshold_sat) { + sat[gaspos] = smin[gaspos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pc[gaspos]; + } + if (water && sw < smin[waterpos]+threshold_sat) { + sat[waterpos] = smin[waterpos]; + props.capPress(1, sat, &cell, pc, 0); + phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pc[waterpos]; + } } return phase_saturations; } From 877bd70c546ddd7de5ce70eec93b7cf012dad35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A5l=20Gr=C3=B8n=C3=A5s=20Drange?= Date: Mon, 8 Aug 2016 10:02:53 +0200 Subject: [PATCH 128/158] transmult and initconfig are ref's, use ref for EclipseState constructor --- examples/compute_initial_state.cpp | 2 +- opm/core/simulator/initStateEquil.hpp | 2 +- tests/test_equil.cpp | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 356f3f42d..2eb27d1f4 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -90,7 +90,7 @@ try Opm::ParseContext parseContext; Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck, parseContext)); const double grav = param.getDefault("gravity", unit::gravity); GridManager gm(eclipseState->getInputGrid()); const UnstructuredGrid& grid = *gm.c_grid(); diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index b03d488a0..cbda500ee 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -200,7 +200,7 @@ namespace Opm std::vector getEquil(const Opm::EclipseState& state) { - const auto& init = *state.getInitConfig(); + const auto& init = state.getInitConfig(); if( !init.hasEquil() ) { OPM_THROW(std::domain_error, "Deck does not provide equilibration data."); diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index ed7f74ffa..caedd0af9 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -366,7 +366,7 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) Opm::ParseContext parseContext; Opm::ParserPtr parser(new Opm::Parser() ); Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck, parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck, parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); @@ -394,7 +394,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); // Test the capillary inversion for oil-water. @@ -448,7 +448,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); @@ -489,7 +489,7 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -552,7 +552,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -632,7 +632,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -715,7 +715,7 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA", parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(deck , parseContext)); + Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); From 39647c6ad3510693a9abd31fea9d4bbfc061fd77 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Wed, 31 Aug 2016 10:02:24 +0200 Subject: [PATCH 129/158] shared_ptr -> const EclipseGrid& --- examples/compute_initial_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 2eb27d1f4..d4e009f78 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -92,7 +92,7 @@ try Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseContext); Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck, parseContext)); const double grav = param.getDefault("gravity", unit::gravity); - GridManager gm(eclipseState->getInputGrid()); + GridManager gm(*eclipseState->getInputGrid()); const UnstructuredGrid& grid = *gm.c_grid(); BlackoilPropertiesFromDeck props(deck, eclipseState, grid, param); warnIfUnusedParams(param); From 5b40f3e6438f693217a8d6e002e51dde4b2defb9 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Wed, 28 Sep 2016 16:38:40 +0200 Subject: [PATCH 130/158] set the Rv and Rs factors to the saturated values for cells which have no gas and no oil the purpose of this is to get a more defined behaviour when doing the gravity correction/upstream cell determination in the flux term. I consider this to be just a kludge, so if anyone has a better idea of what the composition for the non-existing gas and oil phases is, please tell me. (note that generic compositional models do not exhibit this issue because the composition of all fluids is always fully defined because each component is assumed to dissolve in every phase.) --- opm/core/simulator/initStateEquil.hpp | 4 +-- opm/core/simulator/initStateEquil_impl.hpp | 32 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index cbda500ee..861c86a34 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -163,7 +163,7 @@ namespace Opm phaseSaturations(const Grid& grid, const Region& reg, const CellRange& cells, - BlackoilPropertiesInterface& props, + BlackoilPropertiesFromDeck& props, const std::vector swat_init, std::vector< std::vector >& phase_pressures); diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 20f56c5a4..1c0286dff 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -885,7 +885,7 @@ namespace Opm */ template void initStateEquil(const Grid& grid, - BlackoilPropertiesInterface& props, + BlackoilPropertiesFromDeck& props, const Opm::DeckConstPtr deck, const Opm::EclipseStateConstPtr eclipseState, const double gravity, @@ -901,6 +901,36 @@ namespace Opm state.saturation() = Details::convertSats(isc.saturation()); state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); + + // set the Rs and Rv factors to the saturated ones if both the gas and the oil + // saturations are zero. in most cases this does not matter, but when doing the + // gravity correction (in particular, when determining the upstream direction) it + // does. + if (pu.phase_used[BlackoilPhases::Liquid] && pu.phase_used[BlackoilPhases::Vapour]) { + const int posOil = pu.phase_pos[BlackoilPhases::Liquid]; + const int posGas = pu.phase_pos[BlackoilPhases::Vapour]; + for (unsigned cellIdx = 0; cellIdx < state.pressure().size(); ++ cellIdx) { + const double so = isc.saturation()[posOil][cellIdx]; + const double sg = isc.saturation()[posGas][cellIdx]; + + if (so <= 0.0 && sg <= 0.0) { + int pvtRegionIdx = props.cellPvtRegionIndex()[cellIdx]; + const double po = state.pressure()[cellIdx]; + const double pg = po; // hack: include capillary pressure! + const double T = 273.15 + 25.0; // does not matter for isothermal simulations! + const double rsSat = props.oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx, + T, + pg); + const double rvSat = props.gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx, + T, + po); + + state.gasoilratio()[cellIdx] = rsSat; + state.rv()[cellIdx] = rvSat; + } + } + } + initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); } From ec0ac4869cbecd146e66543ccd7b32dc31cfe32b Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Mon, 10 Oct 2016 17:23:03 +0200 Subject: [PATCH 131/158] consolidate the unit system to opm-parser since the unit code within opm-parser is now a drop-in replacement, this simplifies things and make them less error-prone. unfortunately, this requires quite a few PRs. (most are pretty trivial, though.) --- opm/core/simulator/initStateEquil.hpp | 2 +- tests/test_equil.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 861c86a34..0894a2aff 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index caedd0af9..bd50d3d38 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include From 2c30f9e53497eeb7916c96999236e7789618b08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Thu, 13 Oct 2016 16:03:35 +0200 Subject: [PATCH 132/158] Update to shared_ptr-less parser interface. --- examples/compute_initial_state.cpp | 8 ++-- opm/core/simulator/initStateEquil.hpp | 28 +++++------ opm/core/simulator/initStateEquil_impl.hpp | 4 +- tests/test_equil.cpp | 54 +++++++++++----------- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index d4e009f78..f1d1d7204 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -88,11 +88,11 @@ try std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get("deck_filename"); Opm::ParseContext parseContext; - Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile(deck_filename , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck, parseContext)); + Opm::Parser parser; + const Opm::Deck& deck = parser.parseFile(deck_filename , parseContext); + const Opm::EclipseState eclipseState(deck, parseContext); const double grav = param.getDefault("gravity", unit::gravity); - GridManager gm(*eclipseState->getInputGrid()); + GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *gm.c_grid(); BlackoilPropertiesFromDeck props(deck, eclipseState, grid, param); warnIfUnusedParams(param); diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 0894a2aff..6eb58c548 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -72,8 +72,8 @@ namespace Opm template void initStateEquil(const Grid& grid, const BlackoilPropertiesInterface& props, - const Opm::DeckConstPtr deck, - const Opm::EclipseStateConstPtr eclipseState, + const Opm::Deck& deck, + const Opm::EclipseState& eclipseState, const double gravity, BlackoilState& state); @@ -213,16 +213,16 @@ namespace Opm template inline std::vector - equilnum(const Opm::DeckConstPtr deck, - const Opm::EclipseStateConstPtr eclipseState, + equilnum(const Opm::Deck& deck, + const Opm::EclipseState& eclipseState, const Grid& G ) { std::vector eqlnum; - if (deck->hasKeyword("EQLNUM")) { + if (deck.hasKeyword("EQLNUM")) { const int nc = UgGridHelpers::numCells(G); eqlnum.resize(nc); const std::vector& e = - eclipseState->get3DProperties().getIntGridProperty("EQLNUM").getData(); + eclipseState.get3DProperties().getIntGridProperty("EQLNUM").getData(); const int* gc = UgGridHelpers::globalCell(G); for (int cell = 0; cell < nc; ++cell) { const int deck_pos = (gc == NULL) ? cell : gc[cell]; @@ -243,8 +243,8 @@ namespace Opm public: template InitialStateComputer(BlackoilPropertiesInterface& props, - const Opm::DeckConstPtr deck, - const Opm::EclipseStateConstPtr eclipseState, + const Opm::Deck& deck, + const Opm::EclipseState& eclipseState, const Grid& G , const double grav = unit::gravity) : pp_(props.numPhases(), @@ -255,14 +255,14 @@ namespace Opm rv_(UgGridHelpers::numCells(G)) { // Get the equilibration records. - const std::vector rec = getEquil(*eclipseState); - const auto& tables = eclipseState->getTableManager(); + const std::vector rec = getEquil(eclipseState); + const auto& tables = eclipseState.getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); // Create Rs functions. rs_func_.reserve(rec.size()); - if (deck->hasKeyword("DISGAS")) { + if (deck.hasKeyword("DISGAS")) { const TableContainer& rsvdTables = tables.getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { if (eqlmap.cells(i).empty()) @@ -300,7 +300,7 @@ namespace Opm } rv_func_.reserve(rec.size()); - if (deck->hasKeyword("VAPOIL")) { + if (deck.hasKeyword("VAPOIL")) { const TableContainer& rvvdTables = tables.getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { if (eqlmap.cells(i).empty()) @@ -342,8 +342,8 @@ namespace Opm // Check for presence of kw SWATINIT - if (deck->hasKeyword("SWATINIT")) { - const std::vector& swat_init = eclipseState-> + if (deck.hasKeyword("SWATINIT")) { + const std::vector& swat_init = eclipseState. get3DProperties().getDoubleGridProperty("SWATINIT").getData(); const int nc = UgGridHelpers::numCells(G); swat_init_.resize(nc); diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 1c0286dff..f0d948e5e 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -886,8 +886,8 @@ namespace Opm template void initStateEquil(const Grid& grid, BlackoilPropertiesFromDeck& props, - const Opm::DeckConstPtr deck, - const Opm::EclipseStateConstPtr eclipseState, + const Opm::Deck& deck, + const Opm::EclipseState& eclipseState, const double gravity, BlackoilState& state) { diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index bd50d3d38..75d802815 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -66,32 +66,32 @@ static Opm::EquilRecord mkEquilRecord( double datd, double datp, auto dd = DeckItem::make< double >( "datdep" ); dd.push_back( datd ); - auto dd_dim = std::make_shared< Opm::Dimension >( "dddim", 1 ); + Opm::Dimension dd_dim( "dddim", 1 ); dd.push_backDimension( dd_dim, dd_dim ); auto dp = DeckItem::make< double >( "datps" ); dp.push_back( datp ); - auto dp_dim = std::make_shared< Opm::Dimension >( "dpdim", 1 ); + Opm::Dimension dp_dim( "dpdim", 1 ); dp.push_backDimension( dp_dim, dp_dim ); auto zw = DeckItem::make< double >( "zwoc" ); zw.push_back( zwoc ); - auto zw_dim = std::make_shared< Opm::Dimension >( "zwdim", 1 ); + Opm::Dimension zw_dim( "zwdim", 1 ); zw.push_backDimension( zw_dim, zw_dim ); auto pcow = DeckItem::make< double >( "pcow" ); pcow.push_back( pcow_woc ); - auto pcow_dim = std::make_shared< Opm::Dimension >( "pcowdim", 1 ); + Opm::Dimension pcow_dim( "pcowdim", 1 ); pcow.push_backDimension( pcow_dim, pcow_dim ); auto zg = DeckItem::make< double >( "zgoc" ); zg.push_back( zgoc ); - auto zg_dim = std::make_shared< Opm::Dimension >( "zgdim", 1 ); + Opm::Dimension zg_dim( "zgdim", 1 ); zg.push_backDimension( zg_dim, zg_dim ); auto pcgo = DeckItem::make< double >( "pcgo" ); pcgo.push_back( pcgo_goc ); - auto pcgo_dim = std::make_shared< Opm::Dimension >( "pcgodim", 1 ); + Opm::Dimension pcgo_dim( "pcgodim", 1 ); pcgo.push_backDimension( pcgo_dim, pcgo_dim ); auto i1 = DeckItem::make< int >( "i1" ); @@ -364,9 +364,9 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) std::shared_ptr grid(create_grid_cart3d(1, 1, 10), destroy_grid); Opm::ParseContext parseContext; - Opm::ParserPtr parser(new Opm::Parser() ); - Opm::DeckConstPtr deck = parser->parseFile("deadfluids.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck, parseContext)); + Opm::Parser parser; + Opm::Deck deck = parser.parseFile("deadfluids.DATA" , parseContext); + Opm::EclipseState eclipseState(deck, parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); @@ -391,10 +391,10 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) // Test setup. Opm::GridManager gm(1, 1, 40, 1.0, 1.0, 2.5); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParserPtr parser(new Opm::Parser() ); + Opm::Parser parser; Opm::ParseContext parseContext; - Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); + Opm::Deck deck = parser.parseFile("capillary.DATA" , parseContext); + Opm::EclipseState eclipseState(deck , parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); // Test the capillary inversion for oil-water. @@ -445,10 +445,10 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParserPtr parser(new Opm::Parser() ); + Opm::Parser parser; Opm::ParseContext parseContext; - Opm::DeckConstPtr deck = parser->parseFile("capillary.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); + Opm::Deck deck = parser.parseFile("capillary.DATA" , parseContext); + Opm::EclipseState eclipseState(deck , parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); @@ -486,10 +486,10 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParserPtr parser(new Opm::Parser() ); + Opm::Parser parser; Opm::ParseContext parseContext; - Opm::DeckConstPtr deck = parser->parseFile("capillary_overlap.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); + Opm::Deck deck = parser.parseFile("capillary_overlap.DATA" , parseContext); + Opm::EclipseState eclipseState(deck , parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -549,10 +549,10 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParserPtr parser(new Opm::Parser() ); + Opm::Parser parser; Opm::ParseContext parseContext; - Opm::DeckConstPtr deck = parser->parseFile("equil_liveoil.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); + Opm::Deck deck = parser.parseFile("equil_liveoil.DATA" , parseContext); + Opm::EclipseState eclipseState(deck , parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -629,10 +629,10 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParserPtr parser(new Opm::Parser() ); + Opm::Parser parser; Opm::ParseContext parseContext; - Opm::DeckConstPtr deck = parser->parseFile("equil_livegas.DATA" , parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); + Opm::Deck deck = parser.parseFile("equil_livegas.DATA" , parseContext); + Opm::EclipseState eclipseState(deck , parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); @@ -712,10 +712,10 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParserPtr parser(new Opm::Parser() ); Opm::ParseContext parseContext; - Opm::DeckConstPtr deck = parser->parseFile("equil_rsvd_and_rvvd.DATA", parseContext); - Opm::EclipseStateConstPtr eclipseState(new Opm::EclipseState(*deck , parseContext)); + Opm::Parser parser; + Opm::Deck deck = parser.parseFile("equil_rsvd_and_rvvd.DATA", parseContext); + Opm::EclipseState eclipseState(deck , parseContext); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); From 111979f4a67bb3d598ee63cec5b96e4b0d5b7a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Mon, 7 Nov 2016 15:07:04 +0100 Subject: [PATCH 133/158] Use new DeckItem constructor interface. --- tests/test_equil.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 75d802815..913aa24f1 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -64,39 +64,39 @@ static Opm::EquilRecord mkEquilRecord( double datd, double datp, double zgoc, double pcgo_goc ) { using namespace Opm; - auto dd = DeckItem::make< double >( "datdep" ); + DeckItem dd( "datdep", double() ); dd.push_back( datd ); Opm::Dimension dd_dim( "dddim", 1 ); dd.push_backDimension( dd_dim, dd_dim ); - auto dp = DeckItem::make< double >( "datps" ); + DeckItem dp( "datps", double() ); dp.push_back( datp ); Opm::Dimension dp_dim( "dpdim", 1 ); dp.push_backDimension( dp_dim, dp_dim ); - auto zw = DeckItem::make< double >( "zwoc" ); + DeckItem zw( "zwoc", double() ); zw.push_back( zwoc ); Opm::Dimension zw_dim( "zwdim", 1 ); zw.push_backDimension( zw_dim, zw_dim ); - auto pcow = DeckItem::make< double >( "pcow" ); + DeckItem pcow( "pcow", double() ); pcow.push_back( pcow_woc ); Opm::Dimension pcow_dim( "pcowdim", 1 ); pcow.push_backDimension( pcow_dim, pcow_dim ); - auto zg = DeckItem::make< double >( "zgoc" ); + DeckItem zg( "zgoc", double() ); zg.push_back( zgoc ); Opm::Dimension zg_dim( "zgdim", 1 ); zg.push_backDimension( zg_dim, zg_dim ); - auto pcgo = DeckItem::make< double >( "pcgo" ); + DeckItem pcgo( "pcgo", double() ); pcgo.push_back( pcgo_goc ); Opm::Dimension pcgo_dim( "pcgodim", 1 ); pcgo.push_backDimension( pcgo_dim, pcgo_dim ); - auto i1 = DeckItem::make< int >( "i1" ); - auto i2 = DeckItem::make< int >( "i2" ); - auto i3 = DeckItem::make< int >( "i3" ); + DeckItem i1( "i1", int() ); + DeckItem i2( "i2", int() ); + DeckItem i3( "i3", int() ); i1.push_back( 0 ); i2.push_back( 0 ); i3.push_back( 0 ); From a4a0e5985cece3a7a6329f1f096903721167a001 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Thu, 22 Dec 2016 16:01:39 +0100 Subject: [PATCH 134/158] Make it optinal to apply SWATINIT The reasoning behind this to make it possible to initialize the case without SWATINIT in order to compute the same defaulted THPRES values as Ecl. The initialization needs to be re-computed to account for SWATINIT in the simulations. --- opm/core/simulator/initStateEquil.hpp | 27 ++++++++-------------- opm/core/simulator/initStateEquil_impl.hpp | 22 ++++++++++++++++-- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 6eb58c548..a29cb135d 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -68,6 +68,8 @@ namespace Opm * \param[in] props Property object, pvt and capillary properties are used. * \param[in] deck Simulation deck, used to obtain EQUIL and related data. * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. + * \param[in] applySwatInit Make it possible to not apply SWATINIT even if it + * is present in the deck */ template void initStateEquil(const Grid& grid, @@ -75,7 +77,8 @@ namespace Opm const Opm::Deck& deck, const Opm::EclipseState& eclipseState, const double gravity, - BlackoilState& state); + BlackoilState& state, + bool applySwatInit = true); /** @@ -246,13 +249,17 @@ namespace Opm const Opm::Deck& deck, const Opm::EclipseState& eclipseState, const Grid& G , - const double grav = unit::gravity) + const double grav = unit::gravity, + const std::vector& swat_init = {} + ) : pp_(props.numPhases(), std::vector(UgGridHelpers::numCells(G))), sat_(props.numPhases(), std::vector(UgGridHelpers::numCells(G))), rs_(UgGridHelpers::numCells(G)), - rv_(UgGridHelpers::numCells(G)) + rv_(UgGridHelpers::numCells(G)), + swat_init_(swat_init) + { // Get the equilibration records. const std::vector rec = getEquil(eclipseState); @@ -340,20 +347,6 @@ namespace Opm } } - - // Check for presence of kw SWATINIT - if (deck.hasKeyword("SWATINIT")) { - const std::vector& swat_init = eclipseState. - get3DProperties().getDoubleGridProperty("SWATINIT").getData(); - const int nc = UgGridHelpers::numCells(G); - swat_init_.resize(nc); - const int* gc = UgGridHelpers::globalCell(G); - for (int c = 0; c < nc; ++c) { - const int deck_pos = (gc == NULL) ? c : gc[c]; - swat_init_[c] = swat_init[deck_pos]; - } - } - // Compute pressures, saturations, rs and rv factors. calcPressSatRsRv(eqlmap, rec, props, G, grav); diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index f0d948e5e..29ba08d3a 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -882,6 +882,8 @@ namespace Opm * \param[in] props Property object, pvt and capillary properties are used. * \param[in] deck Simulation deck, used to obtain EQUIL and related data. * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. + * \param[in] applySwatInit Make it possible to not apply SWATINIT even if it + * is present in the deck */ template void initStateEquil(const Grid& grid, @@ -889,10 +891,26 @@ namespace Opm const Opm::Deck& deck, const Opm::EclipseState& eclipseState, const double gravity, - BlackoilState& state) + BlackoilState& state, + bool applySwatinit = true) { + typedef EQUIL::DeckDependent::InitialStateComputer ISC; - ISC isc(props, deck, eclipseState, grid, gravity); + //Check for presence of kw SWATINIT + std::vector swat_init = {}; + if (eclipseState.get3DProperties().hasDeckDoubleGridProperty("SWATINIT") && applySwatinit) { + const std::vector& swat_init_ecl = eclipseState. + get3DProperties().getDoubleGridProperty("SWATINIT").getData(); + const int nc = UgGridHelpers::numCells(grid); + swat_init.resize(nc); + const int* gc = UgGridHelpers::globalCell(grid); + for (int c = 0; c < nc; ++c) { + const int deck_pos = (gc == NULL) ? c : gc[c]; + swat_init[c] = swat_init_ecl[deck_pos]; + } + } + + ISC isc(props, deck, eclipseState, grid, gravity, swat_init); const auto pu = props.phaseUsage(); const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] ? pu.phase_pos[BlackoilPhases::Liquid] From fd121224d6955da19e90fd9beebef6bd97fac282 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 4 Jan 2017 11:30:43 +0100 Subject: [PATCH 135/158] Add test for swatinit --- tests/capillarySwatinit.DATA | 86 ++++++++++++++++++++++++++++++++++++ tests/test_equil.cpp | 84 +++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 tests/capillarySwatinit.DATA diff --git a/tests/capillarySwatinit.DATA b/tests/capillarySwatinit.DATA new file mode 100644 index 000000000..d7592bbc8 --- /dev/null +++ b/tests/capillarySwatinit.DATA @@ -0,0 +1,86 @@ +-- Most of the following sections are not actually needed by the test, +-- but it is required by the Eclipse reference manual that they are +-- present. Also, the higher level opm-parser classes +-- (i.e. Opm::EclipseState et al.) assume that they are present. + +------------------------------------- +RUNSPEC + +WATER +OIL +GAS + +DIMENS +40 40 40 / + +TABDIMS + 1 1 40 20 1 20 / + +EQLDIMS +-- NTEQUL + 1 / + +------------------------------------- +GRID + +-- Opm::EclipseState assumes that _some_ grid gets defined, so let's +-- specify a fake one... + +DXV +40*1 / + +DYV +40*1 / + +DZV +40*1 / + +DEPTHZ +1681*123.456 / + +------------------------------------- +PROPS + +PVDO +100 1.0 1.0 +200 0.9 1.0 +/ + +PVDG +100 0.010 0.1 +200 0.005 0.2 +/ + +PVTW +1.0 1.0 4.0E-5 0.96 0.0 +/ + +SWOF +0.2 0 1 0.4 +1 1 0 0.1 +/ + +SGOF +0 0 1 0.2 +0.8 1 0 0.5 +/ + +DENSITY +700 1000 1 +/ + +SWATINIT + 5*0 + 10*0.5 + 5*1 / + +------------------------------------- +SOLUTION + +EQUIL +50 150 50 0.25 20 0.35 1* 1* 0 +/ + +------------------------------------- +SCHEDULE +-- empty section diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 913aa24f1..1a91ad738 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -809,4 +809,88 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) } } +BOOST_AUTO_TEST_CASE (DeckWithSwatinit) +{ + Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + const UnstructuredGrid& grid = *(gm.c_grid()); + Opm::Parser parser; + Opm::ParseContext parseContext; + Opm::Deck deck = parser.parseFile("capillarySwatinit.DATA" , parseContext); + Opm::EclipseState eclipseState(deck , parseContext); + Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + Opm::BlackoilState state( Opm::UgGridHelpers::numCells( grid ) , Opm::UgGridHelpers::numFaces( grid ) , 3); + + // reference saturations + const std::vector s[3]{ + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42192000000000002, 0.77802666666666664, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.00736, 0.792746666666, 0.8, 0.8, 0.8, 0.8, 0.57807999999999993, 0.22197333333333336, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + // sw in cell 13 and 14 is forced to be swu=1 since P_oil - P_wat < 0. + const std::vector swatinit[3]{ + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.00736, 0.792746666666, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + std::vector sats = state.saturation(); + for (int phase = 0; phase < 3; ++phase) { + for (size_t i = 0; i < 20; ++i) { + sats[3*i + phase] = s[phase][i]; + } + } + // reference pcs + const int numCells = Opm::UgGridHelpers::numCells(grid); + std::vector cells(numCells); + for (int c = 0; c < numCells; ++c) { cells[c] = c; } + std::vector pc_original = state.saturation(); + props.capPress(numCells, sats.data(), cells.data(), pc_original.data(), nullptr); + + std::vector pc_scaled_truth = pc_original; + // only modify pcow + // sw = 0.2 + for (size_t i = 0; i < 5; ++i) { + pc_scaled_truth[3*i + 0] = 40000; + } + // sw = 0.5 + for (size_t i = 5; i < 12; ++i) { + pc_scaled_truth[3*i + 0] = 28750; + } + // sw = 1 + for (size_t i = 12; i < 20; ++i) { + pc_scaled_truth[3*i + 0] = 10000; + } + + // compute the initial state + + // apply swatinit + Opm::BlackoilState state_scaled = state; + initStateEquil(grid, props, deck, eclipseState, 10.0, state_scaled, true); + + // don't apply swatinit + Opm::BlackoilState state_unscaled = state; + initStateEquil(grid, props, deck, eclipseState, 10.0, state_unscaled, false); + + // compute pc + std::vector pc_scaled= state.saturation(); + props.capPress(numCells, state_scaled.saturation().data(), cells.data(), pc_scaled.data(), nullptr); + std::vector pc_unscaled= state.saturation(); + props.capPress(numCells, state_unscaled.saturation().data(), cells.data(), pc_unscaled.data(), nullptr); + + // test + const double reltol = 1.0e-6; + for (int phase = 0; phase < 3; ++phase) { + for (size_t i = 0; i < 20; ++i) { + CHECK( pc_original[3*i + phase ], pc_unscaled[3*i + phase ], reltol); + CHECK( pc_scaled_truth[3*i + phase], pc_scaled[3*i + phase ], reltol); + } + } + + for (int phase = 0; phase < 3; ++phase) { + for (size_t i = 0; i < 20; ++i) { + CHECK(state_unscaled.saturation()[3*i + phase], s[phase][i], reltol); + CHECK(state_scaled.saturation()[3*i + phase], swatinit[phase][i], reltol); + } + } +} + BOOST_AUTO_TEST_SUITE_END() From bb4b03d295c486d0d8cd324627d3ee1a61e85f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 6 Jan 2017 15:24:08 +0100 Subject: [PATCH 136/158] Increase max iterations for capillary curve inversion. Triggered by a new two-phase case. --- opm/core/simulator/EquilibrationHelpers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 6d4a4e40e..3a271f63b 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -734,7 +734,7 @@ namespace Opm } else if (f1 > 0.0) { return s1; } else { - const int max_iter = 30; + const int max_iter = 60; const double tol = 1e-6; int iter_used = -1; typedef RegulaFalsi ScalarSolver; From 30030eaac77516a3f7c290a618ef792b2ef734ad Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 22 Feb 2017 15:57:53 +0100 Subject: [PATCH 137/158] Do not set rs=rsSat and rv=rvSat for the saturated case --- opm/core/simulator/initStateEquil_impl.hpp | 29 ---------------------- 1 file changed, 29 deletions(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 29ba08d3a..37b1b1d80 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -920,35 +920,6 @@ namespace Opm state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); - // set the Rs and Rv factors to the saturated ones if both the gas and the oil - // saturations are zero. in most cases this does not matter, but when doing the - // gravity correction (in particular, when determining the upstream direction) it - // does. - if (pu.phase_used[BlackoilPhases::Liquid] && pu.phase_used[BlackoilPhases::Vapour]) { - const int posOil = pu.phase_pos[BlackoilPhases::Liquid]; - const int posGas = pu.phase_pos[BlackoilPhases::Vapour]; - for (unsigned cellIdx = 0; cellIdx < state.pressure().size(); ++ cellIdx) { - const double so = isc.saturation()[posOil][cellIdx]; - const double sg = isc.saturation()[posGas][cellIdx]; - - if (so <= 0.0 && sg <= 0.0) { - int pvtRegionIdx = props.cellPvtRegionIndex()[cellIdx]; - const double po = state.pressure()[cellIdx]; - const double pg = po; // hack: include capillary pressure! - const double T = 273.15 + 25.0; // does not matter for isothermal simulations! - const double rsSat = props.oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx, - T, - pg); - const double rvSat = props.gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx, - T, - po); - - state.gasoilratio()[cellIdx] = rsSat; - state.rv()[cellIdx] = rvSat; - } - } - } - initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); } From 5a9827f7fe70e2d5db3bde2919bcabb430ab3723 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Thu, 16 Mar 2017 12:33:43 +0100 Subject: [PATCH 138/158] Do not extrapolate initial rs and rv values in the depth tables --- opm/core/simulator/EquilibrationHelpers.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 3a271f63b..3c399e8a7 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -273,7 +273,7 @@ namespace Opm if (sat_gas > 0.0) { return satRs(press, temp); } else { - return std::min(satRs(press, temp), linearInterpolation(depth_, rs_, depth)); + return std::min(satRs(press, temp), linearInterpolationNoExtrapolation(depth_, rs_, depth)); } } @@ -353,7 +353,7 @@ namespace Opm if (std::abs(sat_oil) > 1e-16) { return satRv(press, temp); } else { - return std::min(satRv(press, temp), linearInterpolation(depth_, rv_, depth)); + return std::min(satRv(press, temp), linearInterpolationNoExtrapolation(depth_, rv_, depth)); } } From 73e6a96180c5e3e7fea1cfaebcc8398ac251d0a6 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Tue, 21 Mar 2017 15:27:04 +0100 Subject: [PATCH 139/158] Temporarily disabled EQUIL + SWATINIT test. --- tests/test_equil.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 1a91ad738..ac6373fbe 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -809,6 +809,10 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) } } +#if 0 + +Test disabled by Joakim 21.03.2017 to recover green test chain. + BOOST_AUTO_TEST_CASE (DeckWithSwatinit) { Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); @@ -893,4 +897,6 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) } } +#endif + BOOST_AUTO_TEST_SUITE_END() From fde300018ba868aa5e628cdd5809641e440a7df8 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 22 Mar 2017 10:07:56 +0100 Subject: [PATCH 140/158] FIX swatinit test in test_equil The capillarySwatinit.DATA is updated to make it possible to run in Ecl. Referance solutions is updated accordingly. --- tests/capillarySwatinit.DATA | 34 ++++++++++++++++------ tests/test_equil.cpp | 56 ++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/tests/capillarySwatinit.DATA b/tests/capillarySwatinit.DATA index d7592bbc8..f4e693a58 100644 --- a/tests/capillarySwatinit.DATA +++ b/tests/capillarySwatinit.DATA @@ -11,15 +11,17 @@ OIL GAS DIMENS -40 40 40 / +1 1 20 / TABDIMS 1 1 40 20 1 20 / - + EQLDIMS -- NTEQUL 1 / +START + 1 'JAN' 2015 / ------------------------------------- GRID @@ -27,20 +29,31 @@ GRID -- specify a fake one... DXV -40*1 / +1 / DYV -40*1 / +1 / -DZV -40*1 / +DZ +20*5 / -DEPTHZ -1681*123.456 / +TOPS +0 / +PORO +20*0.3 / + +PERMX +20*500 / + +PERMZ +20*500 / ------------------------------------- PROPS +ROCK + 14.7 3E-6 / + PVDO 100 1.0 1.0 200 0.9 1.0 @@ -72,7 +85,7 @@ DENSITY SWATINIT 5*0 10*0.5 - 5*1 / +5*1 / ------------------------------------- SOLUTION @@ -81,6 +94,9 @@ EQUIL 50 150 50 0.25 20 0.35 1* 1* 0 / +RPTSOL + SWATINIT SWAT SGAS SOIL PCOG PCOW +/ ------------------------------------- SCHEDULE -- empty section diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index ac6373fbe..ae8cf320b 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -815,26 +815,29 @@ Test disabled by Joakim 21.03.2017 to recover green test chain. BOOST_AUTO_TEST_CASE (DeckWithSwatinit) { - Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); - const UnstructuredGrid& grid = *(gm.c_grid()); + //Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); Opm::Parser parser; Opm::ParseContext parseContext; Opm::Deck deck = parser.parseFile("capillarySwatinit.DATA" , parseContext); Opm::EclipseState eclipseState(deck , parseContext); + Opm::GridManager gm(eclipseState.getInputGrid()); + const UnstructuredGrid& grid = *(gm.c_grid()); Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + Opm::BlackoilPropertiesFromDeck propsScaled(deck, eclipseState, grid, false); + Opm::BlackoilState state( Opm::UgGridHelpers::numCells( grid ) , Opm::UgGridHelpers::numFaces( grid ) , 3); // reference saturations const std::vector s[3]{ - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42192000000000002, 0.77802666666666664, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0.00736, 0.792746666666, 0.8, 0.8, 0.8, 0.8, 0.57807999999999993, 0.22197333333333336, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.425307, 0.77464, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.0148267, 0.78528, 0.8, 0.8, 0.8, 0.8, 0.574693, 0.22536, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.785173, 0.01472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; // sw in cell 13 and 14 is forced to be swu=1 since P_oil - P_wat < 0. const std::vector swatinit[3]{ { 0.2, 0.2, 0.2, 0.2, 0.2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0.00736, 0.792746666666, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0.0148267, 0.78528, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.785173, 0.01472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; std::vector sats = state.saturation(); for (int phase = 0; phase < 3; ++phase) { @@ -842,6 +845,13 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) sats[3*i + phase] = s[phase][i]; } } + std::vector sats_swatinit = state.saturation(); + for (int phase = 0; phase < 3; ++phase) { + for (size_t i = 0; i < 20; ++i) { + sats_swatinit[3*i + phase] = swatinit[phase][i]; + } + } + // reference pcs const int numCells = Opm::UgGridHelpers::numCells(grid); std::vector cells(numCells); @@ -850,38 +860,36 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) props.capPress(numCells, sats.data(), cells.data(), pc_original.data(), nullptr); std::vector pc_scaled_truth = pc_original; - // only modify pcow - // sw = 0.2 - for (size_t i = 0; i < 5; ++i) { - pc_scaled_truth[3*i + 0] = 40000; - } - // sw = 0.5 - for (size_t i = 5; i < 12; ++i) { - pc_scaled_truth[3*i + 0] = 28750; - } - // sw = 1 - for (size_t i = 12; i < 20; ++i) { - pc_scaled_truth[3*i + 0] = 10000; - } + + // modify pcow for cell 5 - 11 (where sw is changed due to swatinit) + // for the reference scaled pc. + pc_scaled_truth[3*5 + 0] = 84081; + pc_scaled_truth[3*6 + 0] = 70929; + pc_scaled_truth[3*7 + 0] = 57791; + pc_scaled_truth[3*8 + 0] = 44665; + pc_scaled_truth[3*9 + 0] = 31552; + pc_scaled_truth[3*10 + 0] = 18451.5; + pc_scaled_truth[3*11 + 0] = 5364.1; + // compute the initial state // apply swatinit Opm::BlackoilState state_scaled = state; - initStateEquil(grid, props, deck, eclipseState, 10.0, state_scaled, true); + initStateEquil(grid, propsScaled, deck, eclipseState, 9.81, state_scaled, true); // don't apply swatinit Opm::BlackoilState state_unscaled = state; - initStateEquil(grid, props, deck, eclipseState, 10.0, state_unscaled, false); + initStateEquil(grid, props, deck, eclipseState, 9.81, state_unscaled, false); // compute pc std::vector pc_scaled= state.saturation(); - props.capPress(numCells, state_scaled.saturation().data(), cells.data(), pc_scaled.data(), nullptr); + propsScaled.capPress(numCells, state_scaled.saturation().data(), cells.data(), pc_scaled.data(), nullptr); std::vector pc_unscaled= state.saturation(); props.capPress(numCells, state_unscaled.saturation().data(), cells.data(), pc_unscaled.data(), nullptr); // test - const double reltol = 1.0e-6; + const double reltol = 1.0e-3; for (int phase = 0; phase < 3; ++phase) { for (size_t i = 0; i < 20; ++i) { CHECK( pc_original[3*i + phase ], pc_unscaled[3*i + phase ], reltol); From 020a9af41e95b638153b7c11e969345415df47fa Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 22 Mar 2017 10:26:03 +0100 Subject: [PATCH 141/158] Enable swatinit equil test --- tests/test_equil.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index ae8cf320b..24ba00f67 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -809,10 +809,6 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) } } -#if 0 - -Test disabled by Joakim 21.03.2017 to recover green test chain. - BOOST_AUTO_TEST_CASE (DeckWithSwatinit) { //Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); @@ -905,6 +901,4 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) } } -#endif - BOOST_AUTO_TEST_SUITE_END() From 3904521dedcdaba92e41d8e1b39323c2f14ee22c Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Fri, 28 Apr 2017 15:32:52 +0200 Subject: [PATCH 142/158] changed: remove embedded 'parameters' namespace in ParamGroup inconsistent and unnecessary. this is purely a cosmetic change, the only exception was a function with the generic name 'split', which was renamed to splitParam to avoid confusion. --- examples/compute_initial_state.cpp | 4 ++-- tests/test_equil.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index f1d1d7204..3e107ba2d 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -40,7 +40,7 @@ namespace { - void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param) + void warnIfUnusedParams(const Opm::ParameterGroup& param) { if (param.anyUnused()) { std::cout << "-------------------- Unused parameters: --------------------\n"; @@ -84,7 +84,7 @@ try using namespace Opm; // Setup. - parameter::ParameterGroup param(argc, argv); + ParameterGroup param(argc, argv); std::cout << "--------------- Reading parameters ---------------" << std::endl; const std::string deck_filename = param.get("deck_filename"); Opm::ParseContext parseContext; diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 24ba00f67..e9b229fae 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE (PhasePressure) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::parameter::ParameterGroup param; + Opm::ParameterGroup param; { using Opm::unit::kilogram; using Opm::unit::meter; @@ -169,7 +169,7 @@ BOOST_AUTO_TEST_CASE (CellSubset) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::parameter::ParameterGroup param; + Opm::ParameterGroup param; { using Opm::unit::kilogram; using Opm::unit::meter; @@ -272,7 +272,7 @@ BOOST_AUTO_TEST_CASE (RegMapping) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::parameter::ParameterGroup param; + Opm::ParameterGroup param; { using Opm::unit::kilogram; using Opm::unit::meter; From 0df94d216ac810dff3989e11386fc0a38c44b262 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 11 Oct 2017 09:39:12 +0200 Subject: [PATCH 143/158] Update the swatinit test base on fix in opm-material#248 --- tests/test_equil.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index e9b229fae..2bc3cfb72 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -829,6 +829,7 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) { 0, 0, 0, 0.0148267, 0.78528, 0.8, 0.8, 0.8, 0.8, 0.574693, 0.22536, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.785173, 0.01472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; + // sw in cell 1-5 is forced to be 0.2 since swl=0.2 // sw in cell 13 and 14 is forced to be swu=1 since P_oil - P_wat < 0. const std::vector swatinit[3]{ { 0.2, 0.2, 0.2, 0.2, 0.2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1 }, @@ -857,8 +858,13 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) std::vector pc_scaled_truth = pc_original; - // modify pcow for cell 5 - 11 (where sw is changed due to swatinit) + // modify pcow for cell 1 - 12 (where sw is changed due to swatinit) // for the reference scaled pc. + pc_scaled_truth[3*0 + 0] = 150031.3; + pc_scaled_truth[3*1 + 0] = 136815.6; + pc_scaled_truth[3*2 + 0] = 123612.7; + pc_scaled_truth[3*3 + 0] = 110422.7; + pc_scaled_truth[3*4 + 0] = 97245.4; pc_scaled_truth[3*5 + 0] = 84081; pc_scaled_truth[3*6 + 0] = 70929; pc_scaled_truth[3*7 + 0] = 57791; @@ -867,7 +873,6 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) pc_scaled_truth[3*10 + 0] = 18451.5; pc_scaled_truth[3*11 + 0] = 5364.1; - // compute the initial state // apply swatinit From 7ba7cf30b0228fbce19f7310e838996425f8186e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 15 Dec 2016 11:00:31 +0100 Subject: [PATCH 144/158] Bugfix: type for target capillary pressure. --- opm/core/simulator/EquilibrationHelpers.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 3c399e8a7..17427b6c4 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -702,7 +702,7 @@ namespace Opm const BlackoilPropertiesInterface& props_; const int phase_; const int cell_; - const int target_pc_; + const double target_pc_; mutable double s_[BlackoilPhases::MaxNumPhases]; mutable double pc_[BlackoilPhases::MaxNumPhases]; }; @@ -775,7 +775,7 @@ namespace Opm const int phase1_; const int phase2_; const int cell_; - const int target_pc_; + const double target_pc_; mutable double s_[BlackoilPhases::MaxNumPhases]; mutable double pc_[BlackoilPhases::MaxNumPhases]; }; From 680d96840a81811db227adb952314df9beccd1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 15 Dec 2016 12:16:24 +0100 Subject: [PATCH 145/158] Update equil regression reference after bugfix. Also reduce some very coarse tolerances to more reasonable levels. --- tests/test_equil.cpp | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 2bc3cfb72..186e29647 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -468,9 +468,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) const auto& sats = comp.saturation(); const std::vector s[3]{ - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42192000000000002, 0.77802666666666664, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0.00736, 0.792746666666, 0.8, 0.8, 0.8, 0.8, 0.57807999999999993, 0.22197333333333336, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.79264, 0.007253333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42190294373815257, 0.77800802072306474, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.0073481611123183965, 0.79272270823081337, 0.8, 0.8, 0.8, 0.8, 0.57809705626184749, 0.22199197927693526, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.79265183888768165, 0.0072772917691866562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { BOOST_REQUIRE(sats[phase].size() == s[phase].size()); @@ -529,9 +529,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) }; const std::vector s_opm[3]{ // opm - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2289309090909091, 0.53406545454545451, 0.78458, 0.9154, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2002466666666666, 0.0846, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77106909090909093, 0.46593454545454549, 0.015173333333333336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22892931226886132, 0.53406457830052489, 0.78457075254244724, 0.91539712466977541, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20023624994125844, 0.084602875330224592, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77107068773113863, 0.46593542169947511, 0.015192997516294321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); @@ -591,9 +591,9 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77102, 0.46578, 0.01458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; const std::vector s_opm[3]{ // opm - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2291709091, 0.5343054545, 0.78472, 0.91529, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2005866667, 0.08471, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7708290909, 0.4656945455, 0.01469333333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22916963446461344, 0.53430490523774521, 0.78471886612242092, 0.91528324362210933, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20057438297017782, 0.084716756377890667, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77083036553538653, 0.46569509476225479, 0.014706750907401245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); @@ -645,7 +645,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) // but the answer we are checking is the result of an ODE // solver, and it is unclear if we should check it against // the true answer or something else. - const double reltol = 5.0e-3; + const double reltol = 1.0e-3; const double reltol_ecl = 1.0; BOOST_CHECK_CLOSE(pressures[0][first], 1.48215e+07, reltol_ecl); // eclipse BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); @@ -702,8 +702,7 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03}; for (size_t i = 0; i < rv_opm.size(); ++i) { - //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - CHECK(rv[i], rv_opm[i], 100.*reltol); + CHECK(rv[i], rv_opm[i], reltol); CHECK(rv[i], rv_ecl[i], reltol_ecl); } } @@ -755,16 +754,16 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) }; const std::vector s_opm[3]{ // opm - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22232000, 0.52882909, 0.78153000, 0.91817000, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.19636333, 0.08183000, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77768000, 0.47117091, 0.02210667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22231423543119974, 0.52882640735211706, 0.78152142505479982, 0.91816512259416283, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.19636279642563928, 0.08183487740583717, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77768576456880023, 0.47117359264788294, 0.022115778519560897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - CHECK(sats[phase][i], s_opm[phase][i], 100.*reltol); + CHECK(sats[phase][i], s_opm[phase][i], reltol); CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; @@ -773,7 +772,7 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) const auto& rs = comp.rs(); const std::vector rs_opm { // opm 74.62498302, 74.65959041, 74.69438035, 74.72935336, - 74.76450995, 74.79985061, 74.83537588, 74.87527125, + 74.76450995, 74.79985061, 74.83537588, 74.87527065, 74.96863769, 75.08891765, 52.5, 57.5, 62.5, 67.5, 72.5, 76.45954841, 76.70621045, 76.95287736, 77.19954913, 77.44622578}; @@ -802,9 +801,9 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) for (size_t i = 0; i < rv_opm.size(); ++i) { //std::cout << std::setprecision(10) << rs[i] << '\n'; - BOOST_CHECK_CLOSE(rs[i], rs_opm[i], 100*reltol); + BOOST_CHECK_CLOSE(rs[i], rs_opm[i], reltol); BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); - BOOST_CHECK_CLOSE(rv[i], rv_opm[i], 100.*reltol); + BOOST_CHECK_CLOSE(rv[i], rv_opm[i], reltol); BOOST_CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); } } From 9e95d662bd80a15aad66c238ea1074b209ff0348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 6 Mar 2017 15:12:30 +0100 Subject: [PATCH 146/158] Update swatinit tests to account for bugfix. --- tests/test_equil.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 186e29647..251a4e65f 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -824,16 +824,16 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) // reference saturations const std::vector s[3]{ - { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.425307, 0.77464, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0.0148267, 0.78528, 0.8, 0.8, 0.8, 0.8, 0.574693, 0.22536, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.785173, 0.01472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42528761746004229, 0.77462669821009045, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0.014813991154779993, 0.78525420807446045, 0.8, 0.8, 0.8, 0.8, 0.57471238253995771, 0.22537330178990955, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.78518600884522005, 0.014745791925539575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; // sw in cell 1-5 is forced to be 0.2 since swl=0.2 // sw in cell 13 and 14 is forced to be swu=1 since P_oil - P_wat < 0. const std::vector swatinit[3]{ { 0.2, 0.2, 0.2, 0.2, 0.2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0.0148267, 0.78528, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0.8, 0.8, 0.8, 0.785173, 0.01472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0.014813991154779993, 0.78525420807446045, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0.8, 0.8, 0.8, 0.78518600884522005, 0.014745791925539575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; std::vector sats = state.saturation(); for (int phase = 0; phase < 3; ++phase) { From b9b75a109c50d4684a737880648216ecf583a1b3 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Thu, 16 Nov 2017 13:04:26 +0100 Subject: [PATCH 147/158] Remove BlackoilProps from equil initalization code Use FluidSystem and materialLaw from opm-material directly not via the BlackoilProps in opm-core --- examples/compute_initial_state.cpp | 21 +- opm/core/simulator/EquilibrationHelpers.hpp | 368 ++++++++--------- opm/core/simulator/initStateEquil.hpp | 131 +++--- opm/core/simulator/initStateEquil_impl.hpp | 305 +++++++------- tests/test_equil.cpp | 428 ++++++++++++++------ 5 files changed, 715 insertions(+), 538 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 3e107ba2d..67c00a363 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -29,11 +29,16 @@ #include #include #include +#include + #include #include #include +#include + + #include #include @@ -97,10 +102,24 @@ try BlackoilPropertiesFromDeck props(deck, eclipseState, grid, param); warnIfUnusedParams(param); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + + // Forward declaring the MaterialLawManager template. + typedef Opm::ThreePhaseMaterialTraits MaterialTraits; + typedef Opm::EclMaterialLawManager MaterialLawManager; + + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + // Initialisation. //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); BlackoilState state( UgGridHelpers::numCells(grid) , UgGridHelpers::numFaces(grid), 3); - initStateEquil(grid, props, deck, eclipseState, grav, state); + initStateEquil(grid, materialLawManager, deck, eclipseState, grav, state); // Output. const std::string output_dir = param.getDefault("output_dir", "output"); diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 17427b6c4..1c2643265 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -20,7 +20,6 @@ #ifndef OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED #define OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED -#include #include #include #include @@ -28,6 +27,10 @@ #include +#include +#include +#include + #include @@ -87,71 +90,21 @@ namespace Opm namespace EQUIL { - template - class DensityCalculator; - - /** - * Facility for calculating phase densities based on the - * BlackoilPropertiesInterface. - * - * Implements the crucial operator()(p,svol) - * function that is expected by class EquilReg. - */ - template <> - class DensityCalculator< BlackoilPropertiesInterface > { - public: - /** - * Constructor. - * - * \param[in] props Implementation of the - * BlackoilPropertiesInterface. - * - * \param[in] c Single cell used as a representative cell - * in a PVT region. - */ - DensityCalculator(const BlackoilPropertiesInterface& props, - const int c) - : props_(props) - , c_(1, c) - { - } - - /** - * Compute phase densities of all phases at phase point - * given by (pressure, surface volume) tuple. - * - * \param[in] p Fluid pressure. - * - * \param[in] T Temperature. - * - * \param[in] z Surface volumes of all phases. - * - * \return Phase densities at phase point. - */ - std::vector - operator()(const double p, - const double T, - const std::vector& z) const - { - const int np = props_.numPhases(); - std::vector A(np * np, 0); - - assert (z.size() == std::vector::size_type(np)); - - double* dAdp = 0; - props_.matrix(1, &p, &T, &z[0], &c_[0], &A[0], dAdp); - - std::vector rho(np, 0.0); - props_.density(1, &A[0], &c_[0], &rho[0]); - - return rho; - } - - private: - const BlackoilPropertiesInterface& props_; - const std::vector c_; - }; + typedef Opm::FluidSystems::BlackOil FluidSystemSimple; + // Adjust oil pressure according to gas saturation and cap pressure + typedef Opm::SimpleModularFluidState SatOnlyFluidState; /** * Types and routines relating to phase mixing in @@ -224,6 +177,7 @@ namespace Opm * tabulated as a function of depth policy. Data * typically taken from keyword 'RSVD'. */ + template class RsVD : public RsFunction { public: /** @@ -234,19 +188,14 @@ namespace Opm * \param[in] depth Depth nodes. * \param[in] rs Dissolved gas-oil ratio at @c depth. */ - RsVD(const BlackoilPropertiesInterface& props, - const int cell, + RsVD(const int pvtRegionIdx, const std::vector& depth, const std::vector& rs) - : props_(props) - , cell_(cell) + : pvtRegionIdx_(pvtRegionIdx) , depth_(depth) , rs_(rs) { - auto pu = props_.phaseUsage(); - std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); - z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; - z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; + } /** @@ -278,23 +227,13 @@ namespace Opm } private: - const BlackoilPropertiesInterface& props_; - const int cell_; + const int pvtRegionIdx_; std::vector depth_; /**< Depth nodes */ std::vector rs_; /**< Dissolved gas-oil ratio */ - double z_[BlackoilPhases::MaxNumPhases]; - mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; double satRs(const double press, const double temp) const { - props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); - // Rs/Bo is in the gas row and oil column of A_. - // 1/Bo is in the oil row and column. - // Recall also that it is stored in column-major order. - const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const int np = props_.numPhases(); - return A_[np*opos + gpos] / A_[np*opos + opos]; + return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press); } }; @@ -304,6 +243,7 @@ namespace Opm * tabulated as a function of depth policy. Data * typically taken from keyword 'RVVD'. */ + template class RvVD : public RsFunction { public: /** @@ -314,19 +254,14 @@ namespace Opm * \param[in] depth Depth nodes. * \param[in] rv Dissolved gas-oil ratio at @c depth. */ - RvVD(const BlackoilPropertiesInterface& props, - const int cell, + RvVD(const int pvtRegionIdx, const std::vector& depth, const std::vector& rv) - : props_(props) - , cell_(cell) + : pvtRegionIdx_(pvtRegionIdx) , depth_(depth) , rv_(rv) { - auto pu = props_.phaseUsage(); - std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); - z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0; - z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1e100; + } /** @@ -358,23 +293,13 @@ namespace Opm } private: - const BlackoilPropertiesInterface& props_; - const int cell_; + const int pvtRegionIdx_; std::vector depth_; /**< Depth nodes */ std::vector rv_; /**< Vaporized oil-gas ratio */ - double z_[BlackoilPhases::MaxNumPhases]; - mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; double satRv(const double press, const double temp) const { - props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); - // Rv/Bg is in the oil row and gas column of A_. - // 1/Bg is in the gas row and column. - // Recall also that it is stored in column-major order. - const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const int np = props_.numPhases(); - return A_[np*gpos + opos] / A_[np*gpos + gpos]; + return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press); } }; @@ -393,6 +318,7 @@ namespace Opm * This should yield Rs-values that are constant below the * contact, and decreasing above the contact. */ + template class RsSatAtContact : public RsFunction { public: /** @@ -403,13 +329,9 @@ namespace Opm * \param[in] p_contact oil pressure at the contact * \param[in] T_contact temperature at the contact */ - RsSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact, const double T_contact) - : props_(props), cell_(cell) + RsSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact) + : pvtRegionIdx_(pvtRegionIdx) { - auto pu = props_.phaseUsage(); - std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); - z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1e100; - z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0; rs_sat_contact_ = satRs(p_contact, T_contact); } @@ -442,22 +364,12 @@ namespace Opm } private: - const BlackoilPropertiesInterface& props_; - const int cell_; - double z_[BlackoilPhases::MaxNumPhases]; + const int pvtRegionIdx_; double rs_sat_contact_; - mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; double satRs(const double press, const double temp) const { - props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); - // Rs/Bo is in the gas row and oil column of A_. - // 1/Bo is in the oil row and column. - // Recall also that it is stored in column-major order. - const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const int np = props_.numPhases(); - return A_[np*opos + gpos] / A_[np*opos + opos]; + return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press); } }; @@ -476,6 +388,7 @@ namespace Opm * This should yield Rv-values that are constant below the * contact, and decreasing above the contact. */ + template class RvSatAtContact : public RsFunction { public: /** @@ -486,13 +399,9 @@ namespace Opm * \param[in] p_contact oil pressure at the contact * \param[in] T_contact temperature at the contact */ - RvSatAtContact(const BlackoilPropertiesInterface& props, const int cell, const double p_contact, const double T_contact) - : props_(props), cell_(cell) + RvSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact) + :pvtRegionIdx_(pvtRegionIdx) { - auto pu = props_.phaseUsage(); - std::fill(z_, z_ + BlackoilPhases::MaxNumPhases, 0.0); - z_[pu.phase_pos[BlackoilPhases::Vapour]] = 1.0; - z_[pu.phase_pos[BlackoilPhases::Liquid]] = 1e100; rv_sat_contact_ = satRv(p_contact, T_contact); } @@ -525,22 +434,12 @@ namespace Opm } private: - const BlackoilPropertiesInterface& props_; - const int cell_; - double z_[BlackoilPhases::MaxNumPhases]; + const int pvtRegionIdx_; double rv_sat_contact_; - mutable double A_[BlackoilPhases::MaxNumPhases * BlackoilPhases::MaxNumPhases]; double satRv(const double press, const double temp) const { - props_.matrix(1, &press, &temp, z_, &cell_, A_, 0); - // Rv/Bg is in the oil row and gas column of A_. - // 1/Bg is in the gas row and column. - // Recall also that it is stored in column-major order. - const int opos = props_.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gpos = props_.phaseUsage().phase_pos[BlackoilPhases::Vapour]; - const int np = props_.numPhases(); - return A_[np*gpos + opos] / A_[np*gpos + gpos]; + return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);; } }; @@ -565,7 +464,6 @@ namespace Opm * that calculates the phase densities of all phases in @c * svol at fluid pressure @c press. */ - template class EquilReg { public: /** @@ -578,23 +476,19 @@ namespace Opm * \param[in] pu Summary of current active phases. */ EquilReg(const EquilRecord& rec, - const DensCalc& density, std::shared_ptr rs, std::shared_ptr rv, + const int pvtIdx, const PhaseUsage& pu) : rec_ (rec) - , density_(density) , rs_ (rs) , rv_ (rv) + , pvtIdx_ (pvtIdx) , pu_ (pu) + { } - /** - * Type of density calculator. - */ - typedef DensCalc CalcDensity; - /** * Type of dissolved gas-oil ratio calculator. */ @@ -639,11 +533,6 @@ namespace Opm */ double pcgo_goc() const { return this->rec_.gasOilContactCapillaryPressure(); } - /** - * Retrieve phase density calculator of current region. - */ - const CalcDensity& - densityCalculator() const { return this->density_; } /** * Retrieve dissolved gas-oil ratio calculator of current @@ -659,6 +548,12 @@ namespace Opm const CalcEvaporation& evaporationCalculator() const { return *this->rv_; } + /** + * Retrieve active fluid phase summary. + */ + const int + pvtIdx() const { return this->pvtIdx_; } + /** * Retrieve active fluid phase summary. */ @@ -667,9 +562,9 @@ namespace Opm private: EquilRecord rec_; /**< Equilibration data */ - DensCalc density_; /**< Density calculator */ std::shared_ptr rs_; /**< RS calculator */ std::shared_ptr rv_; /**< RV calculator */ + const int pvtIdx_; PhaseUsage pu_; /**< Active phase summary */ }; @@ -678,54 +573,117 @@ namespace Opm /// Functor for inverting capillary pressure function. /// Function represented is /// f(s) = pc(s) - target_pc + template struct PcEq { - PcEq(const BlackoilPropertiesInterface& props, + PcEq(std::shared_ptr materialLawManager, const int phase, const int cell, const double target_pc) - : props_(props), + : materialLawManager_(materialLawManager), phase_(phase), cell_(cell), target_pc_(target_pc) { - std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); + fluidState_.setSaturation(FluidSystem::waterPhaseIdx, 0.0); + fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); + fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + } + + double operator()(double s) const { - s_[phase_] = s; - props_.capPress(1, s_, &cell_, pc_, 0); - return pc_[phase_] - target_pc_; + const auto& matParams = materialLawManager_->materialLawParams(cell_); + fluidState_.setSaturation(phase_, s); + MaterialLaw::capillaryPressures(pc_, matParams, fluidState_); + double sign = (phase_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; + double pc = pc_[FluidSystem::oilPhaseIdx] + sign * pc_[phase_]; + return pc - target_pc_; } private: - const BlackoilPropertiesInterface& props_; + + std::shared_ptr materialLawManager_; const int phase_; const int cell_; const double target_pc_; - mutable double s_[BlackoilPhases::MaxNumPhases]; + mutable SatOnlyFluidState fluidState_; mutable double pc_[BlackoilPhases::MaxNumPhases]; }; + template + double minSaturations(std::shared_ptr materialLawManager, const int phase, const int cell) { + const auto& scaledDrainageInfo = + materialLawManager->oilWaterScaledEpsInfoDrainage(cell); + + // Find minimum and maximum saturations. + switch(phase) { + case FluidSystem::waterPhaseIdx : + { + return scaledDrainageInfo.Swl; + break; + } + case FluidSystem::gasPhaseIdx : + { + return scaledDrainageInfo.Sgl; + break; + } + case FluidSystem::oilPhaseIdx : + { + OPM_THROW(std::runtime_error, "Min saturation not implemented for oil phase."); + break; + } + default: OPM_THROW(std::runtime_error, "Unknown phaseIdx ."); + } + return -1.0; + } + + template + double maxSaturations(std::shared_ptr materialLawManager, const int phase, const int cell) { + const auto& scaledDrainageInfo = + materialLawManager->oilWaterScaledEpsInfoDrainage(cell); + + // Find minimum and maximum saturations. + switch(phase) { + case FluidSystem::waterPhaseIdx : + { + return scaledDrainageInfo.Swu; + break; + } + case FluidSystem::gasPhaseIdx : + { + return scaledDrainageInfo.Sgu; + break; + } + case FluidSystem::oilPhaseIdx : + { + OPM_THROW(std::runtime_error, "Max saturation not implemented for oil phase."); + break; + } + default: OPM_THROW(std::runtime_error, "Unknown phaseIdx ."); + } + return -1.0; + + } + /// Compute saturation of some phase corresponding to a given /// capillary pressure. - inline double satFromPc(const BlackoilPropertiesInterface& props, + template + inline double satFromPc(std::shared_ptr materialLawManager, const int phase, const int cell, const double target_pc, const bool increasing = false) { - // Find minimum and maximum saturations. - double sminarr[BlackoilPhases::MaxNumPhases]; - double smaxarr[BlackoilPhases::MaxNumPhases]; - props.satRange(1, &cell, sminarr, smaxarr); - const double s0 = increasing ? smaxarr[phase] : sminarr[phase]; - const double s1 = increasing ? sminarr[phase] : smaxarr[phase]; + // Find minimum and maximum saturations. + const double s0 = increasing ? maxSaturations(materialLawManager, phase, cell) : minSaturations(materialLawManager, phase, cell); + const double s1 = increasing ? minSaturations(materialLawManager, phase, cell) : maxSaturations(materialLawManager, phase, cell); // Create the equation f(s) = pc(s) - target_pc - const PcEq f(props, phase, cell, target_pc); + const PcEq f(materialLawManager, phase, cell, target_pc); const double f0 = f(s0); const double f1 = f(s1); @@ -747,36 +705,46 @@ namespace Opm /// Functor for inverting a sum of capillary pressure functions. /// Function represented is /// f(s) = pc1(s) + pc2(1 - s) - target_pc + template struct PcEqSum { - PcEqSum(const BlackoilPropertiesInterface& props, + PcEqSum(std::shared_ptr materialLawManager, const int phase1, const int phase2, const int cell, const double target_pc) - : props_(props), + : materialLawManager_(materialLawManager), phase1_(phase1), phase2_(phase2), cell_(cell), target_pc_(target_pc) { - std::fill(s_, s_ + BlackoilPhases::MaxNumPhases, 0.0); + fluidState_.setSaturation(FluidSystem::waterPhaseIdx, 0.0); + fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); + fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); } double operator()(double s) const { - s_[phase1_] = s; - s_[phase2_] = 1.0 - s; - props_.capPress(1, s_, &cell_, pc_, 0); - return pc_[phase1_] + pc_[phase2_] - target_pc_; + const auto& matParams = materialLawManager_->materialLawParams(cell_); + fluidState_.setSaturation(phase1_, s); + fluidState_.setSaturation(phase2_, 1.0 - s); + + MaterialLaw::capillaryPressures(pc_, matParams, fluidState_); + double sign1 = (phase1_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; + double pc1 = pc_[FluidSystem::oilPhaseIdx] + sign1 * pc_[phase1_]; + double sign2 = (phase2_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; + double pc2 = pc_[FluidSystem::oilPhaseIdx] + sign2 * pc_[phase2_]; + + return pc1 + pc2 - target_pc_; } private: - const BlackoilPropertiesInterface& props_; + std::shared_ptr materialLawManager_; const int phase1_; const int phase2_; const int cell_; const double target_pc_; - mutable double s_[BlackoilPhases::MaxNumPhases]; + mutable SatOnlyFluidState fluidState_; mutable double pc_[BlackoilPhases::MaxNumPhases]; }; @@ -786,21 +754,20 @@ namespace Opm /// Compute saturation of some phase corresponding to a given /// capillary pressure, where the capillary pressure function /// is given as a sum of two other functions. - inline double satFromSumOfPcs(const BlackoilPropertiesInterface& props, + + template + inline double satFromSumOfPcs(std::shared_ptr materialLawManager, const int phase1, const int phase2, const int cell, const double target_pc) { // Find minimum and maximum saturations. - double sminarr[BlackoilPhases::MaxNumPhases]; - double smaxarr[BlackoilPhases::MaxNumPhases]; - props.satRange(1, &cell, sminarr, smaxarr); - const double smin = sminarr[phase1]; - const double smax = smaxarr[phase1]; + const double smin = minSaturations(materialLawManager, phase1, cell); + const double smax = maxSaturations(materialLawManager, phase1, cell); // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc - const PcEqSum f(props, phase1, phase2, cell, target_pc); + const PcEqSum f(materialLawManager, phase1, phase2, cell, target_pc); const double f0 = f(smin); const double f1 = f(smax); if (f0 <= 0.0) { @@ -818,19 +785,16 @@ namespace Opm } /// Compute saturation from depth. Used for constant capillary pressure function - inline double satFromDepth(const BlackoilPropertiesInterface& props, + template + inline double satFromDepth(std::shared_ptr materialLawManager, const double cellDepth, const double contactDepth, const int phase, const int cell, const bool increasing = false) { - // Find minimum and maximum saturations. - double sminarr[BlackoilPhases::MaxNumPhases]; - double smaxarr[BlackoilPhases::MaxNumPhases]; - props.satRange(1, &cell, sminarr, smaxarr); - const double s0 = increasing ? smaxarr[phase] : sminarr[phase]; - const double s1 = increasing ? sminarr[phase] : smaxarr[phase]; + const double s0 = increasing ? maxSaturations(materialLawManager, phase, cell) : minSaturations(materialLawManager, phase, cell); + const double s1 = increasing ? minSaturations(materialLawManager, phase, cell) : maxSaturations(materialLawManager, phase, cell); if (cellDepth < contactDepth){ return s0; @@ -841,22 +805,20 @@ namespace Opm } /// Return true if capillary pressure function is constant - inline bool isConstPc(const BlackoilPropertiesInterface& props, + template + inline bool isConstPc(std::shared_ptr materialLawManager, const int phase, const int cell) { - // Find minimum and maximum saturations. - double sminarr[BlackoilPhases::MaxNumPhases]; - double smaxarr[BlackoilPhases::MaxNumPhases]; - props.satRange(1, &cell, sminarr, smaxarr); - // Create the equation f(s) = pc(s); - const PcEq f(props, phase, cell, 0); - const double f0 = f(sminarr[phase]); - const double f1 = f(smaxarr[phase]); + const PcEq f(materialLawManager, phase, cell, 0); + const double f0 = f(minSaturations(materialLawManager, phase, cell)); + const double f1 = f(maxSaturations(materialLawManager, phase, cell)); return std::abs(f0 - f1) < std::numeric_limits::epsilon(); } + + } // namespace Equil } // namespace Opm diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index a29cb135d..4d8956078 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -25,9 +25,11 @@ #include #include #include -#include #include +#include #include +#include + #include #include #include @@ -39,6 +41,11 @@ #include #include +#include +#include +#include + + #include #include #include @@ -54,32 +61,6 @@ struct UnstructuredGrid; namespace Opm { - /** - * Compute initial state by an equilibration procedure. - * - * The following state fields are modified: - * pressure(), - * saturation(), - * surfacevol(), - * gasoilratio(), - * rv(). - * - * \param[in] grid Grid. - * \param[in] props Property object, pvt and capillary properties are used. - * \param[in] deck Simulation deck, used to obtain EQUIL and related data. - * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. - * \param[in] applySwatInit Make it possible to not apply SWATINIT even if it - * is present in the deck - */ - template - void initStateEquil(const Grid& grid, - const BlackoilPropertiesInterface& props, - const Opm::Deck& deck, - const Opm::EclipseState& eclipseState, - const double gravity, - BlackoilState& state, - bool applySwatInit = true); - /** * Types and routines that collectively implement a basic @@ -90,6 +71,7 @@ namespace Opm */ namespace EQUIL { + /** * Compute initial phase pressures by means of equilibration. * @@ -128,7 +110,7 @@ namespace Opm * of pressure values in each cell in the current * equilibration region. */ - template + template std::vector< std::vector > phasePressures(const Grid& G, const Region& reg, @@ -161,12 +143,12 @@ namespace Opm * \return Phase saturations, one vector for each phase, each containing * one saturation value per cell in the region. */ - template + template std::vector< std::vector > phaseSaturations(const Grid& grid, const Region& reg, const CellRange& cells, - BlackoilPropertiesFromDeck& props, + std::shared_ptr materialLawManager, const std::vector swat_init, std::vector< std::vector >& phase_pressures); @@ -244,29 +226,39 @@ namespace Opm class InitialStateComputer { public: - template - InitialStateComputer(BlackoilPropertiesInterface& props, + template + InitialStateComputer(std::shared_ptr materialLawManager, + const PhaseUsage& phaseUsage, const Opm::Deck& deck, const Opm::EclipseState& eclipseState, const Grid& G , const double grav = unit::gravity, const std::vector& swat_init = {} ) - : pp_(props.numPhases(), + : pp_(phaseUsage.num_phases, std::vector(UgGridHelpers::numCells(G))), - sat_(props.numPhases(), + sat_(phaseUsage.num_phases, std::vector(UgGridHelpers::numCells(G))), rs_(UgGridHelpers::numCells(G)), rv_(UgGridHelpers::numCells(G)), - swat_init_(swat_init) + swat_init_(swat_init), + phaseUsage_(phaseUsage) { + + typedef FluidSystems::BlackOil FluidSystem; + + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + // Get the equilibration records. const std::vector rec = getEquil(eclipseState); const auto& tables = eclipseState.getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); + setRegionPvtIdx(G, eclipseState, eqlmap); + // Create Rs functions. rs_func_.reserve(rec.size()); if (deck.hasKeyword("DISGAS")) { @@ -274,10 +266,11 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { if (eqlmap.cells(i).empty()) { - rs_func_.push_back(std::shared_ptr()); + rs_func_.push_back(std::shared_ptr>()); continue; } - const int cell = *(eqlmap.cells(i).begin()); + const int pvtIdx = regionPvtIdx_[i]; + if (!rec[i].liveOilInitConstantRs()) { if (rsvdTables.size() <= 0 ) { OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table not available."); @@ -285,8 +278,7 @@ namespace Opm const RsvdTable& rsvdTable = rsvdTables.getTable(i); std::vector depthColumn = rsvdTable.getColumn("DEPTH").vectorCopy(); std::vector rsColumn = rsvdTable.getColumn("RS").vectorCopy(); - rs_func_.push_back(std::make_shared(props, - cell, + rs_func_.push_back(std::make_shared>(pvtIdx, depthColumn , rsColumn)); } else { if (rec[i].gasOilContactDepth() != rec[i].datumDepth()) { @@ -297,7 +289,7 @@ namespace Opm } const double p_contact = rec[i].datumDepthPressure(); const double T_contact = 273.15 + 20; // standard temperature for now - rs_func_.push_back(std::make_shared(props, cell, p_contact, T_contact)); + rs_func_.push_back(std::make_shared>(pvtIdx, p_contact, T_contact)); } } } else { @@ -312,10 +304,10 @@ namespace Opm for (size_t i = 0; i < rec.size(); ++i) { if (eqlmap.cells(i).empty()) { - rv_func_.push_back(std::shared_ptr()); + rv_func_.push_back(std::shared_ptr>()); continue; } - const int cell = *(eqlmap.cells(i).begin()); + const int pvtIdx = regionPvtIdx_[i]; if (!rec[i].wetGasInitConstantRv()) { if (rvvdTables.size() <= 0) { OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table not available."); @@ -324,9 +316,7 @@ namespace Opm const RvvdTable& rvvdTable = rvvdTables.getTable(i); std::vector depthColumn = rvvdTable.getColumn("DEPTH").vectorCopy(); std::vector rvColumn = rvvdTable.getColumn("RV").vectorCopy(); - - rv_func_.push_back(std::make_shared(props, - cell, + rv_func_.push_back(std::make_shared>(pvtIdx, depthColumn , rvColumn)); } else { @@ -338,7 +328,7 @@ namespace Opm } const double p_contact = rec[i].datumDepthPressure() + rec[i].gasOilContactCapillaryPressure(); const double T_contact = 273.15 + 20; // standard temperature for now - rv_func_.push_back(std::make_shared(props, cell, p_contact, T_contact)); + rv_func_.push_back(std::make_shared>(pvtIdx ,p_contact, T_contact)); } } } else { @@ -348,7 +338,7 @@ namespace Opm } // Compute pressures, saturations, rs and rv factors. - calcPressSatRsRv(eqlmap, rec, props, G, grav); + calcPressSatRsRv(eqlmap, rec, materialLawManager, G, grav); // Modify oil pressure in no-oil regions so that the pressures of present phases can // be recovered from the oil pressure and capillary relations. @@ -363,23 +353,39 @@ namespace Opm const Vec& rv() const { return rv_; } private: - typedef DensityCalculator RhoCalc; - typedef EquilReg EqReg; + + typedef EquilReg EqReg; std::vector< std::shared_ptr > rs_func_; std::vector< std::shared_ptr > rv_func_; + std::vector regionPvtIdx_; + PVec pp_; PVec sat_; Vec rs_; Vec rv_; Vec swat_init_; + PhaseUsage phaseUsage_; - template + template + void setRegionPvtIdx(const Grid& G, const Opm::EclipseState& eclipseState, const RMap& reg) { + + regionPvtIdx_.reserve(reg.activeRegions().size()); + std::vector cellPvtRegionIdx; + extractPvtTableIndex(cellPvtRegionIdx, eclipseState, UgGridHelpers::numCells(G), UgGridHelpers::globalCell(G)); + for (const auto& r : reg.activeRegions()) { + const auto& cells = reg.cells(r); + const int cell = *(cells.begin()); + regionPvtIdx_[r] = cellPvtRegionIdx[cell]; + } + } + + template void calcPressSatRsRv(const RMap& reg , const std::vector< EquilRecord >& rec , - Opm::BlackoilPropertiesInterface& props, + std::shared_ptr materialLawManager, const Grid& G , const double grav) { @@ -391,27 +397,24 @@ namespace Opm + " has no active cells"); continue; } - const int repcell = *cells.begin(); - const RhoCalc calc(props, repcell); - const EqReg eqreg(rec[r], calc, - rs_func_[r], rv_func_[r], - props.phaseUsage()); + const EqReg eqreg(rec[r], + rs_func_[r], rv_func_[r], regionPvtIdx_[r], + phaseUsage_); - PVec pressures = phasePressures(G, eqreg, cells, grav); + PVec pressures = phasePressures(G, eqreg, cells, grav); const std::vector& temp = temperature(G, eqreg, cells); + const PVec sat = phaseSaturations(G, eqreg, cells, materialLawManager, swat_init_, pressures); - const PVec sat = phaseSaturations(G, eqreg, cells, props, swat_init_, pressures); - - const int np = props.numPhases(); + const int np = phaseUsage_.num_phases; for (int p = 0; p < np; ++p) { copyFromRegion(pressures[p], cells, pp_[p]); copyFromRegion(sat[p], cells, sat_[p]); } - if (props.phaseUsage().phase_used[BlackoilPhases::Liquid] - && props.phaseUsage().phase_used[BlackoilPhases::Vapour]) { - const int oilpos = props.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int gaspos = props.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + if (phaseUsage_.phase_used[BlackoilPhases::Liquid] + && phaseUsage_.phase_used[BlackoilPhases::Vapour]) { + const int oilpos = phaseUsage_.phase_pos[BlackoilPhases::Liquid]; + const int gaspos = phaseUsage_.phase_pos[BlackoilPhases::Vapour]; const Vec rs_vals = computeRs(G, cells, pressures[oilpos], temp, *(rs_func_[r]), sat[gaspos]); const Vec rv_vals = computeRs(G, cells, pressures[gaspos], temp, *(rv_func_[r]), sat[oilpos]); copyFromRegion(rs_vals, cells, rs_); diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 37b1b1d80..42314faf0 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -24,8 +24,8 @@ #include #include + #include -#include #include #include @@ -35,6 +35,9 @@ namespace Opm { namespace Details { + + + template class RK4IVP { public: @@ -105,22 +108,17 @@ namespace Opm stepsize() const { return (span_[1] - span_[0]) / N_; } }; - namespace PhasePressODE { - template + namespace PhasePressODE { + template class Water { public: Water(const double temp, - const Density& rho, - const int np, - const int ix, + const int pvtRegionIdx, const double norm_grav) : temp_(temp) - , rho_(rho) - , svol_(np, 0) - , ix_(ix) + , pvtRegionIdx_(pvtRegionIdx) , g_(norm_grav) { - svol_[ix_] = 1.0; } double @@ -132,39 +130,30 @@ namespace Opm private: const double temp_; - const Density& rho_; - std::vector svol_; - const int ix_; + const int pvtRegionIdx_; const double g_; double density(const double press) const { - const std::vector& rho = rho_(press, temp_, svol_); - - return rho[ix_]; + double rho = FluidSystem::waterPvt().inverseFormationVolumeFactor(pvtRegionIdx_, temp_, press); + rho *= FluidSystem::referenceDensity(FluidSystem::waterPhaseIdx, pvtRegionIdx_); + return rho; } }; - template + template class Oil { public: Oil(const double temp, - const Density& rho, const RS& rs, - const int np, - const int oix, - const int gix, + const int pvtRegionIdx, const double norm_grav) : temp_(temp) - , rho_(rho) , rs_(rs) - , svol_(np, 0) - , oix_(oix) - , gix_(gix) + , pvtRegionIdx_(pvtRegionIdx) , g_(norm_grav) { - svol_[oix_] = 1.0; } double @@ -176,45 +165,42 @@ namespace Opm private: const double temp_; - const Density& rho_; const RS& rs_; - mutable std::vector svol_; - const int oix_; - const int gix_; + const int pvtRegionIdx_; const double g_; double density(const double depth, const double press) const { - if (gix_ >= 0) { - svol_[gix_] = rs_(depth, press, temp_); + double rs = rs_(depth, press, temp_); + double bOil = 0.0; + if ( !FluidSystem::enableDissolvedGas() || rs >= FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp_, press) ) { + bOil = FluidSystem::oilPvt().saturatedInverseFormationVolumeFactor(pvtRegionIdx_, temp_, press); + } else { + bOil = FluidSystem::oilPvt().inverseFormationVolumeFactor(pvtRegionIdx_, temp_, press, rs); + } + double rho = bOil * FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, pvtRegionIdx_); + if (FluidSystem::enableDissolvedGas()) { + rho += rs * bOil * FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, pvtRegionIdx_); } - const std::vector& rho = rho_(press, temp_, svol_); - return rho[oix_]; + return rho; } }; - template + template class Gas { public: Gas(const double temp, - const Density& rho, const RV& rv, - const int np, - const int gix, - const int oix, + const int pvtRegionIdx, const double norm_grav) : temp_(temp) - , rho_(rho) , rv_(rv) - , svol_(np, 0) - , gix_(gix) - , oix_(oix) + , pvtRegionIdx_(pvtRegionIdx) , g_(norm_grav) { - svol_[gix_] = 1.0; } double @@ -226,23 +212,27 @@ namespace Opm private: const double temp_; - const Density& rho_; const RV& rv_; - mutable std::vector svol_; - const int gix_; - const int oix_; + const int pvtRegionIdx_; const double g_; double density(const double depth, const double press) const { - if (oix_ >= 0) { - svol_[oix_] = rv_(depth, press, temp_); + double rv = rv_(depth, press, temp_); + double bGas = 0.0; + if ( !FluidSystem::enableVaporizedOil() || rv >= FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp_, press) ) { + bGas = FluidSystem::gasPvt().saturatedInverseFormationVolumeFactor(pvtRegionIdx_, temp_, press); + } else { + bGas = FluidSystem::gasPvt().inverseFormationVolumeFactor(pvtRegionIdx_, temp_, press, rv); + } + double rho = bGas * FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, pvtRegionIdx_); + if (FluidSystem::enableVaporizedOil()) { + rho += rv * bGas * FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, pvtRegionIdx_); } - const std::vector& rho = rho_(press, temp_, svol_); - return rho[gix_]; + return rho; } }; } // namespace PhasePressODE @@ -328,9 +318,10 @@ namespace Opm } } - template + template < class FluidSystem, + class Grid, + class Region, + class CellRange> void water(const Grid& G , const Region& reg , @@ -341,13 +332,10 @@ namespace Opm std::vector& press ) { using PhasePressODE::Water; - typedef Water ODE; + typedef Water ODE; - const PhaseUsage& pu = reg.phaseUsage(); - - const int wix = PhaseIndex::water(pu); const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, reg.densityCalculator(), pu.num_phases, wix, grav); + ODE drho(T, reg.pvtIdx() , grav); double z0; double p0; @@ -379,9 +367,11 @@ namespace Opm } } - template + void oil(const Grid& G , const Region& reg , @@ -393,18 +383,12 @@ namespace Opm double& po_goc) { using PhasePressODE::Oil; - typedef Oil ODE; + typedef Oil ODE; - const PhaseUsage& pu = reg.phaseUsage(); - - const int oix = PhaseIndex::oil(pu); - const int gix = PhaseIndex::gas(pu); const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, - reg.densityCalculator(), - reg.dissolutionCalculator(), - pu.num_phases, oix, gix, grav); + + ODE drho(T, reg.dissolutionCalculator(), + reg.pvtIdx(), grav); double z0; double p0; @@ -444,7 +428,8 @@ namespace Opm else { po_goc = p0; } // GOC *at* datum } - template void @@ -457,19 +442,11 @@ namespace Opm std::vector& press ) { using PhasePressODE::Gas; - typedef Gas ODE; - - const PhaseUsage& pu = reg.phaseUsage(); - - const int gix = PhaseIndex::gas(pu); - const int oix = PhaseIndex::oil(pu); + typedef Gas ODE; const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, - reg.densityCalculator(), - reg.evaporationCalculator(), - pu.num_phases, gix, oix, grav); + ODE drho(T, reg.evaporationCalculator(), + reg.pvtIdx(), grav); double z0; double p0; @@ -502,7 +479,8 @@ namespace Opm } } // namespace PhasePressure - template void @@ -521,19 +499,19 @@ namespace Opm if (PhaseUsed::water(pu)) { const int wix = PhaseIndex::water(pu); - PhasePressure::water(G, reg, span, grav, po_woc, + PhasePressure::water(G, reg, span, grav, po_woc, cells, press[ wix ]); } if (PhaseUsed::oil(pu)) { const int oix = PhaseIndex::oil(pu); - PhasePressure::oil(G, reg, span, grav, cells, + PhasePressure::oil(G, reg, span, grav, cells, press[ oix ], po_woc, po_goc); } if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - PhasePressure::gas(G, reg, span, grav, po_goc, + PhasePressure::gas(G, reg, span, grav, po_goc, cells, press[ gix ]); } } else if (reg.datum() < reg.zgoc()) { // Datum in gas zone @@ -542,19 +520,19 @@ namespace Opm if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - PhasePressure::gas(G, reg, span, grav, po_goc, + PhasePressure::gas(G, reg, span, grav, po_goc, cells, press[ gix ]); } if (PhaseUsed::oil(pu)) { const int oix = PhaseIndex::oil(pu); - PhasePressure::oil(G, reg, span, grav, cells, + PhasePressure::oil(G, reg, span, grav, cells, press[ oix ], po_woc, po_goc); } if (PhaseUsed::water(pu)) { const int wix = PhaseIndex::water(pu); - PhasePressure::water(G, reg, span, grav, po_woc, + PhasePressure::water(G, reg, span, grav, po_woc, cells, press[ wix ]); } } else { // Datum in oil zone @@ -563,19 +541,19 @@ namespace Opm if (PhaseUsed::oil(pu)) { const int oix = PhaseIndex::oil(pu); - PhasePressure::oil(G, reg, span, grav, cells, - press[ oix ], po_woc, po_goc); + PhasePressure::oil(G, reg, span, grav, cells, + press[ oix ], po_woc, po_goc); } if (PhaseUsed::water(pu)) { const int wix = PhaseIndex::water(pu); - PhasePressure::water(G, reg, span, grav, po_woc, + PhasePressure::water(G, reg, span, grav, po_woc, cells, press[ wix ]); } if (PhaseUsed::gas(pu)) { const int gix = PhaseIndex::gas(pu); - PhasePressure::gas(G, reg, span, grav, po_goc, + PhasePressure::gas(G, reg, span, grav, po_goc, cells, press[ gix ]); } } @@ -586,7 +564,8 @@ namespace Opm namespace EQUIL { - template std::vector< std::vector > @@ -654,7 +633,7 @@ namespace Opm span[0] = std::min(span[0],zgoc); span[1] = std::max(span[1],zwoc); - Details::equilibrateOWG(G, reg, grav, span, cells, press); + Details::equilibrateOWG(G, reg, grav, span, cells, press); return press; } @@ -671,12 +650,12 @@ namespace Opm return std::vector(cells.size(), 273.15 + 20.0); } - template + template std::vector< std::vector > phaseSaturations(const Grid& G, const Region& reg, const CellRange& cells, - BlackoilPropertiesInterface& props, + std::shared_ptr materialLawManager, const std::vector swat_init, std::vector< std::vector >& phase_pressures) { @@ -685,8 +664,23 @@ namespace Opm } std::vector< std::vector > phase_saturations = phase_pressures; // Just to get the right size. - double smin[BlackoilPhases::MaxNumPhases] = { 0.0 }; - double smax[BlackoilPhases::MaxNumPhases] = { 0.0 }; + + // Adjust oil pressure according to gas saturation and cap pressure + typedef Opm::SimpleModularFluidState SatOnlyFluidState; + + SatOnlyFluidState fluidState; + typedef typename MaterialLawManager::MaterialLaw MaterialLaw; const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; @@ -696,42 +690,45 @@ namespace Opm std::vector::size_type local_index = 0; for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { const int cell = *ci; - props.satRange(1, &cell, smin, smax); + const auto& scaledDrainageInfo = + materialLawManager->oilWaterScaledEpsInfoDrainage(cell); + const auto& matParams = materialLawManager->materialLawParams(cell); + // Find saturations from pressure differences by // inverting capillary pressure functions. double sw = 0.0; if (water) { - if (isConstPc(props,waterpos,cell)){ + if (isConstPc(materialLawManager,FluidSystem::waterPhaseIdx, cell)){ const double cellDepth = UgGridHelpers::cellCenterDepth(G, cell); - sw = satFromDepth(props,cellDepth,reg.zwoc(),waterpos,cell,false); + sw = satFromDepth(materialLawManager,cellDepth,reg.zwoc(),waterpos,cell,false); phase_saturations[waterpos][local_index] = sw; } else{ const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; if (swat_init.empty()) { // Invert Pc to find sw - sw = satFromPc(props, waterpos, cell, pcov); + sw = satFromPc(materialLawManager, waterpos, cell, pcov); phase_saturations[waterpos][local_index] = sw; } else { // Scale Pc to reflect imposed sw sw = swat_init[cell]; - props.swatInitScaling(cell, pcov, sw); + sw = materialLawManager->applySwatinit(cell, pcov, sw); phase_saturations[waterpos][local_index] = sw; } } } double sg = 0.0; if (gas) { - if (isConstPc(props,gaspos,cell)){ + if (isConstPc(materialLawManager,FluidSystem::gasPhaseIdx,cell)){ const double cellDepth = UgGridHelpers::cellCenterDepth(G, cell); - sg = satFromDepth(props,cellDepth,reg.zgoc(),gaspos,cell,true); + sg = satFromDepth(materialLawManager,cellDepth,reg.zgoc(),gaspos,cell,true); phase_saturations[gaspos][local_index] = sg; } else{ // Note that pcog is defined to be (pg - po), not (po - pg). const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; const double increasing = true; // pcog(sg) expected to be increasing function - sg = satFromPc(props, gaspos, cell, pcog, increasing); + sg = satFromPc(materialLawManager, gaspos, cell, pcog, increasing); phase_saturations[gaspos][local_index] = sg; } } @@ -745,55 +742,69 @@ namespace Opm // Re-scale Pc to reflect imposed sw for vanishing oil phase. // This seems consistent with ecl, and fails to honour // swat_init in case of non-trivial gas-oil cap pressure. - props.swatInitScaling(cell, pcgw, sw); + sw = materialLawManager->applySwatinit(cell, pcgw, sw); } - sw = satFromSumOfPcs(props, waterpos, gaspos, cell, pcgw); + sw = satFromSumOfPcs(materialLawManager, waterpos, gaspos, cell, pcgw); sg = 1.0 - sw; phase_saturations[waterpos][local_index] = sw; phase_saturations[gaspos][local_index] = sg; - // Adjust oil pressure according to gas saturation and cap pressure - double pc[BlackoilPhases::MaxNumPhases]; - double sat[BlackoilPhases::MaxNumPhases]; - sat[waterpos] = sw; - sat[gaspos] = sg; - sat[oilpos] = 1.0 - sat[waterpos] - sat[gaspos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; + + if ( water ) { + fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); + } + else { + fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0); + } + fluidState.setSaturation(FluidSystem::oilPhaseIdx, 1.0 - sw - sg); + fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); + + double pC[/*numPhases=*/3] = { 0.0, 0.0, 0.0 }; + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; + phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pcGas; } phase_saturations[oilpos][local_index] = 1.0 - sw - sg; // Adjust phase pressures for max and min saturation ... - double pc[BlackoilPhases::MaxNumPhases]; - double sat[BlackoilPhases::MaxNumPhases]; double threshold_sat = 1.0e-6; - sat[oilpos] = 1.0; + double so = 1.0; + double pC[/*numPhases=*/BlackoilPhases::MaxNumPhases] = { 0.0, 0.0, 0.0 }; + if (water) { - sat[waterpos] = smax[waterpos]; - sat[oilpos] -= sat[waterpos]; + double swu = scaledDrainageInfo.Swu; + fluidState.setSaturation(FluidSystem::waterPhaseIdx, swu); + so -= swu; } if (gas) { - sat[gaspos] = smax[gaspos]; - sat[oilpos] -= sat[gaspos]; + double sgu = scaledDrainageInfo.Sgu; + fluidState.setSaturation(FluidSystem::gasPhaseIdx, sgu); + so-= sgu; } - if (water && sw > smax[waterpos]-threshold_sat ) { - sat[waterpos] = smax[waterpos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pc[waterpos]; - } else if (gas && sg > smax[gaspos]-threshold_sat) { - sat[gaspos] = smax[gaspos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pc[gaspos]; + fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); + + if (water && sw > scaledDrainageInfo.Swu-threshold_sat ) { + fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swu); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; + phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pcWat; + } else if (gas && sg > scaledDrainageInfo.Sgu-threshold_sat) { + fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgu); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; + phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pcGas; } - if (gas && sg < smin[gaspos]+threshold_sat) { - sat[gaspos] = smin[gaspos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pc[gaspos]; + if (gas && sg < scaledDrainageInfo.Sgl+threshold_sat) { + fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgl); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; + phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pcGas; } - if (water && sw < smin[waterpos]+threshold_sat) { - sat[waterpos] = smin[waterpos]; - props.capPress(1, sat, &cell, pc, 0); - phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pc[waterpos]; + if (water && sw < scaledDrainageInfo.Swl+threshold_sat) { + fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swl); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; + phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pcWat; } } return phase_saturations; @@ -885,9 +896,9 @@ namespace Opm * \param[in] applySwatInit Make it possible to not apply SWATINIT even if it * is present in the deck */ - template + template void initStateEquil(const Grid& grid, - BlackoilPropertiesFromDeck& props, + std::shared_ptr materialLawManager, const Opm::Deck& deck, const Opm::EclipseState& eclipseState, const double gravity, @@ -896,6 +907,9 @@ namespace Opm { typedef EQUIL::DeckDependent::InitialStateComputer ISC; + + PhaseUsage pu = phaseUsageFromDeck(deck); + //Check for presence of kw SWATINIT std::vector swat_init = {}; if (eclipseState.get3DProperties().hasDeckDoubleGridProperty("SWATINIT") && applySwatinit) { @@ -910,8 +924,7 @@ namespace Opm } } - ISC isc(props, deck, eclipseState, grid, gravity, swat_init); - const auto pu = props.phaseUsage(); + ISC isc(materialLawManager, pu, deck, eclipseState, grid, gravity, swat_init); const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] ? pu.phase_pos[BlackoilPhases::Liquid] : pu.phase_pos[BlackoilPhases::Aqua]; @@ -920,7 +933,7 @@ namespace Opm state.gasoilratio() = isc.rs(); state.rv() = isc.rv(); - initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); + //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); } diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 251a4e65f..c5a6069a3 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -22,10 +22,15 @@ #include #include #include +#include + #include #include #include +#include +#include + #include #include @@ -49,6 +54,15 @@ #include #include + +// Forward declaring the MaterialLawManager template. +typedef Opm::ThreePhaseMaterialTraits MaterialTraits; +typedef Opm::EclMaterialLawManager MaterialLawManager; + + #define CHECK(value, expected, reltol) \ { \ if (std::fabs((expected)) < 1.e-14) \ @@ -57,6 +71,87 @@ BOOST_CHECK_CLOSE((value), (expected), (reltol)); \ } +typedef Opm::FluidSystems::BlackOil FluidSystem; +Opm::PhaseUsage initDefaultFluidSystem() { + std::vector > Bo = { + { 101353, 1. }, + { 6.21542e+07, 1 } + }; + std::vector > muo = { + { 101353, 1. }, + { 6.21542e+07, 1 } + }; + + std::vector > Bg = { + { 101353, 1. }, + { 6.21542e+07, 1 } + }; + std::vector > mug = { + { 101353, 1. }, + { 6.21542e+07, 1 } + }; + + double rhoRefO = 700; // [kg] + double rhoRefG = 1000; // [kg] + double rhoRefW = 1000; // [kg] + + FluidSystem::initBegin(/*numPvtRegions=*/1); + FluidSystem::setEnableDissolvedGas(false); + FluidSystem::setEnableVaporizedOil(false); + FluidSystem::setReferenceDensities(rhoRefO, rhoRefW, rhoRefG, /*regionIdx=*/0); + + Opm::GasPvtMultiplexer *gasPvt = new Opm::GasPvtMultiplexer; + gasPvt->setApproach(Opm::GasPvtMultiplexer::DryGasPvt); + auto& dryGasPvt = gasPvt->template getRealPvt::DryGasPvt>(); + dryGasPvt.setNumRegions(/*numPvtRegion=*/1); + dryGasPvt.setReferenceDensities(/*regionIdx=*/0, rhoRefO, rhoRefG, rhoRefW); + dryGasPvt.setGasFormationVolumeFactor(/*regionIdx=*/0, Bg); + dryGasPvt.setGasViscosity(/*regionIdx=*/0, mug); + + Opm::OilPvtMultiplexer *oilPvt = new Opm::OilPvtMultiplexer; + oilPvt->setApproach(Opm::OilPvtMultiplexer::DeadOilPvt); + auto& deadOilPvt = oilPvt->template getRealPvt::DeadOilPvt>(); + deadOilPvt.setNumRegions(/*numPvtRegion=*/1); + deadOilPvt.setReferenceDensities(/*regionIdx=*/0, rhoRefO, rhoRefG, rhoRefW); + deadOilPvt.setInverseOilFormationVolumeFactor(/*regionIdx=*/0, Bo); + deadOilPvt.setOilViscosity(/*regionIdx=*/0, muo); + + Opm::WaterPvtMultiplexer *waterPvt = new Opm::WaterPvtMultiplexer; + waterPvt->setApproach(Opm::WaterPvtMultiplexer::ConstantCompressibilityWaterPvt); + auto& ccWaterPvt = waterPvt->template getRealPvt::ConstantCompressibilityWaterPvt>(); + ccWaterPvt.setNumRegions(/*numPvtRegions=*/1); + ccWaterPvt.setReferenceDensities(/*regionIdx=*/0, rhoRefO, rhoRefG, rhoRefW); + ccWaterPvt.setViscosity(/*regionIdx=*/0, 1); + ccWaterPvt.setCompressibility(/*regionIdx=*/0, 0); + + gasPvt->initEnd(); + oilPvt->initEnd(); + waterPvt->initEnd(); + + typedef std::shared_ptr > GasPvtSharedPtr; + FluidSystem::setGasPvt(GasPvtSharedPtr(gasPvt)); + + typedef std::shared_ptr > OilPvtSharedPtr; + FluidSystem::setOilPvt(OilPvtSharedPtr(oilPvt)); + + typedef std::shared_ptr > WaterPvtSharedPtr; + FluidSystem::setWaterPvt(WaterPvtSharedPtr(waterPvt)); + + FluidSystem::initEnd(); + + Opm::PhaseUsage pu; + pu.num_phases = 2; + // Might just as well assume water-oil. + pu.phase_used[Opm::BlackoilPhases::Aqua] = true; + pu.phase_used[Opm::BlackoilPhases::Liquid] = true; + pu.phase_used[Opm::BlackoilPhases::Vapour] = false; + pu.phase_pos[Opm::BlackoilPhases::Aqua] = 0; + pu.phase_pos[Opm::BlackoilPhases::Liquid] = 1; + pu.phase_pos[Opm::BlackoilPhases::Vapour] = 1; // Unused. + return pu; + +} + BOOST_AUTO_TEST_SUITE () static Opm::EquilRecord mkEquilRecord( double datd, double datp, @@ -123,35 +218,22 @@ BOOST_AUTO_TEST_CASE (PhasePressure) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::ParameterGroup param; - { - using Opm::unit::kilogram; - using Opm::unit::meter; - using Opm::unit::cubic; - - std::stringstream dens; dens << 700*kilogram/cubic(meter); - param.insertParameter("rho2", dens.str()); - } - - typedef Opm::BlackoilPropertiesBasic Props; - Props props(param, G->dimensions, G->number_of_cells); - - typedef Opm::EQUIL::DensityCalculator RhoCalc; - RhoCalc calc(props, 0); - auto record = mkEquilRecord( 0, 1e5, 5, 0, 0, 0 ); - Opm::EQUIL::EquilReg - region(record, calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()); + Opm::PhaseUsage pu = initDefaultFluidSystem(); + + Opm::EQUIL::EquilReg + region(record, + std::make_shared(), + std::make_shared(), + 0, + pu); std::vector cells(G->number_of_cells); std::iota(cells.begin(), cells.end(), 0); const double grav = 10; - const PPress ppress = Opm::EQUIL::phasePressures(*G, region, cells, grav); + const PPress ppress = Opm::EQUIL::phasePressures(*G, region, cells, grav); const int first = 0, last = G->number_of_cells - 1; const double reltol = 1.0e-8; @@ -169,47 +251,38 @@ BOOST_AUTO_TEST_CASE (CellSubset) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::ParameterGroup param; - { - using Opm::unit::kilogram; - using Opm::unit::meter; - using Opm::unit::cubic; + Opm::PhaseUsage pu = initDefaultFluidSystem(); - std::stringstream dens; dens << 700*kilogram/cubic(meter); - param.insertParameter("rho2", dens.str()); - } - - typedef Opm::BlackoilPropertiesBasic Props; - Props props(param, G->dimensions, G->number_of_cells); - - typedef Opm::EQUIL::DensityCalculator RhoCalc; - RhoCalc calc(props, 0); Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - Opm::EQUIL::EquilReg region[] = - { - Opm::EQUIL::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - , - Opm::EQUIL::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - , - Opm::EQUIL::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - , - Opm::EQUIL::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - }; + Opm::EQUIL::EquilReg region[] = + { + Opm::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), + 0, + pu) + , + Opm::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), + 0, + pu) + , + Opm::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), + 0, + pu) + , + Opm::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), + 0, + pu) + }; const int cdim[] = { 2, 1, 2 }; int ncoarse = cdim[0]; @@ -239,7 +312,7 @@ BOOST_AUTO_TEST_CASE (CellSubset) const int rno = int(r - cells.begin()); const double grav = 10; const PPress p = - Opm::EQUIL::phasePressures(*G, region[rno], *r, grav); + Opm::EQUIL::phasePressures(*G, region[rno], *r, grav); PVal::size_type i = 0; for (std::vector::const_iterator @@ -272,46 +345,36 @@ BOOST_AUTO_TEST_CASE (RegMapping) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::ParameterGroup param; - { - using Opm::unit::kilogram; - using Opm::unit::meter; - using Opm::unit::cubic; - - std::stringstream dens; dens << 700*kilogram/cubic(meter); - param.insertParameter("rho2", dens.str()); - } - - typedef Opm::BlackoilPropertiesBasic Props; - Props props(param, G->dimensions, G->number_of_cells); - - typedef Opm::EQUIL::DensityCalculator RhoCalc; - RhoCalc calc(props, 0); - Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - Opm::EQUIL::EquilReg region[] = - { - Opm::EQUIL::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - , - Opm::EQUIL::EquilReg(record[0], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - , - Opm::EQUIL::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) - , - Opm::EQUIL::EquilReg(record[1], calc, - std::make_shared(), - std::make_shared(), - props.phaseUsage()) + Opm::PhaseUsage pu = initDefaultFluidSystem(); + + Opm::EQUIL::EquilReg region[] = + { + Opm::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), + 0, + pu) + , + Opm::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), + 0, + pu) + , + Opm::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), + 0, + pu) + , + Opm::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), + 0, + pu) }; std::vector eqlnum(G->number_of_cells); @@ -336,7 +399,7 @@ BOOST_AUTO_TEST_CASE (RegMapping) const int rno = r; const double grav = 10; const PPress p = - Opm::EQUIL::phasePressures(*G, region[rno], rng, grav); + Opm::EQUIL::phasePressures(*G, region[rno], rng, grav); PVal::size_type i = 0; for (const auto& c : rng) { @@ -366,9 +429,16 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) Opm::ParseContext parseContext; Opm::Parser parser; Opm::Deck deck = parser.parseFile("deadfluids.DATA" , parseContext); - Opm::EclipseState eclipseState(deck, parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, *grid, false); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, *grid, 10.0); + Opm::EclipseState eclipseState(deck, parseContext); // Create material law manager. + + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid->number_of_cells, grid->global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + + Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -395,8 +465,20 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) Opm::ParseContext parseContext; Opm::Deck deck = parser.parseFile("capillary.DATA" , parseContext); Opm::EclipseState eclipseState(deck , parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + + typedef Opm::FluidSystems::BlackOil FluidSystem; + typedef MaterialLawManager::MaterialLaw MaterialLaw; + + if (!FluidSystem::isInitialized()) { + // make sure that we don't initialize the fluid system twice + FluidSystem::initFromDeck(deck, eclipseState); + } // Test the capillary inversion for oil-water. const int cell = 0; const double reltol = 1.0e-7; @@ -407,7 +489,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.2, 0.2, 0.2, 0.466666666666, 0.733333333333, 1.0, 1.0, 1.0, 1.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::EQUIL::satFromPc(props, phase, cell, pc[i], increasing); + const double s_computed = Opm::EQUIL::satFromPc(materialLawManager, phase, cell, pc[i], increasing); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -420,7 +502,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.8, 0.8, 0.8, 0.533333333333, 0.266666666666, 0.0, 0.0, 0.0, 0.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::EQUIL::satFromPc(props, phase, cell, pc[i], increasing); + const double s_computed = Opm::EQUIL::satFromPc(materialLawManager, phase, cell, pc[i], increasing); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -433,7 +515,7 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const std::vector s = { 0.2, 0.333333333333, 0.6, 0.866666666666, 1.0 }; BOOST_REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::EQUIL::satFromSumOfPcs(props, water, gas, cell, pc[i]); + const double s_computed = Opm::EQUIL::satFromSumOfPcs(materialLawManager, water, gas, cell, pc[i]); BOOST_CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -449,9 +531,16 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) Opm::ParseContext parseContext; Opm::Deck deck = parser.parseFile("capillary.DATA" , parseContext); Opm::EclipseState eclipseState(deck , parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 10.0); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + + Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -490,9 +579,15 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) Opm::ParseContext parseContext; Opm::Deck deck = parser.parseFile("capillary_overlap.DATA" , parseContext); Opm::EclipseState eclipseState(deck , parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -553,9 +648,15 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) Opm::ParseContext parseContext; Opm::Deck deck = parser.parseFile("equil_liveoil.DATA" , parseContext); Opm::EclipseState eclipseState(deck , parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -633,9 +734,15 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) Opm::ParseContext parseContext; Opm::Deck deck = parser.parseFile("equil_livegas.DATA" , parseContext); Opm::EclipseState eclipseState(deck , parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -715,9 +822,15 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) Opm::Parser parser; Opm::Deck deck = parser.parseFile("equil_rsvd_and_rvvd.DATA", parseContext); Opm::EclipseState eclipseState(deck , parseContext); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(props, deck, eclipseState, grid, 9.80665); + Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -817,8 +930,15 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) Opm::EclipseState eclipseState(deck , parseContext); Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::BlackoilPropertiesFromDeck props(deck, eclipseState, grid, false); - Opm::BlackoilPropertiesFromDeck propsScaled(deck, eclipseState, grid, false); + + // Create material law manager. + std::vector compressedToCartesianIdx + = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + auto materialLawManager = std::make_shared(); + materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + + auto materialLawManagerScaled = std::make_shared(); + materialLawManagerScaled->initFromDeck(deck, eclipseState, compressedToCartesianIdx); Opm::BlackoilState state( Opm::UgGridHelpers::numCells( grid ) , Opm::UgGridHelpers::numFaces( grid ) , 3); @@ -848,12 +968,43 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) } } + // Adjust oil pressure according to gas saturation and cap pressure + typedef Opm::SimpleModularFluidState SatOnlyFluidState; + + SatOnlyFluidState fluidState; + typedef MaterialLawManager::MaterialLaw MaterialLaw; + + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + // reference pcs - const int numCells = Opm::UgGridHelpers::numCells(grid); - std::vector cells(numCells); - for (int c = 0; c < numCells; ++c) { cells[c] = c; } std::vector pc_original = state.saturation(); - props.capPress(numCells, sats.data(), cells.data(), pc_original.data(), nullptr); + const int numCells = Opm::UgGridHelpers::numCells(grid); + for (int c = 0; c < numCells; ++c) { + std::vector pc = {0,0,0}; + double sw = sats[3*c + 0]; + double so = sats[3*c + 1]; + double sg = sats[3*c + 2]; + fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); + fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); + fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); + const auto& matParams = materialLawManager->materialLawParams(c); + MaterialLaw::capillaryPressures(pc, matParams, fluidState); + pc_original[3*c + 0] = pc[FluidSystem::oilPhaseIdx] - pc[FluidSystem::waterPhaseIdx]; + pc_original[3*c + 1] = 0.0; + pc_original[3*c + 2] = pc[FluidSystem::oilPhaseIdx] + pc[FluidSystem::gasPhaseIdx]; + } std::vector pc_scaled_truth = pc_original; @@ -876,17 +1027,46 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) // apply swatinit Opm::BlackoilState state_scaled = state; - initStateEquil(grid, propsScaled, deck, eclipseState, 9.81, state_scaled, true); + initStateEquil(grid, materialLawManagerScaled, deck, eclipseState, 9.81, state_scaled, true); // don't apply swatinit Opm::BlackoilState state_unscaled = state; - initStateEquil(grid, props, deck, eclipseState, 9.81, state_unscaled, false); + initStateEquil(grid, materialLawManager, deck, eclipseState, 9.81, state_unscaled, false); // compute pc std::vector pc_scaled= state.saturation(); - propsScaled.capPress(numCells, state_scaled.saturation().data(), cells.data(), pc_scaled.data(), nullptr); + for (int c = 0; c < numCells; ++c) { + std::vector pc = {0,0,0}; + double sw = state_scaled.saturation().data()[3*c + 0]; + double so = state_scaled.saturation().data()[3*c + 1]; + double sg = state_scaled.saturation().data()[3*c + 2]; + + fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); + fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); + fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); + const auto& matParams = materialLawManagerScaled->materialLawParams(c); + MaterialLaw::capillaryPressures(pc, matParams, fluidState); + pc_scaled[3*c + 0] = pc[FluidSystem::oilPhaseIdx] - pc[FluidSystem::waterPhaseIdx]; + pc_scaled[3*c + 1] = 0.0; + pc_scaled[3*c + 2] = pc[FluidSystem::oilPhaseIdx] + pc[FluidSystem::gasPhaseIdx]; + } std::vector pc_unscaled= state.saturation(); - props.capPress(numCells, state_unscaled.saturation().data(), cells.data(), pc_unscaled.data(), nullptr); + for (int c = 0; c < numCells; ++c) { + std::vector pc = {0,0,0}; + double sw = state_unscaled.saturation().data()[3*c + 0]; + double so = state_unscaled.saturation().data()[3*c + 1]; + double sg = state_unscaled.saturation().data()[3*c + 2]; + + fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); + fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); + fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); + + const auto& matParams = materialLawManager->materialLawParams(c); + MaterialLaw::capillaryPressures(pc, matParams, fluidState); + pc_unscaled[3*c + 0] = pc[FluidSystem::oilPhaseIdx] - pc[FluidSystem::waterPhaseIdx]; + pc_unscaled[3*c + 1] = 0.0; + pc_unscaled[3*c + 2] = pc[FluidSystem::oilPhaseIdx] + pc[FluidSystem::gasPhaseIdx]; + } // test const double reltol = 1.0e-3; From dc997185d92553818ce0d964cbf1c9489aa72165 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 20 Nov 2017 08:47:41 +0100 Subject: [PATCH 148/158] Remove blackoilPhases and phaseUsage from the initialization code Note 1: The initialization code now always consider 3 phases. For 2-phase cases a trivial (0) state is returned. Note 2: The initialization code does not compute a BlackoilStats, but instead pass the initialization object with the initial state. --- examples/compute_initial_state.cpp | 64 +++++- opm/core/simulator/EquilibrationHelpers.hpp | 20 +- opm/core/simulator/initStateEquil.hpp | 70 +++---- opm/core/simulator/initStateEquil_impl.hpp | 212 +++----------------- tests/test_equil.cpp | 156 +++++++------- 5 files changed, 205 insertions(+), 317 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 67c00a363..05f22e590 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -75,12 +77,45 @@ namespace std::copy(data.begin(), data.end(), std::ostream_iterator(file, "\n")); } + /// Convert saturations from a vector of individual phase saturation vectors + /// to an interleaved format where all values for a given cell come before all + /// values for the next cell, all in a single vector. + template + void convertSats(std::vector& sat_interleaved, const std::vector< std::vector >& sat, const Opm::PhaseUsage& pu) + { + assert(sat.size() == 3); + const auto nc = sat[0].size(); + const auto np = sat_interleaved.size() / nc; + for (size_t c = 0; c < nc; ++c) { + if ( FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) { + const int opos = pu.phase_pos[Opm::BlackoilPhases::Liquid]; + const std::vector& sat_p = sat[ FluidSystem::oilPhaseIdx]; + sat_interleaved[np*c + opos] = sat_p[c]; + } + if ( FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { + const int wpos = pu.phase_pos[Opm::BlackoilPhases::Aqua]; + const std::vector& sat_p = sat[ FluidSystem::waterPhaseIdx]; + sat_interleaved[np*c + wpos] = sat_p[c]; + } + if ( FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { + const int gpos = pu.phase_pos[Opm::BlackoilPhases::Vapour]; + const std::vector& sat_p = sat[ FluidSystem::gasPhaseIdx]; + sat_interleaved[np*c + gpos] = sat_p[c]; + } + } + } + } // anon namespace + + + + + // ----------------- Main program ----------------- int main(int argc, char** argv) @@ -119,7 +154,32 @@ try // Initialisation. //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); BlackoilState state( UgGridHelpers::numCells(grid) , UgGridHelpers::numFaces(grid), 3); - initStateEquil(grid, materialLawManager, deck, eclipseState, grav, state); + typedef FluidSystems::BlackOil FluidSystem; + FluidSystem::initFromDeck(deck, eclipseState); + PhaseUsage pu = phaseUsageFromDeck(deck); + + typedef EQUIL::DeckDependent::InitialStateComputer ISC; + + ISC isc(materialLawManager, eclipseState, grid, grav); + + const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); + const int oilpos = FluidSystem::oilPhaseIdx; + const int waterpos = FluidSystem::waterPhaseIdx; + const int ref_phase = oil ? oilpos : waterpos; + + state.pressure() = isc.press()[ref_phase]; + convertSats(state.saturation(), isc.saturation(), pu); + + if (state.hasCellData(std::string("GASOILRATIO"))) { + std::vector& rs = state.getCellData(std::string("GASOILRATIO")); + rs = isc.rs(); + } + if (state.hasCellData(std::string("RV"))){ + std::vector& rv = state.getCellData(std::string("RV")); + rv = isc.rv(); + } + + // Output. const std::string output_dir = param.getDefault("output_dir", "output"); @@ -132,3 +192,5 @@ catch (const std::exception& e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; } + + diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 1c2643265..eff050102 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -1,5 +1,6 @@ /* Copyright 2014 SINTEF ICT, Applied Mathematics. + Copyright 2017 IRIS This file is part of the Open Porous Media project (OPM). @@ -20,7 +21,6 @@ #ifndef OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED #define OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED -#include #include #include #include @@ -478,13 +478,11 @@ namespace Opm EquilReg(const EquilRecord& rec, std::shared_ptr rs, std::shared_ptr rv, - const int pvtIdx, - const PhaseUsage& pu) + const int pvtIdx) : rec_ (rec) , rs_ (rs) , rv_ (rv) , pvtIdx_ (pvtIdx) - , pu_ (pu) { } @@ -554,18 +552,12 @@ namespace Opm const int pvtIdx() const { return this->pvtIdx_; } - /** - * Retrieve active fluid phase summary. - */ - const PhaseUsage& - phaseUsage() const { return this->pu_; } private: EquilRecord rec_; /**< Equilibration data */ std::shared_ptr rs_; /**< RS calculator */ std::shared_ptr rv_; /**< RV calculator */ const int pvtIdx_; - PhaseUsage pu_; /**< Active phase summary */ }; @@ -588,7 +580,7 @@ namespace Opm fluidState_.setSaturation(FluidSystem::waterPhaseIdx, 0.0); fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); - std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + std::fill(pc_, pc_ + FluidSystem::numPhases, 0.0); } @@ -609,7 +601,7 @@ namespace Opm const int cell_; const double target_pc_; mutable SatOnlyFluidState fluidState_; - mutable double pc_[BlackoilPhases::MaxNumPhases]; + mutable double pc_[FluidSystem::numPhases]; }; template @@ -722,7 +714,7 @@ namespace Opm fluidState_.setSaturation(FluidSystem::waterPhaseIdx, 0.0); fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); - std::fill(pc_, pc_ + BlackoilPhases::MaxNumPhases, 0.0); + std::fill(pc_, pc_ + FluidSystem::numPhases, 0.0); } double operator()(double s) const { @@ -745,7 +737,7 @@ namespace Opm const int cell_; const double target_pc_; mutable SatOnlyFluidState fluidState_; - mutable double pc_[BlackoilPhases::MaxNumPhases]; + mutable double pc_[FluidSystem::numPhases]; }; diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 4d8956078..d3f1110d4 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -24,9 +24,6 @@ #include #include -#include -#include -#include #include #include @@ -40,6 +37,8 @@ #include #include #include +#include + #include #include @@ -198,12 +197,12 @@ namespace Opm template inline std::vector - equilnum(const Opm::Deck& deck, - const Opm::EclipseState& eclipseState, + equilnum(const Opm::EclipseState& eclipseState, const Grid& G ) { std::vector eqlnum; - if (deck.hasKeyword("EQLNUM")) { + + if (eclipseState.get3DProperties().hasDeckIntGridProperty("EQLNUM")) { const int nc = UgGridHelpers::numCells(G); eqlnum.resize(nc); const std::vector& e = @@ -223,45 +222,48 @@ namespace Opm return eqlnum; } - + template class InitialStateComputer { public: template InitialStateComputer(std::shared_ptr materialLawManager, - const PhaseUsage& phaseUsage, - const Opm::Deck& deck, const Opm::EclipseState& eclipseState, const Grid& G , const double grav = unit::gravity, - const std::vector& swat_init = {} + const bool applySwatInit = true ) - : pp_(phaseUsage.num_phases, + : pp_(FluidSystem::numPhases, std::vector(UgGridHelpers::numCells(G))), - sat_(phaseUsage.num_phases, + sat_(FluidSystem::numPhases, std::vector(UgGridHelpers::numCells(G))), rs_(UgGridHelpers::numCells(G)), - rv_(UgGridHelpers::numCells(G)), - swat_init_(swat_init), - phaseUsage_(phaseUsage) - + rv_(UgGridHelpers::numCells(G)) { - typedef FluidSystems::BlackOil FluidSystem; - - // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); + //Check for presence of kw SWATINIT + if (eclipseState.get3DProperties().hasDeckDoubleGridProperty("SWATINIT") && applySwatInit) { + const std::vector& swat_init_ecl = eclipseState. + get3DProperties().getDoubleGridProperty("SWATINIT").getData(); + const int nc = UgGridHelpers::numCells(G); + swat_init_.resize(nc); + const int* gc = UgGridHelpers::globalCell(G); + for (int c = 0; c < nc; ++c) { + const int deck_pos = (gc == NULL) ? c : gc[c]; + swat_init_[c] = swat_init_ecl[deck_pos]; + } + } // Get the equilibration records. const std::vector rec = getEquil(eclipseState); const auto& tables = eclipseState.getTableManager(); // Create (inverse) region mapping. - const RegionMapping<> eqlmap(equilnum(deck, eclipseState, G)); + const RegionMapping<> eqlmap(equilnum(eclipseState, G)); setRegionPvtIdx(G, eclipseState, eqlmap); // Create Rs functions. rs_func_.reserve(rec.size()); - if (deck.hasKeyword("DISGAS")) { + if (FluidSystem::enableDissolvedGas()) { const TableContainer& rsvdTables = tables.getRsvdTables(); for (size_t i = 0; i < rec.size(); ++i) { if (eqlmap.cells(i).empty()) @@ -299,7 +301,7 @@ namespace Opm } rv_func_.reserve(rec.size()); - if (deck.hasKeyword("VAPOIL")) { + if (FluidSystem::enableVaporizedOil()) { const TableContainer& rvvdTables = tables.getRvvdTables(); for (size_t i = 0; i < rec.size(); ++i) { if (eqlmap.cells(i).empty()) @@ -338,7 +340,7 @@ namespace Opm } // Compute pressures, saturations, rs and rv factors. - calcPressSatRsRv(eqlmap, rec, materialLawManager, G, grav); + calcPressSatRsRv(eqlmap, rec, materialLawManager, G, grav); // Modify oil pressure in no-oil regions so that the pressures of present phases can // be recovered from the oil pressure and capillary relations. @@ -366,7 +368,6 @@ namespace Opm Vec rs_; Vec rv_; Vec swat_init_; - PhaseUsage phaseUsage_; template void setRegionPvtIdx(const Grid& G, const Opm::EclipseState& eclipseState, const RMap& reg) { @@ -381,7 +382,7 @@ namespace Opm } } - template + template void calcPressSatRsRv(const RMap& reg , const std::vector< EquilRecord >& rec , @@ -398,23 +399,24 @@ namespace Opm continue; } - const EqReg eqreg(rec[r], - rs_func_[r], rv_func_[r], regionPvtIdx_[r], - phaseUsage_); + const EqReg eqreg(rec[r], rs_func_[r], rv_func_[r], regionPvtIdx_[r]); PVec pressures = phasePressures(G, eqreg, cells, grav); const std::vector& temp = temperature(G, eqreg, cells); const PVec sat = phaseSaturations(G, eqreg, cells, materialLawManager, swat_init_, pressures); - const int np = phaseUsage_.num_phases; + const int np = FluidSystem::numPhases; for (int p = 0; p < np; ++p) { copyFromRegion(pressures[p], cells, pp_[p]); copyFromRegion(sat[p], cells, sat_[p]); } - if (phaseUsage_.phase_used[BlackoilPhases::Liquid] - && phaseUsage_.phase_used[BlackoilPhases::Vapour]) { - const int oilpos = phaseUsage_.phase_pos[BlackoilPhases::Liquid]; - const int gaspos = phaseUsage_.phase_pos[BlackoilPhases::Vapour]; + + const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); + const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); + + if (oil && gas) { + const int oilpos = FluidSystem::oilPhaseIdx; + const int gaspos = FluidSystem::gasPhaseIdx; const Vec rs_vals = computeRs(G, cells, pressures[oilpos], temp, *(rs_func_[r]), sat[gaspos]); const Vec rv_vals = computeRs(G, cells, pressures[gaspos], temp, *(rv_func_[r]), sat[oilpos]); copyFromRegion(rs_vals, cells, rs_); diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 42314faf0..a2435c47e 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -237,60 +237,6 @@ namespace Opm }; } // namespace PhasePressODE - namespace PhaseUsed { - inline bool - water(const PhaseUsage& pu) - { - return bool(pu.phase_used[ Opm::BlackoilPhases::Aqua ]); - } - - inline bool - oil(const PhaseUsage& pu) - { - return bool(pu.phase_used[ Opm::BlackoilPhases::Liquid ]); - } - - inline bool - gas(const PhaseUsage& pu) - { - return bool(pu.phase_used[ Opm::BlackoilPhases::Vapour ]); - } - } // namespace PhaseUsed - - namespace PhaseIndex { - inline int - water(const PhaseUsage& pu) - { - int i = -1; - if (PhaseUsed::water(pu)) { - i = pu.phase_pos[ Opm::BlackoilPhases::Aqua ]; - } - - return i; - } - - inline int - oil(const PhaseUsage& pu) - { - int i = -1; - if (PhaseUsed::oil(pu)) { - i = pu.phase_pos[ Opm::BlackoilPhases::Liquid ]; - } - - return i; - } - - inline int - gas(const PhaseUsage& pu) - { - int i = -1; - if (PhaseUsed::gas(pu)) { - i = pu.phase_pos[ Opm::BlackoilPhases::Vapour ]; - } - - return i; - } - } // namespace PhaseIndex namespace PhasePressure { template >& press) { - const PhaseUsage& pu = reg.phaseUsage(); + const bool water = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); + const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); + const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); + const int oilpos = FluidSystem::oilPhaseIdx; + const int waterpos = FluidSystem::waterPhaseIdx; + const int gaspos = FluidSystem::gasPhaseIdx; if (reg.datum() > reg.zwoc()) { // Datum in water zone double po_woc = -1; double po_goc = -1; - if (PhaseUsed::water(pu)) { - const int wix = PhaseIndex::water(pu); + if (water) { PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ wix ]); + cells, press[ waterpos ]); } - if (PhaseUsed::oil(pu)) { - const int oix = PhaseIndex::oil(pu); + if (oil) { PhasePressure::oil(G, reg, span, grav, cells, - press[ oix ], po_woc, po_goc); + press[ oilpos ], po_woc, po_goc); } - if (PhaseUsed::gas(pu)) { - const int gix = PhaseIndex::gas(pu); + if (gas) { PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gix ]); + cells, press[ gaspos ]); } } else if (reg.datum() < reg.zgoc()) { // Datum in gas zone double po_woc = -1; double po_goc = -1; - if (PhaseUsed::gas(pu)) { - const int gix = PhaseIndex::gas(pu); + if (gas) { PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gix ]); + cells, press[ gaspos ]); } - if (PhaseUsed::oil(pu)) { - const int oix = PhaseIndex::oil(pu); + if (oil) { PhasePressure::oil(G, reg, span, grav, cells, - press[ oix ], po_woc, po_goc); + press[ oilpos ], po_woc, po_goc); } - if (PhaseUsed::water(pu)) { - const int wix = PhaseIndex::water(pu); + if (water) { PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ wix ]); + cells, press[ waterpos ]); } } else { // Datum in oil zone double po_woc = -1; double po_goc = -1; - if (PhaseUsed::oil(pu)) { - const int oix = PhaseIndex::oil(pu); + if (oil) { PhasePressure::oil(G, reg, span, grav, cells, - press[ oix ], po_woc, po_goc); + press[ oilpos ], po_woc, po_goc); } - if (PhaseUsed::water(pu)) { - const int wix = PhaseIndex::water(pu); + if (water) { PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ wix ]); + cells, press[ waterpos ]); } - if (PhaseUsed::gas(pu)) { - const int gix = PhaseIndex::gas(pu); + if (gas) { PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gix ]); + cells, press[ gaspos ]); } } } @@ -621,7 +563,7 @@ namespace Opm } } } - const int np = reg.phaseUsage().num_phases; + const int np = FluidSystem::numPhases; //reg.phaseUsage().num_phases; typedef std::vector pval; std::vector press(np, pval(ncell, 0.0)); @@ -659,7 +601,7 @@ namespace Opm const std::vector swat_init, std::vector< std::vector >& phase_pressures) { - if (!reg.phaseUsage().phase_used[BlackoilPhases::Liquid]) { + if (!FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) { OPM_THROW(std::runtime_error, "Cannot initialise: not handling water-gas cases."); } @@ -682,11 +624,11 @@ namespace Opm SatOnlyFluidState fluidState; typedef typename MaterialLawManager::MaterialLaw MaterialLaw; - const bool water = reg.phaseUsage().phase_used[BlackoilPhases::Aqua]; - const bool gas = reg.phaseUsage().phase_used[BlackoilPhases::Vapour]; - const int oilpos = reg.phaseUsage().phase_pos[BlackoilPhases::Liquid]; - const int waterpos = reg.phaseUsage().phase_pos[BlackoilPhases::Aqua]; - const int gaspos = reg.phaseUsage().phase_pos[BlackoilPhases::Vapour]; + const bool water = FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx); + const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); + const int oilpos = FluidSystem::oilPhaseIdx; + const int waterpos = FluidSystem::waterPhaseIdx; + const int gaspos = FluidSystem::gasPhaseIdx; std::vector::size_type local_index = 0; for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { const int cell = *ci; @@ -769,7 +711,7 @@ namespace Opm double threshold_sat = 1.0e-6; double so = 1.0; - double pC[/*numPhases=*/BlackoilPhases::MaxNumPhases] = { 0.0, 0.0, 0.0 }; + double pC[FluidSystem::numPhases] = { 0.0, 0.0, 0.0 }; if (water) { double swu = scaledDrainageInfo.Swu; @@ -850,94 +792,6 @@ namespace Opm } // namespace Equil - namespace Details - { - /// Convert saturations from a vector of individual phase saturation vectors - /// to an interleaved format where all values for a given cell come before all - /// values for the next cell, all in a single vector. - inline std::vector - convertSats(const std::vector< std::vector >& sat) - { - const auto np = sat.size(); - const auto nc = sat[0].size(); - - std::vector s(np * nc); - - for (decltype(sat.size()) p = 0; p < np; ++p) { - const auto& sat_p = sat[p]; - double* sp = & s[0*nc + p]; - - for (decltype(sat[0].size()) c = 0; - c < nc; ++c, sp += np) - { - *sp = sat_p[c]; - } - } - - return s; - } - } // namespace Details - - - /** - * Compute initial state by an equilibration procedure. - * - * The following state fields are modified: - * pressure(), - * saturation(), - * surfacevol(), - * gasoilratio(), - * rv(). - * - * \param[in] grid Grid. - * \param[in] props Property object, pvt and capillary properties are used. - * \param[in] deck Simulation deck, used to obtain EQUIL and related data. - * \param[in] gravity Acceleration of gravity, assumed to be in Z direction. - * \param[in] applySwatInit Make it possible to not apply SWATINIT even if it - * is present in the deck - */ - template - void initStateEquil(const Grid& grid, - std::shared_ptr materialLawManager, - const Opm::Deck& deck, - const Opm::EclipseState& eclipseState, - const double gravity, - BlackoilState& state, - bool applySwatinit = true) - { - - typedef EQUIL::DeckDependent::InitialStateComputer ISC; - - PhaseUsage pu = phaseUsageFromDeck(deck); - - //Check for presence of kw SWATINIT - std::vector swat_init = {}; - if (eclipseState.get3DProperties().hasDeckDoubleGridProperty("SWATINIT") && applySwatinit) { - const std::vector& swat_init_ecl = eclipseState. - get3DProperties().getDoubleGridProperty("SWATINIT").getData(); - const int nc = UgGridHelpers::numCells(grid); - swat_init.resize(nc); - const int* gc = UgGridHelpers::globalCell(grid); - for (int c = 0; c < nc; ++c) { - const int deck_pos = (gc == NULL) ? c : gc[c]; - swat_init[c] = swat_init_ecl[deck_pos]; - } - } - - ISC isc(materialLawManager, pu, deck, eclipseState, grid, gravity, swat_init); - const int ref_phase = pu.phase_used[BlackoilPhases::Liquid] - ? pu.phase_pos[BlackoilPhases::Liquid] - : pu.phase_pos[BlackoilPhases::Aqua]; - state.pressure() = isc.press()[ref_phase]; - state.saturation() = Details::convertSats(isc.saturation()); - state.gasoilratio() = isc.rs(); - state.rv() = isc.rv(); - - //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); - } - - - } // namespace Opm #endif // OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index c5a6069a3..0ce421404 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -23,13 +23,11 @@ #include #include #include +#include - -#include -#include -#include #include #include +#include #include @@ -42,7 +40,6 @@ #include -#include #include #include @@ -55,11 +52,12 @@ #include +typedef Opm::FluidSystems::BlackOil FluidSystem; // Forward declaring the MaterialLawManager template. typedef Opm::ThreePhaseMaterialTraits MaterialTraits; +/*wettingPhaseIdx=*/FluidSystem::waterPhaseIdx, +/*nonWettingPhaseIdx=*/FluidSystem::oilPhaseIdx, +/*gasPhaseIdx=*/FluidSystem::gasPhaseIdx> MaterialTraits; typedef Opm::EclMaterialLawManager MaterialLawManager; @@ -71,8 +69,8 @@ typedef Opm::EclMaterialLawManager MaterialLawManager; BOOST_CHECK_CLOSE((value), (expected), (reltol)); \ } -typedef Opm::FluidSystems::BlackOil FluidSystem; -Opm::PhaseUsage initDefaultFluidSystem() { + +void initDefaultFluidSystem() { std::vector > Bo = { { 101353, 1. }, { 6.21542e+07, 1 } @@ -139,17 +137,6 @@ Opm::PhaseUsage initDefaultFluidSystem() { FluidSystem::initEnd(); - Opm::PhaseUsage pu; - pu.num_phases = 2; - // Might just as well assume water-oil. - pu.phase_used[Opm::BlackoilPhases::Aqua] = true; - pu.phase_used[Opm::BlackoilPhases::Liquid] = true; - pu.phase_used[Opm::BlackoilPhases::Vapour] = false; - pu.phase_pos[Opm::BlackoilPhases::Aqua] = 0; - pu.phase_pos[Opm::BlackoilPhases::Liquid] = 1; - pu.phase_pos[Opm::BlackoilPhases::Vapour] = 1; // Unused. - return pu; - } BOOST_AUTO_TEST_SUITE () @@ -220,14 +207,13 @@ BOOST_AUTO_TEST_CASE (PhasePressure) auto record = mkEquilRecord( 0, 1e5, 5, 0, 0, 0 ); - Opm::PhaseUsage pu = initDefaultFluidSystem(); + initDefaultFluidSystem(); Opm::EQUIL::EquilReg region(record, std::make_shared(), std::make_shared(), - 0, - pu); + 0); std::vector cells(G->number_of_cells); std::iota(cells.begin(), cells.end(), 0); @@ -251,8 +237,7 @@ BOOST_AUTO_TEST_CASE (CellSubset) std::shared_ptr G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::PhaseUsage pu = initDefaultFluidSystem(); - + initDefaultFluidSystem(); Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; @@ -262,26 +247,22 @@ BOOST_AUTO_TEST_CASE (CellSubset) Opm::EQUIL::EquilReg(record[0], std::make_shared(), std::make_shared(), - 0, - pu) + 0) , Opm::EQUIL::EquilReg(record[0], std::make_shared(), std::make_shared(), - 0, - pu) + 0) , Opm::EQUIL::EquilReg(record[1], std::make_shared(), std::make_shared(), - 0, - pu) + 0) , Opm::EQUIL::EquilReg(record[1], std::make_shared(), std::make_shared(), - 0, - pu) + 0) }; const int cdim[] = { 2, 1, 2 }; @@ -348,33 +329,29 @@ BOOST_AUTO_TEST_CASE (RegMapping) Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - Opm::PhaseUsage pu = initDefaultFluidSystem(); + initDefaultFluidSystem(); Opm::EQUIL::EquilReg region[] = { Opm::EQUIL::EquilReg(record[0], std::make_shared(), std::make_shared(), - 0, - pu) + 0) , Opm::EQUIL::EquilReg(record[0], std::make_shared(), std::make_shared(), - 0, - pu) + 0) , Opm::EQUIL::EquilReg(record[1], std::make_shared(), std::make_shared(), - 0, - pu) + 0) , Opm::EQUIL::EquilReg(record[1], std::make_shared(), std::make_shared(), - 0, - pu) + 0) }; std::vector eqlnum(G->number_of_cells); @@ -436,9 +413,12 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) auto materialLawManager = std::make_shared(); materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + typedef Opm::FluidSystems::BlackOil FluidSystem; - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, *grid, 10.0); + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, *grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); @@ -538,9 +518,13 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) auto materialLawManager = std::make_shared(); materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + typedef Opm::FluidSystems::BlackOil FluidSystem; + + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 10.0); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 10.0); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -585,9 +569,13 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) auto materialLawManager = std::make_shared(); materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + typedef Opm::FluidSystems::BlackOil FluidSystem; - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -654,9 +642,11 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) auto materialLawManager = std::make_shared(); materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + typedef Opm::FluidSystems::BlackOil FluidSystem; - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -740,9 +730,12 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) auto materialLawManager = std::make_shared(); materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + typedef Opm::FluidSystems::BlackOil FluidSystem; - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -828,9 +821,12 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) auto materialLawManager = std::make_shared(); materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::PhaseUsage pu = phaseUsageFromDeck(deck); + typedef Opm::FluidSystems::BlackOil FluidSystem; - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, pu, deck, eclipseState, grid, 9.80665); + // Initialize the fluid system + FluidSystem::initFromDeck(deck, eclipseState); + + Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); const auto& pressures = comp.press(); BOOST_REQUIRE(pressures.size() == 3); BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); @@ -940,8 +936,6 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) auto materialLawManagerScaled = std::make_shared(); materialLawManagerScaled->initFromDeck(deck, eclipseState, compressedToCartesianIdx); - Opm::BlackoilState state( Opm::UgGridHelpers::numCells( grid ) , Opm::UgGridHelpers::numFaces( grid ) , 3); - // reference saturations const std::vector s[3]{ { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.42528761746004229, 0.77462669821009045, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, @@ -955,18 +949,6 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) { 0, 0, 0, 0.014813991154779993, 0.78525420807446045, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.78518600884522005, 0.014745791925539575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - std::vector sats = state.saturation(); - for (int phase = 0; phase < 3; ++phase) { - for (size_t i = 0; i < 20; ++i) { - sats[3*i + phase] = s[phase][i]; - } - } - std::vector sats_swatinit = state.saturation(); - for (int phase = 0; phase < 3; ++phase) { - for (size_t i = 0; i < 20; ++i) { - sats_swatinit[3*i + phase] = swatinit[phase][i]; - } - } // Adjust oil pressure according to gas saturation and cap pressure typedef Opm::SimpleModularFluidState pc_original = state.saturation(); const int numCells = Opm::UgGridHelpers::numCells(grid); + std::vector pc_original(numCells * FluidSystem::numPhases); for (int c = 0; c < numCells; ++c) { std::vector pc = {0,0,0}; - double sw = sats[3*c + 0]; - double so = sats[3*c + 1]; - double sg = sats[3*c + 2]; + double sw = s[0][c]; + double so = s[1][c]; + double sg = s[2][c]; fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); @@ -1024,22 +1006,18 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) pc_scaled_truth[3*11 + 0] = 5364.1; // compute the initial state - // apply swatinit - Opm::BlackoilState state_scaled = state; - initStateEquil(grid, materialLawManagerScaled, deck, eclipseState, 9.81, state_scaled, true); - + Opm::EQUIL::DeckDependent::InitialStateComputer compScaled(materialLawManagerScaled, eclipseState, grid, 9.81, true); // don't apply swatinit - Opm::BlackoilState state_unscaled = state; - initStateEquil(grid, materialLawManager, deck, eclipseState, 9.81, state_unscaled, false); + Opm::EQUIL::DeckDependent::InitialStateComputer compUnscaled(materialLawManager, eclipseState, grid, 9.81, false); // compute pc - std::vector pc_scaled= state.saturation(); + std::vector pc_scaled(numCells * FluidSystem::numPhases); for (int c = 0; c < numCells; ++c) { std::vector pc = {0,0,0}; - double sw = state_scaled.saturation().data()[3*c + 0]; - double so = state_scaled.saturation().data()[3*c + 1]; - double sg = state_scaled.saturation().data()[3*c + 2]; + double sw = compScaled.saturation().data()[0][c]; + double so = compScaled.saturation().data()[1][c]; + double sg = compScaled.saturation().data()[2][c]; fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); @@ -1050,12 +1028,12 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) pc_scaled[3*c + 1] = 0.0; pc_scaled[3*c + 2] = pc[FluidSystem::oilPhaseIdx] + pc[FluidSystem::gasPhaseIdx]; } - std::vector pc_unscaled= state.saturation(); + std::vector pc_unscaled(numCells * FluidSystem::numPhases); for (int c = 0; c < numCells; ++c) { std::vector pc = {0,0,0}; - double sw = state_unscaled.saturation().data()[3*c + 0]; - double so = state_unscaled.saturation().data()[3*c + 1]; - double sg = state_unscaled.saturation().data()[3*c + 2]; + double sw = compUnscaled.saturation().data()[0][c]; + double so = compUnscaled.saturation().data()[1][c]; + double sg = compUnscaled.saturation().data()[2][c]; fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); @@ -1079,8 +1057,8 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) for (int phase = 0; phase < 3; ++phase) { for (size_t i = 0; i < 20; ++i) { - CHECK(state_unscaled.saturation()[3*i + phase], s[phase][i], reltol); - CHECK(state_scaled.saturation()[3*i + phase], swatinit[phase][i], reltol); + CHECK(compUnscaled.saturation()[phase][i], s[phase][i], reltol); + CHECK(compScaled.saturation()[phase][i], swatinit[phase][i], reltol); } } } From 9389aecc26ba97dc0cfa96c2fa8d8b5a272d9c99 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 21 Nov 2017 12:07:59 +0100 Subject: [PATCH 149/158] Use &ref not shared_pointer to MaterialLawManager --- examples/compute_initial_state.cpp | 4 +- opm/core/simulator/EquilibrationHelpers.hpp | 28 +++++++------- opm/core/simulator/initStateEquil.hpp | 6 +-- opm/core/simulator/initStateEquil_impl.hpp | 10 ++--- tests/test_equil.cpp | 42 ++++++++++----------- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 05f22e590..c8e17442d 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -148,8 +148,8 @@ try /*gasPhaseIdx=*/Opm::BlackoilPhases::Vapour> MaterialTraits; typedef Opm::EclMaterialLawManager MaterialLawManager; - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); // Initialisation. //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index eff050102..8044dafbe 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -568,7 +568,7 @@ namespace Opm template struct PcEq { - PcEq(std::shared_ptr materialLawManager, + PcEq(const MaterialLawManager& materialLawManager, const int phase, const int cell, const double target_pc) @@ -587,7 +587,7 @@ namespace Opm double operator()(double s) const { - const auto& matParams = materialLawManager_->materialLawParams(cell_); + const auto& matParams = materialLawManager_.materialLawParams(cell_); fluidState_.setSaturation(phase_, s); MaterialLaw::capillaryPressures(pc_, matParams, fluidState_); double sign = (phase_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; @@ -596,7 +596,7 @@ namespace Opm } private: - std::shared_ptr materialLawManager_; + const MaterialLawManager& materialLawManager_; const int phase_; const int cell_; const double target_pc_; @@ -605,9 +605,9 @@ namespace Opm }; template - double minSaturations(std::shared_ptr materialLawManager, const int phase, const int cell) { + double minSaturations(const MaterialLawManager& materialLawManager, const int phase, const int cell) { const auto& scaledDrainageInfo = - materialLawManager->oilWaterScaledEpsInfoDrainage(cell); + materialLawManager.oilWaterScaledEpsInfoDrainage(cell); // Find minimum and maximum saturations. switch(phase) { @@ -632,9 +632,9 @@ namespace Opm } template - double maxSaturations(std::shared_ptr materialLawManager, const int phase, const int cell) { + double maxSaturations(const MaterialLawManager& materialLawManager, const int phase, const int cell) { const auto& scaledDrainageInfo = - materialLawManager->oilWaterScaledEpsInfoDrainage(cell); + materialLawManager.oilWaterScaledEpsInfoDrainage(cell); // Find minimum and maximum saturations. switch(phase) { @@ -664,7 +664,7 @@ namespace Opm /// Compute saturation of some phase corresponding to a given /// capillary pressure. template - inline double satFromPc(std::shared_ptr materialLawManager, + inline double satFromPc(const MaterialLawManager& materialLawManager, const int phase, const int cell, const double target_pc, @@ -700,7 +700,7 @@ namespace Opm template struct PcEqSum { - PcEqSum(std::shared_ptr materialLawManager, + PcEqSum(const MaterialLawManager& materialLawManager, const int phase1, const int phase2, const int cell, @@ -718,7 +718,7 @@ namespace Opm } double operator()(double s) const { - const auto& matParams = materialLawManager_->materialLawParams(cell_); + const auto& matParams = materialLawManager_.materialLawParams(cell_); fluidState_.setSaturation(phase1_, s); fluidState_.setSaturation(phase2_, 1.0 - s); @@ -731,7 +731,7 @@ namespace Opm return pc1 + pc2 - target_pc_; } private: - std::shared_ptr materialLawManager_; + const MaterialLawManager& materialLawManager_; const int phase1_; const int phase2_; const int cell_; @@ -748,7 +748,7 @@ namespace Opm /// is given as a sum of two other functions. template - inline double satFromSumOfPcs(std::shared_ptr materialLawManager, + inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager, const int phase1, const int phase2, const int cell, @@ -778,7 +778,7 @@ namespace Opm /// Compute saturation from depth. Used for constant capillary pressure function template - inline double satFromDepth(std::shared_ptr materialLawManager, + inline double satFromDepth(const MaterialLawManager& materialLawManager, const double cellDepth, const double contactDepth, const int phase, @@ -798,7 +798,7 @@ namespace Opm /// Return true if capillary pressure function is constant template - inline bool isConstPc(std::shared_ptr materialLawManager, + inline bool isConstPc(const MaterialLawManager& materialLawManager, const int phase, const int cell) { diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index d3f1110d4..6d3e07115 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -147,7 +147,7 @@ namespace Opm phaseSaturations(const Grid& grid, const Region& reg, const CellRange& cells, - std::shared_ptr materialLawManager, + MaterialLawManager& materialLawManager, const std::vector swat_init, std::vector< std::vector >& phase_pressures); @@ -226,7 +226,7 @@ namespace Opm class InitialStateComputer { public: template - InitialStateComputer(std::shared_ptr materialLawManager, + InitialStateComputer(MaterialLawManager& materialLawManager, const Opm::EclipseState& eclipseState, const Grid& G , const double grav = unit::gravity, @@ -386,7 +386,7 @@ namespace Opm void calcPressSatRsRv(const RMap& reg , const std::vector< EquilRecord >& rec , - std::shared_ptr materialLawManager, + MaterialLawManager& materialLawManager, const Grid& G , const double grav) { diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index a2435c47e..be796e70d 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -597,7 +597,7 @@ namespace Opm phaseSaturations(const Grid& G, const Region& reg, const CellRange& cells, - std::shared_ptr materialLawManager, + MaterialLawManager& materialLawManager, const std::vector swat_init, std::vector< std::vector >& phase_pressures) { @@ -633,8 +633,8 @@ namespace Opm for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { const int cell = *ci; const auto& scaledDrainageInfo = - materialLawManager->oilWaterScaledEpsInfoDrainage(cell); - const auto& matParams = materialLawManager->materialLawParams(cell); + materialLawManager.oilWaterScaledEpsInfoDrainage(cell); + const auto& matParams = materialLawManager.materialLawParams(cell); // Find saturations from pressure differences by // inverting capillary pressure functions. @@ -653,7 +653,7 @@ namespace Opm phase_saturations[waterpos][local_index] = sw; } else { // Scale Pc to reflect imposed sw sw = swat_init[cell]; - sw = materialLawManager->applySwatinit(cell, pcov, sw); + sw = materialLawManager.applySwatinit(cell, pcov, sw); phase_saturations[waterpos][local_index] = sw; } } @@ -684,7 +684,7 @@ namespace Opm // Re-scale Pc to reflect imposed sw for vanishing oil phase. // This seems consistent with ecl, and fails to honour // swat_init in case of non-trivial gas-oil cap pressure. - sw = materialLawManager->applySwatinit(cell, pcgw, sw); + sw = materialLawManager.applySwatinit(cell, pcgw, sw); } sw = satFromSumOfPcs(materialLawManager, waterpos, gaspos, cell, pcgw); sg = 1.0 - sw; diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 0ce421404..e0d1be864 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -410,8 +410,8 @@ BOOST_AUTO_TEST_CASE (DeckAllDead) std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid->number_of_cells, grid->global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; @@ -449,8 +449,8 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; typedef MaterialLawManager::MaterialLaw MaterialLaw; @@ -515,8 +515,8 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; @@ -566,8 +566,8 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; @@ -639,8 +639,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; @@ -727,8 +727,8 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; @@ -818,8 +818,8 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); typedef Opm::FluidSystems::BlackOil FluidSystem; @@ -930,11 +930,11 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - auto materialLawManager = std::make_shared(); - materialLawManager->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManager = MaterialLawManager(); + materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - auto materialLawManagerScaled = std::make_shared(); - materialLawManagerScaled->initFromDeck(deck, eclipseState, compressedToCartesianIdx); + MaterialLawManager materialLawManagerScaled = MaterialLawManager(); + materialLawManagerScaled.initFromDeck(deck, eclipseState, compressedToCartesianIdx); // reference saturations const std::vector s[3]{ @@ -981,7 +981,7 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); - const auto& matParams = materialLawManager->materialLawParams(c); + const auto& matParams = materialLawManager.materialLawParams(c); MaterialLaw::capillaryPressures(pc, matParams, fluidState); pc_original[3*c + 0] = pc[FluidSystem::oilPhaseIdx] - pc[FluidSystem::waterPhaseIdx]; pc_original[3*c + 1] = 0.0; @@ -1022,7 +1022,7 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); - const auto& matParams = materialLawManagerScaled->materialLawParams(c); + const auto& matParams = materialLawManagerScaled.materialLawParams(c); MaterialLaw::capillaryPressures(pc, matParams, fluidState); pc_scaled[3*c + 0] = pc[FluidSystem::oilPhaseIdx] - pc[FluidSystem::waterPhaseIdx]; pc_scaled[3*c + 1] = 0.0; @@ -1039,7 +1039,7 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); - const auto& matParams = materialLawManager->materialLawParams(c); + const auto& matParams = materialLawManager.materialLawParams(c); MaterialLaw::capillaryPressures(pc, matParams, fluidState); pc_unscaled[3*c + 0] = pc[FluidSystem::oilPhaseIdx] - pc[FluidSystem::waterPhaseIdx]; pc_unscaled[3*c + 1] = 0.0; From 44c7fb8816938fa96d8b0fedd569cb4394162a21 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 21 Nov 2017 12:27:09 +0100 Subject: [PATCH 150/158] Cleaning the initialization code -remove whitespaces -fix documentation --- examples/compute_initial_state.cpp | 38 +++------- opm/core/simulator/EquilibrationHelpers.hpp | 51 ++++--------- opm/core/simulator/initStateEquil.hpp | 27 ++++--- opm/core/simulator/initStateEquil_impl.hpp | 80 ++++++++++----------- tests/test_equil.cpp | 8 +-- 5 files changed, 76 insertions(+), 128 deletions(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index c8e17442d..33c6f4a4a 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -1,5 +1,6 @@ /* Copyright 2014 SINTEF ICT, Applied Mathematics. + Copyright 2017 IRIS This file is part of the Open Porous Media project (OPM). @@ -27,20 +28,17 @@ #include #include #include -#include #include #include #include #include - #include #include #include #include - #include #include @@ -105,17 +103,8 @@ namespace } } - - } // anon namespace - - - - - - - // ----------------- Main program ----------------- int main(int argc, char** argv) @@ -134,18 +123,19 @@ try const double grav = param.getDefault("gravity", unit::gravity); GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *gm.c_grid(); - BlackoilPropertiesFromDeck props(deck, eclipseState, grid, param); warnIfUnusedParams(param); // Create material law manager. std::vector compressedToCartesianIdx = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); + typedef FluidSystems::BlackOil FluidSystem; + // Forward declaring the MaterialLawManager template. typedef Opm::ThreePhaseMaterialTraits MaterialTraits; + /*wettingPhaseIdx=*/FluidSystem::waterPhaseIdx, + /*nonWettingPhaseIdx=*/FluidSystem::oilPhaseIdx, + /*gasPhaseIdx=*/FluidSystem::gasPhaseIdx> MaterialTraits; typedef Opm::EclMaterialLawManager MaterialLawManager; MaterialLawManager materialLawManager = MaterialLawManager(); @@ -154,7 +144,6 @@ try // Initialisation. //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); BlackoilState state( UgGridHelpers::numCells(grid) , UgGridHelpers::numFaces(grid), 3); - typedef FluidSystems::BlackOil FluidSystem; FluidSystem::initFromDeck(deck, eclipseState); PhaseUsage pu = phaseUsageFromDeck(deck); @@ -169,17 +158,8 @@ try state.pressure() = isc.press()[ref_phase]; convertSats(state.saturation(), isc.saturation(), pu); - - if (state.hasCellData(std::string("GASOILRATIO"))) { - std::vector& rs = state.getCellData(std::string("GASOILRATIO")); - rs = isc.rs(); - } - if (state.hasCellData(std::string("RV"))){ - std::vector& rv = state.getCellData(std::string("RV")); - rv = isc.rv(); - } - - + state.gasoilratio() = isc.rs(); + state.rv() = isc.rv(); // Output. const std::string output_dir = param.getDefault("output_dir", "output"); @@ -192,5 +172,3 @@ catch (const std::exception& e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; throw; } - - diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index 8044dafbe..cf1b58c30 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -41,36 +41,33 @@ namespace Opm { namespace EQUIL { - template - class DensityCalculator; - - template <> - class DensityCalculator< BlackoilPropertiesInterface >; - namespace Miscibility { class RsFunction; class NoMixing; + template class RsVD; + template class RsSatAtContact; } - template class EquilReg; + template struct PcEq; - inline double satFromPc(const BlackoilPropertiesInterface& props, + template + inline double satFromPc(const MaterialLawManager& materialLawManager, const int phase, const int cell, const double target_pc, - const bool increasing = false); - struct PcEqSum - inline double satFromSumOfPcs(const BlackoilPropertiesInterface& props, + const bool increasing = false) + template + inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager, const int phase1, const int phase2, const int cell, - const double target_pc); + const double target_pc) } // namespace Equil } // namespace Opm @@ -183,8 +180,7 @@ namespace Opm /** * Constructor. * - * \param[in] props property object - * \param[in] cell any cell in the pvt region + * \param[in] pvtRegionIdx The pvt region index * \param[in] depth Depth nodes. * \param[in] rs Dissolved gas-oil ratio at @c depth. */ @@ -195,7 +191,6 @@ namespace Opm , depth_(depth) , rs_(rs) { - } /** @@ -249,8 +244,7 @@ namespace Opm /** * Constructor. * - * \param[in] props property object - * \param[in] cell any cell in the pvt region + * \param[in] pvtRegionIdx The pvt region index * \param[in] depth Depth nodes. * \param[in] rv Dissolved gas-oil ratio at @c depth. */ @@ -261,7 +255,6 @@ namespace Opm , depth_(depth) , rv_(rv) { - } /** @@ -324,8 +317,7 @@ namespace Opm /** * Constructor. * - * \param[in] props property object - * \param[in] cell any cell in the pvt region + * \param[in] pvtRegionIdx The pvt region index * \param[in] p_contact oil pressure at the contact * \param[in] T_contact temperature at the contact */ @@ -394,8 +386,7 @@ namespace Opm /** * Constructor. * - * \param[in] props property object - * \param[in] cell any cell in the pvt region + * \param[in] pvtRegionIdx The pvt region index * \param[in] p_contact oil pressure at the contact * \param[in] T_contact temperature at the contact */ @@ -470,10 +461,9 @@ namespace Opm * Constructor. * * \param[in] rec Equilibration data of current region. - * \param[in] density Density calculator of current region. * \param[in] rs Calculator of dissolved gas-oil ratio. * \param[in] rv Calculator of vapourised oil-gas ratio. - * \param[in] pu Summary of current active phases. + * \param[in] pvtRegionIdx The pvt region index */ EquilReg(const EquilRecord& rec, std::shared_ptr rs, @@ -483,7 +473,6 @@ namespace Opm , rs_ (rs) , rv_ (rv) , pvtIdx_ (pvtIdx) - { } @@ -547,7 +536,7 @@ namespace Opm evaporationCalculator() const { return *this->rv_; } /** - * Retrieve active fluid phase summary. + * Retrieve pvtIdx of the region. */ const int pvtIdx() const { return this->pvtIdx_; } @@ -581,10 +570,7 @@ namespace Opm fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); std::fill(pc_, pc_ + FluidSystem::numPhases, 0.0); - } - - double operator()(double s) const { const auto& matParams = materialLawManager_.materialLawParams(cell_); @@ -595,7 +581,6 @@ namespace Opm return pc - target_pc_; } private: - const MaterialLawManager& materialLawManager_; const int phase_; const int cell_; @@ -656,11 +641,9 @@ namespace Opm default: OPM_THROW(std::runtime_error, "Unknown phaseIdx ."); } return -1.0; - } - /// Compute saturation of some phase corresponding to a given /// capillary pressure. template @@ -727,7 +710,6 @@ namespace Opm double pc1 = pc_[FluidSystem::oilPhaseIdx] + sign1 * pc_[phase1_]; double sign2 = (phase2_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; double pc2 = pc_[FluidSystem::oilPhaseIdx] + sign2 * pc_[phase2_]; - return pc1 + pc2 - target_pc_; } private: @@ -746,7 +728,6 @@ namespace Opm /// Compute saturation of some phase corresponding to a given /// capillary pressure, where the capillary pressure function /// is given as a sum of two other functions. - template inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager, const int phase1, @@ -809,8 +790,6 @@ namespace Opm return std::abs(f0 - f1) < std::numeric_limits::epsilon(); } - - } // namespace Equil } // namespace Opm diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index 6d3e07115..e379dad85 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -2,6 +2,7 @@ Copyright 2014 SINTEF ICT, Applied Mathematics. Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services Copyright 2015 NTNU + Copyright 2017 IRIS This file is part of the Open Porous Media project (OPM). @@ -39,12 +40,10 @@ #include #include - #include #include #include - #include #include #include @@ -70,7 +69,6 @@ namespace Opm */ namespace EQUIL { - /** * Compute initial phase pressures by means of equilibration. * @@ -121,6 +119,11 @@ namespace Opm /** * Compute initial phase saturations by means of equilibration. * + * \tparam FluidSystem The FluidSystem from opm-material + * Must be initialized before used. + * + * \tparam Grid Type of the grid + * * \tparam Region Type of an equilibration region information * base. Typically an instance of the EquilReg * class template. @@ -132,10 +135,15 @@ namespace Opm * as well as provide an inner type, * const_iterator, to traverse the range. * + * \tparam MaterialLawManager The MaterialLawManager from opm-material + * + * \param[in] G Grid. * \param[in] reg Current equilibration region. * \param[in] cells Range that spans the cells of the current * equilibration region. - * \param[in] props Property object, needed for capillary functions. + * \param[in] materialLawManager The MaterialLawManager from opm-material + * \param[in] swat_init A vector of initial water saturations. + * The capillary pressure is scaled to fit these values * \param[in] phase_pressures Phase pressures, one vector for each active phase, * of pressure values in each cell in the current * equilibration region. @@ -201,7 +209,6 @@ namespace Opm const Grid& G ) { std::vector eqlnum; - if (eclipseState.get3DProperties().hasDeckIntGridProperty("EQLNUM")) { const int nc = UgGridHelpers::numCells(G); eqlnum.resize(nc); @@ -239,7 +246,6 @@ namespace Opm rs_(UgGridHelpers::numCells(G)), rv_(UgGridHelpers::numCells(G)) { - //Check for presence of kw SWATINIT if (eclipseState.get3DProperties().hasDeckDoubleGridProperty("SWATINIT") && applySwatInit) { const std::vector& swat_init_ecl = eclipseState. @@ -252,13 +258,11 @@ namespace Opm swat_init_[c] = swat_init_ecl[deck_pos]; } } - // Get the equilibration records. const std::vector rec = getEquil(eclipseState); const auto& tables = eclipseState.getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(eclipseState, G)); - setRegionPvtIdx(G, eclipseState, eqlmap); // Create Rs functions. @@ -272,7 +276,6 @@ namespace Opm continue; } const int pvtIdx = regionPvtIdx_[i]; - if (!rec[i].liveOilInitConstantRs()) { if (rsvdTables.size() <= 0 ) { OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table not available."); @@ -355,14 +358,10 @@ namespace Opm const Vec& rv() const { return rv_; } private: - typedef EquilReg EqReg; - std::vector< std::shared_ptr > rs_func_; std::vector< std::shared_ptr > rv_func_; - std::vector regionPvtIdx_; - PVec pp_; PVec sat_; Vec rs_; @@ -410,10 +409,8 @@ namespace Opm copyFromRegion(pressures[p], cells, pp_[p]); copyFromRegion(sat[p], cells, sat_[p]); } - const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); - if (oil && gas) { const int oilpos = FluidSystem::oilPhaseIdx; const int gaspos = FluidSystem::gasPhaseIdx; diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index be796e70d..761499ba6 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -2,6 +2,7 @@ Copyright 2014 SINTEF ICT, Applied Mathematics. Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services Copyright 2015 NTNU + Copyright 2017 IRIS This file is part of the Open Porous Media project (OPM). @@ -35,9 +36,6 @@ namespace Opm { namespace Details { - - - template class RK4IVP { public: @@ -108,8 +106,8 @@ namespace Opm stepsize() const { return (span_[1] - span_[0]) / N_; } }; - namespace PhasePressODE { - template + namespace PhasePressODE { + template class Water { public: Water(const double temp, @@ -317,7 +315,6 @@ namespace Opm class Grid, class Region, class CellRange> - void oil(const Grid& G , const Region& reg , @@ -332,7 +329,6 @@ namespace Opm typedef Oil ODE; const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, reg.dissolutionCalculator(), reg.pvtIdx(), grav); @@ -690,7 +686,6 @@ namespace Opm sg = 1.0 - sw; phase_saturations[waterpos][local_index] = sw; phase_saturations[gaspos][local_index] = sg; - if ( water ) { fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); } @@ -712,42 +707,41 @@ namespace Opm double so = 1.0; double pC[FluidSystem::numPhases] = { 0.0, 0.0, 0.0 }; + if (water) { + double swu = scaledDrainageInfo.Swu; + fluidState.setSaturation(FluidSystem::waterPhaseIdx, swu); + so -= swu; + } + if (gas) { + double sgu = scaledDrainageInfo.Sgu; + fluidState.setSaturation(FluidSystem::gasPhaseIdx, sgu); + so-= sgu; + } + fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); - if (water) { - double swu = scaledDrainageInfo.Swu; - fluidState.setSaturation(FluidSystem::waterPhaseIdx, swu); - so -= swu; - } - if (gas) { - double sgu = scaledDrainageInfo.Sgu; - fluidState.setSaturation(FluidSystem::gasPhaseIdx, sgu); - so-= sgu; - } - fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); - - if (water && sw > scaledDrainageInfo.Swu-threshold_sat ) { - fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swu); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; - phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pcWat; - } else if (gas && sg > scaledDrainageInfo.Sgu-threshold_sat) { - fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgu); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; - phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pcGas; - } - if (gas && sg < scaledDrainageInfo.Sgl+threshold_sat) { - fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgl); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; - phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pcGas; - } - if (water && sw < scaledDrainageInfo.Swl+threshold_sat) { - fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swl); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; - phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pcWat; - } + if (water && sw > scaledDrainageInfo.Swu-threshold_sat ) { + fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swu); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; + phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pcWat; + } else if (gas && sg > scaledDrainageInfo.Sgu-threshold_sat) { + fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgu); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; + phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pcGas; + } + if (gas && sg < scaledDrainageInfo.Sgl+threshold_sat) { + fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgl); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; + phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pcGas; + } + if (water && sw < scaledDrainageInfo.Swl+threshold_sat) { + fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swl); + MaterialLaw::capillaryPressures(pC, matParams, fluidState); + double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; + phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pcWat; + } } return phase_saturations; } diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index e0d1be864..3c40a2877 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -210,10 +210,10 @@ BOOST_AUTO_TEST_CASE (PhasePressure) initDefaultFluidSystem(); Opm::EQUIL::EquilReg - region(record, - std::make_shared(), - std::make_shared(), - 0); + region(record, + std::make_shared(), + std::make_shared(), + 0); std::vector cells(G->number_of_cells); std::iota(cells.begin(), cells.end(), 0); From 740ff891abc1c872cf157cd0d0484f9071ea7d87 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 21 Nov 2017 15:00:46 +0100 Subject: [PATCH 151/158] Remove the usage of partition_unif_idx() from opm-core --- tests/test_equil.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 3c40a2877..25a48bbc9 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -38,8 +38,6 @@ #include #include -#include - #include #include @@ -355,18 +353,26 @@ BOOST_AUTO_TEST_CASE (RegMapping) }; std::vector eqlnum(G->number_of_cells); + // [ 0 1; 2 3] { - std::vector cells(G->number_of_cells); - std::iota(cells.begin(), cells.end(), 0); - - const int cdim[] = { 2, 1, 2 }; - int ncoarse = cdim[0]; - for (std::size_t d = 1; d < 3; ++d) { ncoarse *= cdim[d]; } - - partition_unif_idx(G->dimensions, G->number_of_cells, - G->cartdims, cdim, - &cells[0], &eqlnum[0]); + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 5; ++j) { + eqlnum[i*10 + j] = 0; + } + for (int j = 5; j < 10; ++j) { + eqlnum[i*10 + j] = 1; + } + } + for (int i = 5; i < 10; ++i) { + for (int j = 0; j < 5; ++j) { + eqlnum[i*10 + j] = 2; + } + for (int j = 5; j < 10; ++j) { + eqlnum[i*10 + j] = 3; + } + } } + Opm::RegionMapping<> eqlmap(eqlnum); PPress ppress(2, PVal(G->number_of_cells, 0)); From 1e10d25c24acc34c9bebd5d89e7dd51c33661693 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 22 Nov 2017 08:31:57 +0100 Subject: [PATCH 152/158] Adress PR review issues --- opm/core/simulator/EquilibrationHelpers.hpp | 48 +++++++++++---------- tests/test_equil.cpp | 18 ++++---- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp index cf1b58c30..05e841db2 100644 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ b/opm/core/simulator/EquilibrationHelpers.hpp @@ -538,8 +538,7 @@ namespace Opm /** * Retrieve pvtIdx of the region. */ - const int - pvtIdx() const { return this->pvtIdx_; } + int pvtIdx() const { return this->pvtIdx_; } private: @@ -566,27 +565,29 @@ namespace Opm cell_(cell), target_pc_(target_pc) { - fluidState_.setSaturation(FluidSystem::waterPhaseIdx, 0.0); - fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); - fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); - std::fill(pc_, pc_ + FluidSystem::numPhases, 0.0); + } double operator()(double s) const { const auto& matParams = materialLawManager_.materialLawParams(cell_); - fluidState_.setSaturation(phase_, s); - MaterialLaw::capillaryPressures(pc_, matParams, fluidState_); + SatOnlyFluidState fluidState; + fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0); + fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0); + fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0); + fluidState.setSaturation(phase_, s); + + double pc[FluidSystem::numPhases]; + std::fill(pc, pc + FluidSystem::numPhases, 0.0); + MaterialLaw::capillaryPressures(pc, matParams, fluidState); double sign = (phase_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; - double pc = pc_[FluidSystem::oilPhaseIdx] + sign * pc_[phase_]; - return pc - target_pc_; + double pcPhase = pc[FluidSystem::oilPhaseIdx] + sign * pc[phase_]; + return pcPhase - target_pc_; } private: const MaterialLawManager& materialLawManager_; const int phase_; const int cell_; const double target_pc_; - mutable SatOnlyFluidState fluidState_; - mutable double pc_[FluidSystem::numPhases]; }; template @@ -694,22 +695,25 @@ namespace Opm cell_(cell), target_pc_(target_pc) { - fluidState_.setSaturation(FluidSystem::waterPhaseIdx, 0.0); - fluidState_.setSaturation(FluidSystem::oilPhaseIdx, 0.0); - fluidState_.setSaturation(FluidSystem::gasPhaseIdx, 0.0); - std::fill(pc_, pc_ + FluidSystem::numPhases, 0.0); } double operator()(double s) const { const auto& matParams = materialLawManager_.materialLawParams(cell_); - fluidState_.setSaturation(phase1_, s); - fluidState_.setSaturation(phase2_, 1.0 - s); + SatOnlyFluidState fluidState; + fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0); + fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0); + fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0); + fluidState.setSaturation(phase1_, s); + fluidState.setSaturation(phase2_, 1.0 - s); - MaterialLaw::capillaryPressures(pc_, matParams, fluidState_); + double pc[FluidSystem::numPhases]; + std::fill(pc, pc + FluidSystem::numPhases, 0.0); + + MaterialLaw::capillaryPressures(pc, matParams, fluidState); double sign1 = (phase1_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; - double pc1 = pc_[FluidSystem::oilPhaseIdx] + sign1 * pc_[phase1_]; + double pc1 = pc[FluidSystem::oilPhaseIdx] + sign1 * pc[phase1_]; double sign2 = (phase2_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; - double pc2 = pc_[FluidSystem::oilPhaseIdx] + sign2 * pc_[phase2_]; + double pc2 = pc[FluidSystem::oilPhaseIdx] + sign2 * pc[phase2_]; return pc1 + pc2 - target_pc_; } private: @@ -718,8 +722,6 @@ namespace Opm const int phase2_; const int cell_; const double target_pc_; - mutable SatOnlyFluidState fluidState_; - mutable double pc_[FluidSystem::numPhases]; }; diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 25a48bbc9..255608c3e 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -67,8 +67,9 @@ typedef Opm::EclMaterialLawManager MaterialLawManager; BOOST_CHECK_CLOSE((value), (expected), (reltol)); \ } - -void initDefaultFluidSystem() { +namespace +{ +static void initDefaultFluidSystem() { std::vector > Bo = { { 101353, 1. }, { 6.21542e+07, 1 } @@ -96,25 +97,25 @@ void initDefaultFluidSystem() { FluidSystem::setEnableVaporizedOil(false); FluidSystem::setReferenceDensities(rhoRefO, rhoRefW, rhoRefG, /*regionIdx=*/0); - Opm::GasPvtMultiplexer *gasPvt = new Opm::GasPvtMultiplexer; + auto gasPvt = std::make_shared>(); gasPvt->setApproach(Opm::GasPvtMultiplexer::DryGasPvt); - auto& dryGasPvt = gasPvt->template getRealPvt::DryGasPvt>(); + auto& dryGasPvt = gasPvt->getRealPvt::DryGasPvt>(); dryGasPvt.setNumRegions(/*numPvtRegion=*/1); dryGasPvt.setReferenceDensities(/*regionIdx=*/0, rhoRefO, rhoRefG, rhoRefW); dryGasPvt.setGasFormationVolumeFactor(/*regionIdx=*/0, Bg); dryGasPvt.setGasViscosity(/*regionIdx=*/0, mug); - Opm::OilPvtMultiplexer *oilPvt = new Opm::OilPvtMultiplexer; + auto oilPvt = std::make_shared>(); oilPvt->setApproach(Opm::OilPvtMultiplexer::DeadOilPvt); - auto& deadOilPvt = oilPvt->template getRealPvt::DeadOilPvt>(); + auto& deadOilPvt = oilPvt->getRealPvt::DeadOilPvt>(); deadOilPvt.setNumRegions(/*numPvtRegion=*/1); deadOilPvt.setReferenceDensities(/*regionIdx=*/0, rhoRefO, rhoRefG, rhoRefW); deadOilPvt.setInverseOilFormationVolumeFactor(/*regionIdx=*/0, Bo); deadOilPvt.setOilViscosity(/*regionIdx=*/0, muo); - Opm::WaterPvtMultiplexer *waterPvt = new Opm::WaterPvtMultiplexer; + auto waterPvt = std::make_shared>(); waterPvt->setApproach(Opm::WaterPvtMultiplexer::ConstantCompressibilityWaterPvt); - auto& ccWaterPvt = waterPvt->template getRealPvt::ConstantCompressibilityWaterPvt>(); + auto& ccWaterPvt = waterPvt->getRealPvt::ConstantCompressibilityWaterPvt>(); ccWaterPvt.setNumRegions(/*numPvtRegions=*/1); ccWaterPvt.setReferenceDensities(/*regionIdx=*/0, rhoRefO, rhoRefG, rhoRefW); ccWaterPvt.setViscosity(/*regionIdx=*/0, 1); @@ -136,6 +137,7 @@ void initDefaultFluidSystem() { FluidSystem::initEnd(); } +} BOOST_AUTO_TEST_SUITE () From da6c4bf0c4b9707ff37b73cfd2e283a0fcdb0ff6 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 22 Nov 2017 09:24:52 +0100 Subject: [PATCH 153/158] Fix 2p bug --- opm/core/simulator/initStateEquil_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp index 761499ba6..ef5d69962 100644 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ b/opm/core/simulator/initStateEquil_impl.hpp @@ -433,7 +433,7 @@ namespace Opm const CellRange& cells, std::vector< std::vector >& press) { - const bool water = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); + const bool water = FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx); const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); const int oilpos = FluidSystem::oilPhaseIdx; From 54e751fe70ae55cca3cd40febd9ce5bbb86652cd Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Fri, 24 Nov 2017 10:52:57 +0100 Subject: [PATCH 154/158] Adress PR review issues 2 --- tests/test_equil.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/tests/test_equil.cpp b/tests/test_equil.cpp index 255608c3e..5e33ae536 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cpp @@ -88,9 +88,9 @@ static void initDefaultFluidSystem() { { 6.21542e+07, 1 } }; - double rhoRefO = 700; // [kg] - double rhoRefG = 1000; // [kg] - double rhoRefW = 1000; // [kg] + double rhoRefO = 700; // [kg/m3] + double rhoRefG = 1000; // [kg/m3] + double rhoRefW = 1000; // [kg/m3] FluidSystem::initBegin(/*numPvtRegions=*/1); FluidSystem::setEnableDissolvedGas(false); @@ -125,17 +125,10 @@ static void initDefaultFluidSystem() { oilPvt->initEnd(); waterPvt->initEnd(); - typedef std::shared_ptr > GasPvtSharedPtr; - FluidSystem::setGasPvt(GasPvtSharedPtr(gasPvt)); - - typedef std::shared_ptr > OilPvtSharedPtr; - FluidSystem::setOilPvt(OilPvtSharedPtr(oilPvt)); - - typedef std::shared_ptr > WaterPvtSharedPtr; - FluidSystem::setWaterPvt(WaterPvtSharedPtr(waterPvt)); - + FluidSystem::setGasPvt(std::move(gasPvt)); + FluidSystem::setOilPvt(std::move(oilPvt)); + FluidSystem::setWaterPvt(std::move(waterPvt)); FluidSystem::initEnd(); - } } From 022f535508484146c4a6797edd3037d133140626 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Mon, 27 Nov 2017 11:33:06 +0100 Subject: [PATCH 155/158] Fix pvtIndex map for cases with non-active eqlnum regions. --- opm/core/simulator/initStateEquil.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp index e379dad85..218a2ddb0 100644 --- a/opm/core/simulator/initStateEquil.hpp +++ b/opm/core/simulator/initStateEquil.hpp @@ -263,6 +263,8 @@ namespace Opm const auto& tables = eclipseState.getTableManager(); // Create (inverse) region mapping. const RegionMapping<> eqlmap(equilnum(eclipseState, G)); + const int invalidRegion = -1; + regionPvtIdx_.resize(rec.size(), invalidRegion); setRegionPvtIdx(G, eclipseState, eqlmap); // Create Rs functions. @@ -371,7 +373,6 @@ namespace Opm template void setRegionPvtIdx(const Grid& G, const Opm::EclipseState& eclipseState, const RMap& reg) { - regionPvtIdx_.reserve(reg.activeRegions().size()); std::vector cellPvtRegionIdx; extractPvtTableIndex(cellPvtRegionIdx, eclipseState, UgGridHelpers::numCells(G), UgGridHelpers::globalCell(G)); for (const auto& r : reg.activeRegions()) { From 5e4dd591057f9d236bf6a096adf5da6919ee7aa1 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 12 Oct 2017 17:27:46 +0200 Subject: [PATCH 156/158] replace #if HAVE_CONFIG_H by #ifdef HAVE_CONFIG_H it seems like most build systems pass a -DHAVE_CONFIG_H flag to the compiler which still causes `#if HAVE_CONFIG_H` to be false while it clearly is supposed to be triggered. That said, I do not really see a good reason why the inclusion of the `config.h` file should be guarded in the first place: the file is guaranteed to always available by proper build systems, and if it was not included the build either breaks at the linking stage or -- at the very least -- the runtime behavior of the resulting libraries will be very awkward. --- examples/compute_initial_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp index 33c6f4a4a..a2bae9344 100644 --- a/examples/compute_initial_state.cpp +++ b/examples/compute_initial_state.cpp @@ -19,7 +19,7 @@ */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG_H From c2e9a7a518dd2bed42ff75af6ab89f0bf1e084af Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Tue, 2 Jan 2018 12:43:56 +0100 Subject: [PATCH 157/158] move the hydrostatic equilibrium code to its proper location and make it compile this just moves the hydrostatic equilibrium code from its historc location at opm/core to ebos/equil and adds minimal changes to make it compile. this allows to clean up that code without disturbing the legacy simulators. --- opm/core/simulator/EquilibrationHelpers.hpp | 799 -------------------- opm/core/simulator/initStateEquil.hpp | 446 ----------- opm/core/simulator/initStateEquil_impl.hpp | 791 ------------------- opm/core/utility/RegionMapping.hpp | 181 ----- 4 files changed, 2217 deletions(-) delete mode 100644 opm/core/simulator/EquilibrationHelpers.hpp delete mode 100644 opm/core/simulator/initStateEquil.hpp delete mode 100644 opm/core/simulator/initStateEquil_impl.hpp delete mode 100644 opm/core/utility/RegionMapping.hpp diff --git a/opm/core/simulator/EquilibrationHelpers.hpp b/opm/core/simulator/EquilibrationHelpers.hpp deleted file mode 100644 index 05e841db2..000000000 --- a/opm/core/simulator/EquilibrationHelpers.hpp +++ /dev/null @@ -1,799 +0,0 @@ -/* - Copyright 2014 SINTEF ICT, Applied Mathematics. - Copyright 2017 IRIS - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - -#ifndef OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED -#define OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED - -#include -#include -#include - -#include - -#include -#include -#include - -#include - - -/* ----- synopsis of EquilibrationHelpers.hpp ---- - -namespace Opm -{ - namespace EQUIL { - - namespace Miscibility { - class RsFunction; - class NoMixing; - template - class RsVD; - template - class RsSatAtContact; - } - - class EquilReg; - - - template - struct PcEq; - - template - inline double satFromPc(const MaterialLawManager& materialLawManager, - const int phase, - const int cell, - const double target_pc, - const bool increasing = false) - template - inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager, - const int phase1, - const int phase2, - const int cell, - const double target_pc) - } // namespace Equil -} // namespace Opm - ----- end of synopsis of EquilibrationHelpers.hpp ---- -*/ - - -namespace Opm -{ - /** - * Types and routines that collectively implement a basic - * ECLIPSE-style equilibration-based initialisation scheme. - * - * This namespace is intentionally nested to avoid name clashes - * with other parts of OPM. - */ - namespace EQUIL { - - - typedef Opm::FluidSystems::BlackOil FluidSystemSimple; - - // Adjust oil pressure according to gas saturation and cap pressure - typedef Opm::SimpleModularFluidState SatOnlyFluidState; - - /** - * Types and routines relating to phase mixing in - * equilibration calculations. - */ - namespace Miscibility { - - /** - * Base class for phase mixing functions. - */ - class RsFunction - { - public: - /** - * Function call operator. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \param[in] temp Temperature at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. - */ - virtual double operator()(const double depth, - const double press, - const double temp, - const double sat = 0.0) const = 0; - }; - - - /** - * Type that implements "no phase mixing" policy. - */ - class NoMixing : public RsFunction { - public: - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \param[in] temp Temperature at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. In "no mixing - * policy", this is identically zero. - */ - double - operator()(const double /* depth */, - const double /* press */, - const double /* temp */, - const double /* sat */ = 0.0) const - { - return 0.0; - } - }; - - - /** - * Type that implements "dissolved gas-oil ratio" - * tabulated as a function of depth policy. Data - * typically taken from keyword 'RSVD'. - */ - template - class RsVD : public RsFunction { - public: - /** - * Constructor. - * - * \param[in] pvtRegionIdx The pvt region index - * \param[in] depth Depth nodes. - * \param[in] rs Dissolved gas-oil ratio at @c depth. - */ - RsVD(const int pvtRegionIdx, - const std::vector& depth, - const std::vector& rs) - : pvtRegionIdx_(pvtRegionIdx) - , depth_(depth) - , rs_(rs) - { - } - - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \param[in] temp Temperature at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. - */ - double - operator()(const double depth, - const double press, - const double temp, - const double sat_gas = 0.0) const - { - if (sat_gas > 0.0) { - return satRs(press, temp); - } else { - return std::min(satRs(press, temp), linearInterpolationNoExtrapolation(depth_, rs_, depth)); - } - } - - private: - const int pvtRegionIdx_; - std::vector depth_; /**< Depth nodes */ - std::vector rs_; /**< Dissolved gas-oil ratio */ - - double satRs(const double press, const double temp) const - { - return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press); - } - }; - - - /** - * Type that implements "vaporized oil-gas ratio" - * tabulated as a function of depth policy. Data - * typically taken from keyword 'RVVD'. - */ - template - class RvVD : public RsFunction { - public: - /** - * Constructor. - * - * \param[in] pvtRegionIdx The pvt region index - * \param[in] depth Depth nodes. - * \param[in] rv Dissolved gas-oil ratio at @c depth. - */ - RvVD(const int pvtRegionIdx, - const std::vector& depth, - const std::vector& rv) - : pvtRegionIdx_(pvtRegionIdx) - , depth_(depth) - , rv_(rv) - { - } - - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RV - * value. - * - * \param[in] press Pressure at which to calculate RV - * value. - * - * \param[in] temp Temperature at which to calculate RV - * value. - * - * \return Vaporized oil-gas ratio (RV) at depth @c - * depth and pressure @c press. - */ - double - operator()(const double depth, - const double press, - const double temp, - const double sat_oil = 0.0 ) const - { - if (std::abs(sat_oil) > 1e-16) { - return satRv(press, temp); - } else { - return std::min(satRv(press, temp), linearInterpolationNoExtrapolation(depth_, rv_, depth)); - } - } - - private: - const int pvtRegionIdx_; - std::vector depth_; /**< Depth nodes */ - std::vector rv_; /**< Vaporized oil-gas ratio */ - - double satRv(const double press, const double temp) const - { - return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press); - } - }; - - - /** - * Class that implements "dissolved gas-oil ratio" (Rs) - * as function of depth and pressure as follows: - * - * 1. The Rs at the gas-oil contact is equal to the - * saturated Rs value, Rs_sat_contact. - * - * 2. The Rs elsewhere is equal to Rs_sat_contact, but - * constrained to the saturated value as given by the - * local pressure. - * - * This should yield Rs-values that are constant below the - * contact, and decreasing above the contact. - */ - template - class RsSatAtContact : public RsFunction { - public: - /** - * Constructor. - * - * \param[in] pvtRegionIdx The pvt region index - * \param[in] p_contact oil pressure at the contact - * \param[in] T_contact temperature at the contact - */ - RsSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact) - : pvtRegionIdx_(pvtRegionIdx) - { - rs_sat_contact_ = satRs(p_contact, T_contact); - } - - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RS - * value. - * - * \param[in] press Pressure at which to calculate RS - * value. - * - * \param[in] temp Temperature at which to calculate RS - * value. - * - * \return Dissolved gas-oil ratio (RS) at depth @c - * depth and pressure @c press. - */ - double - operator()(const double /* depth */, - const double press, - const double temp, - const double sat_gas = 0.0) const - { - if (sat_gas > 0.0) { - return satRs(press, temp); - } else { - return std::min(satRs(press, temp), rs_sat_contact_); - } - } - - private: - const int pvtRegionIdx_; - double rs_sat_contact_; - - double satRs(const double press, const double temp) const - { - return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press); - } - }; - - - /** - * Class that implements "vaporized oil-gas ratio" (Rv) - * as function of depth and pressure as follows: - * - * 1. The Rv at the gas-oil contact is equal to the - * saturated Rv value, Rv_sat_contact. - * - * 2. The Rv elsewhere is equal to Rv_sat_contact, but - * constrained to the saturated value as given by the - * local pressure. - * - * This should yield Rv-values that are constant below the - * contact, and decreasing above the contact. - */ - template - class RvSatAtContact : public RsFunction { - public: - /** - * Constructor. - * - * \param[in] pvtRegionIdx The pvt region index - * \param[in] p_contact oil pressure at the contact - * \param[in] T_contact temperature at the contact - */ - RvSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact) - :pvtRegionIdx_(pvtRegionIdx) - { - rv_sat_contact_ = satRv(p_contact, T_contact); - } - - /** - * Function call. - * - * \param[in] depth Depth at which to calculate RV - * value. - * - * \param[in] press Pressure at which to calculate RV - * value. - * - * \param[in] temp Temperature at which to calculate RV - * value. - * - * \return Dissolved oil-gas ratio (RV) at depth @c - * depth and pressure @c press. - */ - double - operator()(const double /*depth*/, - const double press, - const double temp, - const double sat_oil = 0.0) const - { - if (sat_oil > 0.0) { - return satRv(press, temp); - } else { - return std::min(satRv(press, temp), rv_sat_contact_); - } - } - - private: - const int pvtRegionIdx_; - double rv_sat_contact_; - - double satRv(const double press, const double temp) const - { - return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);; - } - }; - - } // namespace Miscibility - - /** - * Aggregate information base of an equilibration region. - * - * Provides inquiry methods for retrieving depths of contacs - * and pressure values as well as a means of calculating fluid - * densities, dissolved gas-oil ratio and vapourised oil-gas - * ratios. - * - * \tparam DensCalc Type that provides access to a phase - * density calculation facility. Must implement an operator() - * declared as - * - * std::vector - * operator()(const double press, - * const std::vector& svol ) - * - * that calculates the phase densities of all phases in @c - * svol at fluid pressure @c press. - */ - class EquilReg { - public: - /** - * Constructor. - * - * \param[in] rec Equilibration data of current region. - * \param[in] rs Calculator of dissolved gas-oil ratio. - * \param[in] rv Calculator of vapourised oil-gas ratio. - * \param[in] pvtRegionIdx The pvt region index - */ - EquilReg(const EquilRecord& rec, - std::shared_ptr rs, - std::shared_ptr rv, - const int pvtIdx) - : rec_ (rec) - , rs_ (rs) - , rv_ (rv) - , pvtIdx_ (pvtIdx) - { - } - - /** - * Type of dissolved gas-oil ratio calculator. - */ - typedef Miscibility::RsFunction CalcDissolution; - - /** - * Type of vapourised oil-gas ratio calculator. - */ - typedef Miscibility::RsFunction CalcEvaporation; - - /** - * Datum depth in current region - */ - double datum() const { return this->rec_.datumDepth(); } - - /** - * Pressure at datum depth in current region. - */ - double pressure() const { return this->rec_.datumDepthPressure(); } - - /** - * Depth of water-oil contact. - */ - double zwoc() const { return this->rec_.waterOilContactDepth(); } - - /** - * water-oil capillary pressure at water-oil contact. - * - * \return P_o - P_w at WOC. - */ - double pcow_woc() const { return this->rec_.waterOilContactCapillaryPressure(); } - - /** - * Depth of gas-oil contact. - */ - double zgoc() const { return this->rec_.gasOilContactDepth(); } - - /** - * Gas-oil capillary pressure at gas-oil contact. - * - * \return P_g - P_o at GOC. - */ - double pcgo_goc() const { return this->rec_.gasOilContactCapillaryPressure(); } - - - /** - * Retrieve dissolved gas-oil ratio calculator of current - * region. - */ - const CalcDissolution& - dissolutionCalculator() const { return *this->rs_; } - - /** - * Retrieve vapourised oil-gas ratio calculator of current - * region. - */ - const CalcEvaporation& - evaporationCalculator() const { return *this->rv_; } - - /** - * Retrieve pvtIdx of the region. - */ - int pvtIdx() const { return this->pvtIdx_; } - - - private: - EquilRecord rec_; /**< Equilibration data */ - std::shared_ptr rs_; /**< RS calculator */ - std::shared_ptr rv_; /**< RV calculator */ - const int pvtIdx_; - }; - - - - /// Functor for inverting capillary pressure function. - /// Function represented is - /// f(s) = pc(s) - target_pc - template - struct PcEq - { - PcEq(const MaterialLawManager& materialLawManager, - const int phase, - const int cell, - const double target_pc) - : materialLawManager_(materialLawManager), - phase_(phase), - cell_(cell), - target_pc_(target_pc) - { - - } - double operator()(double s) const - { - const auto& matParams = materialLawManager_.materialLawParams(cell_); - SatOnlyFluidState fluidState; - fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0); - fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0); - fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0); - fluidState.setSaturation(phase_, s); - - double pc[FluidSystem::numPhases]; - std::fill(pc, pc + FluidSystem::numPhases, 0.0); - MaterialLaw::capillaryPressures(pc, matParams, fluidState); - double sign = (phase_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; - double pcPhase = pc[FluidSystem::oilPhaseIdx] + sign * pc[phase_]; - return pcPhase - target_pc_; - } - private: - const MaterialLawManager& materialLawManager_; - const int phase_; - const int cell_; - const double target_pc_; - }; - - template - double minSaturations(const MaterialLawManager& materialLawManager, const int phase, const int cell) { - const auto& scaledDrainageInfo = - materialLawManager.oilWaterScaledEpsInfoDrainage(cell); - - // Find minimum and maximum saturations. - switch(phase) { - case FluidSystem::waterPhaseIdx : - { - return scaledDrainageInfo.Swl; - break; - } - case FluidSystem::gasPhaseIdx : - { - return scaledDrainageInfo.Sgl; - break; - } - case FluidSystem::oilPhaseIdx : - { - OPM_THROW(std::runtime_error, "Min saturation not implemented for oil phase."); - break; - } - default: OPM_THROW(std::runtime_error, "Unknown phaseIdx ."); - } - return -1.0; - } - - template - double maxSaturations(const MaterialLawManager& materialLawManager, const int phase, const int cell) { - const auto& scaledDrainageInfo = - materialLawManager.oilWaterScaledEpsInfoDrainage(cell); - - // Find minimum and maximum saturations. - switch(phase) { - case FluidSystem::waterPhaseIdx : - { - return scaledDrainageInfo.Swu; - break; - } - case FluidSystem::gasPhaseIdx : - { - return scaledDrainageInfo.Sgu; - break; - } - case FluidSystem::oilPhaseIdx : - { - OPM_THROW(std::runtime_error, "Max saturation not implemented for oil phase."); - break; - } - default: OPM_THROW(std::runtime_error, "Unknown phaseIdx ."); - } - return -1.0; - } - - - /// Compute saturation of some phase corresponding to a given - /// capillary pressure. - template - inline double satFromPc(const MaterialLawManager& materialLawManager, - const int phase, - const int cell, - const double target_pc, - const bool increasing = false) - { - // Find minimum and maximum saturations. - const double s0 = increasing ? maxSaturations(materialLawManager, phase, cell) : minSaturations(materialLawManager, phase, cell); - const double s1 = increasing ? minSaturations(materialLawManager, phase, cell) : maxSaturations(materialLawManager, phase, cell); - - // Create the equation f(s) = pc(s) - target_pc - const PcEq f(materialLawManager, phase, cell, target_pc); - const double f0 = f(s0); - const double f1 = f(s1); - - if (f0 <= 0.0) { - return s0; - } else if (f1 > 0.0) { - return s1; - } else { - const int max_iter = 60; - const double tol = 1e-6; - int iter_used = -1; - typedef RegulaFalsi ScalarSolver; - const double sol = ScalarSolver::solve(f, std::min(s0, s1), std::max(s0, s1), max_iter, tol, iter_used); - return sol; - } - } - - - /// Functor for inverting a sum of capillary pressure functions. - /// Function represented is - /// f(s) = pc1(s) + pc2(1 - s) - target_pc - template - struct PcEqSum - { - PcEqSum(const MaterialLawManager& materialLawManager, - const int phase1, - const int phase2, - const int cell, - const double target_pc) - : materialLawManager_(materialLawManager), - phase1_(phase1), - phase2_(phase2), - cell_(cell), - target_pc_(target_pc) - { - } - double operator()(double s) const - { - const auto& matParams = materialLawManager_.materialLawParams(cell_); - SatOnlyFluidState fluidState; - fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0); - fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0); - fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0); - fluidState.setSaturation(phase1_, s); - fluidState.setSaturation(phase2_, 1.0 - s); - - double pc[FluidSystem::numPhases]; - std::fill(pc, pc + FluidSystem::numPhases, 0.0); - - MaterialLaw::capillaryPressures(pc, matParams, fluidState); - double sign1 = (phase1_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; - double pc1 = pc[FluidSystem::oilPhaseIdx] + sign1 * pc[phase1_]; - double sign2 = (phase2_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0; - double pc2 = pc[FluidSystem::oilPhaseIdx] + sign2 * pc[phase2_]; - return pc1 + pc2 - target_pc_; - } - private: - const MaterialLawManager& materialLawManager_; - const int phase1_; - const int phase2_; - const int cell_; - const double target_pc_; - }; - - - - - /// Compute saturation of some phase corresponding to a given - /// capillary pressure, where the capillary pressure function - /// is given as a sum of two other functions. - template - inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager, - const int phase1, - const int phase2, - const int cell, - const double target_pc) - { - // Find minimum and maximum saturations. - const double smin = minSaturations(materialLawManager, phase1, cell); - const double smax = maxSaturations(materialLawManager, phase1, cell); - - // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc - const PcEqSum f(materialLawManager, phase1, phase2, cell, target_pc); - const double f0 = f(smin); - const double f1 = f(smax); - if (f0 <= 0.0) { - return smin; - } else if (f1 > 0.0) { - return smax; - } else { - const int max_iter = 30; - const double tol = 1e-6; - int iter_used = -1; - typedef RegulaFalsi ScalarSolver; - const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used); - return sol; - } - } - - /// Compute saturation from depth. Used for constant capillary pressure function - template - inline double satFromDepth(const MaterialLawManager& materialLawManager, - const double cellDepth, - const double contactDepth, - const int phase, - const int cell, - const bool increasing = false) - { - const double s0 = increasing ? maxSaturations(materialLawManager, phase, cell) : minSaturations(materialLawManager, phase, cell); - const double s1 = increasing ? minSaturations(materialLawManager, phase, cell) : maxSaturations(materialLawManager, phase, cell); - - if (cellDepth < contactDepth){ - return s0; - } else { - return s1; - } - - } - - /// Return true if capillary pressure function is constant - template - inline bool isConstPc(const MaterialLawManager& materialLawManager, - const int phase, - const int cell) - { - // Create the equation f(s) = pc(s); - const PcEq f(materialLawManager, phase, cell, 0); - const double f0 = f(minSaturations(materialLawManager, phase, cell)); - const double f1 = f(maxSaturations(materialLawManager, phase, cell)); - return std::abs(f0 - f1) < std::numeric_limits::epsilon(); - } - - } // namespace Equil -} // namespace Opm - - -#endif // OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED diff --git a/opm/core/simulator/initStateEquil.hpp b/opm/core/simulator/initStateEquil.hpp deleted file mode 100644 index 218a2ddb0..000000000 --- a/opm/core/simulator/initStateEquil.hpp +++ /dev/null @@ -1,446 +0,0 @@ -/* - Copyright 2014 SINTEF ICT, Applied Mathematics. - Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services - Copyright 2015 NTNU - Copyright 2017 IRIS - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - -#ifndef OPM_INITSTATEEQUIL_HEADER_INCLUDED -#define OPM_INITSTATEEQUIL_HEADER_INCLUDED - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -/** - * \file - * Facilities for an ECLIPSE-style equilibration-based - * initialisation scheme (keyword 'EQUIL'). - */ -struct UnstructuredGrid; - -namespace Opm -{ - - - /** - * Types and routines that collectively implement a basic - * ECLIPSE-style equilibration-based initialisation scheme. - * - * This namespace is intentionally nested to avoid name clashes - * with other parts of OPM. - */ - namespace EQUIL { - - /** - * Compute initial phase pressures by means of equilibration. - * - * This function uses the information contained in an - * equilibration record (i.e., depths and pressurs) as well as - * a density calculator and related data to vertically - * integrate the phase pressure ODE - * \f[ - * \frac{\mathrm{d}p_{\alpha}}{\mathrm{d}z} = - * \rho_{\alpha}(z,p_{\alpha})\cdot g - * \f] - * in which \f$\rho_{\alpha}$ denotes the fluid density of - * fluid phase \f$\alpha\f$, \f$p_{\alpha}\f$ is the - * corresponding phase pressure, \f$z\f$ is the depth and - * \f$g\f$ is the acceleration due to gravity (assumed - * directed downwords, in the positive \f$z\f$ direction). - * - * \tparam Region Type of an equilibration region information - * base. Typically an instance of the EquilReg - * class template. - * - * \tparam CellRange Type of cell range that demarcates the - * cells pertaining to the current - * equilibration region. Must implement - * methods begin() and end() to bound the range - * as well as provide an inner type, - * const_iterator, to traverse the range. - * - * \param[in] G Grid. - * \param[in] reg Current equilibration region. - * \param[in] cells Range that spans the cells of the current - * equilibration region. - * \param[in] grav Acceleration of gravity. - * - * \return Phase pressures, one vector for each active phase, - * of pressure values in each cell in the current - * equilibration region. - */ - template - std::vector< std::vector > - phasePressures(const Grid& G, - const Region& reg, - const CellRange& cells, - const double grav = unit::gravity); - - - - /** - * Compute initial phase saturations by means of equilibration. - * - * \tparam FluidSystem The FluidSystem from opm-material - * Must be initialized before used. - * - * \tparam Grid Type of the grid - * - * \tparam Region Type of an equilibration region information - * base. Typically an instance of the EquilReg - * class template. - * - * \tparam CellRange Type of cell range that demarcates the - * cells pertaining to the current - * equilibration region. Must implement - * methods begin() and end() to bound the range - * as well as provide an inner type, - * const_iterator, to traverse the range. - * - * \tparam MaterialLawManager The MaterialLawManager from opm-material - * - * \param[in] G Grid. - * \param[in] reg Current equilibration region. - * \param[in] cells Range that spans the cells of the current - * equilibration region. - * \param[in] materialLawManager The MaterialLawManager from opm-material - * \param[in] swat_init A vector of initial water saturations. - * The capillary pressure is scaled to fit these values - * \param[in] phase_pressures Phase pressures, one vector for each active phase, - * of pressure values in each cell in the current - * equilibration region. - * \return Phase saturations, one vector for each phase, each containing - * one saturation value per cell in the region. - */ - template - std::vector< std::vector > - phaseSaturations(const Grid& grid, - const Region& reg, - const CellRange& cells, - MaterialLawManager& materialLawManager, - const std::vector swat_init, - std::vector< std::vector >& phase_pressures); - - - - /** - * Compute initial Rs values. - * - * \tparam CellRangeType Type of cell range that demarcates the - * cells pertaining to the current - * equilibration region. Must implement - * methods begin() and end() to bound the range - * as well as provide an inner type, - * const_iterator, to traverse the range. - * - * \param[in] grid Grid. - * \param[in] cells Range that spans the cells of the current - * equilibration region. - * \param[in] oil_pressure Oil pressure for each cell in range. - * \param[in] temperature Temperature for each cell in range. - * \param[in] rs_func Rs as function of pressure and depth. - * \return Rs values, one for each cell in the 'cells' range. - */ - template - std::vector computeRs(const Grid& grid, - const CellRangeType& cells, - const std::vector oil_pressure, - const std::vector& temperature, - const Miscibility::RsFunction& rs_func, - const std::vector gas_saturation); - - namespace DeckDependent { - inline - std::vector - getEquil(const Opm::EclipseState& state) - { - const auto& init = state.getInitConfig(); - - if( !init.hasEquil() ) { - OPM_THROW(std::domain_error, "Deck does not provide equilibration data."); - } - - const auto& equil = init.getEquil(); - return { equil.begin(), equil.end() }; - } - - template - inline - std::vector - equilnum(const Opm::EclipseState& eclipseState, - const Grid& G ) - { - std::vector eqlnum; - if (eclipseState.get3DProperties().hasDeckIntGridProperty("EQLNUM")) { - const int nc = UgGridHelpers::numCells(G); - eqlnum.resize(nc); - const std::vector& e = - eclipseState.get3DProperties().getIntGridProperty("EQLNUM").getData(); - const int* gc = UgGridHelpers::globalCell(G); - for (int cell = 0; cell < nc; ++cell) { - const int deck_pos = (gc == NULL) ? cell : gc[cell]; - eqlnum[cell] = e[deck_pos] - 1; - } - } - else { - // No explicit equilibration region. - // All cells in region zero. - eqlnum.assign(UgGridHelpers::numCells(G), 0); - } - - return eqlnum; - } - - template - class InitialStateComputer { - public: - template - InitialStateComputer(MaterialLawManager& materialLawManager, - const Opm::EclipseState& eclipseState, - const Grid& G , - const double grav = unit::gravity, - const bool applySwatInit = true - ) - : pp_(FluidSystem::numPhases, - std::vector(UgGridHelpers::numCells(G))), - sat_(FluidSystem::numPhases, - std::vector(UgGridHelpers::numCells(G))), - rs_(UgGridHelpers::numCells(G)), - rv_(UgGridHelpers::numCells(G)) - { - //Check for presence of kw SWATINIT - if (eclipseState.get3DProperties().hasDeckDoubleGridProperty("SWATINIT") && applySwatInit) { - const std::vector& swat_init_ecl = eclipseState. - get3DProperties().getDoubleGridProperty("SWATINIT").getData(); - const int nc = UgGridHelpers::numCells(G); - swat_init_.resize(nc); - const int* gc = UgGridHelpers::globalCell(G); - for (int c = 0; c < nc; ++c) { - const int deck_pos = (gc == NULL) ? c : gc[c]; - swat_init_[c] = swat_init_ecl[deck_pos]; - } - } - // Get the equilibration records. - const std::vector rec = getEquil(eclipseState); - const auto& tables = eclipseState.getTableManager(); - // Create (inverse) region mapping. - const RegionMapping<> eqlmap(equilnum(eclipseState, G)); - const int invalidRegion = -1; - regionPvtIdx_.resize(rec.size(), invalidRegion); - setRegionPvtIdx(G, eclipseState, eqlmap); - - // Create Rs functions. - rs_func_.reserve(rec.size()); - if (FluidSystem::enableDissolvedGas()) { - const TableContainer& rsvdTables = tables.getRsvdTables(); - for (size_t i = 0; i < rec.size(); ++i) { - if (eqlmap.cells(i).empty()) - { - rs_func_.push_back(std::shared_ptr>()); - continue; - } - const int pvtIdx = regionPvtIdx_[i]; - if (!rec[i].liveOilInitConstantRs()) { - if (rsvdTables.size() <= 0 ) { - OPM_THROW(std::runtime_error, "Cannot initialise: RSVD table not available."); - } - const RsvdTable& rsvdTable = rsvdTables.getTable(i); - std::vector depthColumn = rsvdTable.getColumn("DEPTH").vectorCopy(); - std::vector rsColumn = rsvdTable.getColumn("RS").vectorCopy(); - rs_func_.push_back(std::make_shared>(pvtIdx, - depthColumn , rsColumn)); - } else { - if (rec[i].gasOilContactDepth() != rec[i].datumDepth()) { - OPM_THROW(std::runtime_error, - "Cannot initialise: when no explicit RSVD table is given, \n" - "datum depth must be at the gas-oil-contact. " - "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); - } - const double p_contact = rec[i].datumDepthPressure(); - const double T_contact = 273.15 + 20; // standard temperature for now - rs_func_.push_back(std::make_shared>(pvtIdx, p_contact, T_contact)); - } - } - } else { - for (size_t i = 0; i < rec.size(); ++i) { - rs_func_.push_back(std::make_shared()); - } - } - - rv_func_.reserve(rec.size()); - if (FluidSystem::enableVaporizedOil()) { - const TableContainer& rvvdTables = tables.getRvvdTables(); - for (size_t i = 0; i < rec.size(); ++i) { - if (eqlmap.cells(i).empty()) - { - rv_func_.push_back(std::shared_ptr>()); - continue; - } - const int pvtIdx = regionPvtIdx_[i]; - if (!rec[i].wetGasInitConstantRv()) { - if (rvvdTables.size() <= 0) { - OPM_THROW(std::runtime_error, "Cannot initialise: RVVD table not available."); - } - - const RvvdTable& rvvdTable = rvvdTables.getTable(i); - std::vector depthColumn = rvvdTable.getColumn("DEPTH").vectorCopy(); - std::vector rvColumn = rvvdTable.getColumn("RV").vectorCopy(); - rv_func_.push_back(std::make_shared>(pvtIdx, - depthColumn , rvColumn)); - - } else { - if (rec[i].gasOilContactDepth() != rec[i].datumDepth()) { - OPM_THROW(std::runtime_error, - "Cannot initialise: when no explicit RVVD table is given, \n" - "datum depth must be at the gas-oil-contact. " - "In EQUIL region " << (i + 1) << " (counting from 1), this does not hold."); - } - const double p_contact = rec[i].datumDepthPressure() + rec[i].gasOilContactCapillaryPressure(); - const double T_contact = 273.15 + 20; // standard temperature for now - rv_func_.push_back(std::make_shared>(pvtIdx ,p_contact, T_contact)); - } - } - } else { - for (size_t i = 0; i < rec.size(); ++i) { - rv_func_.push_back(std::make_shared()); - } - } - - // Compute pressures, saturations, rs and rv factors. - calcPressSatRsRv(eqlmap, rec, materialLawManager, G, grav); - - // Modify oil pressure in no-oil regions so that the pressures of present phases can - // be recovered from the oil pressure and capillary relations. - } - - typedef std::vector Vec; - typedef std::vector PVec; // One per phase. - - const PVec& press() const { return pp_; } - const PVec& saturation() const { return sat_; } - const Vec& rs() const { return rs_; } - const Vec& rv() const { return rv_; } - - private: - typedef EquilReg EqReg; - std::vector< std::shared_ptr > rs_func_; - std::vector< std::shared_ptr > rv_func_; - std::vector regionPvtIdx_; - PVec pp_; - PVec sat_; - Vec rs_; - Vec rv_; - Vec swat_init_; - - template - void setRegionPvtIdx(const Grid& G, const Opm::EclipseState& eclipseState, const RMap& reg) { - - std::vector cellPvtRegionIdx; - extractPvtTableIndex(cellPvtRegionIdx, eclipseState, UgGridHelpers::numCells(G), UgGridHelpers::globalCell(G)); - for (const auto& r : reg.activeRegions()) { - const auto& cells = reg.cells(r); - const int cell = *(cells.begin()); - regionPvtIdx_[r] = cellPvtRegionIdx[cell]; - } - } - - template - void - calcPressSatRsRv(const RMap& reg , - const std::vector< EquilRecord >& rec , - MaterialLawManager& materialLawManager, - const Grid& G , - const double grav) - { - for (const auto& r : reg.activeRegions()) { - const auto& cells = reg.cells(r); - if (cells.empty()) - { - OpmLog::warning("Equilibration region " + std::to_string(r + 1) - + " has no active cells"); - continue; - } - - const EqReg eqreg(rec[r], rs_func_[r], rv_func_[r], regionPvtIdx_[r]); - - PVec pressures = phasePressures(G, eqreg, cells, grav); - const std::vector& temp = temperature(G, eqreg, cells); - const PVec sat = phaseSaturations(G, eqreg, cells, materialLawManager, swat_init_, pressures); - - const int np = FluidSystem::numPhases; - for (int p = 0; p < np; ++p) { - copyFromRegion(pressures[p], cells, pp_[p]); - copyFromRegion(sat[p], cells, sat_[p]); - } - const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); - const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); - if (oil && gas) { - const int oilpos = FluidSystem::oilPhaseIdx; - const int gaspos = FluidSystem::gasPhaseIdx; - const Vec rs_vals = computeRs(G, cells, pressures[oilpos], temp, *(rs_func_[r]), sat[gaspos]); - const Vec rv_vals = computeRs(G, cells, pressures[gaspos], temp, *(rv_func_[r]), sat[oilpos]); - copyFromRegion(rs_vals, cells, rs_); - copyFromRegion(rv_vals, cells, rv_); - } - } - } - - template - void copyFromRegion(const Vec& source, - const CellRangeType& cells, - Vec& destination) - { - auto s = source.begin(); - auto c = cells.begin(); - const auto e = cells.end(); - for (; c != e; ++c, ++s) { - destination[*c] = *s; - } - } - - }; - } // namespace DeckDependent - } // namespace EQUIL -} // namespace Opm - -#include - -#endif // OPM_INITSTATEEQUIL_HEADER_INCLUDED diff --git a/opm/core/simulator/initStateEquil_impl.hpp b/opm/core/simulator/initStateEquil_impl.hpp deleted file mode 100644 index ef5d69962..000000000 --- a/opm/core/simulator/initStateEquil_impl.hpp +++ /dev/null @@ -1,791 +0,0 @@ -/* - Copyright 2014 SINTEF ICT, Applied Mathematics. - Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services - Copyright 2015 NTNU - Copyright 2017 IRIS - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - -#ifndef OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED -#define OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED - -#include -#include - -#include - -#include -#include -#include -#include - -namespace Opm -{ - namespace Details { - template - class RK4IVP { - public: - RK4IVP(const RHS& f , - const std::array& span, - const double y0 , - const int N ) - : N_(N) - , span_(span) - { - const double h = stepsize(); - const double h2 = h / 2; - const double h6 = h / 6; - - y_.reserve(N + 1); - f_.reserve(N + 1); - - y_.push_back(y0); - f_.push_back(f(span_[0], y0)); - - for (int i = 0; i < N; ++i) { - const double x = span_[0] + i*h; - const double y = y_.back(); - - const double k1 = f_[i]; - const double k2 = f(x + h2, y + h2*k1); - const double k3 = f(x + h2, y + h2*k2); - const double k4 = f(x + h , y + h*k3); - - y_.push_back(y + h6*(k1 + 2*(k2 + k3) + k4)); - f_.push_back(f(x + h, y_.back())); - } - - assert (y_.size() == std::vector::size_type(N + 1)); - } - - double - operator()(const double x) const - { - // Dense output (O(h**3)) according to Shampine - // (Hermite interpolation) - const double h = stepsize(); - int i = (x - span_[0]) / h; - const double t = (x - (span_[0] + i*h)) / h; - - // Crude handling of evaluation point outside "span_"; - if (i < 0) { i = 0; } - if (N_ <= i) { i = N_ - 1; } - - const double y0 = y_[i], y1 = y_[i + 1]; - const double f0 = f_[i], f1 = f_[i + 1]; - - double u = (1 - 2*t) * (y1 - y0); - u += h * ((t - 1)*f0 + t*f1); - u *= t * (t - 1); - u += (1 - t)*y0 + t*y1; - - return u; - } - - private: - int N_; - std::array span_; - std::vector y_; - std::vector f_; - - double - stepsize() const { return (span_[1] - span_[0]) / N_; } - }; - - namespace PhasePressODE { - template - class Water { - public: - Water(const double temp, - const int pvtRegionIdx, - const double norm_grav) - : temp_(temp) - , pvtRegionIdx_(pvtRegionIdx) - , g_(norm_grav) - { - } - - double - operator()(const double /* depth */, - const double press) const - { - return this->density(press) * g_; - } - - private: - const double temp_; - const int pvtRegionIdx_; - const double g_; - - double - density(const double press) const - { - double rho = FluidSystem::waterPvt().inverseFormationVolumeFactor(pvtRegionIdx_, temp_, press); - rho *= FluidSystem::referenceDensity(FluidSystem::waterPhaseIdx, pvtRegionIdx_); - return rho; - } - }; - - template - class Oil { - public: - Oil(const double temp, - const RS& rs, - const int pvtRegionIdx, - const double norm_grav) - : temp_(temp) - , rs_(rs) - , pvtRegionIdx_(pvtRegionIdx) - , g_(norm_grav) - { - } - - double - operator()(const double depth, - const double press) const - { - return this->density(depth, press) * g_; - } - - private: - const double temp_; - const RS& rs_; - const int pvtRegionIdx_; - const double g_; - - double - density(const double depth, - const double press) const - { - double rs = rs_(depth, press, temp_); - double bOil = 0.0; - if ( !FluidSystem::enableDissolvedGas() || rs >= FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp_, press) ) { - bOil = FluidSystem::oilPvt().saturatedInverseFormationVolumeFactor(pvtRegionIdx_, temp_, press); - } else { - bOil = FluidSystem::oilPvt().inverseFormationVolumeFactor(pvtRegionIdx_, temp_, press, rs); - } - double rho = bOil * FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, pvtRegionIdx_); - if (FluidSystem::enableDissolvedGas()) { - rho += rs * bOil * FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, pvtRegionIdx_); - } - - return rho; - } - }; - - template - class Gas { - public: - Gas(const double temp, - const RV& rv, - const int pvtRegionIdx, - const double norm_grav) - : temp_(temp) - , rv_(rv) - , pvtRegionIdx_(pvtRegionIdx) - , g_(norm_grav) - { - } - - double - operator()(const double depth, - const double press) const - { - return this->density(depth, press) * g_; - } - - private: - const double temp_; - const RV& rv_; - const int pvtRegionIdx_; - const double g_; - - double - density(const double depth, - const double press) const - { - double rv = rv_(depth, press, temp_); - double bGas = 0.0; - if ( !FluidSystem::enableVaporizedOil() || rv >= FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp_, press) ) { - bGas = FluidSystem::gasPvt().saturatedInverseFormationVolumeFactor(pvtRegionIdx_, temp_, press); - } else { - bGas = FluidSystem::gasPvt().inverseFormationVolumeFactor(pvtRegionIdx_, temp_, press, rv); - } - double rho = bGas * FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, pvtRegionIdx_); - if (FluidSystem::enableVaporizedOil()) { - rho += rv * bGas * FluidSystem::referenceDensity(FluidSystem::oilPhaseIdx, pvtRegionIdx_); - } - - return rho; - } - }; - } // namespace PhasePressODE - - - namespace PhasePressure { - template - void - assign(const Grid& G , - const std::array& f , - const double split, - const CellRange& cells, - std::vector& p ) - { - - enum { up = 0, down = 1 }; - - std::vector::size_type c = 0; - for (typename CellRange::const_iterator - ci = cells.begin(), ce = cells.end(); - ci != ce; ++ci, ++c) - { - assert (c < p.size()); - - const double z = UgGridHelpers::cellCenterDepth(G, *ci); - p[c] = (z < split) ? f[up](z) : f[down](z); - } - } - - template < class FluidSystem, - class Grid, - class Region, - class CellRange> - void - water(const Grid& G , - const Region& reg , - const std::array& span , - const double grav , - double& po_woc, - const CellRange& cells , - std::vector& press ) - { - using PhasePressODE::Water; - typedef Water ODE; - - const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, reg.pvtIdx() , grav); - - double z0; - double p0; - if (reg.datum() > reg.zwoc()) {//Datum in water zone - z0 = reg.datum(); - p0 = reg.pressure(); - } else { - z0 = reg.zwoc(); - p0 = po_woc - reg.pcow_woc(); // Water pressure at contact - } - - std::array up = {{ z0, span[0] }}; - std::array down = {{ z0, span[1] }}; - - typedef Details::RK4IVP WPress; - std::array wpress = { - { - WPress(drho, up , p0, 2000) - , - WPress(drho, down, p0, 2000) - } - }; - - assign(G, wpress, z0, cells, press); - - if (reg.datum() > reg.zwoc()) { - // Return oil pressure at contact - po_woc = wpress[0](reg.zwoc()) + reg.pcow_woc(); - } - } - - template - void - oil(const Grid& G , - const Region& reg , - const std::array& span , - const double grav , - const CellRange& cells , - std::vector& press , - double& po_woc, - double& po_goc) - { - using PhasePressODE::Oil; - typedef Oil ODE; - - const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, reg.dissolutionCalculator(), - reg.pvtIdx(), grav); - - double z0; - double p0; - if (reg.datum() > reg.zwoc()) {//Datum in water zone, po_woc given - z0 = reg.zwoc(); - p0 = po_woc; - } else if (reg.datum() < reg.zgoc()) {//Datum in gas zone, po_goc given - z0 = reg.zgoc(); - p0 = po_goc; - } else { //Datum in oil zone - z0 = reg.datum(); - p0 = reg.pressure(); - } - - std::array up = {{ z0, span[0] }}; - std::array down = {{ z0, span[1] }}; - - typedef Details::RK4IVP OPress; - std::array opress = { - { - OPress(drho, up , p0, 2000) - , - OPress(drho, down, p0, 2000) - } - }; - - assign(G, opress, z0, cells, press); - - const double woc = reg.zwoc(); - if (z0 > woc) { po_woc = opress[0](woc); } // WOC above datum - else if (z0 < woc) { po_woc = opress[1](woc); } // WOC below datum - else { po_woc = p0; } // WOC *at* datum - - const double goc = reg.zgoc(); - if (z0 > goc) { po_goc = opress[0](goc); } // GOC above datum - else if (z0 < goc) { po_goc = opress[1](goc); } // GOC below datum - else { po_goc = p0; } // GOC *at* datum - } - - template - void - gas(const Grid& G , - const Region& reg , - const std::array& span , - const double grav , - double& po_goc, - const CellRange& cells , - std::vector& press ) - { - using PhasePressODE::Gas; - typedef Gas ODE; - - const double T = 273.15 + 20; // standard temperature for now - ODE drho(T, reg.evaporationCalculator(), - reg.pvtIdx(), grav); - - double z0; - double p0; - if (reg.datum() < reg.zgoc()) {//Datum in gas zone - z0 = reg.datum(); - p0 = reg.pressure(); - } else { - z0 = reg.zgoc(); - p0 = po_goc + reg.pcgo_goc(); // Gas pressure at contact - } - - std::array up = {{ z0, span[0] }}; - std::array down = {{ z0, span[1] }}; - - typedef Details::RK4IVP GPress; - std::array gpress = { - { - GPress(drho, up , p0, 2000) - , - GPress(drho, down, p0, 2000) - } - }; - - assign(G, gpress, z0, cells, press); - - if (reg.datum() < reg.zgoc()) { - // Return oil pressure at contact - po_goc = gpress[1](reg.zgoc()) - reg.pcgo_goc(); - } - } - } // namespace PhasePressure - - template - void - equilibrateOWG(const Grid& G, - const Region& reg, - const double grav, - const std::array& span, - const CellRange& cells, - std::vector< std::vector >& press) - { - const bool water = FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx); - const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); - const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); - const int oilpos = FluidSystem::oilPhaseIdx; - const int waterpos = FluidSystem::waterPhaseIdx; - const int gaspos = FluidSystem::gasPhaseIdx; - - if (reg.datum() > reg.zwoc()) { // Datum in water zone - double po_woc = -1; - double po_goc = -1; - - if (water) { - PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ waterpos ]); - } - - if (oil) { - PhasePressure::oil(G, reg, span, grav, cells, - press[ oilpos ], po_woc, po_goc); - } - - if (gas) { - PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gaspos ]); - } - } else if (reg.datum() < reg.zgoc()) { // Datum in gas zone - double po_woc = -1; - double po_goc = -1; - - if (gas) { - PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gaspos ]); - } - - if (oil) { - PhasePressure::oil(G, reg, span, grav, cells, - press[ oilpos ], po_woc, po_goc); - } - - if (water) { - PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ waterpos ]); - } - } else { // Datum in oil zone - double po_woc = -1; - double po_goc = -1; - - if (oil) { - PhasePressure::oil(G, reg, span, grav, cells, - press[ oilpos ], po_woc, po_goc); - } - - if (water) { - PhasePressure::water(G, reg, span, grav, po_woc, - cells, press[ waterpos ]); - } - - if (gas) { - PhasePressure::gas(G, reg, span, grav, po_goc, - cells, press[ gaspos ]); - } - } - } - } // namespace Details - - - namespace EQUIL { - - - template - std::vector< std::vector > - phasePressures(const Grid& G, - const Region& reg, - const CellRange& cells, - const double grav) - { - std::array span = - {{ std::numeric_limits::max() , - -std::numeric_limits::max() }}; // Symm. about 0. - - int ncell = 0; - { - // This code is only supported in three space dimensions - assert (UgGridHelpers::dimensions(G) == 3); - - const int nd = UgGridHelpers::dimensions(G); - - // Define vertical span as - // - // [minimum(node depth(cells)), maximum(node depth(cells))] - // - // Note: We use a sledgehammer approach--looping all - // the nodes of all the faces of all the 'cells'--to - // compute those bounds. This necessarily entails - // visiting some nodes (and faces) multiple times. - // - // Note: The implementation of 'RK4IVP<>' implicitly - // imposes the requirement that cell centroids are all - // within this vertical span. That requirement is not - // checked. - auto cell2Faces = UgGridHelpers::cell2Faces(G); - auto faceVertices = UgGridHelpers::face2Vertices(G); - - for (typename CellRange::const_iterator - ci = cells.begin(), ce = cells.end(); - ci != ce; ++ci, ++ncell) - { - for (auto fi=cell2Faces[*ci].begin(), - fe=cell2Faces[*ci].end(); - fi != fe; - ++fi) - { - for (auto i = faceVertices[*fi].begin(), e = faceVertices[*fi].end(); - i != e; ++i) - { - const double z = UgGridHelpers::vertexCoordinates(G, *i)[nd-1]; - - if (z < span[0]) { span[0] = z; } - if (z > span[1]) { span[1] = z; } - } - } - } - } - const int np = FluidSystem::numPhases; //reg.phaseUsage().num_phases; - - typedef std::vector pval; - std::vector press(np, pval(ncell, 0.0)); - - const double zwoc = reg.zwoc (); - const double zgoc = reg.zgoc (); - - // make sure goc and woc is within the span for the phase pressure calculation - span[0] = std::min(span[0],zgoc); - span[1] = std::max(span[1],zwoc); - - Details::equilibrateOWG(G, reg, grav, span, cells, press); - - return press; - } - - template - std::vector - temperature(const Grid& /* G */, - const Region& /* reg */, - const CellRange& cells) - { - // use the standard temperature for everything for now - return std::vector(cells.size(), 273.15 + 20.0); - } - - template - std::vector< std::vector > - phaseSaturations(const Grid& G, - const Region& reg, - const CellRange& cells, - MaterialLawManager& materialLawManager, - const std::vector swat_init, - std::vector< std::vector >& phase_pressures) - { - if (!FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) { - OPM_THROW(std::runtime_error, "Cannot initialise: not handling water-gas cases."); - } - - std::vector< std::vector > phase_saturations = phase_pressures; // Just to get the right size. - - // Adjust oil pressure according to gas saturation and cap pressure - typedef Opm::SimpleModularFluidState SatOnlyFluidState; - - SatOnlyFluidState fluidState; - typedef typename MaterialLawManager::MaterialLaw MaterialLaw; - - const bool water = FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx); - const bool gas = FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx); - const int oilpos = FluidSystem::oilPhaseIdx; - const int waterpos = FluidSystem::waterPhaseIdx; - const int gaspos = FluidSystem::gasPhaseIdx; - std::vector::size_type local_index = 0; - for (typename CellRange::const_iterator ci = cells.begin(); ci != cells.end(); ++ci, ++local_index) { - const int cell = *ci; - const auto& scaledDrainageInfo = - materialLawManager.oilWaterScaledEpsInfoDrainage(cell); - const auto& matParams = materialLawManager.materialLawParams(cell); - - // Find saturations from pressure differences by - // inverting capillary pressure functions. - double sw = 0.0; - if (water) { - if (isConstPc(materialLawManager,FluidSystem::waterPhaseIdx, cell)){ - const double cellDepth = UgGridHelpers::cellCenterDepth(G, - cell); - sw = satFromDepth(materialLawManager,cellDepth,reg.zwoc(),waterpos,cell,false); - phase_saturations[waterpos][local_index] = sw; - } - else{ - const double pcov = phase_pressures[oilpos][local_index] - phase_pressures[waterpos][local_index]; - if (swat_init.empty()) { // Invert Pc to find sw - sw = satFromPc(materialLawManager, waterpos, cell, pcov); - phase_saturations[waterpos][local_index] = sw; - } else { // Scale Pc to reflect imposed sw - sw = swat_init[cell]; - sw = materialLawManager.applySwatinit(cell, pcov, sw); - phase_saturations[waterpos][local_index] = sw; - } - } - } - double sg = 0.0; - if (gas) { - if (isConstPc(materialLawManager,FluidSystem::gasPhaseIdx,cell)){ - const double cellDepth = UgGridHelpers::cellCenterDepth(G, - cell); - sg = satFromDepth(materialLawManager,cellDepth,reg.zgoc(),gaspos,cell,true); - phase_saturations[gaspos][local_index] = sg; - } - else{ - // Note that pcog is defined to be (pg - po), not (po - pg). - const double pcog = phase_pressures[gaspos][local_index] - phase_pressures[oilpos][local_index]; - const double increasing = true; // pcog(sg) expected to be increasing function - sg = satFromPc(materialLawManager, gaspos, cell, pcog, increasing); - phase_saturations[gaspos][local_index] = sg; - } - } - if (gas && water && (sg + sw > 1.0)) { - // Overlapping gas-oil and oil-water transition - // zones can lead to unphysical saturations when - // treated as above. Must recalculate using gas-water - // capillary pressure. - const double pcgw = phase_pressures[gaspos][local_index] - phase_pressures[waterpos][local_index]; - if (! swat_init.empty()) { - // Re-scale Pc to reflect imposed sw for vanishing oil phase. - // This seems consistent with ecl, and fails to honour - // swat_init in case of non-trivial gas-oil cap pressure. - sw = materialLawManager.applySwatinit(cell, pcgw, sw); - } - sw = satFromSumOfPcs(materialLawManager, waterpos, gaspos, cell, pcgw); - sg = 1.0 - sw; - phase_saturations[waterpos][local_index] = sw; - phase_saturations[gaspos][local_index] = sg; - if ( water ) { - fluidState.setSaturation(FluidSystem::waterPhaseIdx, sw); - } - else { - fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0); - } - fluidState.setSaturation(FluidSystem::oilPhaseIdx, 1.0 - sw - sg); - fluidState.setSaturation(FluidSystem::gasPhaseIdx, sg); - - double pC[/*numPhases=*/3] = { 0.0, 0.0, 0.0 }; - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; - phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pcGas; - } - phase_saturations[oilpos][local_index] = 1.0 - sw - sg; - - // Adjust phase pressures for max and min saturation ... - double threshold_sat = 1.0e-6; - - double so = 1.0; - double pC[FluidSystem::numPhases] = { 0.0, 0.0, 0.0 }; - if (water) { - double swu = scaledDrainageInfo.Swu; - fluidState.setSaturation(FluidSystem::waterPhaseIdx, swu); - so -= swu; - } - if (gas) { - double sgu = scaledDrainageInfo.Sgu; - fluidState.setSaturation(FluidSystem::gasPhaseIdx, sgu); - so-= sgu; - } - fluidState.setSaturation(FluidSystem::oilPhaseIdx, so); - - if (water && sw > scaledDrainageInfo.Swu-threshold_sat ) { - fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swu); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; - phase_pressures[oilpos][local_index] = phase_pressures[waterpos][local_index] + pcWat; - } else if (gas && sg > scaledDrainageInfo.Sgu-threshold_sat) { - fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgu); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; - phase_pressures[oilpos][local_index] = phase_pressures[gaspos][local_index] - pcGas; - } - if (gas && sg < scaledDrainageInfo.Sgl+threshold_sat) { - fluidState.setSaturation(FluidSystem::gasPhaseIdx, scaledDrainageInfo.Sgl); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcGas = pC[FluidSystem::oilPhaseIdx] + pC[FluidSystem::gasPhaseIdx]; - phase_pressures[gaspos][local_index] = phase_pressures[oilpos][local_index] + pcGas; - } - if (water && sw < scaledDrainageInfo.Swl+threshold_sat) { - fluidState.setSaturation(FluidSystem::waterPhaseIdx, scaledDrainageInfo.Swl); - MaterialLaw::capillaryPressures(pC, matParams, fluidState); - double pcWat = pC[FluidSystem::oilPhaseIdx] - pC[FluidSystem::waterPhaseIdx]; - phase_pressures[waterpos][local_index] = phase_pressures[oilpos][local_index] - pcWat; - } - } - return phase_saturations; - } - - - /** - * Compute initial Rs values. - * - * \tparam CellRangeType Type of cell range that demarcates the - * cells pertaining to the current - * equilibration region. Must implement - * methods begin() and end() to bound the range - * as well as provide an inner type, - * const_iterator, to traverse the range. - * - * \param[in] grid Grid. - * \param[in] cells Range that spans the cells of the current - * equilibration region. - * \param[in] oil_pressure Oil pressure for each cell in range. - * \param[in] temperature Temperature for each cell in range. - * \param[in] rs_func Rs as function of pressure and depth. - * \return Rs values, one for each cell in the 'cells' range. - */ - template - std::vector computeRs(const Grid& grid, - const CellRangeType& cells, - const std::vector oil_pressure, - const std::vector& temperature, - const Miscibility::RsFunction& rs_func, - const std::vector gas_saturation) - { - assert(UgGridHelpers::dimensions(grid) == 3); - std::vector rs(cells.size()); - int count = 0; - for (auto it = cells.begin(); it != cells.end(); ++it, ++count) { - const double depth = UgGridHelpers::cellCenterDepth(grid, *it); - rs[count] = rs_func(depth, oil_pressure[count], temperature[count], gas_saturation[count]); - } - return rs; - } - - } // namespace Equil - - -} // namespace Opm - -#endif // OPM_INITSTATEEQUIL_IMPL_HEADER_INCLUDED diff --git a/opm/core/utility/RegionMapping.hpp b/opm/core/utility/RegionMapping.hpp deleted file mode 100644 index 63d412b0f..000000000 --- a/opm/core/utility/RegionMapping.hpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - Copyright 2014 SINTEF ICT, Applied Mathematics. - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - -#ifndef OPM_REGIONMAPPING_HEADER_INCLUDED -#define OPM_REGIONMAPPING_HEADER_INCLUDED - -#include - -#include -#include - -namespace Opm -{ - - /** - * Forward and reverse mappings between cells and - * regions/partitions (e.g., the ECLIPSE-style 'SATNUM', - * 'PVTNUM', or 'EQUILNUM' arrays). - * - * \tparam Region Type of a forward region mapping. Expected - * to provide indexed access through - * operator[]() as well as inner types - * 'value_type', 'size_type', and - * 'const_iterator'. - */ - template < class Region = std::vector > - class RegionMapping { - public: - /** - * Constructor. - * - * \param[in] reg Forward region mapping, restricted to - * active cells only. - */ - explicit - RegionMapping(const Region& reg) - : reg_(reg) - { - rev_.init(reg_); - } - - /** - * Type of forward (cell-to-region) mapping result. - * Expected to be an integer. - */ - typedef typename Region::value_type RegionId; - - /** - * Type of reverse (region-to-cell) mapping (element) - * result. - */ - typedef typename Region::size_type CellId; - - /** - * Type of reverse region-to-cell range bounds and - * iterators. - */ - typedef typename std::vector::const_iterator CellIter; - - typedef boost::iterator_range Range; - - /** - * Compute region number of given active cell. - * - * \param[in] c Active cell - * \return Region to which @c c belongs. - */ - RegionId - region(const CellId c) const { return reg_[c]; } - - const std::vector& - activeRegions() const - { - return rev_.active; - } - - /** - * Extract active cells in particular region. - * - * \param[in] r Region number - * - * \return Range of active cells in region @c r. Empty if @c r is - * not an active region. - */ - Range - cells(const RegionId r) const { - const auto id = rev_.binid.find(r); - - if (id == rev_.binid.end()) { - // Region 'r' not an active region. Return empty. - return Range(rev_.c.end(), rev_.c.end()); - } - - const auto i = id->second; - - return Range(rev_.c.begin() + rev_.p[i + 0], - rev_.c.begin() + rev_.p[i + 1]); - } - - private: - /** - * Copy of forward region mapping (cell-to-region). - */ - Region reg_; - - /** - * Reverse mapping (region-to-cell). - */ - struct { - typedef typename std::vector::size_type Pos; - - std::unordered_map binid; - std::vector active; - - std::vector p; /**< Region start pointers */ - std::vector c; /**< Region cells */ - - /** - * Compute reverse mapping. Standard linear insertion - * sort algorithm. - */ - void - init(const Region& reg) - { - binid.clear(); - for (const auto& r : reg) { - ++binid[r]; - } - - p .clear(); p.emplace_back(0); - active.clear(); - { - Pos n = 0; - for (auto& id : binid) { - active.push_back(id.first); - p .push_back(id.second); - - id.second = n++; - } - } - - for (decltype(p.size()) i = 1, sz = p.size(); i < sz; ++i) { - p[0] += p[i]; - p[i] = p[0] - p[i]; - } - - assert (p[0] == static_cast(reg.size())); - - c.resize(reg.size()); - { - CellId i = 0; - for (const auto& r : reg) { - auto& pos = p[ binid[r] + 1 ]; - c[ pos++ ] = i++; - } - } - - p[0] = 0; - } - } rev_; /**< Reverse mapping instance */ - }; - -} // namespace Opm - -#endif // OPM_REGIONMAPPING_HEADER_INCLUDED From adb2783a0c744df3f0a6debefec0594d64ae66d2 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Tue, 2 Jan 2018 14:28:52 +0100 Subject: [PATCH 158/158] restore the hydrostatic equilibration test from opm-core This involved quite a bit of kicking and screaming. The result certainly is not pretty, but it works. --- examples/compute_initial_state.cpp | 174 ----- tests/data/equil_base.DATA | 115 +++ .../equil_capillary.DATA} | 16 +- .../equil_capillary_overlap.DATA} | 0 .../equil_capillary_swatinit.DATA} | 0 .../equil_deadfluids.DATA} | 25 +- tests/{ => data}/equil_livegas.DATA | 0 tests/{ => data}/equil_liveoil.DATA | 0 tests/{ => data}/equil_rsvd_and_rvvd.DATA | 0 tests/{test_equil.cpp => test_equil.cc} | 733 ++++++++---------- tests/test_regionmapping.cpp | 155 ---- 11 files changed, 482 insertions(+), 736 deletions(-) delete mode 100644 examples/compute_initial_state.cpp create mode 100644 tests/data/equil_base.DATA rename tests/{capillary.DATA => data/equil_capillary.DATA} (92%) rename tests/{capillary_overlap.DATA => data/equil_capillary_overlap.DATA} (100%) rename tests/{capillarySwatinit.DATA => data/equil_capillary_swatinit.DATA} (100%) rename tests/{deadfluids.DATA => data/equil_deadfluids.DATA} (90%) rename tests/{ => data}/equil_livegas.DATA (100%) rename tests/{ => data}/equil_liveoil.DATA (100%) rename tests/{ => data}/equil_rsvd_and_rvvd.DATA (100%) rename tests/{test_equil.cpp => test_equil.cc} (57%) delete mode 100644 tests/test_regionmapping.cpp diff --git a/examples/compute_initial_state.cpp b/examples/compute_initial_state.cpp deleted file mode 100644 index a2bae9344..000000000 --- a/examples/compute_initial_state.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - Copyright 2014 SINTEF ICT, Applied Mathematics. - Copyright 2017 IRIS - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif // HAVE_CONFIG_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#include - -namespace -{ - void warnIfUnusedParams(const Opm::ParameterGroup& param) - { - if (param.anyUnused()) { - std::cout << "-------------------- Unused parameters: --------------------\n"; - param.displayUsage(); - std::cout << "----------------------------------------------------------------" << std::endl; - } - } - - void outputData(const std::string& output_dir, - const std::string& name, - const std::vector& data) - { - std::ostringstream fname; - fname << output_dir << "/" << name; - boost::filesystem::path fpath = fname.str(); - try { - create_directories(fpath); - } - catch (...) { - OPM_THROW(std::runtime_error, "Creating directories failed: " << fpath); - } - fname << "/" << "initial.txt"; - std::ofstream file(fname.str().c_str()); - if (!file) { - OPM_THROW(std::runtime_error, "Failed to open " << fname.str()); - } - std::copy(data.begin(), data.end(), std::ostream_iterator(file, "\n")); - } - - /// Convert saturations from a vector of individual phase saturation vectors - /// to an interleaved format where all values for a given cell come before all - /// values for the next cell, all in a single vector. - template - void convertSats(std::vector& sat_interleaved, const std::vector< std::vector >& sat, const Opm::PhaseUsage& pu) - { - assert(sat.size() == 3); - const auto nc = sat[0].size(); - const auto np = sat_interleaved.size() / nc; - for (size_t c = 0; c < nc; ++c) { - if ( FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) { - const int opos = pu.phase_pos[Opm::BlackoilPhases::Liquid]; - const std::vector& sat_p = sat[ FluidSystem::oilPhaseIdx]; - sat_interleaved[np*c + opos] = sat_p[c]; - } - if ( FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { - const int wpos = pu.phase_pos[Opm::BlackoilPhases::Aqua]; - const std::vector& sat_p = sat[ FluidSystem::waterPhaseIdx]; - sat_interleaved[np*c + wpos] = sat_p[c]; - } - if ( FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { - const int gpos = pu.phase_pos[Opm::BlackoilPhases::Vapour]; - const std::vector& sat_p = sat[ FluidSystem::gasPhaseIdx]; - sat_interleaved[np*c + gpos] = sat_p[c]; - } - } - } - -} // anon namespace - -// ----------------- Main program ----------------- -int -main(int argc, char** argv) -try -{ - using namespace Opm; - - // Setup. - ParameterGroup param(argc, argv); - std::cout << "--------------- Reading parameters ---------------" << std::endl; - const std::string deck_filename = param.get("deck_filename"); - Opm::ParseContext parseContext; - Opm::Parser parser; - const Opm::Deck& deck = parser.parseFile(deck_filename , parseContext); - const Opm::EclipseState eclipseState(deck, parseContext); - const double grav = param.getDefault("gravity", unit::gravity); - GridManager gm(eclipseState.getInputGrid()); - const UnstructuredGrid& grid = *gm.c_grid(); - warnIfUnusedParams(param); - - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - - typedef FluidSystems::BlackOil FluidSystem; - - // Forward declaring the MaterialLawManager template. - typedef Opm::ThreePhaseMaterialTraits MaterialTraits; - typedef Opm::EclMaterialLawManager MaterialLawManager; - - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - - // Initialisation. - //initBlackoilSurfvolUsingRSorRV(UgGridHelpers::numCells(grid), props, state); - BlackoilState state( UgGridHelpers::numCells(grid) , UgGridHelpers::numFaces(grid), 3); - FluidSystem::initFromDeck(deck, eclipseState); - PhaseUsage pu = phaseUsageFromDeck(deck); - - typedef EQUIL::DeckDependent::InitialStateComputer ISC; - - ISC isc(materialLawManager, eclipseState, grid, grav); - - const bool oil = FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx); - const int oilpos = FluidSystem::oilPhaseIdx; - const int waterpos = FluidSystem::waterPhaseIdx; - const int ref_phase = oil ? oilpos : waterpos; - - state.pressure() = isc.press()[ref_phase]; - convertSats(state.saturation(), isc.saturation(), pu); - state.gasoilratio() = isc.rs(); - state.rv() = isc.rv(); - - // Output. - const std::string output_dir = param.getDefault("output_dir", "output"); - outputData(output_dir, "pressure", state.pressure()); - outputData(output_dir, "saturation", state.saturation()); - outputData(output_dir, "rs", state.gasoilratio()); - outputData(output_dir, "rv", state.rv()); -} -catch (const std::exception& e) { - std::cerr << "Program threw an exception: " << e.what() << "\n"; - throw; -} diff --git a/tests/data/equil_base.DATA b/tests/data/equil_base.DATA new file mode 100644 index 000000000..740ae0850 --- /dev/null +++ b/tests/data/equil_base.DATA @@ -0,0 +1,115 @@ +RUNSPEC + +WATER +GAS +OIL + +METRIC + +DIMENS + 10 1 10 / + +GRID + +DX + 100*1 / +DY + 100*1 / +DZ + 100*1 / + +TOPS + 10*0. / + +PORO + 100*0.3 / + +PERMX + 100*500 / + +PROPS + +PVTW + 4017.55 1.038 3.22E-6 0.318 0.0 / + +ROCK + 14.7 3E-6 / + +SWOF +0.12 0 1 0 +0.18 4.64876033057851E-008 1 0 +0.24 0.000000186 0.997 0 +0.3 4.18388429752066E-007 0.98 0 +0.36 7.43801652892562E-007 0.7 0 +0.42 1.16219008264463E-006 0.35 0 +0.48 1.67355371900826E-006 0.2 0 +0.54 2.27789256198347E-006 0.09 0 +0.6 2.97520661157025E-006 0.021 0 +0.66 3.7654958677686E-006 0.01 0 +0.72 4.64876033057851E-006 0.001 0 +0.78 0.000005625 0.0001 0 +0.84 6.69421487603306E-006 0 0 +0.91 8.05914256198347E-006 0 0 +1 0.00001 0 0 / + + +SGOF +0 0 1 0 +0.001 0 1 0 +0.02 0 0.997 0 +0.05 0.005 0.980 0 +0.12 0.025 0.700 0 +0.2 0.075 0.350 0 +0.25 0.125 0.200 0 +0.3 0.190 0.090 0 +0.4 0.410 0.021 0 +0.45 0.60 0.010 0 +0.5 0.72 0.001 0 +0.6 0.87 0.0001 0 +0.7 0.94 0.000 0 +0.85 0.98 0.000 0 +0.88 0.984 0.000 0 / + +DENSITY + 53.66 64.49 0.0533 / + +PVDG +14.700 166.666 0.008000 +264.70 12.0930 0.009600 +514.70 6.27400 0.011200 +1014.7 3.19700 0.014000 +2014.7 1.61400 0.018900 +2514.7 1.29400 0.020800 +3014.7 1.08000 0.022800 +4014.7 0.81100 0.026800 +5014.7 0.64900 0.030900 +9014.7 0.38600 0.047000 / + +PVTO +0.0010 14.7 1.0620 1.0400 / +0.0905 264.7 1.1500 0.9750 / +0.1800 514.7 1.2070 0.9100 / +0.3710 1014.7 1.2950 0.8300 / +0.6360 2014.7 1.4350 0.6950 / +0.7750 2514.7 1.5000 0.6410 / +0.9300 3014.7 1.5650 0.5940 / +1.2700 4014.7 1.6950 0.5100 + 9014.7 1.5790 0.7400 / +1.6180 5014.7 1.8270 0.4490 + 9014.7 1.7370 0.6310 / +/ + +SOLUTION + +SWAT + 100*0.0 / + +SGAS + 100*0.0 / + +PRESSURE + 100*300.0 / + +SUMMARY + +SCHEDULE diff --git a/tests/capillary.DATA b/tests/data/equil_capillary.DATA similarity index 92% rename from tests/capillary.DATA rename to tests/data/equil_capillary.DATA index 063db39fe..4289102e5 100644 --- a/tests/capillary.DATA +++ b/tests/data/equil_capillary.DATA @@ -11,7 +11,7 @@ OIL GAS DIMENS -40 40 40 / +1 1 20 / TABDIMS 1 1 40 20 1 20 / @@ -27,16 +27,22 @@ GRID -- specify a fake one... DXV -40*1 / +1*1 / DYV -40*1 / +1*1 / DZV -40*1 / +20*5 / DEPTHZ -1681*123.456 / +4*0.0 / + +PORO + 20*0.3 / + +PERMX + 20*500 / ------------------------------------- PROPS diff --git a/tests/capillary_overlap.DATA b/tests/data/equil_capillary_overlap.DATA similarity index 100% rename from tests/capillary_overlap.DATA rename to tests/data/equil_capillary_overlap.DATA diff --git a/tests/capillarySwatinit.DATA b/tests/data/equil_capillary_swatinit.DATA similarity index 100% rename from tests/capillarySwatinit.DATA rename to tests/data/equil_capillary_swatinit.DATA diff --git a/tests/deadfluids.DATA b/tests/data/equil_deadfluids.DATA similarity index 90% rename from tests/deadfluids.DATA rename to tests/data/equil_deadfluids.DATA index 04264774e..e0d63cb37 100644 --- a/tests/deadfluids.DATA +++ b/tests/data/equil_deadfluids.DATA @@ -7,36 +7,43 @@ RUNSPEC WATER -OIL GAS +OIL + +METRIC DIMENS -3 3 3 / +1 1 10 / TABDIMS 1 1 40 20 1 20 / - + EQLDIMS -- NTEQUL 1 / -------------------------------------- GRID -- Opm::EclipseState assumes that _some_ grid gets defined, so let's -- specify a fake one... DXV -1 2 3 / +1*1 / DYV -4 5 6 / +1*1 / DZV -7 8 9 / +10*1 / -DEPTHZ -16*123.456 / +TOPS +1*0.0 / + +PORO + 10*0.3 / + +PERMX + 10*500 / ------------------------------------- PROPS diff --git a/tests/equil_livegas.DATA b/tests/data/equil_livegas.DATA similarity index 100% rename from tests/equil_livegas.DATA rename to tests/data/equil_livegas.DATA diff --git a/tests/equil_liveoil.DATA b/tests/data/equil_liveoil.DATA similarity index 100% rename from tests/equil_liveoil.DATA rename to tests/data/equil_liveoil.DATA diff --git a/tests/equil_rsvd_and_rvvd.DATA b/tests/data/equil_rsvd_and_rvvd.DATA similarity index 100% rename from tests/equil_rsvd_and_rvvd.DATA rename to tests/data/equil_rsvd_and_rvvd.DATA diff --git a/tests/test_equil.cpp b/tests/test_equil.cc similarity index 57% rename from tests/test_equil.cpp rename to tests/test_equil.cc index 5e33ae536..80a7616d3 100644 --- a/tests/test_equil.cpp +++ b/tests/test_equil.cc @@ -1,45 +1,38 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: /* - Copyright 2014 SINTEF ICT, Applied Mathematics. -*/ + This file is part of the Open Porous Media project (OPM). + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + + Consult the COPYING file in the top-level source directory of this + module for the precise wording of the license and the list of + copyright holders. +*/ #include "config.h" -/* --- Boost.Test boilerplate --- */ -#if HAVE_DYNAMIC_BOOST_TEST -#define BOOST_TEST_DYN_LINK -#endif - -#define NVERBOSE // Suppress own messages when throw()ing - -#define BOOST_TEST_MODULE UnitsTest -#include -#include - -/* --- our own headers --- */ - -#include +#include +#include +#include #include -#include #include -#include -#include - -#include -#include -#include - - -#include -#include -#include -#include -#include -#include -#include #include +#include + #include #include #include @@ -48,28 +41,56 @@ #include #include #include +#include +#define CHECK(value, expected) \ + { \ + if ((value) != (expected)) \ + std::abort(); \ + } -typedef Opm::FluidSystems::BlackOil FluidSystem; -// Forward declaring the MaterialLawManager template. -typedef Opm::ThreePhaseMaterialTraits MaterialTraits; -typedef Opm::EclMaterialLawManager MaterialLawManager; +#define CHECK_CLOSE(value, expected, reltol) \ + { \ + if (std::fabs((expected) - (value)) > 1e-14 && \ + std::fabs(((expected) - (value))/((expected) + (value))) > reltol) \ + std::abort(); \ + } +#define REQUIRE(cond) \ + { \ + if (!(cond)) \ + std::abort(); \ + } -#define CHECK(value, expected, reltol) \ -{ \ - if (std::fabs((expected)) < 1.e-14) \ - BOOST_CHECK_SMALL((value), (reltol)); \ - else \ - BOOST_CHECK_CLOSE((value), (expected), (reltol)); \ +namespace Ewoms { +namespace Properties { +NEW_TYPE_TAG(TestEquilTypeTag, INHERITS_FROM(BlackOilModel, EclBaseProblem)); +}} + +template +std::unique_ptr +initSimulator(const char *filename) +{ + typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator; + + std::string filenameArg = "--ecl-deck-file-name="; + filenameArg += filename; + + const char* argv[] = { + "test_equil", + filenameArg.c_str() + }; + + Ewoms::setupParameters_(/*argc=*/sizeof(argv)/sizeof(argv[0]), argv, /*registerParams=*/false); + + return std::unique_ptr(new Simulator); } -namespace +template +static void initDefaultFluidSystem() { -static void initDefaultFluidSystem() { + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + std::vector > Bo = { { 101353, 1. }, { 6.21542e+07, 1 } @@ -130,13 +151,11 @@ static void initDefaultFluidSystem() { FluidSystem::setWaterPvt(std::move(waterPvt)); FluidSystem::initEnd(); } -} - -BOOST_AUTO_TEST_SUITE () static Opm::EquilRecord mkEquilRecord( double datd, double datp, double zwoc, double pcow_woc, - double zgoc, double pcgo_goc ) { + double zgoc, double pcgo_goc ) +{ using namespace Opm; DeckItem dd( "datdep", double() ); @@ -190,71 +209,74 @@ static Opm::EquilRecord mkEquilRecord( double datd, double datp, return EquilRecord( rec ); } -BOOST_AUTO_TEST_CASE (PhasePressure) +void test_PhasePressure() { typedef std::vector PVal; typedef std::vector PPress; - std::shared_ptr - G(create_grid_cart3d(10, 1, 10), destroy_grid); - auto record = mkEquilRecord( 0, 1e5, 5, 0, 0, 0 ); - initDefaultFluidSystem(); + typedef TTAG(TestEquilTypeTag) TypeTag; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + auto simulator = initSimulator("data/equil_base.DATA"); + initDefaultFluidSystem(); - Opm::EQUIL::EquilReg + Ewoms::EQUIL::EquilReg region(record, - std::make_shared(), - std::make_shared(), + std::make_shared(), + std::make_shared(), 0); - std::vector cells(G->number_of_cells); + std::vector cells(simulator->gridManager().grid().size(0)); std::iota(cells.begin(), cells.end(), 0); const double grav = 10; - const PPress ppress = Opm::EQUIL::phasePressures(*G, region, cells, grav); + const PPress ppress = Ewoms::EQUIL::phasePressures(simulator->gridManager().grid(), region, cells, grav); - const int first = 0, last = G->number_of_cells - 1; + const int first = 0, last = simulator->gridManager().grid().size(0) - 1; const double reltol = 1.0e-8; - BOOST_CHECK_CLOSE(ppress[0][first] , 90e3 , reltol); - BOOST_CHECK_CLOSE(ppress[0][last ] , 180e3 , reltol); - BOOST_CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); - BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); + CHECK_CLOSE(ppress[0][first] , 90e3 , reltol); + CHECK_CLOSE(ppress[0][last ] , 180e3 , reltol); + CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); + CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } -BOOST_AUTO_TEST_CASE (CellSubset) +void test_CellSubset() { typedef std::vector PVal; typedef std::vector PPress; - std::shared_ptr - G(create_grid_cart3d(10, 1, 10), destroy_grid); - - initDefaultFluidSystem(); + typedef TTAG(TestEquilTypeTag) TypeTag; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + auto simulator = initSimulator("data/equil_base.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); + const UnstructuredGrid& grid = *(gm.c_grid()); + initDefaultFluidSystem(); Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - Opm::EQUIL::EquilReg region[] = + Ewoms::EQUIL::EquilReg region[] = { - Opm::EQUIL::EquilReg(record[0], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), 0) , - Opm::EQUIL::EquilReg(record[0], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), 0) , - Opm::EQUIL::EquilReg(record[1], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), 0) , - Opm::EQUIL::EquilReg(record[1], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), 0) }; @@ -263,22 +285,22 @@ BOOST_AUTO_TEST_CASE (CellSubset) for (std::size_t d = 1; d < 3; ++d) { ncoarse *= cdim[d]; } std::vector< std::vector > cells(ncoarse); - for (int c = 0; c < G->number_of_cells; ++c) { + for (int c = 0; c < simulator->gridManager().grid().size(0); ++c) { int ci = c; - const int i = ci % G->cartdims[0]; ci /= G->cartdims[0]; - const int j = ci % G->cartdims[1]; - const int k = ci / G->cartdims[1]; + const int i = ci % grid.cartdims[0]; ci /= grid.cartdims[0]; + const int j = ci % grid.cartdims[1]; + const int k = ci / grid.cartdims[1]; - const int ic = (i / (G->cartdims[0] / cdim[0])); - const int jc = (j / (G->cartdims[1] / cdim[1])); - const int kc = (k / (G->cartdims[2] / cdim[2])); + const int ic = (i / (grid.cartdims[0] / cdim[0])); + const int jc = (j / (grid.cartdims[1] / cdim[1])); + const int kc = (k / (grid.cartdims[2] / cdim[2])); const int ix = ic + cdim[0]*(jc + cdim[1]*kc); assert ((0 <= ix) && (ix < ncoarse)); cells[ix].push_back(c); } - PPress ppress(2, PVal(G->number_of_cells, 0)); + PPress ppress(2, PVal(simulator->gridManager().grid().size(0), 0)); for (std::vector< std::vector >::const_iterator r = cells.begin(), e = cells.end(); r != e; ++r) @@ -286,7 +308,7 @@ BOOST_AUTO_TEST_CASE (CellSubset) const int rno = int(r - cells.begin()); const double grav = 10; const PPress p = - Opm::EQUIL::phasePressures(*G, region[rno], *r, grav); + Ewoms::EQUIL::phasePressures(simulator->gridManager().grid(), region[rno], *r, grav); PVal::size_type i = 0; for (std::vector::const_iterator @@ -300,54 +322,51 @@ BOOST_AUTO_TEST_CASE (CellSubset) } } - const int first = 0, last = G->number_of_cells - 1; + const int first = 0, last = simulator->gridManager().grid().size(0) - 1; const double reltol = 1.0e-8; - BOOST_CHECK_CLOSE(ppress[0][first] , 105e3 , reltol); - BOOST_CHECK_CLOSE(ppress[0][last ] , 195e3 , reltol); - BOOST_CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); - BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); + CHECK_CLOSE(ppress[0][first] , 105e3 , reltol); + CHECK_CLOSE(ppress[0][last ] , 195e3 , reltol); + CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); + CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } - - - -BOOST_AUTO_TEST_CASE (RegMapping) +void test_RegMapping() { typedef std::vector PVal; typedef std::vector PPress; - std::shared_ptr - G(create_grid_cart3d(10, 1, 10), destroy_grid); - Opm::EquilRecord record[] = { mkEquilRecord( 0, 1e5, 2.5, -0.075e5, 0, 0 ), mkEquilRecord( 5, 1.35e5, 7.5, -0.225e5, 5, 0 ) }; - initDefaultFluidSystem(); + typedef TTAG(TestEquilTypeTag) TypeTag; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + auto simulator = initSimulator("data/equil_base.DATA"); + initDefaultFluidSystem(); - Opm::EQUIL::EquilReg region[] = + Ewoms::EQUIL::EquilReg region[] = { - Opm::EQUIL::EquilReg(record[0], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), 0) , - Opm::EQUIL::EquilReg(record[0], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[0], + std::make_shared(), + std::make_shared(), 0) , - Opm::EQUIL::EquilReg(record[1], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), 0) , - Opm::EQUIL::EquilReg(record[1], - std::make_shared(), - std::make_shared(), + Ewoms::EQUIL::EquilReg(record[1], + std::make_shared(), + std::make_shared(), 0) }; - std::vector eqlnum(G->number_of_cells); + std::vector eqlnum(simulator->gridManager().grid().size(0)); // [ 0 1; 2 3] { for (int i = 0; i < 5; ++i) { @@ -368,16 +387,16 @@ BOOST_AUTO_TEST_CASE (RegMapping) } } - Opm::RegionMapping<> eqlmap(eqlnum); + Ewoms::RegionMapping<> eqlmap(eqlnum); - PPress ppress(2, PVal(G->number_of_cells, 0)); + PPress ppress(2, PVal(simulator->gridManager().grid().size(0), 0)); for (const auto& r : eqlmap.activeRegions()) { const auto& rng = eqlmap.cells(r); const int rno = r; const double grav = 10; const PPress p = - Opm::EQUIL::phasePressures(*G, region[rno], rng, grav); + Ewoms::EQUIL::phasePressures(simulator->gridManager().grid(), region[rno], rng, grav); PVal::size_type i = 0; for (const auto& c : rng) { @@ -390,76 +409,47 @@ BOOST_AUTO_TEST_CASE (RegMapping) } } - const int first = 0, last = G->number_of_cells - 1; + const int first = 0, last = simulator->gridManager().grid().size(0) - 1; const double reltol = 1.0e-8; - BOOST_CHECK_CLOSE(ppress[0][first] , 105e3 , reltol); - BOOST_CHECK_CLOSE(ppress[0][last ] , 195e3 , reltol); - BOOST_CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); - BOOST_CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); + CHECK_CLOSE(ppress[0][first] , 105e3 , reltol); + CHECK_CLOSE(ppress[0][last ] , 195e3 , reltol); + CHECK_CLOSE(ppress[1][first] , 103.5e3 , reltol); + CHECK_CLOSE(ppress[1][last ] , 166.5e3 , reltol); } - - -BOOST_AUTO_TEST_CASE (DeckAllDead) +void test_DeckAllDead() { - std::shared_ptr - grid(create_grid_cart3d(1, 1, 10), destroy_grid); - Opm::ParseContext parseContext; - Opm::Parser parser; - Opm::Deck deck = parser.parseFile("deadfluids.DATA" , parseContext); - Opm::EclipseState eclipseState(deck, parseContext); // Create material law manager. + typedef TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_deadfluids.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); + const UnstructuredGrid& grid = *(gm.c_grid()); - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid->number_of_cells, grid->global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - - typedef Opm::FluidSystems::BlackOil FluidSystem; - - // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); - - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, *grid, 10.0); + Ewoms::EQUIL::DeckDependent::InitialStateComputer comp(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 10.0); const auto& pressures = comp.press(); - BOOST_REQUIRE(pressures.size() == 3); - BOOST_REQUIRE(int(pressures[0].size()) == grid->number_of_cells); + REQUIRE(pressures.size() == 3); + REQUIRE(int(pressures[0].size()) == grid.number_of_cells); - const int first = 0, last = grid->number_of_cells - 1; + const int first = 0, last = grid.number_of_cells - 1; // The relative tolerance is too loose to be very useful, // but the answer we are checking is the result of an ODE // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-3; - BOOST_CHECK_CLOSE(pressures[0][first] , 1.496329839e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 1.504526940e7 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 1.504526940e7 , reltol); + CHECK_CLOSE(pressures[0][first] , 1.496329839e7 , reltol); + CHECK_CLOSE(pressures[0][last ] , 1.504526940e7 , reltol); + CHECK_CLOSE(pressures[1][last] , 1.504526940e7 , reltol); } - - -BOOST_AUTO_TEST_CASE (CapillaryInversion) +void test_CapillaryInversion() { // Test setup. - Opm::GridManager gm(1, 1, 40, 1.0, 1.0, 2.5); - const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::Parser parser; - Opm::ParseContext parseContext; - Opm::Deck deck = parser.parseFile("capillary.DATA" , parseContext); - Opm::EclipseState eclipseState(deck , parseContext); + typedef typename TTAG(TestEquilTypeTag) TypeTag; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw; + typedef typename GET_PROP(TypeTag, MaterialLaw)::EclMaterialLawManager MaterialLawManager; + auto simulator = initSimulator("data/equil_capillary.DATA"); - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - - typedef Opm::FluidSystems::BlackOil FluidSystem; - typedef MaterialLawManager::MaterialLaw MaterialLaw; - - if (!FluidSystem::isInitialized()) { - // make sure that we don't initialize the fluid system twice - FluidSystem::initFromDeck(deck, eclipseState); - } // Test the capillary inversion for oil-water. const int cell = 0; const double reltol = 1.0e-7; @@ -468,10 +458,10 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const bool increasing = false; const std::vector pc = { 10.0e5, 0.5e5, 0.4e5, 0.3e5, 0.2e5, 0.1e5, 0.099e5, 0.0e5, -10.0e5 }; const std::vector s = { 0.2, 0.2, 0.2, 0.466666666666, 0.733333333333, 1.0, 1.0, 1.0, 1.0 }; - BOOST_REQUIRE(pc.size() == s.size()); + REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::EQUIL::satFromPc(materialLawManager, phase, cell, pc[i], increasing); - BOOST_CHECK_CLOSE(s_computed, s[i], reltol); + const double s_computed = Ewoms::EQUIL::satFromPc(*simulator->problem().materialLawManager(), phase, cell, pc[i], increasing); + CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -481,10 +471,10 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const bool increasing = true; const std::vector pc = { 10.0e5, 0.6e5, 0.5e5, 0.4e5, 0.3e5, 0.2e5, 0.1e5, 0.0e5, -10.0e5 }; const std::vector s = { 0.8, 0.8, 0.8, 0.533333333333, 0.266666666666, 0.0, 0.0, 0.0, 0.0 }; - BOOST_REQUIRE(pc.size() == s.size()); + REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::EQUIL::satFromPc(materialLawManager, phase, cell, pc[i], increasing); - BOOST_CHECK_CLOSE(s_computed, s[i], reltol); + const double s_computed = Ewoms::EQUIL::satFromPc(*simulator->problem().materialLawManager(), phase, cell, pc[i], increasing); + CHECK_CLOSE(s_computed, s[i], reltol); } } @@ -494,41 +484,27 @@ BOOST_AUTO_TEST_CASE (CapillaryInversion) const int gas = 2; const std::vector pc = { 0.9e5, 0.8e5, 0.6e5, 0.4e5, 0.3e5 }; const std::vector s = { 0.2, 0.333333333333, 0.6, 0.866666666666, 1.0 }; - BOOST_REQUIRE(pc.size() == s.size()); + REQUIRE(pc.size() == s.size()); for (size_t i = 0; i < pc.size(); ++i) { - const double s_computed = Opm::EQUIL::satFromSumOfPcs(materialLawManager, water, gas, cell, pc[i]); - BOOST_CHECK_CLOSE(s_computed, s[i], reltol); + const double s_computed = Ewoms::EQUIL::satFromSumOfPcs(*simulator->problem().materialLawManager(), water, gas, cell, pc[i]); + CHECK_CLOSE(s_computed, s[i], reltol); } } } - - -BOOST_AUTO_TEST_CASE (DeckWithCapillary) +void test_DeckWithCapillary() { - Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + typedef typename TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_capillary.DATA"); + auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::Parser parser; - Opm::ParseContext parseContext; - Opm::Deck deck = parser.parseFile("capillary.DATA" , parseContext); - Opm::EclipseState eclipseState(deck , parseContext); - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - - typedef Opm::FluidSystems::BlackOil FluidSystem; - - // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); - - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 10.0); + Ewoms::EQUIL::DeckDependent::InitialStateComputer comp(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 10.0); const auto& pressures = comp.press(); - BOOST_REQUIRE(pressures.size() == 3); - BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + REQUIRE(pressures.size() == 3); + REQUIRE(int(pressures[0].size()) == grid.number_of_cells); const int first = 0, last = grid.number_of_cells - 1; // The relative tolerance is too loose to be very useful, @@ -536,9 +512,9 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) // solver, and it is unclear if we should check it against // the true answer or something else. const double reltol = 1.0e-6; - BOOST_CHECK_CLOSE(pressures[0][first] , 1.469769063e7 , reltol); - BOOST_CHECK_CLOSE(pressures[0][last ] , 15452880.328284413 , reltol); - BOOST_CHECK_CLOSE(pressures[1][last] , 15462880.328284413 , reltol); + CHECK_CLOSE(pressures[0][first] , 1.469769063e7 , reltol); + CHECK_CLOSE(pressures[0][last ] , 15452880.328284413 , reltol); + CHECK_CLOSE(pressures[1][last] , 15462880.328284413 , reltol); const auto& sats = comp.saturation(); const std::vector s[3]{ @@ -547,39 +523,25 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillary) { 0.8, 0.8, 0.8, 0.79265183888768165, 0.0072772917691866562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s[phase].size()); + REQUIRE(sats[phase].size() == s[phase].size()); for (size_t i = 0; i < s[phase].size(); ++i) { - CHECK(sats[phase][i], s[phase][i], reltol); + CHECK_CLOSE(sats[phase][i], s[phase][i], reltol); } } } - - -BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) +void test_DeckWithCapillaryOverlap() { - Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + typedef typename TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_capillary_overlap.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::Parser parser; - Opm::ParseContext parseContext; - Opm::Deck deck = parser.parseFile("capillary_overlap.DATA" , parseContext); - Opm::EclipseState eclipseState(deck , parseContext); - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - typedef Opm::FluidSystems::BlackOil FluidSystem; - - // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); - - - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); + Ewoms::EQUIL::DeckDependent::InitialStateComputer comp(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 9.80665); const auto& pressures = comp.press(); - BOOST_REQUIRE(pressures.size() == 3); - BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + REQUIRE(pressures.size() == 3); + REQUIRE(int(pressures[0].size()) == grid.number_of_cells); const int first = 0, last = grid.number_of_cells - 1; // The relative tolerance is too loose to be very useful, @@ -588,14 +550,14 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) // the true answer or something else. const double reltol = 1.0e-6; const double reltol_ecl = 1.0; - BOOST_CHECK_CLOSE(pressures[0][first], 1.48324e+07, reltol_ecl); // eclipse - BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][first], 1.49224e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); - - BOOST_CHECK_CLOSE(pressures[0][first] , 14832467.14, reltol); // opm - BOOST_CHECK_CLOSE(pressures[0][last ] , 15479883.47, reltol); - BOOST_CHECK_CLOSE(pressures[1][last ] , 15489883.47, reltol); + CHECK_CLOSE(pressures[0][first], 1.48324e+07, reltol_ecl); // eclipse + CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][first], 1.49224e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); + + CHECK_CLOSE(pressures[0][first] , 14832467.14, reltol); // opm + CHECK_CLOSE(pressures[0][last ] , 15479883.47, reltol); + CHECK_CLOSE(pressures[1][last ] , 15489883.47, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; @@ -605,52 +567,41 @@ BOOST_AUTO_TEST_CASE (DeckWithCapillaryOverlap) // } // std::cout << std::endl; // } - + const std::vector s_ecl[3]{// eclipse { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22874042, 0.53397995, 0.78454906, 0.91542006, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20039, 0.08458, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77125955, 0.46602005, 0.015063271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - const std::vector s_opm[3]{ // opm + const std::vector s_opm[3]{ // opm { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22892931226886132, 0.53406457830052489, 0.78457075254244724, 0.91539712466977541, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20023624994125844, 0.084602875330224592, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77107068773113863, 0.46593542169947511, 0.015192997516294321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); - CHECK(sats[phase][i], s_opm[phase][i], reltol); + CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); } } } - - -BOOST_AUTO_TEST_CASE (DeckWithLiveOil) +void test_DeckWithLiveOil() { - Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + typedef typename TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_liveoil.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::Parser parser; - Opm::ParseContext parseContext; - Opm::Deck deck = parser.parseFile("equil_liveoil.DATA" , parseContext); - Opm::EclipseState eclipseState(deck , parseContext); - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - - typedef Opm::FluidSystems::BlackOil FluidSystem; // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); + Ewoms::EQUIL::DeckDependent::InitialStateComputer comp(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 9.80665); const auto& pressures = comp.press(); - BOOST_REQUIRE(pressures.size() == 3); - BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + REQUIRE(pressures.size() == 3); + REQUIRE(int(pressures[0].size()) == grid.number_of_cells); const int first = 0, last = grid.number_of_cells - 1; // The relative tolerance is too loose to be very useful, @@ -659,15 +610,15 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) // the true answer or something else. const double reltol = 1.0e-6; const double reltol_ecl = 1.0; - BOOST_CHECK_CLOSE(pressures[0][first], 1.48324e+07, reltol_ecl); // eclipse - BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][first], 1.49224e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); - - BOOST_CHECK_CLOSE(pressures[0][first], 1.483246714e7, reltol); // opm - BOOST_CHECK_CLOSE(pressures[0][last], 1.547991652e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][first], 1.492246714e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][last], 1.548991652e7, reltol); + CHECK_CLOSE(pressures[0][first], 1.48324e+07, reltol_ecl); // eclipse + CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][first], 1.49224e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); + + CHECK_CLOSE(pressures[0][first], 1.483246714e7, reltol); // opm + CHECK_CLOSE(pressures[0][last], 1.547991652e7, reltol); + CHECK_CLOSE(pressures[1][first], 1.492246714e7, reltol); + CHECK_CLOSE(pressures[1][last], 1.548991652e7, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; @@ -682,64 +633,51 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveOil) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20073, 0.08469, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77102, 0.46578, 0.01458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - const std::vector s_opm[3]{ // opm + const std::vector s_opm[3]{ // opm { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22916963446461344, 0.53430490523774521, 0.78471886612242092, 0.91528324362210933, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20057438297017782, 0.084716756377890667, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77083036553538653, 0.46569509476225479, 0.014706750907401245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - CHECK(sats[phase][i], s_opm[phase][i], reltol); - CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); + CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } - + const auto& rs = comp.rs(); const std::vector rs_opm {74.61233568, 74.64905212, 74.68578656, 74.72253902, // opm 74.75930951, 74.79609803, 74.83290459, 74.87519876, - 74.96925416, 75.09067512, 75.0, 75.0, - 75.0, 75.0, 75.0, 75.0, + 74.96925416, 75.09067512, 75.0, 75.0, + 75.0, 75.0, 75.0, 75.0, 75.0, 75.0, 75.0, 75.0}; const std::vector rs_ecl {74.612228, 74.648956, 74.685707, 74.722473, // eclipse 74.759254, 74.796051, 74.832870, 74.875145, 74.969231, 75.090706, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, 75.000000, - 75.000000, 75.000000, 75.000000, 75.000000}; + 75.000000, 75.000000, 75.000000, 75.000000}; for (size_t i = 0; i < rs_opm.size(); ++i) { //std::cout << std::setprecision(10) << rs[i] << '\n'; - BOOST_CHECK_CLOSE(rs[i], rs_opm[i], reltol); - BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); + CHECK_CLOSE(rs[i], rs_opm[i], reltol); + CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); } } - - -BOOST_AUTO_TEST_CASE (DeckWithLiveGas) +void test_DeckWithLiveGas() { - Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + typedef typename TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_livegas.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::Parser parser; - Opm::ParseContext parseContext; - Opm::Deck deck = parser.parseFile("equil_livegas.DATA" , parseContext); - Opm::EclipseState eclipseState(deck , parseContext); - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - typedef Opm::FluidSystems::BlackOil FluidSystem; - - // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); - - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); + Ewoms::EQUIL::DeckDependent::InitialStateComputer comp(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 9.80665); const auto& pressures = comp.press(); - BOOST_REQUIRE(pressures.size() == 3); - BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + REQUIRE(pressures.size() == 3); + REQUIRE(int(pressures[0].size()) == grid.number_of_cells); const int first = 0, last = grid.number_of_cells - 1; // The relative tolerance is too loose to be very useful, @@ -748,15 +686,15 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) // the true answer or something else. const double reltol = 1.0e-3; const double reltol_ecl = 1.0; - BOOST_CHECK_CLOSE(pressures[0][first], 1.48215e+07, reltol_ecl); // eclipse - BOOST_CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][first], 1.49115e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); - - BOOST_CHECK_CLOSE(pressures[0][first], 1.482150311e7, reltol); // opm - BOOST_CHECK_CLOSE(pressures[0][last], 1.547988347e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][first], 1.491150311e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][last], 1.548988347e7, reltol); + CHECK_CLOSE(pressures[0][first], 1.48215e+07, reltol_ecl); // eclipse + CHECK_CLOSE(pressures[0][last], 1.54801e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][first], 1.49115e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][last], 1.54901e+07, reltol_ecl); + + CHECK_CLOSE(pressures[0][first], 1.482150311e7, reltol); // opm + CHECK_CLOSE(pressures[0][last], 1.547988347e7, reltol); + CHECK_CLOSE(pressures[1][first], 1.491150311e7, reltol); + CHECK_CLOSE(pressures[1][last], 1.548988347e7, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; @@ -772,27 +710,27 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.75714386, 0.46130988, 0.032345835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - const std::vector s_opm[3]{ // opm + const std::vector s_opm[3]{ // opm { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.24310545, 0.5388, 0.78458, 0.91540, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.18288667, 0.0846, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.75689455, 0.4612, 0.03253333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - CHECK(sats[phase][i], s_opm[phase][i], 100.*reltol); - CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK_CLOSE(sats[phase][i], s_opm[phase][i], 100.*reltol); + CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } - + const auto& rv = comp.rv(); const std::vector rv_opm { // opm 2.4884509e-4, 2.4910378e-4, 2.4936267e-4, 2.4962174e-4, - 2.4988100e-4, 2.5014044e-4, 2.5040008e-4, 2.5065990e-4, - 2.5091992e-4, 2.5118012e-4, 2.5223082e-4, 2.5105e-4, - 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4, + 2.4988100e-4, 2.5014044e-4, 2.5040008e-4, 2.5065990e-4, + 2.5091992e-4, 2.5118012e-4, 2.5223082e-4, 2.5105e-4, + 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4, 2.5105e-4}; const std::vector rv_ecl { // eclipse @@ -801,36 +739,25 @@ BOOST_AUTO_TEST_CASE (DeckWithLiveGas) 0.25091995E-03, 0.25118008E-03, 0.25223137E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03, 0.25104999E-03}; - + for (size_t i = 0; i < rv_opm.size(); ++i) { - CHECK(rv[i], rv_opm[i], reltol); - CHECK(rv[i], rv_ecl[i], reltol_ecl); + CHECK_CLOSE(rv[i], rv_opm[i], reltol); + CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); } } -BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) +void test_DeckWithRSVDAndRVVD() { - Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); + typedef typename TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_rsvd_and_rvvd.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); + Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); - Opm::ParseContext parseContext; - Opm::Parser parser; - Opm::Deck deck = parser.parseFile("equil_rsvd_and_rvvd.DATA", parseContext); - Opm::EclipseState eclipseState(deck , parseContext); - // Create material law manager. - std::vector compressedToCartesianIdx - = Opm::compressedToCartesian(grid.number_of_cells, grid.global_cell); - MaterialLawManager materialLawManager = MaterialLawManager(); - materialLawManager.initFromDeck(deck, eclipseState, compressedToCartesianIdx); - typedef Opm::FluidSystems::BlackOil FluidSystem; - - // Initialize the fluid system - FluidSystem::initFromDeck(deck, eclipseState); - - Opm::EQUIL::DeckDependent::InitialStateComputer comp(materialLawManager, eclipseState, grid, 9.80665); + Ewoms::EQUIL::DeckDependent::InitialStateComputer comp(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 9.80665); const auto& pressures = comp.press(); - BOOST_REQUIRE(pressures.size() == 3); - BOOST_REQUIRE(int(pressures[0].size()) == grid.number_of_cells); + REQUIRE(pressures.size() == 3); + REQUIRE(int(pressures[0].size()) == grid.number_of_cells); const int first = 0, last = grid.number_of_cells - 1; // The relative tolerance is too loose to be very useful, @@ -839,15 +766,15 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) // the true answer or something else. const double reltol = 1.0e-6; const double reltol_ecl = 1.0; - BOOST_CHECK_CLOSE(pressures[0][first], 1.48350e+07, reltol_ecl); // eclipse - BOOST_CHECK_CLOSE(pressures[0][last], 1.54794e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][first], 1.49250e+07, reltol_ecl); - BOOST_CHECK_CLOSE(pressures[1][last], 1.54894e+07, reltol_ecl); - - BOOST_CHECK_CLOSE(pressures[0][first], 1.483499660e7, reltol); // opm - BOOST_CHECK_CLOSE(pressures[0][last], 1.547924516e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][first], 1.492499660e7, reltol); - BOOST_CHECK_CLOSE(pressures[1][last], 1.548924516e7, reltol); + CHECK_CLOSE(pressures[0][first], 1.48350e+07, reltol_ecl); // eclipse + CHECK_CLOSE(pressures[0][last], 1.54794e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][first], 1.49250e+07, reltol_ecl); + CHECK_CLOSE(pressures[1][last], 1.54894e+07, reltol_ecl); + + CHECK_CLOSE(pressures[0][first], 1.483499660e7, reltol); // opm + CHECK_CLOSE(pressures[0][last], 1.547924516e7, reltol); + CHECK_CLOSE(pressures[1][first], 1.492499660e7, reltol); + CHECK_CLOSE(pressures[1][last], 1.548924516e7, reltol); const auto& sats = comp.saturation(); // std::cout << "Saturations:\n"; @@ -863,22 +790,22 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77793652, 0.47128031, 0.021931054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - const std::vector s_opm[3]{ // opm + const std::vector s_opm[3]{ // opm { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.22231423543119974, 0.52882640735211706, 0.78152142505479982, 0.91816512259416283, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.19636279642563928, 0.08183487740583717, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.77768576456880023, 0.47117359264788294, 0.022115778519560897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; - + for (int phase = 0; phase < 3; ++phase) { - BOOST_REQUIRE(sats[phase].size() == s_opm[phase].size()); + REQUIRE(sats[phase].size() == s_opm[phase].size()); for (size_t i = 0; i < s_opm[phase].size(); ++i) { //std::cout << std::setprecision(10) << sats[phase][i] << '\n'; - CHECK(sats[phase][i], s_opm[phase][i], reltol); - CHECK(sats[phase][i], s_ecl[phase][i], reltol_ecl); + CHECK_CLOSE(sats[phase][i], s_opm[phase][i], reltol); + CHECK_CLOSE(sats[phase][i], s_ecl[phase][i], reltol_ecl); } std::cout << std::endl; } - + const auto& rs = comp.rs(); const std::vector rs_opm { // opm 74.62498302, 74.65959041, 74.69438035, 74.72935336, @@ -893,13 +820,13 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) 74.968628, 75.088951, 52.500000, 57.500000, 62.500000, 67.500000, 72.500000, 76.168388, 76.349953, 76.531532, 76.713142, 76.894775,}; - + const auto& rv = comp.rv(); const std::vector rv_opm { // opm 2.50e-6, 7.50e-6, 1.25e-5, 1.75e-5, - 2.25e-5, 2.75e-5, 3.25e-5, 3.75e-5, - 4.25e-5, 2.51158386e-4, 2.52203372e-4, 5.75e-5, - 6.25e-5, 6.75e-5, 7.25e-5, 7.75e-5, + 2.25e-5, 2.75e-5, 3.25e-5, 3.75e-5, + 4.25e-5, 2.51158386e-4, 2.52203372e-4, 5.75e-5, + 6.25e-5, 6.75e-5, 7.25e-5, 7.75e-5, 8.25e-5, 8.75e-5, 9.25e-5, 9.75e-5}; const std::vector rv_ecl { // eclipse @@ -908,23 +835,22 @@ BOOST_AUTO_TEST_CASE (DeckWithRSVDAndRVVD) 0.42500000E-04, 0.25115837E-03, 0.25220393E-03, 0.57500001E-04, 0.62500003E-04, 0.67499997E-04, 0.72499999E-04, 0.77500001E-04, 0.82500002E-04, 0.87499997E-04, 0.92499999E-04, 0.97500000E-04}; - + for (size_t i = 0; i < rv_opm.size(); ++i) { //std::cout << std::setprecision(10) << rs[i] << '\n'; - BOOST_CHECK_CLOSE(rs[i], rs_opm[i], reltol); - BOOST_CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); - BOOST_CHECK_CLOSE(rv[i], rv_opm[i], reltol); - BOOST_CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); + CHECK_CLOSE(rs[i], rs_opm[i], reltol); + CHECK_CLOSE(rs[i], rs_ecl[i], reltol_ecl); + CHECK_CLOSE(rv[i], rv_opm[i], reltol); + CHECK_CLOSE(rv[i], rv_ecl[i], reltol_ecl); } } -BOOST_AUTO_TEST_CASE (DeckWithSwatinit) +void test_DeckWithSwatinit() { - //Opm::GridManager gm(1, 1, 20, 1.0, 1.0, 5.0); - Opm::Parser parser; - Opm::ParseContext parseContext; - Opm::Deck deck = parser.parseFile("capillarySwatinit.DATA" , parseContext); - Opm::EclipseState eclipseState(deck , parseContext); +#if 0 + typedef typename TTAG(TestEquilTypeTag) TypeTag; + auto simulator = initSimulator("data/equil_capillary_swatinit.DATA"); + const auto& eclipseState = simulator->gridManager().eclState(); Opm::GridManager gm(eclipseState.getInputGrid()); const UnstructuredGrid& grid = *(gm.c_grid()); @@ -953,17 +879,17 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) // Adjust oil pressure according to gas saturation and cap pressure typedef Opm::SimpleModularFluidState SatOnlyFluidState; + /*numPhases=*/3, + /*numComponents=*/3, + FluidSystem, + /*storePressure=*/false, + /*storeTemperature=*/false, + /*storeComposition=*/false, + /*storeFugacity=*/false, + /*storeSaturation=*/true, + /*storeDensity=*/false, + /*storeViscosity=*/false, + /*storeEnthalpy=*/false> SatOnlyFluidState; SatOnlyFluidState fluidState; typedef MaterialLawManager::MaterialLaw MaterialLaw; @@ -1008,9 +934,9 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) // compute the initial state // apply swatinit - Opm::EQUIL::DeckDependent::InitialStateComputer compScaled(materialLawManagerScaled, eclipseState, grid, 9.81, true); + Ewoms::EQUIL::DeckDependent::InitialStateComputer compScaled(materialLawManagerScaled, eclipseState, simulator->gridManager().grid(), 9.81, true); // don't apply swatinit - Opm::EQUIL::DeckDependent::InitialStateComputer compUnscaled(materialLawManager, eclipseState, grid, 9.81, false); + Ewoms::EQUIL::DeckDependent::InitialStateComputer compUnscaled(*simulator->problem().materialLawManager(), eclipseState, simulator->gridManager().grid(), 9.81, false); // compute pc std::vector pc_scaled(numCells * FluidSystem::numPhases); @@ -1051,17 +977,38 @@ BOOST_AUTO_TEST_CASE (DeckWithSwatinit) const double reltol = 1.0e-3; for (int phase = 0; phase < 3; ++phase) { for (size_t i = 0; i < 20; ++i) { - CHECK( pc_original[3*i + phase ], pc_unscaled[3*i + phase ], reltol); - CHECK( pc_scaled_truth[3*i + phase], pc_scaled[3*i + phase ], reltol); + CHECK_CLOSE( pc_original[3*i + phase ], pc_unscaled[3*i + phase ], reltol); + CHECK_CLOSE( pc_scaled_truth[3*i + phase], pc_scaled[3*i + phase ], reltol); } } for (int phase = 0; phase < 3; ++phase) { for (size_t i = 0; i < 20; ++i) { - CHECK(compUnscaled.saturation()[phase][i], s[phase][i], reltol); - CHECK(compScaled.saturation()[phase][i], swatinit[phase][i], reltol); + CHECK_CLOSE(compUnscaled.saturation()[phase][i], s[phase][i], reltol); + CHECK_CLOSE(compScaled.saturation()[phase][i], swatinit[phase][i], reltol); } } +#endif } -BOOST_AUTO_TEST_SUITE_END() +int main(int argc, char** argv) +{ + Dune::MPIHelper::instance(argc, argv); + + typedef TTAG(TestEquilTypeTag) TypeTag; + Ewoms::registerAllParameters_(); + + test_PhasePressure(); + test_CellSubset(); + test_RegMapping(); + test_DeckAllDead(); + test_CapillaryInversion(); + test_DeckWithCapillary(); + test_DeckWithCapillaryOverlap(); + test_DeckWithLiveOil(); + test_DeckWithLiveGas(); + test_DeckWithRSVDAndRVVD(); + //test_DeckWithSwatinit(); + + return 0; +} diff --git a/tests/test_regionmapping.cpp b/tests/test_regionmapping.cpp deleted file mode 100644 index 760a719f9..000000000 --- a/tests/test_regionmapping.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - Copyright 2014 SINTEF ICT, Applied Mathematics. - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ - -#include "config.h" - -/* --- Boost.Test boilerplate --- */ -#if HAVE_DYNAMIC_BOOST_TEST -#define BOOST_TEST_DYN_LINK -#endif - -#define NVERBOSE // Suppress own messages when throw()ing - -#define BOOST_TEST_MODULE RegionMapping - -#include -#include -#include - -/* --- our own headers --- */ - -#include - -#include -#include - -BOOST_AUTO_TEST_SUITE () - - -BOOST_AUTO_TEST_CASE (Forward) -{ - std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; - - Opm::RegionMapping<> rm(regions); - - for (decltype(regions.size()) i = 0, n = regions.size(); i < n; ++i) { - BOOST_CHECK_EQUAL(rm.region(i), regions[i]); - } -} - - -BOOST_AUTO_TEST_CASE (ActiveRegions) -{ - // 0 1 2 3 4 5 6 7 8 - std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; - - Opm::RegionMapping<> rm(regions); - - std::vector region_ids = { 2, 3, 4, 5, 6, 7 }; - - auto active = [®ion_ids](const int reg) - { - auto b = region_ids.begin(); - auto e = region_ids.end(); - - return std::find(b, e, reg) != e; - }; - - BOOST_CHECK_EQUAL(rm.activeRegions().size(), region_ids.size()); - - for (const auto& reg : rm.activeRegions()) { - BOOST_CHECK(active(reg)); - } -} - - -BOOST_AUTO_TEST_CASE (Consecutive) -{ - using RegionCells = std::map>; - - // 0 1 2 3 4 5 6 7 8 - std::vector regions = { 2, 5, 2, 4, 2, 7, 6, 3, 6 }; - - Opm::RegionMapping<> rm(regions); - - std::vector region_ids = { 2, 3, 4, 5, 6, 7 }; - RegionCells region_cells; - { - using VT = RegionCells::value_type; - - region_cells.insert(VT(2, { 0, 2, 4 })); - region_cells.insert(VT(3, { 7 })); - region_cells.insert(VT(4, { 3 })); - region_cells.insert(VT(5, { 1 })); - region_cells.insert(VT(6, { 6, 8 })); - region_cells.insert(VT(7, { 5 })); - } - - for (const auto& reg : region_ids) { - const auto& cells = rm.cells(reg); - const auto& expect = region_cells[reg]; - - BOOST_CHECK_EQUAL_COLLECTIONS(cells .begin(), cells .end(), - expect.begin(), expect.end()); - } - - // Verify that there are no cells in unused regions 0 and 1. - for (const auto& r : { 0, 1 }) { - BOOST_CHECK(rm.cells(r).empty()); - } -} - - -BOOST_AUTO_TEST_CASE (NonConsecutive) -{ - using RegionCells = std::map>; - - // 0 1 2 3 4 5 6 7 8 - std::vector regions = { 2, 4, 2, 4, 2, 7, 6, 3, 6 }; - - Opm::RegionMapping<> rm(regions); - - std::vector region_ids = { 2, 3, 4, 6, 7 }; - RegionCells region_cells; - { - using VT = RegionCells::value_type; - - region_cells.insert(VT(2, { 0, 2, 4 })); - region_cells.insert(VT(3, { 7 })); - region_cells.insert(VT(4, { 1, 3 })); - region_cells.insert(VT(6, { 6, 8 })); - region_cells.insert(VT(7, { 5 })); - } - - for (const auto& reg : region_ids) { - const auto& cells = rm.cells(reg); - const auto& expect = region_cells[reg]; - - BOOST_CHECK_EQUAL_COLLECTIONS(cells .begin(), cells .end(), - expect.begin(), expect.end()); - } - - // Verify that there are no cells in unused regions 0, 1, and 5. - for (const auto& r : { 0, 1, 5 }) { - BOOST_CHECK(rm.cells(r).empty()); - } -} - - -BOOST_AUTO_TEST_SUITE_END()