Initialise More Data Members at Construction Time

In particular, apply explicit default constructors to most data
members and push initialisation to initialiser list if convenient.

While here, also split long lines and apply const in more places.
Finally, reset well- and connection-level PI values to zero in
WellState::shutWell().  This is in preparation of including shut
wells in BlackoilWellModel's internal state.
This commit is contained in:
Bård Skaflestad 2021-03-02 00:14:34 +01:00
parent 1de5c9539c
commit 6e9d2bd89e
4 changed files with 130 additions and 95 deletions

View File

@ -410,26 +410,26 @@ namespace Opm {
protected: protected:
Simulator& ebosSimulator_; Simulator& ebosSimulator_;
std::vector< Well > wells_ecl_; std::vector< Well > wells_ecl_{};
std::vector< std::vector<PerforationData> > well_perf_data_; std::vector< std::vector<PerforationData> > well_perf_data_{};
std::vector< WellProdIndexCalculator > prod_index_calc_; std::vector< WellProdIndexCalculator > prod_index_calc_{};
std::vector< ParallelWellInfo > parallel_well_info_; std::vector< ParallelWellInfo > parallel_well_info_;
std::vector< ParallelWellInfo* > local_parallel_well_info_; std::vector< ParallelWellInfo* > local_parallel_well_info_;
bool wells_active_; bool wells_active_{false};
// a vector of all the wells. // a vector of all the wells.
std::vector<WellInterfacePtr > well_container_; std::vector<WellInterfacePtr > well_container_{};
// map from logically cartesian cell indices to compressed ones // Map from logically cartesian cell indices to compressed ones.
// cells not in the interior are not mapped. This deactivates // Cells not in the interior are not mapped. This deactivates
// these for distributed wells and make the distribution non-overlapping. // these for distributed wells and makes the distribution non-overlapping.
std::vector<int> cartesian_to_compressed_; std::vector<int> cartesian_to_compressed_{};
std::vector<bool> is_cell_perforated_; std::vector<bool> is_cell_perforated_{};
std::function<bool(const Well&)> not_on_process_; std::function<bool(const Well&)> not_on_process_{};
void initializeWellProdIndCalculators(); void initializeWellProdIndCalculators();
void initializeWellPerfData(); void initializeWellPerfData();
@ -453,36 +453,36 @@ namespace Opm {
const ModelParameters param_; const ModelParameters param_;
bool terminal_output_; bool terminal_output_{false};
std::vector<int> pvt_region_idx_; std::vector<int> pvt_region_idx_{};
PhaseUsage phase_usage_; PhaseUsage phase_usage_;
size_t global_num_cells_; size_t global_num_cells_{};
// the number of the cells in the local grid // the number of the cells in the local grid
size_t local_num_cells_; size_t local_num_cells_{};
double gravity_; double gravity_{};
std::vector<double> depth_; std::vector<double> depth_{};
bool initial_step_; bool initial_step_{};
bool report_step_starts_; bool report_step_starts_{};
bool glift_debug = false; bool glift_debug = false;
bool alternative_well_rate_init_; bool alternative_well_rate_init_{};
std::optional<int> last_run_wellpi_{}; std::optional<int> last_run_wellpi_{};
std::unique_ptr<RateConverterType> rateConverter_; std::unique_ptr<RateConverterType> rateConverter_{};
std::unique_ptr<VFPProperties> vfp_properties_; std::unique_ptr<VFPProperties> vfp_properties_{};
SimulatorReportSingle last_report_; SimulatorReportSingle last_report_{};
WellTestState wellTestState_; WellTestState wellTestState_{};
std::unique_ptr<GuideRate> guideRate_; std::unique_ptr<GuideRate> guideRate_{};
std::map<std::string, double> node_pressures_{}; // Storing network pressures for output. std::map<std::string, double> node_pressures_{}; // Storing network pressures for output.
mutable std::unordered_set<std::string> closed_this_step_{}; mutable std::unordered_set<std::string> closed_this_step_{};
// used to better efficiency of calcuation // used to better efficiency of calcuation
mutable BVector scaleAddRes_; mutable BVector scaleAddRes_{};
std::vector< Scalar > B_avg_; std::vector<Scalar> B_avg_{};
const Grid& grid() const const Grid& grid() const
{ return ebosSimulator_.vanguard().grid(); } { return ebosSimulator_.vanguard().grid(); }

View File

@ -1,23 +1,23 @@
/* /*
Copyright 2016 - 2019 SINTEF Digital, Mathematics & Cybernetics. Copyright 2016 - 2019 SINTEF Digital, Mathematics & Cybernetics.
Copyright 2016 - 2018 Equinor ASA. Copyright 2016 - 2018 Equinor ASA.
Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2016 - 2018 Norce AS Copyright 2016 - 2018 Norce AS
This file is part of the Open Porous Media project (OPM). This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
OPM is distributed in the hope that it will be useful, OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp> #include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
@ -27,51 +27,62 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <fmt/format.h> #include <fmt/format.h>
namespace Opm { namespace Opm {
template<typename TypeTag> template<typename TypeTag>
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
BlackoilWellModel(Simulator& ebosSimulator, const PhaseUsage& phase_usage) BlackoilWellModel(Simulator& ebosSimulator, const PhaseUsage& phase_usage)
: ebosSimulator_(ebosSimulator), : ebosSimulator_(ebosSimulator)
phase_usage_(phase_usage), , terminal_output_((ebosSimulator.gridView().comm().rank() == 0) &&
active_wgstate_(phase_usage), EWOMS_GET_PARAM(TypeTag, bool, EnableTerminalOutput))
last_valid_wgstate_(phase_usage), , phase_usage_(phase_usage)
nupcol_wgstate_(phase_usage) , active_wgstate_(phase_usage)
, last_valid_wgstate_(phase_usage)
, nupcol_wgstate_(phase_usage)
{ {
terminal_output_ = false;
if (ebosSimulator.gridView().comm().rank() == 0)
terminal_output_ = EWOMS_GET_PARAM(TypeTag, bool, EnableTerminalOutput);
// Create the guide rate container. // Create the guide rate container.
guideRate_.reset(new GuideRate (ebosSimulator_.vanguard().schedule())); this->guideRate_ =
std::make_unique<GuideRate>(ebosSimulator_.vanguard().schedule());
local_num_cells_ = ebosSimulator_.gridView().size(0); local_num_cells_ = ebosSimulator_.gridView().size(0);
// Number of cells the global grid view // Number of cells the global grid view
global_num_cells_ = ebosSimulator_.vanguard().globalNumCells(); global_num_cells_ = ebosSimulator_.vanguard().globalNumCells();
// Set up cartesian mapping. // Set up cartesian mapping.
const auto& grid = ebosSimulator_.vanguard().grid(); {
const auto& cartDims = Opm::UgGridHelpers::cartDims(grid); const auto& grid = this->ebosSimulator_.vanguard().grid();
setupCartesianToCompressed_(Opm::UgGridHelpers::globalCell(grid), const auto& cartDims = Opm::UgGridHelpers::cartDims(grid);
cartDims[0]*cartDims[1]*cartDims[2]); setupCartesianToCompressed_(Opm::UgGridHelpers::globalCell(grid),
auto& parallel_wells = ebosSimulator.vanguard().parallelWells(); cartDims[0] * cartDims[1] * cartDims[2]);
parallel_well_info_.assign(parallel_wells.begin(), parallel_wells.end());
const auto& pwell_info = parallel_well_info_;
std::size_t numProcs = ebosSimulator.gridView().comm().size();
not_on_process_ = [&pwell_info, numProcs](const Well& well) {
if (well.getStatus() == Well::Status::SHUT)
return true;
if (numProcs == 1u)
return false;
std::pair<std::string, bool> value{well.name(), true}; // false indicate not active!
auto candidate = std::lower_bound(pwell_info.begin(),
pwell_info.end(),
value);
return candidate == pwell_info.end() || *candidate != value;
};
alternative_well_rate_init_ = EWOMS_GET_PARAM(TypeTag, bool, AlternativeWellRateInit); auto& parallel_wells = ebosSimulator.vanguard().parallelWells();
this->parallel_well_info_.assign(parallel_wells.begin(),
parallel_wells.end());
}
const auto numProcs = ebosSimulator.gridView().comm().size();
this->not_on_process_ = [this, numProcs](const Well& well) {
if (well.getStatus() == Well::Status::SHUT)
return true;
if (numProcs == decltype(numProcs){1})
return false;
// Recall: false indicates NOT active!
const auto value = std::make_pair(well.name(), true);
auto candidate = std::lower_bound(this->parallel_well_info_.begin(),
this->parallel_well_info_.end(),
value);
return (candidate == this->parallel_well_info_.end())
|| (*candidate != value);
};
this->alternative_well_rate_init_ =
EWOMS_GET_PARAM(TypeTag, bool, AlternativeWellRateInit);
} }
template<typename TypeTag> template<typename TypeTag>

View File

@ -271,7 +271,7 @@ namespace Opm
WellInterface<TypeTag>:: WellInterface<TypeTag>::
phaseUsage() const phaseUsage() const
{ {
assert(phase_usage_); assert(phase_usage_ != nullptr);
return *phase_usage_; return *phase_usage_;
} }

View File

@ -154,7 +154,7 @@ namespace Opm
const auto& well_info = this->wellMap().at(wname); const auto& well_info = this->wellMap().at(wname);
const int connpos = well_info[1]; const int connpos = well_info[1];
const int num_perf_this_well = well_info[2]; const int num_perf_this_well = well_info[2];
int global_num_perf_this_well = parallel_well_info[w]->communication().sum(num_perf_this_well); const int global_num_perf_this_well = parallel_well_info[w]->communication().sum(num_perf_this_well);
for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf) { for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf) {
if (wells_ecl[w].getStatus() == Well::Status::OPEN) { if (wells_ecl[w].getStatus() == Well::Status::OPEN) {
@ -225,7 +225,7 @@ namespace Opm
} }
auto it = prevState->wellMap().find(well.name()); auto it = prevState->wellMap().find(well.name());
if ( it != end ) if (it != end)
{ {
const int newIndex = w; const int newIndex = w;
const int oldIndex = it->second[ 0 ]; const int oldIndex = it->second[ 0 ];
@ -283,14 +283,16 @@ namespace Opm
const int connpos = new_iter->second[1]; const int connpos = new_iter->second[1];
const int num_perf_this_well = new_iter->second[2]; const int num_perf_this_well = new_iter->second[2];
int num_perf_changed = (num_perf_old_well != num_perf_this_well) ? 1 : 0; const int num_perf_changed = parallel_well_info[w]->communication()
num_perf_changed = parallel_well_info[w]->communication().sum(num_perf_changed); .sum(static_cast<int>(num_perf_old_well != num_perf_this_well));
bool global_num_perf_same = (num_perf_changed == 0); const bool global_num_perf_same = num_perf_changed == 0;
// copy perforation rates when the number of perforations is equal,
// otherwise initialize perfphaserates to well rates divided by the number of perforations.
if( global_num_perf_same ) // copy perforation rates when the number of
// perforations is equal, otherwise initialize
// perfphaserates to well rates divided by the
// number of perforations.
if (global_num_perf_same)
{ {
int old_perf_phase_idx = oldPerf_idx_beg *np; int old_perf_phase_idx = oldPerf_idx_beg *np;
for (int perf_phase_idx = connpos*np; for (int perf_phase_idx = connpos*np;
@ -299,15 +301,16 @@ namespace Opm
perfPhaseRates()[ perf_phase_idx ] = prevState->perfPhaseRates()[ old_perf_phase_idx ]; perfPhaseRates()[ perf_phase_idx ] = prevState->perfPhaseRates()[ old_perf_phase_idx ];
} }
} else { } else {
int global_num_perf_this_well = parallel_well_info[w]->communication().sum(num_perf_this_well); const int global_num_perf_this_well = parallel_well_info[w]->communication().sum(num_perf_this_well);
for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf) { for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf) {
for (int p = 0; p < np; ++p) { for (int p = 0; p < np; ++p) {
perfPhaseRates()[np*perf + p] = wellRates()[np*newIndex + p] / double(global_num_perf_this_well); perfPhaseRates()[np*perf + p] = wellRates()[np*newIndex + p] / double(global_num_perf_this_well);
} }
} }
} }
// perfPressures // perfPressures
if( global_num_perf_same ) if (global_num_perf_same)
{ {
int oldPerf_idx = oldPerf_idx_beg; int oldPerf_idx = oldPerf_idx_beg;
for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx ) for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx )
@ -315,9 +318,10 @@ namespace Opm
perfPress()[ perf ] = prevState->perfPress()[ oldPerf_idx ]; perfPress()[ perf ] = prevState->perfPress()[ oldPerf_idx ];
} }
} }
// perfSolventRates // perfSolventRates
if (pu.has_solvent) { if (pu.has_solvent) {
if( global_num_perf_same ) if (global_num_perf_same)
{ {
int oldPerf_idx = oldPerf_idx_beg; int oldPerf_idx = oldPerf_idx_beg;
for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx ) for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx )
@ -328,10 +332,12 @@ namespace Opm
} }
// polymer injectivity related // polymer injectivity related
// here we did not consider the case that we close some perforation during the running //
// and also, wells can be shut and re-opened // here we did not consider the case that we close
// some perforation during the running and also,
// wells can be shut and re-opened
if (pu.has_polymermw) { if (pu.has_polymermw) {
if( num_perf_old_well == num_perf_this_well ) if (global_num_perf_same)
{ {
int oldPerf_idx = oldPerf_idx_beg; int oldPerf_idx = oldPerf_idx_beg;
for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx ) for (int perf = connpos; perf < connpos + num_perf_this_well; ++perf, ++oldPerf_idx )
@ -354,10 +360,13 @@ namespace Opm
} }
} }
// If in the new step, there is no THP related target/limit anymore, its thp value should be // If in the new step, there is no THP related
// set to zero. // target/limit anymore, its thp value should be set to
const bool has_thp = well.isInjector() ? well.injectionControls(summary_state).hasControl(Well::InjectorCMode::THP) // zero.
const bool has_thp = well.isInjector()
? well.injectionControls (summary_state).hasControl(Well::InjectorCMode::THP)
: well.productionControls(summary_state).hasControl(Well::ProducerCMode::THP); : well.productionControls(summary_state).hasControl(Well::ProducerCMode::THP);
if (!has_thp) { if (!has_thp) {
thp()[w] = 0.0; thp()[w] = 0.0;
} }
@ -382,6 +391,7 @@ namespace Opm
seg_pressdrop_friction_.assign(nw, 0.); seg_pressdrop_friction_.assign(nw, 0.);
seg_pressdrop_acceleration_.assign(nw, 0.); seg_pressdrop_acceleration_.assign(nw, 0.);
} }
updateWellsDefaultALQ(wells_ecl); updateWellsDefaultALQ(wells_ecl);
do_glift_optimization_ = true; do_glift_optimization_ = true;
} }
@ -816,7 +826,8 @@ namespace Opm
/// One rate pr well /// One rate pr well
double solventWellRate(const int w) const { double solventWellRate(const int w) const {
return parallel_well_info_[w]->sumPerfValues(&perfRateSolvent_[0] + first_perf_index_[w], &perfRateSolvent_[0] + first_perf_index_[w+1]); return parallel_well_info_[w]->sumPerfValues(&perfRateSolvent_[0] + first_perf_index_[w + 0],
&perfRateSolvent_[0] + first_perf_index_[w + 1]);
} }
/// One rate pr well connection. /// One rate pr well connection.
@ -825,7 +836,8 @@ namespace Opm
/// One rate pr well /// One rate pr well
double polymerWellRate(const int w) const { double polymerWellRate(const int w) const {
return parallel_well_info_[w]->sumPerfValues(&perfRatePolymer_[0] + first_perf_index_[w], &perfRatePolymer_[0] + first_perf_index_[w+1]); return parallel_well_info_[w]->sumPerfValues(&perfRatePolymer_[0] + first_perf_index_[w + 0],
&perfRatePolymer_[0] + first_perf_index_[w + 1]);
} }
/// One rate pr well connection. /// One rate pr well connection.
@ -834,7 +846,8 @@ namespace Opm
/// One rate pr well /// One rate pr well
double brineWellRate(const int w) const { double brineWellRate(const int w) const {
return parallel_well_info_[w]->sumPerfValues(&perfRateBrine_[0] + first_perf_index_[w], &perfRateBrine_[0] + first_perf_index_[w+1]); return parallel_well_info_[w]->sumPerfValues(&perfRateBrine_[0] + first_perf_index_[w + 0],
&perfRateBrine_[0] + first_perf_index_[w + 1]);
} }
std::vector<double>& wellReservoirRates() std::vector<double>& wellReservoirRates()
@ -980,8 +993,19 @@ namespace Opm
virtual void shutWell(int well_index) override { virtual void shutWell(int well_index) override {
WellState::shutWell(well_index); WellState::shutWell(well_index);
const int np = numPhases(); const int np = numPhases();
for (int p = 0; p < np; ++p)
this->well_reservoir_rates_[np * well_index + p] = 0; auto* resv = &this->well_reservoir_rates_[np*well_index + 0];
auto* wpi = &this->productivity_index_[np*well_index + 0];
for (int p = 0; p < np; ++p) {
resv[p] = 0.0;
wpi[p] = 0.0;
}
const auto first = this->first_perf_index_[well_index + 0]*np;
const auto last = this->first_perf_index_[well_index + 1]*np;
std::fill(this->conn_productivity_index_.begin() + first,
this->conn_productivity_index_.begin() + last, 0.0);
} }
virtual void stopWell(int well_index) override { virtual void stopWell(int well_index) override {