From 39e23c4d41877ff1341c860c0ee52381189e1c94 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 23 Jun 2020 12:01:34 +0200 Subject: [PATCH 1/2] store polymer rates for output --- opm/simulators/wells/StandardWell_impl.hpp | 6 +++- .../wells/WellStateFullyImplicitBlackoil.hpp | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/opm/simulators/wells/StandardWell_impl.hpp b/opm/simulators/wells/StandardWell_impl.hpp index c1a96944b..c9c92a303 100644 --- a/opm/simulators/wells/StandardWell_impl.hpp +++ b/opm/simulators/wells/StandardWell_impl.hpp @@ -666,12 +666,16 @@ namespace Opm if (has_polymer) { // TODO: the application of well efficiency factor has not been tested with an example yet const unsigned waterCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx); - EvalWell cq_s_poly = cq_s[waterCompIdx] * well_efficiency_factor_; + EvalWell cq_s_poly = cq_s[waterCompIdx]; if (this->isInjector()) { cq_s_poly *= wpolymer(); } else { 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(); + + cq_s_poly *= well_efficiency_factor_; connectionRates_[perf][contiPolymerEqIdx] = Base::restrictEval(cq_s_poly); if (this->has_polymermw) { diff --git a/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp b/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp index 3b19d0545..6421ac7ce 100644 --- a/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp +++ b/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp @@ -154,6 +154,9 @@ namespace Opm productivity_index_.resize(nw * np, 0.0); well_potentials_.resize(nw * np, 0.0); + perfRatePolymer_.clear(); + perfRatePolymer_.resize(nperf, 0.0); + // intialize wells that have been there before // order may change so the mapping is based on the well name if (prevState && !prevState->wellMap().empty()) { @@ -560,6 +563,10 @@ namespace Opm well.rates.set( rt::solvent, solventWellRate(w) ); } + if ( pu.has_polymer ) { + well.rates.set( rt::polymer, polymerWellRate(w) ); + } + well.rates.set( rt::dissolved_gas, this->well_dissolved_gas_rates_[w] ); well.rates.set( rt::vaporized_oil, this->well_vaporized_oil_rates_[w] ); @@ -817,6 +824,24 @@ namespace Opm return solvent_well_rate; } + /// One rate pr well connection. + std::vector& perfRatePolymer() { return perfRatePolymer_; } + const std::vector& perfRatePolymer() const { return perfRatePolymer_; } + + /// One rate pr well + double polymerWellRate(const int w) const { + int connpos = 0; + for (int iw = 0; iw < w; ++iw) { + connpos += this->well_perf_data_[iw].size(); + } + double polymer_well_rate = 0.0; + const int endperf = connpos + this->well_perf_data_[w].size(); + for (int perf = connpos; perf < endperf; ++perf ) { + polymer_well_rate += perfRatePolymer_[perf]; + } + return polymer_well_rate; + } + std::vector& wellReservoirRates() { return well_reservoir_rates_; @@ -1064,6 +1089,9 @@ namespace Opm std::vector perfRateSolvent_; + // only for output + std::vector perfRatePolymer_; + // it is the throughput of water flow through the perforations // it is used as a measure of formation damage around well-bore due to particle deposition // it will only be used for injectors to check the injectivity From a99254f91739404d0b999f4b773d2becd42da3bc Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 23 Jun 2020 14:06:34 +0200 Subject: [PATCH 2/2] clean up based on review --- opm/simulators/wells/BlackoilWellModel.hpp | 1 - .../wells/BlackoilWellModel_impl.hpp | 11 +++--- .../wells/WellStateFullyImplicitBlackoil.hpp | 35 ++++++++----------- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index 802282459..d87501042 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -277,7 +277,6 @@ namespace Opm { std::vector< Well > wells_ecl_; std::vector< std::vector > well_perf_data_; - std::vector first_perf_index_; bool wells_active_; diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index a8237d5c2..f68f26e39 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -565,8 +565,6 @@ namespace Opm { const auto& grid = ebosSimulator_.vanguard().grid(); const auto& cartDims = Opm::UgGridHelpers::cartDims(grid); well_perf_data_.resize(wells_ecl_.size()); - first_perf_index_.clear(); - first_perf_index_.resize(wells_ecl_.size() + 1, 0); int well_index = 0; for (const auto& well : wells_ecl_) { well_perf_data_[well_index].clear(); @@ -597,7 +595,6 @@ namespace Opm { } } } - first_perf_index_[well_index + 1] = first_perf_index_[well_index] + well_perf_data_[well_index].size(); ++well_index; } } @@ -715,7 +712,7 @@ namespace Opm { numComponents(), numPhases(), w, - first_perf_index_[w], + well_state_.firstPerfIndex()[w], well_perf_data_[w])); } else { well_container.emplace_back(new MultisegmentWell(well_ecl, @@ -726,7 +723,7 @@ namespace Opm { numComponents(), numPhases(), w, - first_perf_index_[w], + well_state_.firstPerfIndex()[w], well_perf_data_[w])); } if (wellIsStopped) @@ -782,7 +779,7 @@ namespace Opm { numComponents(), numPhases(), index_well_ecl, - first_perf_index_[index_well_ecl], + well_state_.firstPerfIndex()[index_well_ecl], well_perf_data_[index_well_ecl])); } else { return WellInterfacePtr(new MultisegmentWell(well_ecl, @@ -793,7 +790,7 @@ namespace Opm { numComponents(), numPhases(), index_well_ecl, - first_perf_index_[index_well_ecl], + well_state_.firstPerfIndex()[index_well_ecl], well_perf_data_[index_well_ecl])); } } diff --git a/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp b/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp index 6421ac7ce..ead86aba9 100644 --- a/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp +++ b/opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace Opm { @@ -131,6 +132,8 @@ namespace Opm perf_skin_pressure_.resize(nperf, 0.0); int connpos = 0; + first_perf_index_.resize(nw+1, 0); + first_perf_index_[0] = connpos; for (int w = 0; w < nw; ++w) { // Initialize perfphaserates_ to well // rates divided by the number of perforations. @@ -144,6 +147,7 @@ namespace Opm perfPress()[perf] = cellPressures[well_perf_data[w][perf-connpos].cell_index]; } connpos += num_perf_this_well; + first_perf_index_[w+1] = connpos; } current_injection_controls_.resize(nw); @@ -805,6 +809,10 @@ namespace Opm effective_events_occurred_[w] = effective_events_occurred; } + const std::vector& firstPerfIndex() const + { + return first_perf_index_; + } /// One rate pr well connection. std::vector& perfRateSolvent() { return perfRateSolvent_; } @@ -812,16 +820,7 @@ namespace Opm /// One rate pr well double solventWellRate(const int w) const { - int connpos = 0; - for (int iw = 0; iw < w; ++iw) { - connpos += this->well_perf_data_[iw].size(); - } - double solvent_well_rate = 0.0; - const int endperf = connpos + this->well_perf_data_[w].size(); - for (int perf = connpos; perf < endperf; ++perf ) { - solvent_well_rate += perfRateSolvent_[perf]; - } - return solvent_well_rate; + return std::accumulate(&perfRateSolvent_[0] + first_perf_index_[w], &perfRateSolvent_[0] + first_perf_index_[w+1], 0.0); } /// One rate pr well connection. @@ -830,16 +829,7 @@ namespace Opm /// One rate pr well double polymerWellRate(const int w) const { - int connpos = 0; - for (int iw = 0; iw < w; ++iw) { - connpos += this->well_perf_data_[iw].size(); - } - double polymer_well_rate = 0.0; - const int endperf = connpos + this->well_perf_data_[w].size(); - for (int perf = connpos; perf < endperf; ++perf ) { - polymer_well_rate += perfRatePolymer_[perf]; - } - return polymer_well_rate; + return std::accumulate(&perfRatePolymer_[0] + first_perf_index_[w], &perfRatePolymer_[0] + first_perf_index_[w+1], 0.0); } std::vector& wellReservoirRates() @@ -1066,6 +1056,11 @@ namespace Opm private: std::vector perfphaserates_; + + // vector with size number of wells +1. + // iterate over all perforations of a given well + // for (int perf = first_perf_index_[well_index]; perf < first_perf_index_[well_index+1]; ++perf) + std::vector first_perf_index_; std::vector current_injection_controls_; std::vector current_production_controls_;