compute fluid in place by regions.

This commit is contained in:
Liu Ming 2016-07-19 09:33:03 +08:00 committed by Atgeirr Flø Rasmussen
parent 28583e4237
commit 056708574c
10 changed files with 136 additions and 87 deletions

View File

@ -261,8 +261,10 @@ namespace Opm {
const WellModel& wellModel() const { return well_model_; }
/// Calculate FIP
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw);
std::vector<V>
computeFluidInPlace(const ReservoirState& x,
const WellState& xw,
const std::vector<int>& fipnum);
protected:

View File

@ -2297,36 +2297,45 @@ namespace detail {
template <class Grid, class WellModel, class Implementation>
V
std::vector<V>
BlackoilModelBase<Grid, WellModel, Implementation>::
computeFluidInPlace(const ReservoirState& x,
const WellState& xw)
const WellState& xw,
const std::vector<int>& fipnum)
{
SolutionState state = asImpl().variableState(x, xw);
const Opm::PhaseUsage& pu = fluid_.phaseUsage();
using namespace Opm::AutoDiffGrid;
const int nc = numCells(grid_);
const ADB& press = state.pressure;
const ADB& temp = state.temperature;
const std::vector<ADB>& sat = state.saturation;
const ADB& rs = state.rs;
const ADB& rv = state.rv;
const int np = x.numPhases();
SolutionState state(np);
const DataBlock s = Eigen::Map<const DataBlock>(& x.saturation()[0], nc, np);
state.pressure = ADB::constant(Eigen::Map<const V>(& x.pressure()[0], nc, 1));
state.temperature = ADB::constant(Eigen::Map<const V>(& x.temperature()[0], nc, 1));
state.saturation[Water] = ADB::constant(s.col(Water));
state.saturation[Oil] = ADB::constant(s.col(Oil));
state.saturation[Gas] = ADB::constant(s.col(Gas));
state.rs = ADB::constant(Eigen::Map<const V>(& x.gasoilratio()[0], nc, 1));
state.rv = ADB::constant(Eigen::Map<const V>(& x.rv()[0], nc, 1));
state.canonical_phase_pressures = computePressures(state.pressure,
state.saturation[Water],
state.saturation[Oil],
state.saturation[Gas]);
const Opm::PhaseUsage& pu = fluid_.phaseUsage();
const std::vector<PhasePresence> cond = phaseCondition();
const ADB pv_mult = poroMult(press);
const ADB pv_mult = poroMult(state.pressure);
const V& pv = geo_.poreVolume();
const int maxnp = Opm::BlackoilPhases::MaxNumPhases;
std::vector<V> fip(5, V::Zero(nc));
// std::cout << "Oil sat: \n";
//std::cout << sat[pu.phase_pos[Oil]].value() << std::endl;
//std::cout << "Gas sat: \n";
//std::cout << sat[pu.phase_pos[Gas]].value() << std::endl;
for (int phase = 0; phase < maxnp; ++phase) {
if (active_[ phase ]) {
const int pos = pu.phase_pos[ phase ];
const auto& b = asImpl().fluidReciprocFVF(phase, state.canonical_phase_pressures[phase], temp, rs, rv, cond);
fip[phase] = ((pv_mult * b * sat[pos] * pv).value());
const auto& b = asImpl().fluidReciprocFVF(phase, state.canonical_phase_pressures[phase], state.temperature, state.rs, state.rv, cond);
fip[phase] = ((pv_mult * b * state.saturation[pos] * pv).value());
}
}
@ -2338,10 +2347,19 @@ namespace detail {
fip[4] = state.rv.value() * fip[pg];
}
V values(5);
for (int i = 0; i < 5; ++i) {
values[i] = int(fip[i].sum());
const int dims = *std::max_element(fipnum.begin(), fipnum.end()) + 1;
std::vector<V> values(dims, V::Zero(5));
for (int d = 0; d < dims; ++d) {
for (int c = 0; c < nc; ++c) {
if (fipnum[c] == d) {
for (int i = 0; i < 5; ++i) {
values[d][i] += fip[i][c];
}
}
}
}
return values;
}

View File

@ -248,10 +248,12 @@ namespace Opm {
/// Compute fluid in place.
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw) const
std::vector<V>
computeFluidInPlace(const ReservoirState& x,
const WellState& xw,
const std::vector<int>& fipnum) const
{
return transport_solver_.computeFluidInPlace(x, xw);
return transport_solver_.computeFluidInPlace(x, xw, fipnum);
}

View File

@ -159,10 +159,12 @@ namespace Opm {
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw)
std::vector<V>
computeFluidInPlace(const ReservoirState& x,
const WellState& xw,
const std::vector<int>& fipnum)
{
return asImpl().computeFluidInPlace(x, xw);
return asImpl().computeFluidInPlace(x, xw, fipnum);
}

View File

@ -126,8 +126,10 @@ namespace Opm {
int wellIterationsLastStep() const;
/// Compute fluid in place.
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw) const;
std::vector<V>
computeFluidInPlace(const ReservoirState& x,
const WellState& xw,
const std::vector<int>& fipnum) const;
/// Reference to physical model.
const PhysicalModel& model() const;

View File

@ -100,10 +100,12 @@ namespace Opm
}
template <class PhysicalModel>
V NonlinearSolver<PhysicalModel>::computeFluidInPlace(const ReservoirState& x,
const WellState& xw) const
std::vector<V>
NonlinearSolver<PhysicalModel>::computeFluidInPlace(const ReservoirState& x,
const WellState& xw,
const std::vector<int>& fipnum) const
{
return model_->computeFluidInPlace(x, xw);
return model_->computeFluidInPlace(x, xw, fipnum);
}

