Merge pull request #635 from GitPaean/wells_refactoring

A first step towards Wells refactoring
This commit is contained in:
Atgeirr Flø Rasmussen 2016-04-06 16:08:18 +02:00
commit cebc393caf
8 changed files with 217 additions and 72 deletions

View File

@ -269,20 +269,51 @@ namespace Opm {
ADB mob; // Phase mobility (per cell)
};
class StandardWells {
protected:
struct WellOps {
WellOps(const Wells* wells);
explicit WellOps(const Wells* wells);
Eigen::SparseMatrix<double> w2p; // well -> perf (scatter)
Eigen::SparseMatrix<double> p2w; // perf -> well (gather)
std::vector<int> well_cells; // the set of perforated cells
};
public:
explicit StandardWells(const Wells* wells);
const Wells& wells() const;
// return true if wells are available in the reservoir
bool wellsActive() const;
void setWellsActive(const bool wells_active);
// return true if wells are available on this process
bool localWellsActive() const;
const WellOps& wellOps() const;
//Density of each well perforation
V& wellPerforationDensities();
const V& wellPerforationDensities() const;
// Diff to bhp for each well perforation.
V& wellPerforationPressureDiffs();
const V& wellPerforationPressureDiffs() const;
protected:
bool wells_active_;
const Wells* wells_;
const WellOps wops_;
V well_perforation_densities_;
V well_perforation_pressure_diffs_;
};
// --------- Data members ---------
const Grid& grid_;
const BlackoilPropsAdInterface& fluid_;
const DerivedGeology& geo_;
const RockCompressibility* rock_comp_props_;
const Wells* wells_;
StandardWells std_wells_;
VFPProperties vfp_properties_;
const NewtonIterationBlackoilInterface& linsolver_;
// For each canonical phase -> true if active
@ -291,13 +322,11 @@ namespace Opm {
const std::vector<int> canph_;
const std::vector<int> cells_; // All grid cells
HelperOps ops_;
const WellOps wops_;
const bool has_disgas_;
const bool has_vapoil_;
ModelParameters param_;
bool use_threshold_pressure_;
bool wells_active_;
V threshold_pressures_by_connection_;
std::vector<ReservoirResidualQuant> rq_;
@ -305,8 +334,6 @@ namespace Opm {
V isRs_;
V isRv_;
V isSg_;
V well_perforation_densities_; //Density of each well perforation
V well_perforation_pressure_diffs_; // Diff to bhp for each well perforation.
LinearisedBlackoilResidual residual_;
@ -338,12 +365,18 @@ namespace Opm {
return static_cast<const Implementation&>(*this);
}
// return true if wells are available in the reservoir
bool wellsActive() const { return wells_active_; }
// return true if wells are available on this process
bool localWellsActive() const { return wells_ ? (wells_->number_of_wells > 0 ) : false; }
// return wells object
const Wells& wells () const { assert( bool(wells_ != 0) ); return *wells_; }
/// return the StandardWells object
StandardWells& stdWells() { return std_wells_; }
const StandardWells& stdWells() const { return std_wells_; }
/// return the Well struct in the StandardWells
const Wells& wells() const { return std_wells_.wells(); }
/// return true if wells are available in the reservoir
bool wellsActive() const { return std_wells_.wellsActive(); }
/// return true if wells are available on this process
bool localWellsActive() const { return std_wells_.localWellsActive(); }
int numWellVars() const;

View File

@ -159,14 +159,13 @@ namespace detail {
, fluid_ (fluid)
, geo_ (geo)
, rock_comp_props_(rock_comp_props)
, wells_ (wells_arg)
, std_wells_ (wells_arg)
, vfp_properties_(eclState->getTableManager()->getVFPInjTables(), eclState->getTableManager()->getVFPProdTables())
, linsolver_ (linsolver)
, active_(detail::activePhases(fluid.phaseUsage()))
, canph_ (detail::active2Canonical(fluid.phaseUsage()))
, cells_ (detail::buildAllCells(Opm::AutoDiffGrid::numCells(grid)))
, ops_ (grid, geo.nnc())
, wops_ (wells_)
, has_disgas_(has_disgas)
, has_vapoil_(has_vapoil)
, param_( param )
@ -195,9 +194,10 @@ namespace detail {
// Only rank 0 does print to std::cout if terminal_output is enabled
terminal_output_ = (info.communicator().rank()==0);
}
int local_number_of_wells = wells_ ? wells_->number_of_wells : 0;
int local_number_of_wells = localWellsActive() ? wells().number_of_wells : 0;
int global_number_of_wells = info.communicator().sum(local_number_of_wells);
wells_active_ = ( wells_ && global_number_of_wells > 0 );
const bool wells_active = ( wells_arg && global_number_of_wells > 0 );
stdWells().setWellsActive(wells_active);
// Compute the global number of cells
std::vector<int> v( Opm::AutoDiffGrid::numCells(grid_), 1);
global_nc_ = 0;
@ -205,7 +205,7 @@ namespace detail {
}else
#endif
{
wells_active_ = ( wells_ && wells_->number_of_wells > 0 );
stdWells().setWellsActive( localWellsActive() );
global_nc_ = Opm::AutoDiffGrid::numCells(grid_);
}
}
@ -420,6 +420,7 @@ namespace detail {
template <class Grid, class Implementation>
BlackoilModelBase<Grid, Implementation>::
StandardWells::
WellOps::WellOps(const Wells* wells)
: w2p(),
p2w(),
@ -457,12 +458,135 @@ namespace detail {
template <class Grid, class Implementation>
BlackoilModelBase<Grid, Implementation>::
StandardWells::StandardWells(const Wells* wells_arg)
: wells_(wells_arg)
, wops_(wells_arg)
, well_perforation_densities_(V())
, well_perforation_pressure_diffs_(V())
{
}
template <class Grid, class Implementation>
const Wells&
BlackoilModelBase<Grid, Implementation>::
StandardWells::wells() const
{
assert(wells_ != 0);
return *(wells_);
}
template <class Grid, class Implementation>
bool
BlackoilModelBase<Grid, Implementation>::
StandardWells::wellsActive() const
{
return wells_active_;
}
template <class Grid, class Implementation>
void
BlackoilModelBase<Grid, Implementation>::
StandardWells::setWellsActive(const bool wells_active)
{
wells_active_ = wells_active;
}
template <class Grid, class Implementation>
bool
BlackoilModelBase<Grid, Implementation>::
StandardWells::localWellsActive() const
{
return wells_ ? (wells_->number_of_wells > 0 ) : false;
}
template <class Grid, class Implementation>
const typename BlackoilModelBase<Grid, Implementation>::StandardWells::WellOps&
BlackoilModelBase<Grid, Implementation>::
StandardWells::wellOps() const
{
return wops_;
}
template <class Grid, class Implementation>
V&
BlackoilModelBase<Grid, Implementation>::
StandardWells::wellPerforationDensities()
{
return well_perforation_densities_;
}
template <class Grid, class Implementation>
const V&
BlackoilModelBase<Grid, Implementation>::
StandardWells::wellPerforationDensities() const
{
return well_perforation_densities_;
}
template <class Grid, class Implementation>
V&
BlackoilModelBase<Grid, Implementation>::
StandardWells::wellPerforationPressureDiffs()
{
return well_perforation_pressure_diffs_;
}
template <class Grid, class Implementation>
const V&
BlackoilModelBase<Grid, Implementation>::
StandardWells::wellPerforationPressureDiffs() const
{
return well_perforation_pressure_diffs_;
}
template <class Grid, class Implementation>
int
BlackoilModelBase<Grid, Implementation>::numWellVars() const
{
// For each well, we have a bhp variable, and one flux per phase.
const int nw = localWellsActive() ? wells().number_of_wells : 0;
const int nw = stdWells().localWellsActive() ? wells().number_of_wells : 0;
return (numPhases() + 1) * nw;
}
@ -578,7 +702,7 @@ namespace detail {
BlackoilModelBase<Grid, Implementation>::variableWellStateInitials(const WellState& xw, std::vector<V>& vars0) const
{
// Initial well rates.
if ( localWellsActive() )
if ( stdWells().localWellsActive() )
{
// Need to reshuffle well rates, from phase running fastest
// to wells running fastest.
@ -817,7 +941,7 @@ namespace detail {
}
}
const std::vector<int>& well_cells = wops_.well_cells;
const std::vector<int>& well_cells = stdWells().wellOps().well_cells;
// Use cell values for the temperature as the wells don't knows its temperature yet.
const ADB perf_temp = subset(state.temperature, well_cells);
@ -895,7 +1019,7 @@ namespace detail {
b_perf, rsmax_perf, rvmax_perf, surf_dens_perf);
const int nperf = wells().well_connpos[wells().number_of_wells];
const std::vector<int>& well_cells = wops_.well_cells;
const std::vector<int>& well_cells = stdWells().wellOps().well_cells;
// Extract well connection depths.
const V depth = cellCentroidsZToEigen(grid_);
@ -911,8 +1035,8 @@ namespace detail {
wells(), perf_depth, cd, grav);
// 4. Store the results
well_perforation_densities_ = Eigen::Map<const V>(cd.data(), nperf);
well_perforation_pressure_diffs_ = Eigen::Map<const V>(cdp.data(), nperf);
stdWells().wellPerforationDensities() = Eigen::Map<const V>(cd.data(), nperf);
stdWells().wellPerforationPressureDiffs() = Eigen::Map<const V>(cdp.data(), nperf);
}
@ -1111,7 +1235,7 @@ namespace detail {
const int nc = Opm::AutoDiffGrid::numCells(grid_);
const int np = asImpl().numPhases();
for (int phase = 0; phase < np; ++phase) {
residual_.material_balance_eq[phase] -= superset(cq_s[phase], wops_.well_cells, nc);
residual_.material_balance_eq[phase] -= superset(cq_s[phase], stdWells().wellOps().well_cells, nc);
}
}
@ -1134,7 +1258,7 @@ namespace detail {
return;
} else {
const int np = asImpl().numPhases();
const std::vector<int>& well_cells = wops_.well_cells;
const std::vector<int>& well_cells = stdWells().wellOps().well_cells;
mob_perfcells.resize(np, ADB::null());
b_perfcells.resize(np, ADB::null());
for (int phase = 0; phase < np; ++phase) {
@ -1164,17 +1288,17 @@ namespace detail {
const int nperf = wells().well_connpos[nw];
const Opm::PhaseUsage& pu = fluid_.phaseUsage();
V Tw = Eigen::Map<const V>(wells().WI, nperf);
const std::vector<int>& well_cells = wops_.well_cells;
const std::vector<int>& well_cells = stdWells().wellOps().well_cells;
// pressure diffs computed already (once per step, not changing per iteration)
const V& cdp = well_perforation_pressure_diffs_;
const V& cdp = stdWells().wellPerforationPressureDiffs();
// Extract needed quantities for the perforation cells
const ADB& p_perfcells = subset(state.pressure, well_cells);
const ADB& rv_perfcells = subset(state.rv, well_cells);
const ADB& rs_perfcells = subset(state.rs, well_cells);
// Perforation pressure
const ADB perfpressure = (wops_.w2p * state.bhp) + cdp;
const ADB perfpressure = (stdWells().wellOps().w2p * state.bhp) + cdp;
// Pressure drawdown (also used to determine direction of flow)
const ADB drawdown = p_perfcells - perfpressure;
@ -1194,8 +1318,8 @@ namespace detail {
}
// Handle cross flow
const V numInjectingPerforations = (wops_.p2w * ADB::constant(selectInjectingPerforations)).value();
const V numProducingPerforations = (wops_.p2w * ADB::constant(selectProducingPerforations)).value();
const V numInjectingPerforations = (stdWells().wellOps().p2w * ADB::constant(selectInjectingPerforations)).value();
const V numProducingPerforations = (stdWells().wellOps().p2w * ADB::constant(selectProducingPerforations)).value();
for (int w = 0; w < nw; ++w) {
if (!wells().allow_cf[w]) {
for (int perf = wells().well_connpos[w] ; perf < wells().well_connpos[w+1]; ++perf) {
@ -1246,7 +1370,7 @@ namespace detail {
std::vector<ADB> wbq(np, ADB::null());
ADB wbqt = ADB::constant(V::Zero(nw));
for (int phase = 0; phase < np; ++phase) {
const ADB& q_ps = wops_.p2w * cq_ps[phase];
const ADB& q_ps = stdWells().wellOps().p2w * cq_ps[phase];
const ADB& q_s = subset(state.qs, Span(nw, 1, phase*nw));
Selector<double> injectingPhase_selector(q_s.value(), Selector<double>::GreaterZero);
const int pos = pu.phase_pos[phase];
@ -1258,7 +1382,7 @@ namespace detail {
std::vector<ADB> cmix_s(np, ADB::null());
for (int phase = 0; phase < np; ++phase) {
const int pos = pu.phase_pos[phase];
cmix_s[phase] = wops_.w2p * notDeadWells_selector.select(ADB::constant(compi.col(pos)), wbq[phase]/wbqt);
cmix_s[phase] = stdWells().wellOps().w2p * notDeadWells_selector.select(ADB::constant(compi.col(pos)), wbq[phase]/wbqt);
}
// compute volume ratio between connection at standard conditions
@ -1323,8 +1447,8 @@ namespace detail {
xw.perfPhaseRates().assign(cq.data(), cq.data() + nperf*np);
// Update the perforation pressures.
const V& cdp = well_perforation_pressure_diffs_;
const V perfpressure = (wops_.w2p * state.bhp.value().matrix()).array() + cdp;
const V& cdp = stdWells().wellPerforationPressureDiffs();
const V perfpressure = (stdWells().wellOps().w2p * state.bhp.value().matrix()).array() + cdp;
xw.perfPress().assign(perfpressure.data(), perfpressure.data() + nperf);
}
@ -1347,7 +1471,7 @@ namespace detail {
const int nw = wells().number_of_wells;
ADB qs = state.qs;
for (int phase = 0; phase < np; ++phase) {
qs -= superset(wops_.p2w * cq_s[phase], Span(nw, 1, phase*nw), nw*np);
qs -= superset(stdWells().wellOps().p2w * cq_s[phase], Span(nw, 1, phase*nw), nw*np);
}
@ -1608,14 +1732,14 @@ namespace detail {
if (well_type == INJECTOR) {
double dp = detail::computeHydrostaticCorrection(
wells(), w, vfp_properties_.getInj()->getTable(vfp)->getDatumDepth(),
well_perforation_densities_, gravity);
stdWells().wellPerforationDensities(), gravity);
xw.bhp()[w] = vfp_properties_.getInj()->bhp(vfp, aqua, liquid, vapour, thp) - dp;
}
else if (well_type == PRODUCER) {
double dp = detail::computeHydrostaticCorrection(
wells(), w, vfp_properties_.getProd()->getTable(vfp)->getDatumDepth(),
well_perforation_densities_, gravity);
stdWells().wellPerforationDensities(), gravity);
xw.bhp()[w] = vfp_properties_.getProd()->bhp(vfp, aqua, liquid, vapour, thp, alq) - dp;
}
@ -1847,7 +1971,7 @@ namespace detail {
case THP:
{
const int perf = wells().well_connpos[w];
rho_v[w] = well_perforation_densities_[perf];
rho_v[w] = stdWells().wellPerforationDensities()[perf];
const int table_id = well_controls_iget_vfp(wc, current);
const double target = well_controls_iget_target(wc, current);
@ -1910,7 +2034,7 @@ namespace detail {
//Perform hydrostatic correction to computed targets
double gravity = detail::getGravity(geo_.gravity(), UgGridHelpers::dimensions(grid_));
const ADB::V dp_v = detail::computeHydrostaticCorrection(wells(), vfp_ref_depth_v, well_perforation_densities_, gravity);
const ADB::V dp_v = detail::computeHydrostaticCorrection(wells(), vfp_ref_depth_v, stdWells().wellPerforationDensities(), gravity);
const ADB dp = ADB::constant(dp_v);
const ADB dp_inj = superset(subset(dp, thp_inj_elems), thp_inj_elems, nw);
const ADB dp_prod = superset(subset(dp, thp_prod_elems), thp_prod_elems, nw);
@ -2351,14 +2475,14 @@ namespace detail {
if (well_type == INJECTOR) {
double dp = detail::computeHydrostaticCorrection(
wells(), w, vfp_properties_.getInj()->getTable(table_id)->getDatumDepth(),
well_perforation_densities_, gravity);
stdWells().wellPerforationDensities(), gravity);
well_state.thp()[w] = vfp_properties_.getInj()->thp(table_id, aqua, liquid, vapour, bhp[w] + dp);
}
else if (well_type == PRODUCER) {
double dp = detail::computeHydrostaticCorrection(
wells(), w, vfp_properties_.getProd()->getTable(table_id)->getDatumDepth(),
well_perforation_densities_, gravity);
stdWells().wellPerforationDensities(), gravity);
well_state.thp()[w] = vfp_properties_.getProd()->thp(table_id, aqua, liquid, vapour, bhp[w] + dp, alq);
}

View File

@ -116,7 +116,6 @@ namespace Opm {
// For non-segmented wells, it should be the density calculated with AVG or SEG way.
// while usually SEG way by default.
using Base::well_perforation_densities_; //Density of each well perforation
using Base::pvdt_;
using Base::geo_;
using Base::active_;
@ -136,10 +135,6 @@ namespace Opm {
using Base::param_;
using Base::linsolver_;
// Diff to bhp for each well perforation. only for usual wells.
// For segmented wells, they are zeros.
using Base::well_perforation_pressure_diffs_;
// Pressure correction due to the different depth of the perforation
// and the cell center of the grid block
// For the non-segmented wells, since the perforation are forced to be
@ -211,11 +206,10 @@ namespace Opm {
MultiSegmentWellOps wops_ms_;
// return wells object
// TODO: remove this wells structure
using Base::stdWells;
using Base::wells;
using Base::updatePrimalVariableFromState;
using Base::wellsActive;
using Base::updatePrimalVariableFromState;
using Base::phaseCondition;
using Base::fluidRvSat;
using Base::fluidRsSat;

View File

@ -370,7 +370,7 @@ namespace Opm {
std::vector<int>& well_cells = wops_ms_.well_cells;
well_perforation_densities_ = V::Zero(nperf_total);
stdWells().wellPerforationDensities() = V::Zero(nperf_total);
const V perf_press = Eigen::Map<const V>(xw.perfPress().data(), nperf_total);
@ -471,8 +471,8 @@ namespace Opm {
wells(), perf_cell_depth, cd, grav);
// 4. Store the results
well_perforation_densities_ = Eigen::Map<const V>(cd.data(), nperf_total); // This one is not useful for segmented wells at all
well_perforation_pressure_diffs_ = Eigen::Map<const V>(cdp.data(), nperf_total);
stdWells().wellPerforationDensities() = Eigen::Map<const V>(cd.data(), nperf_total); // This one is not useful for segmented wells at all
stdWells().wellPerforationPressureDiffs() = Eigen::Map<const V>(cdp.data(), nperf_total);
if ( !wops_ms_.has_multisegment_wells ) {
well_perforation_cell_densities_ = V::Zero(nperf_total);
@ -698,7 +698,7 @@ namespace Opm {
// Compute drawdown.
ADB h_nc = msperf_selector.select(well_segment_perforation_pressure_diffs_,
ADB::constant(well_perforation_pressure_diffs_));
ADB::constant( stdWells().wellPerforationPressureDiffs() ));
const V h_cj = msperf_selector.select(well_perforation_cell_pressure_diffs_, V::Zero(nperf));
// Special handling for when we are called from solveWellEq().
@ -862,7 +862,7 @@ namespace Opm {
// we need th concept of preforation pressures
xw.perfPress().resize(nperf_total, -1.e100);
const V& cdp = well_perforation_pressure_diffs_;
const V& cdp = stdWells().wellPerforationPressureDiffs();
int start_segment = 0;
int start_perforation = 0;
for (int i = 0; i < nw; ++i) {

View File

@ -110,13 +110,11 @@ namespace Opm {
using Base::fluid_;
using Base::geo_;
using Base::rock_comp_props_;
using Base::wells_;
using Base::linsolver_;
using Base::active_;
using Base::canph_;
using Base::cells_;
using Base::ops_;
using Base::wops_;
using Base::has_disgas_;
using Base::has_vapoil_;
using Base::param_;
@ -124,7 +122,6 @@ namespace Opm {
using Base::threshold_pressures_by_connection_;
using Base::rq_;
using Base::phaseCondition_;
using Base::well_perforation_pressure_diffs_;
using Base::residual_;
using Base::terminal_output_;
using Base::primalVariable_;
@ -133,7 +130,7 @@ namespace Opm {
// --------- Protected methods ---------
// Need to declare Base members we want to use here.
using Base::wellsActive;
using Base::stdWells;
using Base::wells;
using Base::variableState;
using Base::computeGasPressure;

View File

@ -389,7 +389,6 @@ namespace Opm {
std::vector<double>& rvmax_perf,
std::vector<double>& surf_dens_perf)
{
using namespace Opm::AutoDiffGrid;
// 1. Compute properties required by computeConnectionPressureDelta().
// Note that some of the complexity of this part is due to the function
@ -765,7 +764,7 @@ namespace Opm {
Base::extractWellPerfProperties(state, mob_perfcells, b_perfcells);
if (has_solvent_) {
int gas_pos = fluid_.phaseUsage().phase_pos[Gas];
const std::vector<int>& well_cells = wops_.well_cells;
const std::vector<int>& well_cells = stdWells().wellOps().well_cells;
const int nperf = well_cells.size();
// Gas and solvent is combinded and solved together
// The input in the well equation is then the

View File

@ -158,13 +158,11 @@ namespace Opm {
using Base::fluid_;
using Base::geo_;
using Base::rock_comp_props_;
using Base::wells_;
using Base::linsolver_;
using Base::active_;
using Base::canph_;
using Base::cells_;
using Base::ops_;
using Base::wops_;
using Base::has_disgas_;
using Base::has_vapoil_;
using Base::param_;
@ -172,7 +170,6 @@ namespace Opm {
using Base::threshold_pressures_by_connection_;
using Base::rq_;
using Base::phaseCondition_;
using Base::well_perforation_pressure_diffs_;
using Base::residual_;
using Base::terminal_output_;
using Base::primalVariable_;
@ -181,8 +178,9 @@ namespace Opm {
// --------- Protected methods ---------
// Need to declare Base members we want to use here.
using Base::wellsActive;
using Base::stdWells;
using Base::wells;
using Base::wellsActive;
using Base::variableState;
using Base::computePressures;
using Base::computeGasPressure;

View File

@ -731,8 +731,8 @@ namespace Opm {
ADB b_perfcells = subset(rq_[water_pos].b, well_cells);
const ADB& p_perfcells = subset(state.pressure, well_cells);
const V& cdp = well_perforation_pressure_diffs_;
const ADB perfpressure = (wops_.w2p * state.bhp) + cdp;
const V& cdp = stdWells().wellPerforationPressureDiffs();
const ADB perfpressure = (stdWells().wellOps().w2p * state.bhp) + cdp;
// Pressure drawdown (also used to determine direction of flow)
const ADB drawdown = p_perfcells - perfpressure;