mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-07-07 04:53:03 -05:00
Merge pull request #3116 from joakim-hove/action-update-ecl-well
Update ecl wells for all matching wells after actionx
This commit is contained in:
commit
7ea78e9c36
|
@ -45,6 +45,7 @@
|
|||
#include <dune/geometry/referenceelements.hh>
|
||||
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
|
@ -1449,8 +1450,8 @@ protected:
|
|||
|
||||
|
||||
void
|
||||
updateEclWell(int, const std::string&) {
|
||||
throw std::logic_error("updateEclWell() method not implemented for class eclpeacemanwell");
|
||||
updateEclWells(int, const std::unordered_set<std::string>&) {
|
||||
throw std::logic_error("updateEclWells() method not implemented for class eclpeacemanwell");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1377,6 +1377,7 @@ public:
|
|||
pyaction->run(ecl_state, schedule, reportStep, summaryState);
|
||||
}
|
||||
|
||||
bool commit_wellstate = false;
|
||||
auto simTime = schedule.simTime(reportStep);
|
||||
for (const auto& action : actions.pending(actionState, simTime)) {
|
||||
auto actionResult = action->eval(context);
|
||||
|
@ -1393,19 +1394,24 @@ public:
|
|||
|
||||
const auto& wellpi = this->fetchWellPI(reportStep, *action, schedule, matching_wells);
|
||||
|
||||
schedule.applyAction(reportStep, Opm::TimeService::from_time_t(simTime), *action, actionResult, wellpi);
|
||||
auto affected_wells = schedule.applyAction(reportStep, Opm::TimeService::from_time_t(simTime), *action, actionResult, wellpi);
|
||||
actionState.add_run(*action, simTime);
|
||||
|
||||
for ( const auto& [wname, _] : wellpi) {
|
||||
(void)_;
|
||||
if (this->wellModel_.hasWell(wname))
|
||||
this->wellModel_.updateEclWell(reportStep, wname);
|
||||
}
|
||||
this->wellModel_.updateEclWells(reportStep, affected_wells);
|
||||
if (!affected_wells.empty())
|
||||
commit_wellstate = true;
|
||||
} else {
|
||||
std::string msg = "The action: " + action->name() + " evaluated to false at " + ts;
|
||||
Opm::OpmLog::info(msg);
|
||||
}
|
||||
}
|
||||
/*
|
||||
The well state has been stored in a previous object when the time step
|
||||
has completed successfully, the action process might have modified the
|
||||
well state, and to be certain that is not overwritten when starting
|
||||
the next timestep we must commit it.
|
||||
*/
|
||||
if (commit_wellstate)
|
||||
this->wellModel_.commitWellState();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include <dune/grid/common/gridenums.hh>
|
||||
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -658,7 +659,7 @@ public:
|
|||
|
||||
|
||||
void
|
||||
updateEclWell(int, const std::string&) {
|
||||
updateEclWells(int, const std::unordered_set<std::string>&) {
|
||||
throw std::logic_error("wellPI() method not implemented for class eclwellmanager");
|
||||
}
|
||||
|
||||
|
|
|
@ -365,8 +365,7 @@ namespace Opm {
|
|||
/// Returns true if the well was actually found and shut.
|
||||
bool forceShutWellByNameIfPredictionMode(const std::string& wellname, const double simulation_time);
|
||||
|
||||
void updateEclWell(const int timeStepIdx, const int well_index);
|
||||
void updateEclWell(const int timeStepIdx, const std::string& wname);
|
||||
void updateEclWells(const int timeStepIdx, const std::unordered_set<std::string>& wells);
|
||||
bool hasWell(const std::string& wname);
|
||||
double wellPI(const int well_index) const;
|
||||
double wellPI(const std::string& well_name) const;
|
||||
|
|
|
@ -2622,55 +2622,38 @@ namespace Opm {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateEclWell(const int timeStepIdx, const int well_index)
|
||||
{
|
||||
updateEclWells(const int timeStepIdx, const std::unordered_set<std::string>& wells) {
|
||||
const auto& schedule = this->ebosSimulator_.vanguard().schedule();
|
||||
const auto& wname = this->wells_ecl_[well_index].name();
|
||||
this->wells_ecl_[well_index] = schedule.getWell(wname, timeStepIdx);
|
||||
for (const auto& wname : wells) {
|
||||
auto well_iter = std::find_if( this->wells_ecl_.begin(), this->wells_ecl_.end(), [wname] (const auto& well) -> bool { return well.name() == wname;});
|
||||
if (well_iter != this->wells_ecl_.end()) {
|
||||
auto well_index = std::distance( this->wells_ecl_.begin(), well_iter );
|
||||
this->wells_ecl_[well_index] = schedule.getWell(wname, timeStepIdx);
|
||||
|
||||
const auto& well = this->wells_ecl_[well_index];
|
||||
auto& pd = this->well_perf_data_[well_index];
|
||||
auto pdIter = pd.begin();
|
||||
for (const auto& conn : well.getConnections()) {
|
||||
if (conn.state() != Connection::State::SHUT) {
|
||||
pdIter->connection_transmissibility_factor = conn.CF();
|
||||
++pdIter;
|
||||
const auto& well = this->wells_ecl_[well_index];
|
||||
auto& pd = this->well_perf_data_[well_index];
|
||||
auto pdIter = pd.begin();
|
||||
for (const auto& conn : well.getConnections()) {
|
||||
if (conn.state() != Connection::State::SHUT) {
|
||||
pdIter->connection_transmissibility_factor = conn.CF();
|
||||
++pdIter;
|
||||
}
|
||||
}
|
||||
this->wellState().updateStatus(well_index, well.getStatus());
|
||||
this->wellState().resetConnectionTransFactors(well_index, pd);
|
||||
this->prod_index_calc_[well_index].reInit(well);
|
||||
}
|
||||
}
|
||||
|
||||
this->wellState().resetConnectionTransFactors(well_index, pd);
|
||||
this->prod_index_calc_[well_index].reInit(well);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
BlackoilWellModel<TypeTag>::
|
||||
updateEclWell(const int timeStepIdx, const std::string& wname)
|
||||
{
|
||||
auto well_iter = std::find_if(this->wells_ecl_.begin(), this->wells_ecl_.end(),
|
||||
[&wname](const auto& well) -> bool
|
||||
{
|
||||
return well.name() == wname;
|
||||
});
|
||||
|
||||
if (well_iter == this->wells_ecl_.end()) {
|
||||
throw std::logic_error { "Could not find well: " + wname };
|
||||
}
|
||||
|
||||
auto well_index = std::distance(this->wells_ecl_.begin(), well_iter);
|
||||
this->updateEclWell(timeStepIdx, well_index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
double
|
||||
BlackoilWellModel<TypeTag>::
|
||||
|
@ -2762,6 +2745,26 @@ namespace Opm {
|
|||
ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX);
|
||||
};
|
||||
|
||||
auto updateEclWell = [this, timeStepIdx](const int well_index) -> void
|
||||
{
|
||||
const auto& schedule = this->schedule();
|
||||
const auto& wname = this->wells_ecl_[well_index].name();
|
||||
this->wells_ecl_[well_index] = schedule.getWell(wname, timeStepIdx);
|
||||
|
||||
const auto& well = this->wells_ecl_[well_index];
|
||||
auto& pd = this->well_perf_data_[well_index];
|
||||
auto pdIter = pd.begin();
|
||||
for (const auto& conn : well.getConnections()) {
|
||||
if (conn.state() != Connection::State::SHUT) {
|
||||
pdIter->connection_transmissibility_factor = conn.CF();
|
||||
++pdIter;
|
||||
}
|
||||
}
|
||||
this->wellState().resetConnectionTransFactors(well_index, pd);
|
||||
this->prod_index_calc_[well_index].reInit(well);
|
||||
};
|
||||
|
||||
|
||||
auto rescaleWellPI =
|
||||
[this, timeStepIdx](const int well_index,
|
||||
const double newWellPI) -> void
|
||||
|
@ -2770,8 +2773,6 @@ namespace Opm {
|
|||
|
||||
auto& schedule = this->ebosSimulator_.vanguard().schedule(); // Mutable
|
||||
schedule.applyWellProdIndexScaling(wname, timeStepIdx, newWellPI);
|
||||
|
||||
this->updateEclWell(timeStepIdx, well_index);
|
||||
};
|
||||
|
||||
// Minimal well setup to compute PI/II values
|
||||
|
@ -2797,6 +2798,7 @@ namespace Opm {
|
|||
for (auto wellID = 0*nw; wellID < nw; ++wellID) {
|
||||
if (hasWellPIEvent(wellID)) {
|
||||
rescaleWellPI(wellID, this->wellPI(wellID));
|
||||
updateEclWell(wellID);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -239,6 +239,22 @@ namespace Opm
|
|||
this->thp_[well_index] = 0;
|
||||
}
|
||||
|
||||
void updateStatus(int well_index, Well::Status status) {
|
||||
switch (status) {
|
||||
case Well::Status::OPEN:
|
||||
this->openWell(well_index);
|
||||
break;
|
||||
case Well::Status::SHUT:
|
||||
this->shutWell(well_index);
|
||||
break;
|
||||
case Well::Status::STOP:
|
||||
this->stopWell(well_index);
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid well status");
|
||||
}
|
||||
}
|
||||
|
||||
virtual data::Wells
|
||||
report(const PhaseUsage& pu,
|
||||
const int* globalCellIdxMap,
|
||||
|
|
|
@ -66,6 +66,7 @@ namespace Opm
|
|||
using BaseType :: numWells;
|
||||
using BaseType :: numPhases;
|
||||
using BaseType :: resetConnectionTransFactors;
|
||||
using BaseType :: updateStatus;
|
||||
|
||||
/// Allocate and initialize if wells is non-null. Also tries
|
||||
/// to give useful initial values to the bhp(), wellRates()
|
||||
|
@ -166,8 +167,8 @@ namespace Opm
|
|||
is_producer_[w] = wells_ecl[w].isProducer();
|
||||
}
|
||||
|
||||
current_injection_controls_.resize(nw);
|
||||
current_production_controls_.resize(nw);
|
||||
current_injection_controls_.resize(nw, Well::InjectorCMode::CMODE_UNDEFINED);
|
||||
current_production_controls_.resize(nw, Well::ProducerCMode::CMODE_UNDEFINED);
|
||||
for (int w = 0; w < nw; ++w) {
|
||||
if (wells_ecl[w].isProducer()) {
|
||||
const auto controls = wells_ecl[w].productionControls(summary_state);
|
||||
|
|
Loading…
Reference in New Issue
Block a user