View File

@ -157,7 +157,13 @@ namespace Opm
const Wells* wells,
const BlackoilState& x,
WellState& xw);
V computeFIP(const ReservoirState& state);
void
FIPUnitConvert(const UnitSystem& units,
std::vector<V>& fip);
V
FIPTotals(const std::vector<V>& fip);
void computeWellPotentials(const Wells* wells,

View File

@ -135,10 +135,13 @@ namespace Opm
std::vector<double> well_potentials;
DynamicListEconLimited dynamic_list_econ_limited;
const auto& units = eclipse_state_->getUnits();
bool ooip_computed = false;
V OOIP;
double pv = geo_.poreVolume().sum();
std::vector<int> fipnum = eclipse_state_->get3DProperties().getRegions("FIPNUM");
if (fipnum.empty()) {
fipnum.resize(AutoDiffGrid::numCells(grid_));
std::fill(fipnum.begin(), fipnum.end(), 0);
}
std::vector<V> OOIP;
// Main simulation loop.
while (!timer.done()) {
// Report timestep.
@ -189,18 +192,11 @@ namespace Opm
auto solver = asImpl().createSolver(well_model);
// Compute FIP;
// Compute orignal FIP;
if (!ooip_computed) {
OOIP = solver->computeFluidInPlace(state, well_state);
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
pv = unit::convert::to(pv, unit::stb);
OOIP[0] = unit::convert::to(OOIP[0], unit::stb);
OOIP[1] = unit::convert::to(OOIP[1], unit::stb);
OOIP[2] = unit::convert::to(OOIP[2], 1000*unit::cubic(unit::feet));
OOIP[3] = unit::convert::to(OOIP[3], 1000*unit::cubic(unit::feet));
OOIP[4] = unit::convert::to(OOIP[4], unit::stb);
ooip_computed = true;
}
OOIP = solver->computeFluidInPlace(state, well_state, fipnum);
FIPUnitConvert(eclipse_state_->getUnits(), OOIP);
ooip_computed = true;
}
if( terminal_output_ )
@ -266,19 +262,17 @@ namespace Opm
// Report timing.
const double st = solver_timer.secsSinceStart();
V COIP = solver->computeFluidInPlace(state, well_state);
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
COIP[0] = unit::convert::to(COIP[0], unit::stb);
COIP[1] = unit::convert::to(COIP[1], unit::stb);
COIP[2] = unit::convert::to(COIP[2], 1000*unit::cubic(unit::feet));
COIP[3] = unit::convert::to(COIP[3], 1000*unit::cubic(unit::feet));
COIP[4] = unit::convert::to(COIP[4], unit::stb);
}
OpmLog::info("*********************Fluid in Place******************");
OpmLog::info("PORV : " + std::to_string(pv));
OpmLog::info("----------Oil--------VapOil-------Wat---------Gas--------DisGas");
OpmLog::info("Currently : " + std::to_string(COIP[1]) + " " + std::to_string(COIP[4]) + " " + std::to_string(COIP[0]) + " " + std::to_string(COIP[2]) + " " + std::to_string(COIP[3]));
OpmLog::info("Originally: " + std::to_string(OOIP[1]) + " " + std::to_string(OOIP[4]) + " " + std::to_string(OOIP[0]) + " " + std::to_string(OOIP[2]) + " " + std::to_string(OOIP[3]));
// Compute current FIP.
std::vector<V> COIP;
COIP = solver->computeFluidInPlace(state, well_state, fipnum);
FIPUnitConvert(eclipse_state_->getUnits(), COIP);
V OOIP_totals = FIPTotals(OOIP);
V COIP_totals = FIPTotals(COIP);
OpmLog::info("*****************************Field Totals**************************");
OpmLog::info(" Liquid VAPOUR Water Free Gas Dissolved Gas");
OpmLog::info("Currently in place: " + std::to_string(COIP_totals[1]) + " " + std::to_string(COIP_totals[4]) + " " + std::to_string(COIP_totals[0]) + " " + std::to_string(COIP_totals[2]) + " " + std::to_string(COIP_totals[3]));
OpmLog::info("Originally in place: " + std::to_string(OOIP_totals[1]) + " " + std::to_string(OOIP_totals[4]) + " " + std::to_string(OOIP_totals[0]) + " " + std::to_string(OOIP_totals[2]) + " " + std::to_string(OOIP_totals[3]) + "\n");
// accumulate total time
stime += st;
@ -657,29 +651,38 @@ namespace Opm
template <class Implementation>
V SimulatorBase<Implementation>::computeFIP(const ReservoirState& state)
void
SimulatorBase<Implementation>::FIPUnitConvert(const UnitSystem& units,
std::vector<V>& fip)
{
using namespace Opm::AutoDiffGrid;
const int np = state.numPhases();
const int nc = numCells(grid_);
const Opm::PhaseUsage& pu = props_.phaseUsage();
V so = V::Zero(nc);
V sw = V::Zero(nc);
V sg = V::Zero(nc);
for (int c = 0; c < nc; ++c) {
so[c] = state.saturation()[c*np + pu.phase_pos[BlackoilPhases::Liquid]];
sw[c] = state.saturation()[c*np + pu.phase_pos[BlackoilPhases::Aqua]];
sg[c] = state.saturation()[c*np + pu.phase_pos[BlackoilPhases::Vapour]];
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
for (int i = 0; i < fip.size(); ++i) {
fip[i][0] = unit::convert::to(fip[i][0], unit::stb);
fip[i][1] = unit::convert::to(fip[i][1], unit::stb);
fip[i][2] = unit::convert::to(fip[i][2], 1000*unit::cubic(unit::feet));
fip[i][3] = unit::convert::to(fip[i][3], 1000*unit::cubic(unit::feet));
fip[i][4] = unit::convert::to(fip[i][4], unit::stb);
}
}
// Get Bo, Bw, Bg.
V fip(V::Zero(np));
fip[0] = (geo_.poreVolume() * so).sum();
fip[1] = (geo_.poreVolume() * sw).sum();
fip[2] = (geo_.poreVolume() * sg).sum();
return fip;
}
template <class Implementation>
V
SimulatorBase<Implementation>::FIPTotals(const std::vector<V>& fip)
{
V totals(V::Zero(5));
for (int i = 0; i < 5; ++i) {
for (size_t reg = 0; reg < fip.size(); ++reg) {
totals[i] += fip[reg][i];
}
}
return totals;
}
template <class Implementation>
void
SimulatorBase<Implementation>::

