Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c5cae3268d
@ -57,6 +57,7 @@ opm/core/fluid/SatFuncStone2.cpp \
|
||||
opm/core/fluid/SatFuncSimple.cpp \
|
||||
opm/core/fluid/blackoil/BlackoilPvtProperties.cpp \
|
||||
opm/core/fluid/blackoil/SinglePvtDead.cpp \
|
||||
opm/core/fluid/blackoil/SinglePvtDeadSpline.cpp \
|
||||
opm/core/fluid/blackoil/SinglePvtInterface.cpp \
|
||||
opm/core/fluid/blackoil/SinglePvtLiveGas.cpp \
|
||||
opm/core/fluid/blackoil/SinglePvtLiveOil.cpp \
|
||||
@ -150,15 +151,18 @@ opm/core/fluid/PvtPropertiesIncompFromDeck.hpp \
|
||||
opm/core/fluid/RockBasic.hpp \
|
||||
opm/core/fluid/RockCompressibility.hpp \
|
||||
opm/core/fluid/RockFromDeck.hpp \
|
||||
opm/core/fluid/SaturationPropsBasic.hpp \
|
||||
opm/core/fluid/SaturationPropsFromDeck.hpp \
|
||||
opm/core/fluid/SatFuncStone2.hpp \
|
||||
opm/core/fluid/SatFuncSimple.hpp \
|
||||
opm/core/fluid/SaturationPropsBasic.hpp \
|
||||
opm/core/fluid/SaturationPropsFromDeck.hpp \
|
||||
opm/core/fluid/SaturationPropsFromDeck_impl.hpp \
|
||||
opm/core/fluid/SaturationPropsInterface.hpp \
|
||||
opm/core/fluid/SimpleFluid2p.hpp \
|
||||
opm/core/fluid/blackoil/BlackoilPhases.hpp \
|
||||
opm/core/fluid/blackoil/BlackoilPvtProperties.hpp \
|
||||
opm/core/fluid/blackoil/SinglePvtConstCompr.hpp \
|
||||
opm/core/fluid/blackoil/SinglePvtDead.hpp \
|
||||
opm/core/fluid/blackoil/SinglePvtDeadSpline.hpp \
|
||||
opm/core/fluid/blackoil/SinglePvtInterface.hpp \
|
||||
opm/core/fluid/blackoil/SinglePvtLiveGas.hpp \
|
||||
opm/core/fluid/blackoil/SinglePvtLiveOil.hpp \
|
||||
@ -233,6 +237,7 @@ opm/core/utility/ColumnExtract.hpp \
|
||||
opm/core/utility/ErrorMacros.hpp \
|
||||
opm/core/utility/Factory.hpp \
|
||||
opm/core/utility/MonotCubicInterpolator.hpp \
|
||||
opm/core/utility/NonuniformTableLinear.hpp \
|
||||
opm/core/utility/RootFinders.hpp \
|
||||
opm/core/utility/SparseTable.hpp \
|
||||
opm/core/utility/SparseVector.hpp \
|
||||
|
@ -94,7 +94,7 @@ main(int argc, char** argv)
|
||||
// Grid init
|
||||
grid.reset(new GridManager(*deck));
|
||||
// Rock and fluid init
|
||||
props.reset(new BlackoilPropertiesFromDeck(*deck, *grid->c_grid()));
|
||||
props.reset(new BlackoilPropertiesFromDeck(*deck, *grid->c_grid(), param));
|
||||
// check_well_controls = param.getDefault("check_well_controls", false);
|
||||
// max_well_control_iterations = param.getDefault("max_well_control_iterations", 10);
|
||||
// Rock compressibility.
|
||||
|
@ -175,7 +175,7 @@ main(int argc, char** argv)
|
||||
// Grid init
|
||||
grid.reset(new Opm::GridManager(deck));
|
||||
// Rock and fluid init
|
||||
props.reset(new Opm::BlackoilPropertiesFromDeck(deck, *grid->c_grid()));
|
||||
props.reset(new BlackoilPropertiesFromDeck(deck, *grid->c_grid(), param));
|
||||
// Wells init.
|
||||
wells.reset(new Opm::WellsManager(deck, *grid->c_grid(), props->permeability()));
|
||||
check_well_controls = param.getDefault("check_well_controls", false);
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <opm/core/fluid/BlackoilPropertiesFromDeck.hpp>
|
||||
#include <opm/core/utility/parameters/ParameterGroup.hpp>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
@ -26,11 +27,15 @@ namespace Opm
|
||||
const UnstructuredGrid& grid)
|
||||
{
|
||||
rock_.init(deck, grid);
|
||||
pvt_.init(deck);
|
||||
satprops_.init(deck, grid);
|
||||
if (pvt_.numPhases() != satprops_.numPhases()) {
|
||||
THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data ("
|
||||
<< pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
|
||||
pvt_.init(deck, 200);
|
||||
SaturationPropsFromDeck<SatFuncStone2Uniform>* ptr
|
||||
= new SaturationPropsFromDeck<SatFuncStone2Uniform>();
|
||||
satprops_.reset(ptr);
|
||||
ptr->init(deck, grid, 200);
|
||||
|
||||
if (pvt_.numPhases() != satprops_->numPhases()) {
|
||||
THROW("BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
|
||||
<< pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,13 +44,42 @@ namespace Opm
|
||||
const parameter::ParameterGroup& param)
|
||||
{
|
||||
rock_.init(deck, grid);
|
||||
const int samples = param.getDefault("dead_tab_size", 1025);
|
||||
pvt_.init(deck, samples);
|
||||
satprops_.init(deck, grid, param);
|
||||
const int pvt_samples = param.getDefault("pvt_tab_size", 200);
|
||||
pvt_.init(deck, pvt_samples);
|
||||
|
||||
if (pvt_.numPhases() != satprops_.numPhases()) {
|
||||
THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data ("
|
||||
<< pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
|
||||
// Unfortunate lack of pointer smartness here...
|
||||
const int sat_samples = param.getDefault("sat_tab_size", 200);
|
||||
std::string threephase_model = param.getDefault<std::string>("threephase_model", "simple");
|
||||
bool use_stone2 = (threephase_model == "stone2");
|
||||
if (sat_samples > 1) {
|
||||
if (use_stone2) {
|
||||
SaturationPropsFromDeck<SatFuncStone2Uniform>* ptr
|
||||
= new SaturationPropsFromDeck<SatFuncStone2Uniform>();
|
||||
satprops_.reset(ptr);
|
||||
ptr->init(deck, grid, sat_samples);
|
||||
} else {
|
||||
SaturationPropsFromDeck<SatFuncSimpleUniform>* ptr
|
||||
= new SaturationPropsFromDeck<SatFuncSimpleUniform>();
|
||||
satprops_.reset(ptr);
|
||||
ptr->init(deck, grid, sat_samples);
|
||||
}
|
||||
} else {
|
||||
if (use_stone2) {
|
||||
SaturationPropsFromDeck<SatFuncStone2Nonuniform>* ptr
|
||||
= new SaturationPropsFromDeck<SatFuncStone2Nonuniform>();
|
||||
satprops_.reset(ptr);
|
||||
ptr->init(deck, grid, sat_samples);
|
||||
} else {
|
||||
SaturationPropsFromDeck<SatFuncSimpleNonuniform>* ptr
|
||||
= new SaturationPropsFromDeck<SatFuncSimpleNonuniform>();
|
||||
satprops_.reset(ptr);
|
||||
ptr->init(deck, grid, sat_samples);
|
||||
}
|
||||
}
|
||||
|
||||
if (pvt_.numPhases() != satprops_->numPhases()) {
|
||||
THROW("BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
|
||||
<< pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +284,7 @@ namespace Opm
|
||||
double* kr,
|
||||
double* dkrds) const
|
||||
{
|
||||
satprops_.relperm(n, s, cells, kr, dkrds);
|
||||
satprops_->relperm(n, s, cells, kr, dkrds);
|
||||
}
|
||||
|
||||
|
||||
@ -269,7 +303,7 @@ namespace Opm
|
||||
double* pc,
|
||||
double* dpcds) const
|
||||
{
|
||||
satprops_.capPress(n, s, cells, pc, dpcds);
|
||||
satprops_->capPress(n, s, cells, pc, dpcds);
|
||||
}
|
||||
|
||||
|
||||
@ -285,7 +319,7 @@ namespace Opm
|
||||
double* smin,
|
||||
double* smax) const
|
||||
{
|
||||
satprops_.satRange(n, cells, smin, smax);
|
||||
satprops_->satRange(n, cells, smin, smax);
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <opm/core/fluid/SaturationPropsFromDeck.hpp>
|
||||
#include <opm/core/eclipse/EclipseGridParser.hpp>
|
||||
#include <opm/core/utility/parameters/ParameterGroup.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
struct UnstructuredGrid;
|
||||
|
||||
@ -52,8 +53,11 @@ namespace Opm
|
||||
/// mapping from cell indices (typically from a processed grid)
|
||||
/// to logical cartesian indices consistent with the deck.
|
||||
/// \param[in] param Parameters. Accepted parameters include:
|
||||
/// dead_tab_size (1025) number of uniform sample points for dead-oil pvt tables.
|
||||
/// tab_size_kr (200) number of uniform sample points for saturation tables.
|
||||
/// pvt_tab_size (200) number of uniform sample points for dead-oil pvt tables.
|
||||
/// sat_tab_size (200) number of uniform sample points for saturation tables.
|
||||
/// threephase_model("simple") three-phase relperm model (accepts "simple" and "stone2").
|
||||
/// For both size parameters, a 0 or negative value indicates that no spline fitting is to
|
||||
/// be done, and the input fluid data used directly for linear interpolation.
|
||||
BlackoilPropertiesFromDeck(const EclipseGridParser& deck,
|
||||
const UnstructuredGrid& grid,
|
||||
const parameter::ParameterGroup& param);
|
||||
@ -178,7 +182,7 @@ namespace Opm
|
||||
private:
|
||||
RockFromDeck rock_;
|
||||
BlackoilPvtProperties pvt_;
|
||||
SaturationPropsFromDeck satprops_;
|
||||
boost::scoped_ptr<SaturationPropsInterface> satprops_;
|
||||
mutable std::vector<double> B_;
|
||||
mutable std::vector<double> dB_;
|
||||
mutable std::vector<double> R_;
|
||||
|
@ -31,7 +31,7 @@ namespace Opm
|
||||
{
|
||||
rock_.init(deck, grid);
|
||||
pvt_.init(deck);
|
||||
satprops_.init(deck, grid);
|
||||
satprops_.init(deck, grid, 200);
|
||||
if (pvt_.numPhases() != satprops_.numPhases()) {
|
||||
THROW("IncompPropertiesFromDeck::IncompPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
|
||||
<< pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
|
||||
|
@ -135,7 +135,7 @@ namespace Opm
|
||||
private:
|
||||
RockFromDeck rock_;
|
||||
PvtPropertiesIncompFromDeck pvt_;
|
||||
SaturationPropsFromDeck satprops_;
|
||||
SaturationPropsFromDeck<SatFuncStone2Uniform> satprops_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <opm/core/fluid/SatFuncSimple.hpp>
|
||||
#include <opm/core/fluid/blackoil/BlackoilPhases.hpp>
|
||||
#include <opm/core/fluid/SaturationPropsFromDeck.hpp>
|
||||
@ -6,21 +25,14 @@
|
||||
#include <opm/core/utility/buildUniformMonotoneTable.hpp>
|
||||
#include <opm/core/utility/ErrorMacros.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
void SatFuncSimple::init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg)
|
||||
{
|
||||
init(deck, table_num, phase_usg, 200);
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimple::init(const EclipseGridParser& deck,
|
||||
void SatFuncSimpleUniform::init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int samples)
|
||||
@ -65,7 +77,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimple::evalKr(const double* s, double* kr) const
|
||||
void SatFuncSimpleUniform::evalKr(const double* s, double* kr) const
|
||||
{
|
||||
if (phase_usage.num_phases == 3) {
|
||||
// A simplified relative permeability model.
|
||||
@ -106,7 +118,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimple::evalKrDeriv(const double* s, double* kr, double* dkrds) const
|
||||
void SatFuncSimpleUniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
|
||||
{
|
||||
const int np = phase_usage.num_phases;
|
||||
std::fill(dkrds, dkrds + np*np, 0.0);
|
||||
@ -172,7 +184,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimple::evalPc(const double* s, double* pc) const
|
||||
void SatFuncSimpleUniform::evalPc(const double* s, double* pc) const
|
||||
{
|
||||
pc[phase_usage.phase_pos[Liquid]] = 0.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
@ -185,7 +197,206 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
|
||||
void SatFuncSimple::evalPcDeriv(const double* s, double* pc, double* dpcds) const
|
||||
void SatFuncSimpleUniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
|
||||
{
|
||||
// The problem of determining three-phase capillary pressures
|
||||
// is very hard experimentally, usually one extends two-phase
|
||||
// data (as for relative permeability).
|
||||
// In our approach the derivative matrix is quite sparse, only
|
||||
// the diagonal elements corresponding to non-oil phases are
|
||||
// (potentially) nonzero.
|
||||
const int np = phase_usage.num_phases;
|
||||
std::fill(dpcds, dpcds + np*np, 0.0);
|
||||
pc[phase_usage.phase_pos[Liquid]] = 0.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int pos = phase_usage.phase_pos[Aqua];
|
||||
pc[pos] = pcow_(s[pos]);
|
||||
dpcds[np*pos + pos] = pcow_.derivative(s[pos]);
|
||||
}
|
||||
if (phase_usage.phase_used[Vapour]) {
|
||||
int pos = phase_usage.phase_pos[Vapour];
|
||||
pc[pos] = pcog_(s[pos]);
|
||||
dpcds[np*pos + pos] = pcog_.derivative(s[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ====== Methods for SatFuncSimpleNonuniform ======
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void SatFuncSimpleNonuniform::init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int /*samples*/)
|
||||
{
|
||||
phase_usage = phase_usg;
|
||||
double swco = 0.0;
|
||||
double swmax = 1.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
const SWOF::table_t& swof_table = deck.getSWOF().swof_;
|
||||
const std::vector<double>& sw = swof_table[table_num][0];
|
||||
const std::vector<double>& krw = swof_table[table_num][1];
|
||||
const std::vector<double>& krow = swof_table[table_num][2];
|
||||
const std::vector<double>& pcow = swof_table[table_num][3];
|
||||
krw_ = NonuniformTableLinear<double>(sw, krw);
|
||||
krow_ = NonuniformTableLinear<double>(sw, krow);
|
||||
pcow_ = NonuniformTableLinear<double>(sw, pcow);
|
||||
krocw_ = krow[0]; // At connate water -> ecl. SWOF
|
||||
swco = sw[0];
|
||||
smin_[phase_usage.phase_pos[Aqua]] = sw[0];
|
||||
swmax = sw.back();
|
||||
smax_[phase_usage.phase_pos[Aqua]] = sw.back();
|
||||
}
|
||||
if (phase_usage.phase_used[Vapour]) {
|
||||
const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
|
||||
const std::vector<double>& sg = sgof_table[table_num][0];
|
||||
const std::vector<double>& krg = sgof_table[table_num][1];
|
||||
const std::vector<double>& krog = sgof_table[table_num][2];
|
||||
const std::vector<double>& pcog = sgof_table[table_num][3];
|
||||
krg_ = NonuniformTableLinear<double>(sg, krg);
|
||||
krog_ = NonuniformTableLinear<double>(sg, krog);
|
||||
pcog_ = NonuniformTableLinear<double>(sg, pcog);
|
||||
smin_[phase_usage.phase_pos[Vapour]] = sg[0];
|
||||
if (std::fabs(sg.back() + swco - 1.0) > 1e-3) {
|
||||
THROW("Gas maximum saturation in SGOF table = " << sg.back() <<
|
||||
", should equal (1.0 - connate water sat) = " << (1.0 - swco));
|
||||
}
|
||||
smax_[phase_usage.phase_pos[Vapour]] = sg.back();
|
||||
}
|
||||
// These only consider water min/max sats. Consider gas sats?
|
||||
smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax;
|
||||
smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco;
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimpleNonuniform::evalKr(const double* s, double* kr) const
|
||||
{
|
||||
if (phase_usage.num_phases == 3) {
|
||||
// A simplified relative permeability model.
|
||||
double sw = s[Aqua];
|
||||
double sg = s[Vapour];
|
||||
double krw = krw_(sw);
|
||||
double krg = krg_(sg);
|
||||
double krow = krow_(sw + sg); // = 1 - so
|
||||
// double krog = krog_(sg); // = 1 - so - sw
|
||||
// double krocw = krocw_;
|
||||
kr[Aqua] = krw;
|
||||
kr[Vapour] = krg;
|
||||
kr[Liquid] = krow;
|
||||
if (kr[Liquid] < 0.0) {
|
||||
kr[Liquid] = 0.0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// We have a two-phase situation. We know that oil is active.
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int wpos = phase_usage.phase_pos[Aqua];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sw = s[wpos];
|
||||
double krw = krw_(sw);
|
||||
double krow = krow_(sw);
|
||||
kr[wpos] = krw;
|
||||
kr[opos] = krow;
|
||||
} else {
|
||||
ASSERT(phase_usage.phase_used[Vapour]);
|
||||
int gpos = phase_usage.phase_pos[Vapour];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sg = s[gpos];
|
||||
double krg = krg_(sg);
|
||||
double krog = krog_(sg);
|
||||
kr[gpos] = krg;
|
||||
kr[opos] = krog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimpleNonuniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
|
||||
{
|
||||
const int np = phase_usage.num_phases;
|
||||
std::fill(dkrds, dkrds + np*np, 0.0);
|
||||
|
||||
if (np == 3) {
|
||||
// A simplified relative permeability model.
|
||||
double sw = s[Aqua];
|
||||
double sg = s[Vapour];
|
||||
double krw = krw_(sw);
|
||||
double dkrww = krw_.derivative(sw);
|
||||
double krg = krg_(sg);
|
||||
double dkrgg = krg_.derivative(sg);
|
||||
double krow = krow_(sw + sg);
|
||||
double dkrow = krow_.derivative(sw + sg);
|
||||
// double krog = krog_(sg);
|
||||
// double dkrog = krog_.derivative(sg);
|
||||
// double krocw = krocw_;
|
||||
kr[Aqua] = krw;
|
||||
kr[Vapour] = krg;
|
||||
kr[Liquid] = krow;
|
||||
//krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
|
||||
if (kr[Liquid] < 0.0) {
|
||||
kr[Liquid] = 0.0;
|
||||
}
|
||||
dkrds[Aqua + Aqua*np] = dkrww;
|
||||
dkrds[Vapour + Vapour*np] = dkrgg;
|
||||
//dkrds[Liquid + Aqua*np] = dkrow;
|
||||
dkrds[Liquid + Liquid*np] = -dkrow;
|
||||
//krocw*((dkrow/krocw + dkrww)*(krog/krocw + krg) - dkrww);
|
||||
dkrds[Liquid + Vapour*np] = 0.0;
|
||||
//krocw*((krow/krocw + krw)*(dkrog/krocw + dkrgg) - dkrgg)
|
||||
//+ krocw*((dkrow/krocw + krw)*(krog/krocw + krg) - dkrgg);
|
||||
return;
|
||||
}
|
||||
// We have a two-phase situation. We know that oil is active.
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int wpos = phase_usage.phase_pos[Aqua];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sw = s[wpos];
|
||||
double krw = krw_(sw);
|
||||
double dkrww = krw_.derivative(sw);
|
||||
double krow = krow_(sw);
|
||||
double dkrow = krow_.derivative(sw);
|
||||
kr[wpos] = krw;
|
||||
kr[opos] = krow;
|
||||
dkrds[wpos + wpos*np] = dkrww;
|
||||
dkrds[opos + wpos*np] = dkrow; // Row opos, column wpos, fortran order.
|
||||
} else {
|
||||
ASSERT(phase_usage.phase_used[Vapour]);
|
||||
int gpos = phase_usage.phase_pos[Vapour];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sg = s[gpos];
|
||||
double krg = krg_(sg);
|
||||
double dkrgg = krg_.derivative(sg);
|
||||
double krog = krog_(sg);
|
||||
double dkrog = krog_.derivative(sg);
|
||||
kr[gpos] = krg;
|
||||
kr[opos] = krog;
|
||||
dkrds[gpos + gpos*np] = dkrgg;
|
||||
dkrds[opos + gpos*np] = dkrog;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SatFuncSimpleNonuniform::evalPc(const double* s, double* pc) const
|
||||
{
|
||||
pc[phase_usage.phase_pos[Liquid]] = 0.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int pos = phase_usage.phase_pos[Aqua];
|
||||
pc[pos] = pcow_(s[pos]);
|
||||
}
|
||||
if (phase_usage.phase_used[Vapour]) {
|
||||
int pos = phase_usage.phase_pos[Vapour];
|
||||
pc[pos] = pcog_(s[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
void SatFuncSimpleNonuniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
|
||||
{
|
||||
// The problem of determining three-phase capillary pressures
|
||||
// is very hard experimentally, usually one extends two-phase
|
||||
|
@ -18,17 +18,21 @@
|
||||
*/
|
||||
#ifndef SATFUNCSIMPLE_HPP
|
||||
#define SATFUNCSIMPLE_HPP
|
||||
|
||||
#include <opm/core/eclipse/EclipseGridParser.hpp>
|
||||
#include <opm/core/utility/UniformTableLinear.hpp>
|
||||
#include <opm/core/utility/NonuniformTableLinear.hpp>
|
||||
#include <opm/core/fluid/blackoil/BlackoilPhases.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class SatFuncSimple: public BlackoilPhases
|
||||
class SatFuncSimpleUniform : public BlackoilPhases
|
||||
{
|
||||
public:
|
||||
void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg);
|
||||
void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg,
|
||||
void init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int samples);
|
||||
void evalKr(const double* s, double* kr) const;
|
||||
void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
|
||||
@ -46,5 +50,31 @@ namespace Opm
|
||||
UniformTableLinear<double> pcog_;
|
||||
double krocw_; // = krow_(s_wc)
|
||||
};
|
||||
|
||||
|
||||
class SatFuncSimpleNonuniform : public BlackoilPhases
|
||||
{
|
||||
public:
|
||||
void init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int samples);
|
||||
void evalKr(const double* s, double* kr) const;
|
||||
void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
|
||||
void evalPc(const double* s, double* pc) const;
|
||||
void evalPcDeriv(const double* s, double* pc, double* dpcds) const;
|
||||
double smin_[PhaseUsage::MaxNumPhases];
|
||||
double smax_[PhaseUsage::MaxNumPhases];
|
||||
private:
|
||||
PhaseUsage phase_usage; // A copy of the outer class' phase_usage_.
|
||||
NonuniformTableLinear<double> krw_;
|
||||
NonuniformTableLinear<double> krow_;
|
||||
NonuniformTableLinear<double> pcow_;
|
||||
NonuniformTableLinear<double> krg_;
|
||||
NonuniformTableLinear<double> krog_;
|
||||
NonuniformTableLinear<double> pcog_;
|
||||
double krocw_; // = krow_(s_wc)
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
#endif // SATFUNCSIMPLE_HPP
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <opm/core/fluid/SatFuncStone2.hpp>
|
||||
#include <opm/core/fluid/blackoil/BlackoilPhases.hpp>
|
||||
#include <opm/core/fluid/SaturationPropsFromDeck.hpp>
|
||||
@ -6,20 +25,14 @@
|
||||
#include <opm/core/utility/buildUniformMonotoneTable.hpp>
|
||||
#include <opm/core/utility/ErrorMacros.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
void SatFuncStone2::init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg)
|
||||
{
|
||||
init(deck, table_num, phase_usg, 200);
|
||||
}
|
||||
|
||||
void SatFuncStone2::init(const EclipseGridParser& deck,
|
||||
void SatFuncStone2Uniform::init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int samples)
|
||||
@ -64,7 +77,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
void SatFuncStone2::evalKr(const double* s, double* kr) const
|
||||
void SatFuncStone2Uniform::evalKr(const double* s, double* kr) const
|
||||
{
|
||||
if (phase_usage.num_phases == 3) {
|
||||
// Stone-II relative permeability model.
|
||||
@ -105,7 +118,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
void SatFuncStone2::evalKrDeriv(const double* s, double* kr, double* dkrds) const
|
||||
void SatFuncStone2Uniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
|
||||
{
|
||||
const int np = phase_usage.num_phases;
|
||||
std::fill(dkrds, dkrds + np*np, 0.0);
|
||||
@ -167,7 +180,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
void SatFuncStone2::evalPc(const double* s, double* pc) const
|
||||
void SatFuncStone2Uniform::evalPc(const double* s, double* pc) const
|
||||
{
|
||||
pc[phase_usage.phase_pos[Liquid]] = 0.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
@ -180,7 +193,7 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
|
||||
void SatFuncStone2::evalPcDeriv(const double* s, double* pc, double* dpcds) const
|
||||
void SatFuncStone2Uniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
|
||||
{
|
||||
// The problem of determining three-phase capillary pressures
|
||||
// is very hard experimentally, usually one extends two-phase
|
||||
@ -206,4 +219,199 @@ namespace Opm
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ====== Methods for SatFuncSimpleNonuniform ======
|
||||
|
||||
|
||||
|
||||
|
||||
void SatFuncStone2Nonuniform::init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int /*samples*/)
|
||||
{
|
||||
phase_usage = phase_usg;
|
||||
double swco = 0.0;
|
||||
double swmax = 1.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
const SWOF::table_t& swof_table = deck.getSWOF().swof_;
|
||||
const std::vector<double>& sw = swof_table[table_num][0];
|
||||
const std::vector<double>& krw = swof_table[table_num][1];
|
||||
const std::vector<double>& krow = swof_table[table_num][2];
|
||||
const std::vector<double>& pcow = swof_table[table_num][3];
|
||||
krw_ = NonuniformTableLinear<double>(sw, krw);
|
||||
krow_ = NonuniformTableLinear<double>(sw, krow);
|
||||
pcow_ = NonuniformTableLinear<double>(sw, pcow);
|
||||
krocw_ = krow[0]; // At connate water -> ecl. SWOF
|
||||
swco = sw[0];
|
||||
smin_[phase_usage.phase_pos[Aqua]] = sw[0];
|
||||
swmax = sw.back();
|
||||
smax_[phase_usage.phase_pos[Aqua]] = sw.back();
|
||||
}
|
||||
if (phase_usage.phase_used[Vapour]) {
|
||||
const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
|
||||
const std::vector<double>& sg = sgof_table[table_num][0];
|
||||
const std::vector<double>& krg = sgof_table[table_num][1];
|
||||
const std::vector<double>& krog = sgof_table[table_num][2];
|
||||
const std::vector<double>& pcog = sgof_table[table_num][3];
|
||||
krg_ = NonuniformTableLinear<double>(sg, krg);
|
||||
krog_ = NonuniformTableLinear<double>(sg, krog);
|
||||
pcog_ = NonuniformTableLinear<double>(sg, pcog);
|
||||
smin_[phase_usage.phase_pos[Vapour]] = sg[0];
|
||||
if (std::fabs(sg.back() + swco - 1.0) > 1e-3) {
|
||||
THROW("Gas maximum saturation in SGOF table = " << sg.back() <<
|
||||
", should equal (1.0 - connate water sat) = " << (1.0 - swco));
|
||||
}
|
||||
smax_[phase_usage.phase_pos[Vapour]] = sg.back();
|
||||
}
|
||||
// These only consider water min/max sats. Consider gas sats?
|
||||
smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax;
|
||||
smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco;
|
||||
}
|
||||
|
||||
|
||||
void SatFuncStone2Nonuniform::evalKr(const double* s, double* kr) const
|
||||
{
|
||||
if (phase_usage.num_phases == 3) {
|
||||
// Stone-II relative permeability model.
|
||||
double sw = s[Aqua];
|
||||
double sg = s[Vapour];
|
||||
double krw = krw_(sw);
|
||||
double krg = krg_(sg);
|
||||
double krow = krow_(sw + sg); // = 1 - so
|
||||
double krog = krog_(sg); // = 1 - so - sw
|
||||
double krocw = krocw_;
|
||||
kr[Aqua] = krw;
|
||||
kr[Vapour] = krg;
|
||||
kr[Liquid] = krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
|
||||
if (kr[Liquid] < 0.0) {
|
||||
kr[Liquid] = 0.0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// We have a two-phase situation. We know that oil is active.
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int wpos = phase_usage.phase_pos[Aqua];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sw = s[wpos];
|
||||
double krw = krw_(sw);
|
||||
double krow = krow_(sw);
|
||||
kr[wpos] = krw;
|
||||
kr[opos] = krow;
|
||||
} else {
|
||||
ASSERT(phase_usage.phase_used[Vapour]);
|
||||
int gpos = phase_usage.phase_pos[Vapour];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sg = s[gpos];
|
||||
double krg = krg_(sg);
|
||||
double krog = krog_(sg);
|
||||
kr[gpos] = krg;
|
||||
kr[opos] = krog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SatFuncStone2Nonuniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
|
||||
{
|
||||
const int np = phase_usage.num_phases;
|
||||
std::fill(dkrds, dkrds + np*np, 0.0);
|
||||
|
||||
if (np == 3) {
|
||||
// Stone-II relative permeability model.
|
||||
double sw = s[Aqua];
|
||||
double sg = s[Vapour];
|
||||
double krw = krw_(sw);
|
||||
double dkrww = krw_.derivative(sw);
|
||||
double krg = krg_(sg);
|
||||
double dkrgg = krg_.derivative(sg);
|
||||
double krow = krow_(sw + sg);
|
||||
double dkrow = krow_.derivative(sw + sg);
|
||||
double krog = krog_(sg);
|
||||
double dkrog = krog_.derivative(sg);
|
||||
double krocw = krocw_;
|
||||
kr[Aqua] = krw;
|
||||
kr[Vapour] = krg;
|
||||
kr[Liquid] = krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
|
||||
if (kr[Liquid] < 0.0) {
|
||||
kr[Liquid] = 0.0;
|
||||
}
|
||||
dkrds[Aqua + Aqua*np] = dkrww;
|
||||
dkrds[Vapour + Vapour*np] = dkrgg;
|
||||
dkrds[Liquid + Aqua*np] = krocw*((dkrow/krocw + dkrww)*(krog/krocw + krg) - dkrww);
|
||||
dkrds[Liquid + Vapour*np] = krocw*((krow/krocw + krw)*(dkrog/krocw + dkrgg) - dkrgg)
|
||||
+ krocw*((dkrow/krocw + krw)*(krog/krocw + krg) - dkrgg);
|
||||
return;
|
||||
}
|
||||
// We have a two-phase situation. We know that oil is active.
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int wpos = phase_usage.phase_pos[Aqua];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sw = s[wpos];
|
||||
double krw = krw_(sw);
|
||||
double dkrww = krw_.derivative(sw);
|
||||
double krow = krow_(sw);
|
||||
double dkrow = krow_.derivative(sw);
|
||||
kr[wpos] = krw;
|
||||
kr[opos] = krow;
|
||||
dkrds[wpos + wpos*np] = dkrww;
|
||||
dkrds[opos + wpos*np] = dkrow; // Row opos, column wpos, fortran order.
|
||||
} else {
|
||||
ASSERT(phase_usage.phase_used[Vapour]);
|
||||
int gpos = phase_usage.phase_pos[Vapour];
|
||||
int opos = phase_usage.phase_pos[Liquid];
|
||||
double sg = s[gpos];
|
||||
double krg = krg_(sg);
|
||||
double dkrgg = krg_.derivative(sg);
|
||||
double krog = krog_(sg);
|
||||
double dkrog = krog_.derivative(sg);
|
||||
kr[gpos] = krg;
|
||||
kr[opos] = krog;
|
||||
dkrds[gpos + gpos*np] = dkrgg;
|
||||
dkrds[opos + gpos*np] = dkrog;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SatFuncStone2Nonuniform::evalPc(const double* s, double* pc) const
|
||||
{
|
||||
pc[phase_usage.phase_pos[Liquid]] = 0.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int pos = phase_usage.phase_pos[Aqua];
|
||||
pc[pos] = pcow_(s[pos]);
|
||||
}
|
||||
if (phase_usage.phase_used[Vapour]) {
|
||||
int pos = phase_usage.phase_pos[Vapour];
|
||||
pc[pos] = pcog_(s[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
void SatFuncStone2Nonuniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
|
||||
{
|
||||
// The problem of determining three-phase capillary pressures
|
||||
// is very hard experimentally, usually one extends two-phase
|
||||
// data (as for relative permeability).
|
||||
// In our approach the derivative matrix is quite sparse, only
|
||||
// the diagonal elements corresponding to non-oil phases are
|
||||
// (potentially) nonzero.
|
||||
const int np = phase_usage.num_phases;
|
||||
std::fill(dpcds, dpcds + np*np, 0.0);
|
||||
pc[phase_usage.phase_pos[Liquid]] = 0.0;
|
||||
if (phase_usage.phase_used[Aqua]) {
|
||||
int pos = phase_usage.phase_pos[Aqua];
|
||||
pc[pos] = pcow_(s[pos]);
|
||||
dpcds[np*pos + pos] = pcow_.derivative(s[pos]);
|
||||
}
|
||||
if (phase_usage.phase_used[Vapour]) {
|
||||
int pos = phase_usage.phase_pos[Vapour];
|
||||
pc[pos] = pcog_(s[pos]);
|
||||
dpcds[np*pos + pos] = pcog_.derivative(s[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -18,17 +18,21 @@
|
||||
*/
|
||||
#ifndef SATFUNCSTONE2_HPP
|
||||
#define SATFUNCSTONE2_HPP
|
||||
|
||||
#include <opm/core/eclipse/EclipseGridParser.hpp>
|
||||
#include <opm/core/utility/UniformTableLinear.hpp>
|
||||
#include <opm/core/utility/NonuniformTableLinear.hpp>
|
||||
#include <opm/core/fluid/blackoil/BlackoilPhases.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class SatFuncStone2: public BlackoilPhases
|
||||
class SatFuncStone2Uniform : public BlackoilPhases
|
||||
{
|
||||
public:
|
||||
void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg);
|
||||
void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg,
|
||||
void init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int samples);
|
||||
void evalKr(const double* s, double* kr) const;
|
||||
void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
|
||||
@ -46,5 +50,31 @@ namespace Opm
|
||||
UniformTableLinear<double> pcog_;
|
||||
double krocw_; // = krow_(s_wc)
|
||||
};
|
||||
|
||||
|
||||
class SatFuncStone2Nonuniform : public BlackoilPhases
|
||||
{
|
||||
public:
|
||||
void init(const EclipseGridParser& deck,
|
||||
const int table_num,
|
||||
const PhaseUsage phase_usg,
|
||||
const int samples);
|
||||
void evalKr(const double* s, double* kr) const;
|
||||
void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
|
||||
void evalPc(const double* s, double* pc) const;
|
||||
void evalPcDeriv(const double* s, double* pc, double* dpcds) const;
|
||||
double smin_[PhaseUsage::MaxNumPhases];
|
||||
double smax_[PhaseUsage::MaxNumPhases];
|
||||
private:
|
||||
PhaseUsage phase_usage; // A copy of the outer class' phase_usage_.
|
||||
NonuniformTableLinear<double> krw_;
|
||||
NonuniformTableLinear<double> krow_;
|
||||
NonuniformTableLinear<double> pcow_;
|
||||
NonuniformTableLinear<double> krg_;
|
||||
NonuniformTableLinear<double> krog_;
|
||||
NonuniformTableLinear<double> pcog_;
|
||||
double krocw_; // = krow_(s_wc)
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
#endif // SATFUNCSTONE2_HPP
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include <opm/core/fluid/SaturationPropsFromDeck.hpp>
|
||||
#include <opm/core/grid.h>
|
||||
#include <opm/core/fluid/blackoil/phaseUsageFromDeck.hpp>
|
||||
#include <opm/core/utility/buildUniformMonotoneTable.hpp>
|
||||
#include <opm/core/utility/ErrorMacros.hpp>
|
||||
#include <iostream>
|
||||
@ -27,236 +26,9 @@
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
/// Default constructor.
|
||||
SaturationPropsFromDeck::SaturationPropsFromDeck()
|
||||
{
|
||||
}
|
||||
// This file should be removed in the future.
|
||||
// Holding off until refactoring of SaturationPropsFromDeck class is done.
|
||||
|
||||
/// Initialize from deck.
|
||||
void SaturationPropsFromDeck::init(const EclipseGridParser& deck,
|
||||
const UnstructuredGrid& grid)
|
||||
{
|
||||
phase_usage_ = phaseUsageFromDeck(deck);
|
||||
|
||||
// Extract input data.
|
||||
// Oil phase should be active.
|
||||
if (!phase_usage_.phase_used[Liquid]) {
|
||||
THROW("SaturationPropsFromDeck::init() -- oil phase must be active.");
|
||||
}
|
||||
|
||||
// Obtain SATNUM, if it exists, and create cell_to_func_.
|
||||
// Otherwise, let the cell_to_func_ mapping be just empty.
|
||||
int satfuncs_expected = 1;
|
||||
if (deck.hasField("SATNUM")) {
|
||||
const std::vector<int>& satnum = deck.getIntegerValue("SATNUM");
|
||||
satfuncs_expected = *std::max_element(satnum.begin(), satnum.end());
|
||||
const int num_cells = grid.number_of_cells;
|
||||
cell_to_func_.resize(num_cells);
|
||||
const int* gc = grid.global_cell;
|
||||
for (int cell = 0; cell < num_cells; ++cell) {
|
||||
const int deck_pos = (gc == NULL) ? cell : gc[cell];
|
||||
cell_to_func_[cell] = satnum[deck_pos] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Find number of tables, check for consistency.
|
||||
enum { Uninitialized = -1 };
|
||||
int num_tables = Uninitialized;
|
||||
if (phase_usage_.phase_used[Aqua]) {
|
||||
const SWOF::table_t& swof_table = deck.getSWOF().swof_;
|
||||
num_tables = swof_table.size();
|
||||
if (num_tables < satfuncs_expected) {
|
||||
THROW("Found " << num_tables << " SWOF tables, SATNUM specifies at least " << satfuncs_expected);
|
||||
}
|
||||
}
|
||||
if (phase_usage_.phase_used[Vapour]) {
|
||||
const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
|
||||
int num_sgof_tables = sgof_table.size();
|
||||
if (num_sgof_tables < satfuncs_expected) {
|
||||
THROW("Found " << num_tables << " SGOF tables, SATNUM specifies at least " << satfuncs_expected);
|
||||
}
|
||||
if (num_tables == Uninitialized) {
|
||||
num_tables = num_sgof_tables;
|
||||
} else if (num_tables != num_sgof_tables) {
|
||||
THROW("Inconsistent number of tables in SWOF and SGOF.");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize tables.
|
||||
satfuncset_.resize(num_tables);
|
||||
for (int table = 0; table < num_tables; ++table) {
|
||||
satfuncset_[table].init(deck, table, phase_usage_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Initialize from deck, grid and parameters
|
||||
void SaturationPropsFromDeck::init(const EclipseGridParser& deck,
|
||||
const UnstructuredGrid& grid,
|
||||
const parameter::ParameterGroup& param)
|
||||
{
|
||||
phase_usage_ = phaseUsageFromDeck(deck);
|
||||
|
||||
// Extract input data.
|
||||
// Oil phase should be active.
|
||||
if (!phase_usage_.phase_used[Liquid]) {
|
||||
THROW("SaturationPropsFromDeck::init() -- oil phase must be active.");
|
||||
}
|
||||
|
||||
// Obtain SATNUM, if it exists, and create cell_to_func_.
|
||||
// Otherwise, let the cell_to_func_ mapping be just empty.
|
||||
int satfuncs_expected = 1;
|
||||
if (deck.hasField("SATNUM")) {
|
||||
const std::vector<int>& satnum = deck.getIntegerValue("SATNUM");
|
||||
satfuncs_expected = *std::max_element(satnum.begin(), satnum.end());
|
||||
const int num_cells = grid.number_of_cells;
|
||||
cell_to_func_.resize(num_cells);
|
||||
const int* gc = grid.global_cell;
|
||||
for (int cell = 0; cell < num_cells; ++cell) {
|
||||
const int deck_pos = (gc == NULL) ? cell : gc[cell];
|
||||
cell_to_func_[cell] = satnum[deck_pos] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Find number of tables, check for consistency.
|
||||
enum { Uninitialized = -1 };
|
||||
int num_tables = Uninitialized;
|
||||
if (phase_usage_.phase_used[Aqua]) {
|
||||
const SWOF::table_t& swof_table = deck.getSWOF().swof_;
|
||||
num_tables = swof_table.size();
|
||||
if (num_tables < satfuncs_expected) {
|
||||
THROW("Found " << num_tables << " SWOF tables, SATNUM specifies at least " << satfuncs_expected);
|
||||
}
|
||||
}
|
||||
if (phase_usage_.phase_used[Vapour]) {
|
||||
const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
|
||||
int num_sgof_tables = sgof_table.size();
|
||||
if (num_sgof_tables < satfuncs_expected) {
|
||||
THROW("Found " << num_tables << " SGOF tables, SATNUM specifies at least " << satfuncs_expected);
|
||||
}
|
||||
if (num_tables == Uninitialized) {
|
||||
num_tables = num_sgof_tables;
|
||||
} else if (num_tables != num_sgof_tables) {
|
||||
THROW("Inconsistent number of tables in SWOF and SGOF.");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize tables.
|
||||
const int tab_size = param.getDefault("tab_size_kr", 200);
|
||||
satfuncset_.resize(num_tables);
|
||||
for (int table = 0; table < num_tables; ++table) {
|
||||
satfuncset_[table].init(deck, table, phase_usage_, tab_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \return P, the number of phases.
|
||||
int SaturationPropsFromDeck::numPhases() const
|
||||
{
|
||||
return phase_usage_.num_phases;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Relative permeability.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] s Array of nP saturation values.
|
||||
/// \param[in] cells Array of n cell indices to be associated with the s values.
|
||||
/// \param[out] kr Array of nP relperm values, array must be valid before calling.
|
||||
/// \param[out] dkrds If non-null: array of nP^2 relperm derivative values,
|
||||
/// array must be valid before calling.
|
||||
/// The P^2 derivative matrix is
|
||||
/// m_{ij} = \frac{dkr_i}{ds^j},
|
||||
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
|
||||
void SaturationPropsFromDeck::relperm(const int n,
|
||||
const double* s,
|
||||
const int* cells,
|
||||
double* kr,
|
||||
double* dkrds) const
|
||||
{
|
||||
ASSERT (cells != 0);
|
||||
|
||||
const int np = phase_usage_.num_phases;
|
||||
if (dkrds) {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalKrDeriv(s + np*i, kr + np*i, dkrds + np*np*i);
|
||||
}
|
||||
} else {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalKr(s + np*i, kr + np*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Capillary pressure.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] s Array of nP saturation values.
|
||||
/// \param[in] cells Array of n cell indices to be associated with the s values.
|
||||
/// \param[out] pc Array of nP capillary pressure values, array must be valid before calling.
|
||||
/// \param[out] dpcds If non-null: array of nP^2 derivative values,
|
||||
/// array must be valid before calling.
|
||||
/// The P^2 derivative matrix is
|
||||
/// m_{ij} = \frac{dpc_i}{ds^j},
|
||||
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
|
||||
void SaturationPropsFromDeck::capPress(const int n,
|
||||
const double* s,
|
||||
const int* cells,
|
||||
double* pc,
|
||||
double* dpcds) const
|
||||
{
|
||||
ASSERT (cells != 0);
|
||||
|
||||
const int np = phase_usage_.num_phases;
|
||||
if (dpcds) {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalPcDeriv(s + np*i, pc + np*i, dpcds + np*np*i);
|
||||
}
|
||||
} else {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalPc(s + np*i, pc + np*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Obtain the range of allowable saturation values.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] cells Array of n cell indices.
|
||||
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
|
||||
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
|
||||
void SaturationPropsFromDeck::satRange(const int n,
|
||||
const int* cells,
|
||||
double* smin,
|
||||
double* smax) const
|
||||
{
|
||||
ASSERT (cells != 0);
|
||||
|
||||
const int np = phase_usage_.num_phases;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (int p = 0; p < np; ++p) {
|
||||
smin[np*i + p] = funcForCell(cells[i]).smin_[p];
|
||||
smax[np*i + p] = funcForCell(cells[i]).smax_[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map the cell number to the correct function set.
|
||||
const SaturationPropsFromDeck::satfunc_t&
|
||||
SaturationPropsFromDeck::funcForCell(const int cell) const
|
||||
{
|
||||
return cell_to_func_.empty() ? satfuncset_[0] : satfuncset_[cell_to_func_[cell]];
|
||||
}
|
||||
} // namespace Opm
|
||||
|
||||
|
||||
|
@ -19,9 +19,10 @@
|
||||
|
||||
#ifndef OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED
|
||||
#define OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED
|
||||
|
||||
#include <opm/core/fluid/SaturationPropsInterface.hpp>
|
||||
#include <opm/core/utility/parameters/ParameterGroup.hpp>
|
||||
#include <opm/core/eclipse/EclipseGridParser.hpp>
|
||||
#include <opm/core/utility/UniformTableLinear.hpp>
|
||||
#include <opm/core/fluid/blackoil/BlackoilPhases.hpp>
|
||||
#include <opm/core/fluid/SatFuncStone2.hpp>
|
||||
#include <opm/core/fluid/SatFuncSimple.hpp>
|
||||
@ -32,23 +33,31 @@ struct UnstructuredGrid;
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
class SaturationPropsFromDeck : public BlackoilPhases
|
||||
|
||||
|
||||
/// Interface to saturation functions from deck.
|
||||
/// Possible values for template argument (for now):
|
||||
/// SatFuncSetStone2Nonuniform,
|
||||
/// SatFuncSetStone2Uniform.
|
||||
/// SatFuncSetSimpleNonuniform,
|
||||
/// SatFuncSetSimpleUniform.
|
||||
template <class SatFuncSet>
|
||||
class SaturationPropsFromDeck : public SaturationPropsInterface
|
||||
{
|
||||
public:
|
||||
/// Default constructor.
|
||||
SaturationPropsFromDeck();
|
||||
|
||||
/// Initialize from deck and grid.
|
||||
/// \param deck Deck input parser
|
||||
/// \param grid Grid to which property object applies, needed for the
|
||||
/// \param[in] deck Deck input parser
|
||||
/// \param[in] grid Grid to which property object applies, needed for the
|
||||
/// mapping from cell indices (typically from a processed grid)
|
||||
/// to logical cartesian indices consistent with the deck.
|
||||
void init(const EclipseGridParser& deck,
|
||||
const UnstructuredGrid& grid);
|
||||
|
||||
/// \param[in] samples Number of uniform sample points for saturation tables.
|
||||
/// NOTE: samples will only be used with the SatFuncSetUniform template argument.
|
||||
void init(const EclipseGridParser& deck,
|
||||
const UnstructuredGrid& grid,
|
||||
const parameter::ParameterGroup& param);
|
||||
const int samples);
|
||||
|
||||
/// \return P, the number of phases.
|
||||
int numPhases() const;
|
||||
@ -94,11 +103,12 @@ namespace Opm
|
||||
|
||||
private:
|
||||
PhaseUsage phase_usage_;
|
||||
typedef SatFuncSimple satfunc_t;
|
||||
std::vector<satfunc_t> satfuncset_;
|
||||
std::vector<SatFuncSet> satfuncset_;
|
||||
std::vector<int> cell_to_func_; // = SATNUM - 1
|
||||
|
||||
const satfunc_t& funcForCell(const int cell) const;
|
||||
typedef SatFuncSet Funcs;
|
||||
|
||||
const Funcs& funcForCell(const int cell) const;
|
||||
};
|
||||
|
||||
|
||||
@ -106,6 +116,7 @@ namespace Opm
|
||||
} // namespace Opm
|
||||
|
||||
|
||||
#include <opm/core/fluid/SaturationPropsFromDeck_impl.hpp>
|
||||
|
||||
|
||||
#endif // OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED
|
||||
|
221
opm/core/fluid/SaturationPropsFromDeck_impl.hpp
Normal file
221
opm/core/fluid/SaturationPropsFromDeck_impl.hpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_SATURATIONPROPSFROMDECK_IMPL_HEADER_INCLUDED
|
||||
#define OPM_SATURATIONPROPSFROMDECK_IMPL_HEADER_INCLUDED
|
||||
|
||||
|
||||
#include <opm/core/utility/UniformTableLinear.hpp>
|
||||
#include <opm/core/utility/NonuniformTableLinear.hpp>
|
||||
#include <opm/core/fluid/blackoil/phaseUsageFromDeck.hpp>
|
||||
#include <opm/core/grid.h>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
|
||||
// ----------- Methods of SaturationPropsFromDeck ---------
|
||||
|
||||
|
||||
/// Default constructor.
|
||||
template <class SatFuncSet>
|
||||
SaturationPropsFromDeck<SatFuncSet>::SaturationPropsFromDeck()
|
||||
{
|
||||
}
|
||||
|
||||
/// Initialize from deck.
|
||||
template <class SatFuncSet>
|
||||
void SaturationPropsFromDeck<SatFuncSet>::init(const EclipseGridParser& deck,
|
||||
const UnstructuredGrid& grid,
|
||||
const int samples)
|
||||
{
|
||||
phase_usage_ = phaseUsageFromDeck(deck);
|
||||
|
||||
// Extract input data.
|
||||
// Oil phase should be active.
|
||||
if (!phase_usage_.phase_used[Liquid]) {
|
||||
THROW("SaturationPropsFromDeck::init() -- oil phase must be active.");
|
||||
}
|
||||
|
||||
// Obtain SATNUM, if it exists, and create cell_to_func_.
|
||||
// Otherwise, let the cell_to_func_ mapping be just empty.
|
||||
int satfuncs_expected = 1;
|
||||
if (deck.hasField("SATNUM")) {
|
||||
const std::vector<int>& satnum = deck.getIntegerValue("SATNUM");
|
||||
satfuncs_expected = *std::max_element(satnum.begin(), satnum.end());
|
||||
const int num_cells = grid.number_of_cells;
|
||||
cell_to_func_.resize(num_cells);
|
||||
const int* gc = grid.global_cell;
|
||||
for (int cell = 0; cell < num_cells; ++cell) {
|
||||
const int deck_pos = (gc == NULL) ? cell : gc[cell];
|
||||
cell_to_func_[cell] = satnum[deck_pos] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Find number of tables, check for consistency.
|
||||
enum { Uninitialized = -1 };
|
||||
int num_tables = Uninitialized;
|
||||
if (phase_usage_.phase_used[Aqua]) {
|
||||
const SWOF::table_t& swof_table = deck.getSWOF().swof_;
|
||||
num_tables = swof_table.size();
|
||||
if (num_tables < satfuncs_expected) {
|
||||
THROW("Found " << num_tables << " SWOF tables, SATNUM specifies at least " << satfuncs_expected);
|
||||
}
|
||||
}
|
||||
if (phase_usage_.phase_used[Vapour]) {
|
||||
const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
|
||||
int num_sgof_tables = sgof_table.size();
|
||||
if (num_sgof_tables < satfuncs_expected) {
|
||||
THROW("Found " << num_tables << " SGOF tables, SATNUM specifies at least " << satfuncs_expected);
|
||||
}
|
||||
if (num_tables == Uninitialized) {
|
||||
num_tables = num_sgof_tables;
|
||||
} else if (num_tables != num_sgof_tables) {
|
||||
THROW("Inconsistent number of tables in SWOF and SGOF.");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize tables.
|
||||
satfuncset_.resize(num_tables);
|
||||
for (int table = 0; table < num_tables; ++table) {
|
||||
satfuncset_[table].init(deck, table, phase_usage_, samples);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// \return P, the number of phases.
|
||||
template <class SatFuncSet>
|
||||
int SaturationPropsFromDeck<SatFuncSet>::numPhases() const
|
||||
{
|
||||
return phase_usage_.num_phases;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Relative permeability.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] s Array of nP saturation values.
|
||||
/// \param[in] cells Array of n cell indices to be associated with the s values.
|
||||
/// \param[out] kr Array of nP relperm values, array must be valid before calling.
|
||||
/// \param[out] dkrds If non-null: array of nP^2 relperm derivative values,
|
||||
/// array must be valid before calling.
|
||||
/// The P^2 derivative matrix is
|
||||
/// m_{ij} = \frac{dkr_i}{ds^j},
|
||||
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
|
||||
template <class SatFuncSet>
|
||||
void SaturationPropsFromDeck<SatFuncSet>::relperm(const int n,
|
||||
const double* s,
|
||||
const int* cells,
|
||||
double* kr,
|
||||
double* dkrds) const
|
||||
{
|
||||
ASSERT (cells != 0);
|
||||
|
||||
const int np = phase_usage_.num_phases;
|
||||
if (dkrds) {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalKrDeriv(s + np*i, kr + np*i, dkrds + np*np*i);
|
||||
}
|
||||
} else {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalKr(s + np*i, kr + np*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Capillary pressure.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] s Array of nP saturation values.
|
||||
/// \param[in] cells Array of n cell indices to be associated with the s values.
|
||||
/// \param[out] pc Array of nP capillary pressure values, array must be valid before calling.
|
||||
/// \param[out] dpcds If non-null: array of nP^2 derivative values,
|
||||
/// array must be valid before calling.
|
||||
/// The P^2 derivative matrix is
|
||||
/// m_{ij} = \frac{dpc_i}{ds^j},
|
||||
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
|
||||
template <class SatFuncSet>
|
||||
void SaturationPropsFromDeck<SatFuncSet>::capPress(const int n,
|
||||
const double* s,
|
||||
const int* cells,
|
||||
double* pc,
|
||||
double* dpcds) const
|
||||
{
|
||||
ASSERT (cells != 0);
|
||||
|
||||
const int np = phase_usage_.num_phases;
|
||||
if (dpcds) {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalPcDeriv(s + np*i, pc + np*i, dpcds + np*np*i);
|
||||
}
|
||||
} else {
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
funcForCell(cells[i]).evalPc(s + np*i, pc + np*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Obtain the range of allowable saturation values.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] cells Array of n cell indices.
|
||||
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
|
||||
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
|
||||
template <class SatFuncSet>
|
||||
void SaturationPropsFromDeck<SatFuncSet>::satRange(const int n,
|
||||
const int* cells,
|
||||
double* smin,
|
||||
double* smax) const
|
||||
{
|
||||
ASSERT (cells != 0);
|
||||
|
||||
const int np = phase_usage_.num_phases;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (int p = 0; p < np; ++p) {
|
||||
smin[np*i + p] = funcForCell(cells[i]).smin_[p];
|
||||
smax[np*i + p] = funcForCell(cells[i]).smax_[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Map the cell number to the correct function set.
|
||||
template <class SatFuncSet>
|
||||
const typename SaturationPropsFromDeck<SatFuncSet>::Funcs&
|
||||
SaturationPropsFromDeck<SatFuncSet>::funcForCell(const int cell) const
|
||||
{
|
||||
return cell_to_func_.empty() ? satfuncset_[0] : satfuncset_[cell_to_func_[cell]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif // OPM_SATURATIONPROPSFROMDECK_IMPL_HEADER_INCLUDED
|
85
opm/core/fluid/SaturationPropsInterface.hpp
Normal file
85
opm/core/fluid/SaturationPropsInterface.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_SATURATIONPROPSINTERFACE_HEADER_INCLUDED
|
||||
#define OPM_SATURATIONPROPSINTERFACE_HEADER_INCLUDED
|
||||
|
||||
#include <opm/core/fluid/blackoil/BlackoilPhases.hpp>
|
||||
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
class SaturationPropsInterface : public BlackoilPhases
|
||||
{
|
||||
public:
|
||||
/// Virtual destructor.
|
||||
virtual ~SaturationPropsInterface() {};
|
||||
|
||||
/// \return P, the number of phases.
|
||||
virtual int numPhases() const = 0;
|
||||
|
||||
/// Relative permeability.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] s Array of nP saturation values.
|
||||
/// \param[out] kr Array of nP relperm values, array must be valid before calling.
|
||||
/// \param[out] dkrds If non-null: array of nP^2 relperm derivative values,
|
||||
/// array must be valid before calling.
|
||||
/// The P^2 derivative matrix is
|
||||
/// m_{ij} = \frac{dkr_i}{ds^j},
|
||||
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
|
||||
virtual void relperm(const int n,
|
||||
const double* s,
|
||||
const int* cells,
|
||||
double* kr,
|
||||
double* dkrds) const = 0;
|
||||
|
||||
/// Capillary pressure.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[in] s Array of nP saturation values.
|
||||
/// \param[out] pc Array of nP capillary pressure values, array must be valid before calling.
|
||||
/// \param[out] dpcds If non-null: array of nP^2 derivative values,
|
||||
/// array must be valid before calling.
|
||||
/// The P^2 derivative matrix is
|
||||
/// m_{ij} = \frac{dpc_i}{ds^j},
|
||||
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
|
||||
virtual void capPress(const int n,
|
||||
const double* s,
|
||||
const int* cells,
|
||||
double* pc,
|
||||
double* dpcds) const = 0;
|
||||
|
||||
/// Obtain the range of allowable saturation values.
|
||||
/// \param[in] n Number of data points.
|
||||
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
|
||||
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
|
||||
virtual void satRange(const int n,
|
||||
const int* cells,
|
||||
double* smin,
|
||||
double* smax) const = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
|
||||
|
||||
#endif // OPM_SATURATIONPROPSINTERFACE_HEADER_INCLUDED
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <opm/core/fluid/blackoil/BlackoilPvtProperties.hpp>
|
||||
#include <opm/core/fluid/blackoil/SinglePvtDead.hpp>
|
||||
#include <opm/core/fluid/blackoil/SinglePvtDeadSpline.hpp>
|
||||
#include <opm/core/fluid/blackoil/SinglePvtLiveOil.hpp>
|
||||
#include <opm/core/fluid/blackoil/SinglePvtLiveGas.hpp>
|
||||
#include <opm/core/fluid/blackoil/SinglePvtConstCompr.hpp>
|
||||
@ -78,7 +79,11 @@ namespace Opm
|
||||
// Oil PVT
|
||||
if (phase_usage_.phase_used[Liquid]) {
|
||||
if (deck.hasField("PVDO")) {
|
||||
props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDead(deck.getPVDO().pvdo_, samples));
|
||||
if (samples > 0) {
|
||||
props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDeadSpline(deck.getPVDO().pvdo_, samples));
|
||||
} else {
|
||||
props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDead(deck.getPVDO().pvdo_));
|
||||
}
|
||||
} else if (deck.hasField("PVTO")) {
|
||||
props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtLiveOil(deck.getPVTO().pvto_));
|
||||
} else if (deck.hasField("PVCDO")) {
|
||||
@ -90,7 +95,11 @@ namespace Opm
|
||||
// Gas PVT
|
||||
if (phase_usage_.phase_used[Vapour]) {
|
||||
if (deck.hasField("PVDG")) {
|
||||
props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDead(deck.getPVDG().pvdg_, samples));
|
||||
if (samples > 0) {
|
||||
props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDeadSpline(deck.getPVDG().pvdg_, samples));
|
||||
} else {
|
||||
props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDead(deck.getPVDG().pvdg_));
|
||||
}
|
||||
} else if (deck.hasField("PVTG")) {
|
||||
props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtLiveGas(deck.getPVTG().pvtg_));
|
||||
} else {
|
||||
|
@ -47,7 +47,13 @@ namespace Opm
|
||||
BlackoilPvtProperties();
|
||||
|
||||
/// Initialize from deck.
|
||||
void init(const EclipseGridParser& deck, const int samples = 16);
|
||||
/// \param deck An input deck.
|
||||
/// \param samples If greater than zero, indicates the number of
|
||||
/// uniform samples to be taken from monotone spline
|
||||
/// curves interpolating the fluid data.
|
||||
/// Otherwise, interpolate linearly in the original
|
||||
/// data without fitting a spline.
|
||||
void init(const EclipseGridParser& deck, const int samples);
|
||||
|
||||
/// Number of active phases.
|
||||
int numPhases() const;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2010, 2011, 2012 SINTEF ICT, Applied Mathematics.
|
||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <opm/core/fluid/blackoil/SinglePvtDead.hpp>
|
||||
#include <opm/core/utility/buildUniformMonotoneTable.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
// Extra includes for debug dumping of tables.
|
||||
@ -33,7 +33,7 @@ namespace Opm
|
||||
// Member functions
|
||||
//-------------------------------------------------------------------------
|
||||
/// Constructor
|
||||
SinglePvtDead::SinglePvtDead(const table_t& pvd_table, const int samples)
|
||||
SinglePvtDead::SinglePvtDead(const table_t& pvd_table)
|
||||
{
|
||||
const int region_number = 0;
|
||||
if (pvd_table.size() != 1) {
|
||||
@ -50,8 +50,8 @@ namespace Opm
|
||||
B_inv[i] = 1.0 / pvd_table[region_number][1][i];
|
||||
visc[i] = pvd_table[region_number][2][i];
|
||||
}
|
||||
buildUniformMonotoneTable(press, B_inv, samples, one_over_B_);
|
||||
buildUniformMonotoneTable(press, visc, samples, viscosity_);
|
||||
one_over_B_ = NonuniformTableLinear<double>(press, B_inv);
|
||||
viscosity_ = NonuniformTableLinear<double>(press, visc);
|
||||
|
||||
// Dumping the created tables.
|
||||
// static int count = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2010, 2011, 2012 SINTEF ICT, Applied Mathematics.
|
||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
|
||||
#include <opm/core/fluid/blackoil/SinglePvtInterface.hpp>
|
||||
#include <opm/core/utility/UniformTableLinear.hpp>
|
||||
#include <opm/core/utility/NonuniformTableLinear.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
@ -37,7 +37,7 @@ namespace Opm
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::vector<std::vector<double> > > table_t;
|
||||
SinglePvtDead(const table_t& pvd_table, const int samples = 16);
|
||||
SinglePvtDead(const table_t& pvd_table);
|
||||
virtual ~SinglePvtDead();
|
||||
|
||||
/// Viscosity as a function of p and z.
|
||||
@ -73,11 +73,11 @@ namespace Opm
|
||||
double* output_dRdp) const;
|
||||
private:
|
||||
// PVT properties of dry gas or dead oil
|
||||
UniformTableLinear<double> one_over_B_;
|
||||
UniformTableLinear<double> viscosity_;
|
||||
NonuniformTableLinear<double> one_over_B_;
|
||||
NonuniformTableLinear<double> viscosity_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPM_SINGLEPVTDEAD_HEADER_INCLUDED
|
||||
|
||||
#endif // OPM_SINGLEPVTDEAD_HEADER_INCLUDED
|
||||
|
127
opm/core/fluid/blackoil/SinglePvtDeadSpline.cpp
Normal file
127
opm/core/fluid/blackoil/SinglePvtDeadSpline.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2010, 2011, 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <opm/core/fluid/blackoil/SinglePvtDeadSpline.hpp>
|
||||
#include <opm/core/utility/buildUniformMonotoneTable.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
// Extra includes for debug dumping of tables.
|
||||
// #include <boost/lexical_cast.hpp>
|
||||
// #include <string>
|
||||
// #include <fstream>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Member functions
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/// Constructor
|
||||
SinglePvtDeadSpline::SinglePvtDeadSpline(const table_t& pvd_table, const int samples)
|
||||
{
|
||||
const int region_number = 0;
|
||||
if (pvd_table.size() != 1) {
|
||||
THROW("More than one PVT-region");
|
||||
}
|
||||
|
||||
// Copy data
|
||||
const int sz = pvd_table[region_number][0].size();
|
||||
std::vector<double> press(sz);
|
||||
std::vector<double> B_inv(sz);
|
||||
std::vector<double> visc(sz);
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
press[i] = pvd_table[region_number][0][i];
|
||||
B_inv[i] = 1.0 / pvd_table[region_number][1][i];
|
||||
visc[i] = pvd_table[region_number][2][i];
|
||||
}
|
||||
buildUniformMonotoneTable(press, B_inv, samples, one_over_B_);
|
||||
buildUniformMonotoneTable(press, visc, samples, viscosity_);
|
||||
|
||||
// Dumping the created tables.
|
||||
// static int count = 0;
|
||||
// std::ofstream os((std::string("dump-") + boost::lexical_cast<std::string>(count++)).c_str());
|
||||
// os.precision(15);
|
||||
// os << "1/B\n\n" << one_over_B_
|
||||
// << "\n\nvisc\n\n" << viscosity_ << std::endl;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SinglePvtDeadSpline::~SinglePvtDeadSpline()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SinglePvtDeadSpline::mu(const int n,
|
||||
const double* p,
|
||||
const double* /*z*/,
|
||||
double* output_mu) const
|
||||
{
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
output_mu[i] = viscosity_(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SinglePvtDeadSpline::B(const int n,
|
||||
const double* p,
|
||||
const double* /*z*/,
|
||||
double* output_B) const
|
||||
{
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
output_B[i] = 1.0/one_over_B_(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SinglePvtDeadSpline::dBdp(const int n,
|
||||
const double* p,
|
||||
const double* /*z*/,
|
||||
double* output_B,
|
||||
double* output_dBdp) const
|
||||
{
|
||||
B(n, p, 0, output_B);
|
||||
// #pragma omp parallel for
|
||||
for (int i = 0; i < n; ++i) {
|
||||
double Bg = output_B[i];
|
||||
output_dBdp[i] = -Bg*Bg*one_over_B_.derivative(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SinglePvtDeadSpline::R(const int n,
|
||||
const double* /*p*/,
|
||||
const double* /*z*/,
|
||||
double* output_R) const
|
||||
{
|
||||
std::fill(output_R, output_R + n, 0.0);
|
||||
}
|
||||
|
||||
void SinglePvtDeadSpline::dRdp(const int n,
|
||||
const double* /*p*/,
|
||||
const double* /*z*/,
|
||||
double* output_R,
|
||||
double* output_dRdp) const
|
||||
{
|
||||
std::fill(output_R, output_R + n, 0.0);
|
||||
std::fill(output_dRdp, output_dRdp + n, 0.0);
|
||||
}
|
||||
|
||||
}
|
84
opm/core/fluid/blackoil/SinglePvtDeadSpline.hpp
Normal file
84
opm/core/fluid/blackoil/SinglePvtDeadSpline.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright 2010, 2011, 2012 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_SINGLEPVTDEADSPLINE_HEADER_INCLUDED
|
||||
#define OPM_SINGLEPVTDEADSPLINE_HEADER_INCLUDED
|
||||
|
||||
|
||||
#include <opm/core/fluid/blackoil/SinglePvtInterface.hpp>
|
||||
#include <opm/core/utility/UniformTableLinear.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
/// Class for immiscible dead oil and dry gas.
|
||||
/// For all the virtual methods, the following apply: p and z
|
||||
/// are expected to be of size n and n*num_phases, respectively.
|
||||
/// Output arrays shall be of size n, and must be valid before
|
||||
/// calling the method.
|
||||
class SinglePvtDeadSpline : public SinglePvtInterface
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::vector<std::vector<double> > > table_t;
|
||||
|
||||
SinglePvtDeadSpline(const table_t& pvd_table, const int samples);
|
||||
virtual ~SinglePvtDeadSpline();
|
||||
|
||||
/// Viscosity as a function of p and z.
|
||||
virtual void mu(const int n,
|
||||
const double* p,
|
||||
const double* z,
|
||||
double* output_mu) const;
|
||||
|
||||
/// Formation volume factor as a function of p and z.
|
||||
virtual void B(const int n,
|
||||
const double* p,
|
||||
const double* z,
|
||||
double* output_B) const;
|
||||
|
||||
/// Formation volume factor and p-derivative as functions of p and z.
|
||||
virtual void dBdp(const int n,
|
||||
const double* p,
|
||||
const double* z,
|
||||
double* output_B,
|
||||
double* output_dBdp) const;
|
||||
|
||||
/// Solution factor as a function of p and z.
|
||||
virtual void R(const int n,
|
||||
const double* p,
|
||||
const double* z,
|
||||
double* output_R) const;
|
||||
|
||||
/// Solution factor and p-derivative as functions of p and z.
|
||||
virtual void dRdp(const int n,
|
||||
const double* p,
|
||||
const double* z,
|
||||
double* output_R,
|
||||
double* output_dRdp) const;
|
||||
private:
|
||||
// PVT properties of dry gas or dead oil
|
||||
UniformTableLinear<double> one_over_B_;
|
||||
UniformTableLinear<double> viscosity_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPM_SINGLEPVTDEADSPLINE_HEADER_INCLUDED
|
||||
|
244
opm/core/utility/NonuniformTableLinear.hpp
Normal file
244
opm/core/utility/NonuniformTableLinear.hpp
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
Copyright 2009, 2010, 2011, 2012 SINTEF ICT, Applied Mathematics.
|
||||
Copyright 2009, 2010, 2011, 2012 Statoil ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_NONUNIFORMTABLELINEAR_HEADER_INCLUDED
|
||||
#define OPM_NONUNIFORMTABLELINEAR_HEADER_INCLUDED
|
||||
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include <opm/core/utility/ErrorMacros.hpp>
|
||||
#include <opm/core/utility/linearInterpolation.hpp>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
|
||||
/// @brief Exception used for domain errors.
|
||||
struct OutsideDomainException : public std::exception {};
|
||||
|
||||
|
||||
/// @brief This class uses linear interpolation to compute the value
|
||||
/// (and its derivative) of a function f sampled at possibly
|
||||
/// nonuniform points.
|
||||
/// @tparam T the range type of the function (should be an algebraic ring type)
|
||||
template<typename T>
|
||||
class NonuniformTableLinear
|
||||
{
|
||||
public:
|
||||
/// @brief Default constructor.
|
||||
NonuniformTableLinear();
|
||||
|
||||
/// @brief Construct from vectors of x and y values.
|
||||
/// @param x_values vector of domain values
|
||||
/// @param y_values vector of corresponding range values.
|
||||
NonuniformTableLinear(const std::vector<double>& x_values,
|
||||
const std::vector<T>& y_values);
|
||||
|
||||
/// @brief Get the domain.
|
||||
/// @return the domain as a pair of doubles.
|
||||
std::pair<double, double> domain();
|
||||
|
||||
/// @brief Rescale the domain.
|
||||
/// @param new_domain the new domain as a pair of doubles.
|
||||
void rescaleDomain(std::pair<double, double> new_domain);
|
||||
|
||||
/// @brief Evaluate the value at x.
|
||||
/// @param x a domain value
|
||||
/// @return f(x)
|
||||
double operator()(const double x) const;
|
||||
|
||||
/// @brief Evaluate the derivative at x.
|
||||
/// @param x a domain value
|
||||
/// @return f'(x)
|
||||
double derivative(const double x) const;
|
||||
|
||||
/// @brief Evaluate the inverse at y. Requires T to be a double.
|
||||
/// @param y a range value
|
||||
/// @return f^{-1}(y)
|
||||
double inverse(const double y) const;
|
||||
|
||||
/// @brief Equality operator.
|
||||
/// @param other another NonuniformTableLinear.
|
||||
/// @return true if they are represented exactly alike.
|
||||
bool operator==(const NonuniformTableLinear& other) const;
|
||||
|
||||
/// @brief Policies for how to behave when trying to evaluate outside the domain.
|
||||
enum RangePolicy {Throw = 0, ClosestValue = 1, Extrapolate = 2};
|
||||
|
||||
/// @brief Sets the behavioural policy for evaluation to the left of the domain.
|
||||
/// @param rp the policy
|
||||
void setLeftPolicy(RangePolicy rp);
|
||||
|
||||
/// @brief Sets the behavioural policy for evaluation to the right of the domain.
|
||||
/// @param rp the policy
|
||||
void setRightPolicy(RangePolicy rp);
|
||||
|
||||
protected:
|
||||
std::vector<double> x_values_;
|
||||
std::vector<T> y_values_;
|
||||
mutable std::vector<T> x_values_reversed_;
|
||||
mutable std::vector<T> y_values_reversed_;
|
||||
RangePolicy left_;
|
||||
RangePolicy right_;
|
||||
};
|
||||
|
||||
|
||||
// A utility function
|
||||
/// @brief Detect if a sequence is nondecreasing.
|
||||
/// @tparam FI a forward iterator whose value type has operator< defined.
|
||||
/// @param beg start of sequence
|
||||
/// @param end one-beyond-end of sequence
|
||||
/// @return false if there exists two consecutive values (v1, v2) in the sequence
|
||||
/// for which v2 < v1, else returns true.
|
||||
template <typename FI>
|
||||
bool isNondecreasing(const FI beg, const FI end)
|
||||
{
|
||||
if (beg == end) return true;
|
||||
FI it = beg;
|
||||
++it;
|
||||
FI prev = beg;
|
||||
for (; it != end; ++it, ++prev) {
|
||||
if (*it < *prev) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Member implementations.
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
NonuniformTableLinear<T>
|
||||
::NonuniformTableLinear()
|
||||
: left_(ClosestValue), right_(ClosestValue)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
NonuniformTableLinear<T>
|
||||
::NonuniformTableLinear(const std::vector<double>& x_values,
|
||||
const std::vector<T>& y_values)
|
||||
: x_values_(x_values), y_values_(y_values),
|
||||
left_(ClosestValue), right_(ClosestValue)
|
||||
{
|
||||
ASSERT(isNondecreasing(x_values.begin(), x_values.end()));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::pair<double, double>
|
||||
NonuniformTableLinear<T>
|
||||
::domain()
|
||||
{
|
||||
return std::make_pair(x_values_[0], x_values_.back());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
NonuniformTableLinear<T>
|
||||
::rescaleDomain(std::pair<double, double> new_domain)
|
||||
{
|
||||
const double a = x_values_[0];
|
||||
const double b = x_values_.back();
|
||||
const double c = new_domain.first;
|
||||
const double d = new_domain.second;
|
||||
// x in [a, b] -> x in [c, d]
|
||||
for (int i = 0; i < int(x_values_.size()); ++i) {
|
||||
x_values_[i] = (x_values_[i] - a)*(d - c)/(b - a) + c;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline double
|
||||
NonuniformTableLinear<T>
|
||||
::operator()(const double x) const
|
||||
{
|
||||
return Opm::linearInterpolation(x_values_, y_values_, x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline double
|
||||
NonuniformTableLinear<T>
|
||||
::derivative(const double x) const
|
||||
{
|
||||
return Opm::linearInterpolationDerivative(x_values_, y_values_, x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline double
|
||||
NonuniformTableLinear<T>
|
||||
::inverse(const double y) const
|
||||
{
|
||||
if (y_values_.front() < y_values_.back()) {
|
||||
return Opm::linearInterpolation(y_values_, x_values_, y);
|
||||
} else {
|
||||
if (y_values_reversed_.empty()) {
|
||||
y_values_reversed_ = y_values_;
|
||||
std::reverse(y_values_reversed_.begin(), y_values_reversed_.end());
|
||||
ASSERT(isNondecreasing(y_values_reversed_.begin(), y_values_reversed_.end()));
|
||||
x_values_reversed_ = x_values_;
|
||||
std::reverse(x_values_reversed_.begin(), x_values_reversed_.end());
|
||||
}
|
||||
return Opm::linearInterpolation(y_values_reversed_, x_values_reversed_, y);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
NonuniformTableLinear<T>
|
||||
::operator==(const NonuniformTableLinear<T>& other) const
|
||||
{
|
||||
return x_values_ == other.x_values_
|
||||
&& y_values_ == other.y_values_
|
||||
&& left_ == other.left_
|
||||
&& right_ == other.right_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
NonuniformTableLinear<T>
|
||||
::setLeftPolicy(RangePolicy rp)
|
||||
{
|
||||
if (rp != ClosestValue) {
|
||||
THROW("Only ClosestValue RangePolicy implemented.");
|
||||
}
|
||||
left_ = rp;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
NonuniformTableLinear<T>
|
||||
::setRightPolicy(RangePolicy rp)
|
||||
{
|
||||
if (rp != ClosestValue) {
|
||||
THROW("Only ClosestValue RangePolicy implemented.");
|
||||
}
|
||||
right_ = rp;
|
||||
}
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif // OPM_NONUNIFORMTABLELINEAR_HEADER_INCLUDED
|
@ -43,7 +43,7 @@ int main(int argc, char** argv)
|
||||
UnstructuredGrid grid;
|
||||
grid.number_of_cells = 1;
|
||||
grid.global_cell = NULL;
|
||||
Opm::BlackoilPropertiesFromDeck props(deck, grid);
|
||||
Opm::BlackoilPropertiesFromDeck props(deck, grid, param);
|
||||
|
||||
const int n = 1;
|
||||
double p[n] = { 150e5 };
|
||||
|
Loading…
Reference in New Issue
Block a user