adding flag to wops_ms_ to indicate if MSW is involved.

to reduce some extra cost when MSW is not involved.
This commit is contained in:
Kai Bao 2016-03-08 15:44:53 +01:00
parent 96938548c1
commit 8115d918dd
2 changed files with 70 additions and 22 deletions

View File

@ -205,6 +205,7 @@ namespace Opm {
AutoDiffMatrix eliminate_topseg; // change the top segment related to be zero
std::vector<int> well_cells; // the set of perforated cells
V conn_trans_factors; // connection transmissibility factors
bool has_multisegment_wells; // flag indicating whether there is any muli-segment well
};
MultiSegmentWellOps wops_ms_;

View File

@ -109,6 +109,9 @@ namespace Opm {
BlackoilMultiSegmentModel<Grid>::
MultiSegmentWellOps::MultiSegmentWellOps(const std::vector<WellMultiSegmentConstPtr>& wells_ms)
{
// no multi-segment wells are involved by default.
has_multisegment_wells = false;
if (wells_ms.empty()) {
return;
}
@ -120,6 +123,9 @@ namespace Opm {
for (int w = 0; w < nw; ++w) {
total_nperf += wells_ms[w]->numberOfPerforations();
total_nseg += wells_ms[w]->numberOfSegments();
if (wells_ms[w]->isMultiSegmented()) {
has_multisegment_wells = true;
}
}
// Create well_cells and conn_trans_factors.
@ -230,6 +236,12 @@ namespace Opm {
top_well_segments_ = well_state.topSegmentLoc();
const int nw = wellsMultiSegment().size();
if ( !wops_ms_.has_multisegment_wells ) {
segvdt_ = V::Zero(nw);
return;
}
const int nseg_total = well_state.numSegments();
std::vector<double> segment_volume;
segment_volume.reserve(nseg_total);
@ -462,6 +474,12 @@ namespace Opm {
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);
if ( !wops_ms_.has_multisegment_wells ) {
well_perforation_cell_densities_ = V::Zero(nperf_total);
well_perforation_cell_pressure_diffs_ = V::Zero(nperf_total);
return;
}
// compute the average of the fluid densites in the well blocks.
// the average is weighted according to the fluid relative permeabilities.
const std::vector<ADB> kr_adb = Base::computeRelPerm(state);
@ -680,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(well_perforation_pressure_diffs_));
const V h_cj = msperf_selector.select(well_perforation_cell_pressure_diffs_, V::Zero(nperf));
// Special handling for when we are called from solveWellEq().
@ -890,23 +908,27 @@ namespace Opm {
std::vector<ADB> segment_volume_change_dt(np, ADB::null());
for (int phase = 0; phase < np; ++phase) {
// Gain of the surface volume of each component in the segment by dt
segment_volume_change_dt[phase] = segment_comp_surf_volume_current_[phase] -
segment_comp_surf_volume_initial_[phase];
if ( wops_ms_.has_multisegment_wells ) {
// Gain of the surface volume of each component in the segment by dt
segment_volume_change_dt[phase] = segment_comp_surf_volume_current_[phase] -
segment_comp_surf_volume_initial_[phase];
// Special handling for when we are called from solveWellEq().
// TODO: restructure to eliminate need for special treatmemt.
if (segment_volume_change_dt[phase].numBlocks() != segqs.numBlocks()) {
assert(segment_volume_change_dt[phase].numBlocks() > 2);
assert(segqs.numBlocks() == 2);
segment_volume_change_dt[phase] = detail::onlyWellDerivs(segment_volume_change_dt[phase]);
assert(segment_volume_change_dt[phase].numBlocks() == 2);
// Special handling for when we are called from solveWellEq().
// TODO: restructure to eliminate need for special treatmemt.
if (segment_volume_change_dt[phase].numBlocks() != segqs.numBlocks()) {
assert(segment_volume_change_dt[phase].numBlocks() > 2);
assert(segqs.numBlocks() == 2);
segment_volume_change_dt[phase] = detail::onlyWellDerivs(segment_volume_change_dt[phase]);
assert(segment_volume_change_dt[phase].numBlocks() == 2);
}
const ADB cq_s_seg = wops_ms_.p2s * cq_s[phase];
const ADB segqs_phase = subset(segqs, Span(nseg_total, 1, phase * nseg_total));
segqs -= superset(cq_s_seg + wops_ms_.s2s_inlets * segqs_phase + segment_volume_change_dt[phase],
Span(nseg_total, 1, phase * nseg_total), np * nseg_total);
} else {
segqs -= superset(wops_ms_.p2s * cq_s[phase], Span(nseg_total, 1, phase * nseg_total), np * nseg_total);
}
const ADB cq_s_seg = wops_ms_.p2s * cq_s[phase];
const ADB segqs_phase = subset(segqs, Span(nseg_total, 1, phase * nseg_total));
segqs -= superset(cq_s_seg + wops_ms_.s2s_inlets * segqs_phase + segment_volume_change_dt[phase],
Span(nseg_total, 1, phase * nseg_total), np * nseg_total);
}
residual_.well_flux_eq = segqs;
@ -1169,13 +1191,17 @@ namespace Opm {
ADB others_residual = ADB::constant(V::Zero(nseg_total));
// Special handling for when we are called from solveWellEq().
// TODO: restructure to eliminate need for special treatmemt.
ADB wspd = (state.segp.numBlocks() == 2)
? detail::onlyWellDerivs(well_segment_pressures_delta_)
: well_segment_pressures_delta_;
if ( wops_ms_.has_multisegment_wells ) {
// Special handling for when we are called from solveWellEq().
// TODO: restructure to eliminate need for special treatmemt.
ADB wspd = (state.segp.numBlocks() == 2)
? detail::onlyWellDerivs(well_segment_pressures_delta_)
: well_segment_pressures_delta_;
others_residual = wops_ms_.eliminate_topseg * (state.segp - wops_ms_.s2s_outlet * state.segp + wspd);
others_residual = wops_ms_.eliminate_topseg * (state.segp - wops_ms_.s2s_outlet * state.segp + wspd);
} else {
others_residual = wops_ms_.eliminate_topseg * (state.segp - wops_ms_.s2s_outlet * state.segp);
}
// all the control equations
// TODO: can be optimized better
@ -1284,10 +1310,25 @@ namespace Opm {
void
BlackoilMultiSegmentModel<Grid>::computeSegmentFluidProperties(const SolutionState& state)
{
const int nw = wellsMultiSegment().size();
const int nseg_total = state.segp.size();
const int np = numPhases();
if ( !wops_ms_.has_multisegment_wells ){
// not sure if this is needed actually
// TODO: to check later if this is really necessary.
segment_mass_flow_rates_ = ADB::constant(V::Zero(nseg_total));
well_segment_densities_ = ADB::constant(V::Zero(nseg_total));
segment_mass_flow_rates_ = ADB::constant(V::Zero(nseg_total));
segment_viscosities_ = ADB::constant(V::Zero(nseg_total));
for (int phase = 0; phase < np; ++phase) {
segment_comp_surf_volume_current_[phase] = ADB::constant(V::Zero(nseg_total));
segment_comp_surf_volume_initial_[phase] = V::Zero(nseg_total);
}
return;
}
// although we will calculate segment density for non-segmented wells at the same time,
// while under most of the cases, they will not be used,
// since for most of the cases, the density calculation for non-segment wells are
@ -1475,6 +1516,12 @@ namespace Opm {
const int nw = wellsMultiSegment().size();
const int nseg_total = state.segp.size();
if ( !wops_ms_.has_multisegment_wells ) {
well_segment_pressures_delta_ = ADB::constant(V::Zero(nseg_total));
well_segment_perforation_pressure_diffs_ = wops_ms_.s2p * well_segment_pressures_delta_;
return;
}
// calculate the depth difference of the segments
// TODO: we need to store the following values somewhere to avoid recomputation.
V segment_depth_delta = V::Zero(nseg_total);