View File

@ -532,11 +532,12 @@ namespace {
V
std::vector<V>
FullyImplicitCompressiblePolymerSolver::computeFluidInPlace(const PolymerBlackoilState& x,
const WellStateFullyImplicitBlackoilPolymer& xw)
const WellStateFullyImplicitBlackoilPolymer& xw,
const std::vector<int>& fipnum)
{
const SolutionState state = variableState(x, xw);
const SolutionState state = constantState(x, xw);
const int nc = grid_.number_of_cells;
const ADB& press = state.pressure;
@ -554,12 +555,21 @@ namespace {
fip[phase] = (pv_mult * b * sat[phase] * pv).value();
}
V values(5);
for (int i = 0; i < 5; ++i) {
values[i] = fip[i].sum();
const int dims = *std::max_element(fipnum.begin(), fipnum.end());
std::vector<V> values(dims, V::Zero(5));
for (int d = 0; d < dims; ++d) {
for (int c = 0; c < nc; ++c) {
for (int i = 0; i < 5; ++i) {
if (fipnum[c] == d) {
values[d][i] += fip[c][i];
}
}
}
}
return values;
return values;
}

View File

@ -110,8 +110,10 @@ namespace Opm {
const PolymerBlackoilState& current ) const;
/// Compute fluid in place.
V computeFluidInPlace(const PolymerBlackoilState& x,
const WellStateFullyImplicitBlackoilPolymer& xw);
std::vector<V>
computeFluidInPlace(const PolymerBlackoilState& x,
const WellStateFullyImplicitBlackoilPolymer& xw,
const std::vector<int>& fipnum);
private: