Add computeFluidInPlace function.

This commit is contained in:
Liu Ming 2016-07-18 08:50:50 +08:00 committed by Atgeirr Flø Rasmussen
parent 78a5381f5d
commit 28583e4237
9 changed files with 159 additions and 23 deletions

View File

@ -260,6 +260,10 @@ namespace Opm {
WellModel& wellModel() { return well_model_; }
const WellModel& wellModel() const { return well_model_; }
/// Calculate FIP
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw);
protected:
// --------- Types and enums ---------

View File

@ -2295,6 +2295,57 @@ namespace detail {
template <class Grid, class WellModel, class Implementation>
V
BlackoilModelBase<Grid, WellModel, Implementation>::
computeFluidInPlace(const ReservoirState& x,
const WellState& xw)
{
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 std::vector<PhasePresence> cond = phaseCondition();
const ADB pv_mult = poroMult(press);
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());
}
}
if (active_[ Oil ] && active_[ Gas ]) {
// Account for gas dissolved in oil and vaporized oil
const int po = pu.phase_pos[Oil];
const int pg = pu.phase_pos[Gas];
fip[3] = state.rs.value() * fip[po];
fip[4] = state.rv.value() * fip[pg];
}
V values(5);
for (int i = 0; i < 5; ++i) {
values[i] = int(fip[i].sum());
}
return values;
}
} // namespace Opm
#endif // OPM_BLACKOILMODELBASE_IMPL_HEADER_INCLUDED

View File

@ -247,7 +247,12 @@ namespace Opm {
}
/// Compute fluid in place.
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw) const
{
return transport_solver_.computeFluidInPlace(x, xw);
}

View File

@ -159,6 +159,11 @@ namespace Opm {
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw)
{
return asImpl().computeFluidInPlace(x, xw);
}
@ -275,6 +280,10 @@ namespace Opm {
void assembleMassBalanceEq(const SolutionState& state)
{
// Compute b_p and the accumulation term b_p*s_p for each phase,

View File

@ -125,6 +125,10 @@ namespace Opm {
/// Number of well iterations used in all calls to step().
int wellIterationsLastStep() const;
/// Compute fluid in place.
V computeFluidInPlace(const ReservoirState& x,
const WellState& xw) const;
/// Reference to physical model.
const PhysicalModel& model() const;

View File

@ -99,6 +99,14 @@ namespace Opm
return wellIterationsLast_;
}
template <class PhysicalModel>
V NonlinearSolver<PhysicalModel>::computeFluidInPlace(const ReservoirState& x,
const WellState& xw) const
{
return model_->computeFluidInPlace(x, xw);
}
template <class PhysicalModel>
int
NonlinearSolver<PhysicalModel>::

View File

@ -135,12 +135,10 @@ namespace Opm
std::vector<double> well_potentials;
DynamicListEconLimited dynamic_list_econ_limited;
OpmLog::info("PORV: " + std::to_string(unit::convert::to(geo_.poreVolume().sum(), unit::stb)));
V OOIP = asImpl().computeFIP(state);
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));
const auto& units = eclipse_state_->getUnits();
bool ooip_computed = false;
V OOIP;
double pv = geo_.poreVolume().sum();
// Main simulation loop.
while (!timer.done()) {
// Report timestep.
@ -191,6 +189,20 @@ namespace Opm
auto solver = asImpl().createSolver(well_model);
// Compute 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;
}
}
if( terminal_output_ )
{
std::ostringstream step_msg;
@ -254,15 +266,19 @@ namespace Opm
// Report timing.
const double st = solver_timer.secsSinceStart();
V COIP = asImpl().computeFIP(state);
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));
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("----------Oil--------Wat---------Gas");
OpmLog::info("Currently : " + std::to_string(COIP[0]) + " " + std::to_string(COIP[1]) + " " + std::to_string(COIP[2]));
OpmLog::info("Originally: " + std::to_string(OOIP[0]) + " " + std::to_string(OOIP[1]) + " " + std::to_string(OOIP[2]));
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]));
// accumulate total time
stime += st;
@ -655,6 +671,7 @@ namespace Opm
sw[c] = state.saturation()[c*np + pu.phase_pos[BlackoilPhases::Aqua]];
sg[c] = state.saturation()[c*np + pu.phase_pos[BlackoilPhases::Vapour]];
}
// Get Bo, Bw, Bg.
V fip(V::Zero(np));
fip[0] = (geo_.poreVolume() * so).sum();
fip[1] = (geo_.poreVolume() * sw).sum();

View File

@ -520,7 +520,7 @@ namespace {
}
rq_[0].accum[aix] = pv_mult * rq_[0].b * sat[0];
rq_[1].accum[aix] = pv_mult * rq_[1].b * sat[1];
const ADB cmax = ADB::constant(cmax_, state.concentration.blockPattern());
const ADB cmax = ADB::constant(cmax_, state.concentration.blockPattern());
const ADB ads = polymer_props_ad_.adsorption(state.concentration, cmax);
const double rho_rock = polymer_props_ad_.rockDensity();
const V phi = Eigen::Map<const V>(&fluid_.porosity()[0], grid_.number_of_cells, 1);
@ -532,6 +532,39 @@ namespace {
V
FullyImplicitCompressiblePolymerSolver::computeFluidInPlace(const PolymerBlackoilState& x,
const WellStateFullyImplicitBlackoilPolymer& xw)
{
const SolutionState state = variableState(x, xw);
const int nc = grid_.number_of_cells;
const ADB& press = state.pressure;
const ADB& temp = state.temperature;
const std::vector<ADB>& sat = state.saturation;
const std::vector<PhasePresence> cond = phaseCondition();
std::vector<ADB> pressure = computePressures(state);
const ADB pv_mult = poroMult(press);
const V& pv = geo_.poreVolume();
std::vector<V> fip(5, V::Zero(nc));
for (int phase = 0; phase < 2; ++phase) {
const ADB& b = fluidReciprocFVF(phase, pressure[phase], temp, cond, cells_);
fip[phase] = (pv_mult * b * sat[phase] * pv).value();
}
V values(5);
for (int i = 0; i < 5; ++i) {
values[i] = fip[i].sum();
}
return values;
}
void
FullyImplicitCompressiblePolymerSolver::

View File

@ -54,6 +54,13 @@ namespace Opm {
class FullyImplicitCompressiblePolymerSolver
{
public:
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
typedef Eigen::Array<double,
Eigen::Dynamic,
Eigen::Dynamic,
Eigen::RowMajor> DataBlock;
/// Construct a solver. It will retain references to the
/// arguments of this functions, and they are expected to
/// remain in scope for the lifetime of the solver.
@ -102,14 +109,12 @@ namespace Opm {
double relativeChange(const PolymerBlackoilState& previous,
const PolymerBlackoilState& current ) const;
/// Compute fluid in place.
V computeFluidInPlace(const PolymerBlackoilState& x,
const WellStateFullyImplicitBlackoilPolymer& xw);
private:
typedef AutoDiffBlock<double> ADB;
typedef ADB::V V;
typedef ADB::M M;
typedef Eigen::Array<double,
Eigen::Dynamic,
Eigen::Dynamic,
Eigen::RowMajor> DataBlock;
struct ReservoirResidualQuant {
ReservoirResidualQuant();