mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #3287 from joakim-hove/wellcontainer-perf
Wellcontainer perf
This commit is contained in:
@@ -1992,7 +1992,7 @@ namespace Opm {
|
||||
|
||||
auto& perf_pressure = well_state.perfPress(well_index);
|
||||
auto& perf_rates = well_state.perfRates(well_index);
|
||||
auto * perf_phase_rates = well_state.mutable_perfPhaseRates().data() + wm.second[1]*np;
|
||||
auto * perf_phase_rates = &well_state.mutable_perfPhaseRates()[wm.second[1]*np];
|
||||
const auto& perf_data = this->well_perf_data_[well_index];
|
||||
|
||||
for (std::size_t perf_index = 0; perf_index < perf_data.size(); perf_index++) {
|
||||
|
||||
@@ -628,7 +628,8 @@ namespace Opm
|
||||
|
||||
// Store the perforation phase flux for later usage.
|
||||
if (has_solvent && componentIdx == contiSolventEqIdx) {
|
||||
well_state.perfRateSolvent()[first_perf_ + perf] = cq_s[componentIdx].value();
|
||||
auto * perf_rate_solvent = &well_state.perfRateSolvent()[first_perf_];
|
||||
perf_rate_solvent[perf] = cq_s[componentIdx].value();
|
||||
} else {
|
||||
perf_rates[perf*np + ebosCompIdxToFlowCompIdx(componentIdx)] = cq_s[componentIdx].value();
|
||||
}
|
||||
@@ -793,7 +794,8 @@ namespace Opm
|
||||
cq_s_poly *= extendEval(intQuants.polymerConcentration() * intQuants.polymerViscosityCorrection());
|
||||
}
|
||||
// Note. Efficiency factor is handled in the output layer
|
||||
well_state.perfRatePolymer()[first_perf_ + perf] = cq_s_poly.value();
|
||||
auto * perf_rate_polymer = &well_state.perfRatePolymer()[first_perf_];
|
||||
perf_rate_polymer[perf] = cq_s_poly.value();
|
||||
|
||||
cq_s_poly *= well_efficiency_factor_;
|
||||
connectionRates[perf][contiPolymerEqIdx] = Base::restrictEval(cq_s_poly);
|
||||
@@ -825,7 +827,8 @@ namespace Opm
|
||||
const double dis_gas_frac = perf_dis_gas_rate / cq_s_zfrac_effective.value();
|
||||
cq_s_zfrac_effective *= extendEval(dis_gas_frac*intQuants.xVolume() + (1.0-dis_gas_frac)*intQuants.yVolume());
|
||||
}
|
||||
well_state.perfRateSolvent()[first_perf_ + perf] = cq_s_zfrac_effective.value();
|
||||
auto * perf_rate_solvent = &well_state.perfRateSolvent()[first_perf_];
|
||||
perf_rate_solvent[perf] = cq_s_zfrac_effective.value();
|
||||
|
||||
cq_s_zfrac_effective *= well_efficiency_factor_;
|
||||
connectionRates[perf][contiZfracEqIdx] = Base::restrictEval(cq_s_zfrac_effective);
|
||||
@@ -841,7 +844,8 @@ namespace Opm
|
||||
cq_s_sm *= extendEval(intQuants.fluidState().saltConcentration());
|
||||
}
|
||||
// Note. Efficiency factor is handled in the output layer
|
||||
well_state.perfRateBrine()[first_perf_ + perf] = cq_s_sm.value();
|
||||
auto * perf_rate_brine = &well_state.perfRateBrine()[this->first_perf_];
|
||||
perf_rate_brine[perf] = cq_s_sm.value();
|
||||
|
||||
cq_s_sm *= well_efficiency_factor_;
|
||||
connectionRates[perf][contiBrineEqIdx] = Base::restrictEval(cq_s_sm);
|
||||
@@ -1300,9 +1304,11 @@ namespace Opm
|
||||
// other primary variables related to polymer injectivity study
|
||||
if constexpr (Base::has_polymermw) {
|
||||
if (this->isInjector()) {
|
||||
auto * perf_water_velocity = &well_state.perfWaterVelocity()[this->first_perf_];
|
||||
auto * perf_skin_pressure = &well_state.perfSkinPressure()[this->first_perf_];
|
||||
for (int perf = 0; perf < number_of_perforations_; ++perf) {
|
||||
well_state.perfWaterVelocity()[first_perf_ + perf] = primary_variables_[Bhp + 1 + perf];
|
||||
well_state.perfSkinPressure()[first_perf_ + perf] = primary_variables_[Bhp + 1 + number_of_perforations_ + perf];
|
||||
perf_water_velocity[perf] = primary_variables_[Bhp + 1 + perf];
|
||||
perf_skin_pressure[perf] = primary_variables_[Bhp + 1 + number_of_perforations_ + perf];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2099,12 +2105,17 @@ namespace Opm
|
||||
const int np = number_of_phases_;
|
||||
std::vector<double> perfRates(b_perf.size(),0.0);
|
||||
const auto * perf_rates_state = &well_state.perfPhaseRates()[first_perf_ * np];
|
||||
|
||||
for (int perf = 0; perf < nperf; ++perf) {
|
||||
for (int comp = 0; comp < np; ++comp) {
|
||||
perfRates[perf * num_components_ + comp] = perf_rates_state[perf * np + ebosCompIdxToFlowCompIdx(comp)];
|
||||
}
|
||||
if constexpr (has_solvent) {
|
||||
perfRates[perf * num_components_ + contiSolventEqIdx] = well_state.perfRateSolvent()[first_perf_ + perf];
|
||||
}
|
||||
|
||||
if constexpr (has_solvent) {
|
||||
const auto * solvent_perf_rates_state = &well_state.perfRateSolvent()[this->first_perf_];
|
||||
for (int perf = 0; perf < nperf; ++perf) {
|
||||
perfRates[perf * num_components_ + contiSolventEqIdx] = solvent_perf_rates_state[perf];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2800,9 +2811,11 @@ namespace Opm
|
||||
// other primary variables related to polymer injection
|
||||
if constexpr (Base::has_polymermw) {
|
||||
if (this->isInjector()) {
|
||||
const auto * water_velocity = &well_state.perfWaterVelocity()[first_perf_];
|
||||
const auto * skin_pressure = &well_state.perfSkinPressure()[first_perf_];
|
||||
for (int perf = 0; perf < number_of_perforations_; ++perf) {
|
||||
primary_variables_[Bhp + 1 + perf] = well_state.perfWaterVelocity()[first_perf_ + perf];
|
||||
primary_variables_[Bhp + 1 + number_of_perforations_ + perf] = well_state.perfSkinPressure()[first_perf_ + perf];
|
||||
primary_variables_[Bhp + 1 + perf] = water_velocity[perf];
|
||||
primary_variables_[Bhp + 1 + number_of_perforations_ + perf] = skin_pressure[perf];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3167,11 +3180,12 @@ namespace Opm
|
||||
{
|
||||
if constexpr (Base::has_polymermw) {
|
||||
if (this->isInjector()) {
|
||||
auto * perf_water_throughput = &well_state.perfThroughput()[first_perf_];
|
||||
for (int perf = 0; perf < number_of_perforations_; ++perf) {
|
||||
const double perf_water_vel = primary_variables_[Bhp + 1 + perf];
|
||||
// we do not consider the formation damage due to water flowing from reservoir into wellbore
|
||||
if (perf_water_vel > 0.) {
|
||||
well_state.perfThroughput()[first_perf_ + perf] += perf_water_vel * dt;
|
||||
perf_water_throughput[perf] += perf_water_vel * dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3227,7 +3241,8 @@ namespace Opm
|
||||
const EvalWell eq_wat_vel = primary_variables_evaluation_[wat_vel_index] - water_velocity;
|
||||
resWell_[0][wat_vel_index] = eq_wat_vel.value();
|
||||
|
||||
const double throughput = well_state.perfThroughput()[first_perf_ + perf];
|
||||
const auto * perf_water_throughput = &well_state.perfThroughput()[this->first_perf_];
|
||||
const double throughput = perf_water_throughput[perf];
|
||||
const int pskin_index = Bhp + 1 + number_of_perforations_ + perf;
|
||||
|
||||
EvalWell poly_conc(numWellEq_ + numEq, 0.0);
|
||||
@@ -3405,7 +3420,8 @@ namespace Opm
|
||||
const int wat_vel_index = Bhp + 1 + perf;
|
||||
const EvalWell water_velocity = primary_variables_evaluation_[wat_vel_index];
|
||||
if (water_velocity > 0.) { // injecting
|
||||
const double throughput = well_state.perfThroughput()[first_perf_ + perf];
|
||||
const auto * perf_water_throughput = &well_state.perfThroughput()[this->first_perf_];
|
||||
const double throughput = perf_water_throughput[perf];
|
||||
const EvalWell molecular_weight = wpolymermw(throughput, water_velocity, deferred_logger);
|
||||
cq_s_polymw *= molecular_weight;
|
||||
} else {
|
||||
|
||||
@@ -53,6 +53,9 @@ public:
|
||||
this->add(name, value);
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return this->index_map.empty();
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return this->m_data.size();
|
||||
@@ -155,6 +158,14 @@ public:
|
||||
return this->m_data;
|
||||
}
|
||||
|
||||
std::optional<int> well_index(const std::string& wname) const {
|
||||
auto index_iter = this->index_map.find(wname);
|
||||
if (index_iter != this->index_map.end())
|
||||
return index_iter->second;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void update_if(std::size_t index, const std::string& name, const WellContainer<T>& other) {
|
||||
|
||||
@@ -582,20 +582,18 @@ namespace Opm
|
||||
// the maximum water cut value of the completions
|
||||
// it is used to identify the most offending completion
|
||||
double max_ratio_completion = 0;
|
||||
const int np = number_of_phases_;
|
||||
|
||||
const auto * perf_phase_rates = &well_state.perfPhaseRates()[first_perf_ * np];
|
||||
// look for the worst_offending_completion
|
||||
for (const auto& completion : completions_) {
|
||||
|
||||
const int np = number_of_phases_;
|
||||
std::vector<double> completion_rates(np, 0.0);
|
||||
|
||||
// looping through the connections associated with the completion
|
||||
const std::vector<int>& conns = completion.second;
|
||||
for (const int c : conns) {
|
||||
const int index_con = c + first_perf_;
|
||||
|
||||
for (int p = 0; p < np; ++p) {
|
||||
const double connection_rate = well_state.perfPhaseRates()[index_con * np + p];
|
||||
const double connection_rate = perf_phase_rates[c * np + p];
|
||||
completion_rates[p] += connection_rate;
|
||||
}
|
||||
} // end of for (const int c : conns)
|
||||
|
||||
@@ -478,12 +478,19 @@ void WellState::init(const std::vector<double>& cellPressures,
|
||||
if (pu.has_polymermw) {
|
||||
if (global_num_perf_same)
|
||||
{
|
||||
int oldPerf_idx = oldPerf_idx_beg;
|
||||
for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx )
|
||||
auto * throughput_target = &perf_water_throughput_[connpos];
|
||||
auto * pressure_target = &perf_skin_pressure_[connpos];
|
||||
auto * velocity_target = &perf_water_velocity_[connpos];
|
||||
|
||||
const auto * throughput_src = &prevState->perfThroughput()[oldPerf_idx_beg];
|
||||
const auto * pressure_src = &prevState->perfSkinPressure()[oldPerf_idx_beg];
|
||||
const auto * velocity_src = &prevState->perfWaterVelocity()[oldPerf_idx_beg];
|
||||
|
||||
for (int perf = 0; perf < num_perf_this_well; ++perf)
|
||||
{
|
||||
perf_water_throughput_[ perf ] = prevState->perfThroughput()[ oldPerf_idx ];
|
||||
perf_skin_pressure_[ perf ] = prevState->perfSkinPressure()[ oldPerf_idx ];
|
||||
perf_water_velocity_[ perf ] = prevState->perfWaterVelocity()[ oldPerf_idx ];
|
||||
throughput_target[ perf ] = throughput_src[perf];
|
||||
pressure_target[ perf ] = pressure_src[perf];
|
||||
velocity_target[ perf ] = velocity_src[perf];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -780,21 +787,24 @@ void WellState::reportConnections(data::Well& well,
|
||||
for( auto& comp : well.connections) {
|
||||
const auto connPhaseOffset = np * (wt.second[1] + local_comp_index);
|
||||
|
||||
const auto rates = this->perfPhaseRates().begin() + connPhaseOffset;
|
||||
const auto connPI = this->connectionProductivityIndex().begin() + connPhaseOffset;
|
||||
const auto * rates = &this->perfPhaseRates()[connPhaseOffset];
|
||||
const auto connPI = this->connectionProductivityIndex().begin() + connPhaseOffset;
|
||||
|
||||
for( int i = 0; i < np; ++i ) {
|
||||
comp.rates.set( phs[ i ], *(rates + i) );
|
||||
comp.rates.set( phs[ i ], rates[i] );
|
||||
comp.rates.set( pi [ i ], *(connPI + i) );
|
||||
}
|
||||
if ( pu.has_polymer ) {
|
||||
comp.rates.set( rt::polymer, this->perfRatePolymer()[wt.second[1] + local_comp_index]);
|
||||
const auto * perf_polymer_rate = &this->perfRatePolymer()[wt.second[1]];
|
||||
comp.rates.set( rt::polymer, perf_polymer_rate[local_comp_index]);
|
||||
}
|
||||
if ( pu.has_brine ) {
|
||||
comp.rates.set( rt::brine, this->perfRateBrine()[wt.second[1] + local_comp_index]);
|
||||
const auto * perf_brine_rate = &this->perfRateBrine()[wt.second[1]];
|
||||
comp.rates.set( rt::brine, perf_brine_rate[local_comp_index]);
|
||||
}
|
||||
if ( pu.has_solvent ) {
|
||||
comp.rates.set( rt::solvent, this->perfRateSolvent()[wt.second[1] + local_comp_index]);
|
||||
const auto * perf_solvent_rate = &this->perfRateSolvent()[wt.second[1]];
|
||||
comp.rates.set( rt::solvent, perf_solvent_rate[local_comp_index] );
|
||||
}
|
||||
|
||||
++local_comp_index;
|
||||
@@ -1010,20 +1020,20 @@ WellState::calculateSegmentRates(const std::vector<std::vector<int>>& segment_in
|
||||
|
||||
double WellState::solventWellRate(const int w) const
|
||||
{
|
||||
return parallel_well_info_[w]->sumPerfValues(&perfRateSolvent_[0] + first_perf_index_[w],
|
||||
&perfRateSolvent_[0] + first_perf_index_[w] + num_perf_[w]);
|
||||
const auto * perf_rates_solvent = &perfRateSolvent_[first_perf_index_[w]];
|
||||
return parallel_well_info_[w]->sumPerfValues(perf_rates_solvent, perf_rates_solvent + this->num_perf_[w]);
|
||||
}
|
||||
|
||||
double WellState::polymerWellRate(const int w) const
|
||||
{
|
||||
return parallel_well_info_[w]->sumPerfValues(&perfRatePolymer_[0] + first_perf_index_[w],
|
||||
&perfRatePolymer_[0] + first_perf_index_[w] + num_perf_[w]);
|
||||
const auto * perf_rates_polymer = &perfRatePolymer_[first_perf_index_[w]];
|
||||
return parallel_well_info_[w]->sumPerfValues(perf_rates_polymer, perf_rates_polymer + this->num_perf_[w]);
|
||||
}
|
||||
|
||||
double WellState::brineWellRate(const int w) const
|
||||
{
|
||||
return parallel_well_info_[w]->sumPerfValues(&perfRateBrine_[0] + first_perf_index_[w],
|
||||
&perfRateBrine_[0] + first_perf_index_[w] + num_perf_[w]);
|
||||
const auto * perf_rates_brine = &perfRateBrine_[first_perf_index_[w]];
|
||||
return parallel_well_info_[w]->sumPerfValues(perf_rates_brine, perf_rates_brine + this->num_perf_[w]);
|
||||
}
|
||||
|
||||
int WellState::topSegmentIndex(const int w) const
|
||||
|
||||
@@ -516,6 +516,13 @@ BOOST_AUTO_TEST_CASE(TESTWellContainer) {
|
||||
BOOST_CHECK(wci.has("W1"));
|
||||
BOOST_CHECK_EQUAL(wci[1], 2);
|
||||
BOOST_CHECK_EQUAL(wci["W3"], 3);
|
||||
|
||||
auto w3 = wci.well_index("W3");
|
||||
BOOST_CHECK(w3.has_value());
|
||||
BOOST_CHECK_EQUAL(w3.value(), 2);
|
||||
|
||||
auto wx = wci.well_index("WX");
|
||||
BOOST_CHECK(!wx.has_value());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user