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 <dune/geometry/referenceelements.hh>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
|
@ -1449,8 +1450,8 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
updateEclWell(int, const std::string&) {
|
updateEclWells(int, const std::unordered_set<std::string>&) {
|
||||||
throw std::logic_error("updateEclWell() method not implemented for class eclpeacemanwell");
|
throw std::logic_error("updateEclWells() method not implemented for class eclpeacemanwell");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1377,6 +1377,7 @@ public:
|
||||||
pyaction->run(ecl_state, schedule, reportStep, summaryState);
|
pyaction->run(ecl_state, schedule, reportStep, summaryState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool commit_wellstate = false;
|
||||||
auto simTime = schedule.simTime(reportStep);
|
auto simTime = schedule.simTime(reportStep);
|
||||||
for (const auto& action : actions.pending(actionState, simTime)) {
|
for (const auto& action : actions.pending(actionState, simTime)) {
|
||||||
auto actionResult = action->eval(context);
|
auto actionResult = action->eval(context);
|
||||||
|
@ -1393,19 +1394,24 @@ public:
|
||||||
|
|
||||||
const auto& wellpi = this->fetchWellPI(reportStep, *action, schedule, matching_wells);
|
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);
|
actionState.add_run(*action, simTime);
|
||||||
|
this->wellModel_.updateEclWells(reportStep, affected_wells);
|
||||||
for ( const auto& [wname, _] : wellpi) {
|
if (!affected_wells.empty())
|
||||||
(void)_;
|
commit_wellstate = true;
|
||||||
if (this->wellModel_.hasWell(wname))
|
|
||||||
this->wellModel_.updateEclWell(reportStep, wname);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
std::string msg = "The action: " + action->name() + " evaluated to false at " + ts;
|
std::string msg = "The action: " + action->name() + " evaluated to false at " + ts;
|
||||||
Opm::OpmLog::info(msg);
|
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 <dune/grid/common/gridenums.hh>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -658,7 +659,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
void
|
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");
|
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.
|
/// Returns true if the well was actually found and shut.
|
||||||
bool forceShutWellByNameIfPredictionMode(const std::string& wellname, const double simulation_time);
|
bool forceShutWellByNameIfPredictionMode(const std::string& wellname, const double simulation_time);
|
||||||
|
|
||||||
void updateEclWell(const int timeStepIdx, const int well_index);
|
void updateEclWells(const int timeStepIdx, const std::unordered_set<std::string>& wells);
|
||||||
void updateEclWell(const int timeStepIdx, const std::string& wname);
|
|
||||||
bool hasWell(const std::string& wname);
|
bool hasWell(const std::string& wname);
|
||||||
double wellPI(const int well_index) const;
|
double wellPI(const int well_index) const;
|
||||||
double wellPI(const std::string& well_name) const;
|
double wellPI(const std::string& well_name) const;
|
||||||
|
|
|
@ -2622,55 +2622,38 @@ namespace Opm {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
void
|
void
|
||||||
BlackoilWellModel<TypeTag>::
|
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& schedule = this->ebosSimulator_.vanguard().schedule();
|
||||||
const auto& wname = this->wells_ecl_[well_index].name();
|
for (const auto& wname : wells) {
|
||||||
this->wells_ecl_[well_index] = schedule.getWell(wname, timeStepIdx);
|
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];
|
const auto& well = this->wells_ecl_[well_index];
|
||||||
auto& pd = this->well_perf_data_[well_index];
|
auto& pd = this->well_perf_data_[well_index];
|
||||||
auto pdIter = pd.begin();
|
auto pdIter = pd.begin();
|
||||||
for (const auto& conn : well.getConnections()) {
|
for (const auto& conn : well.getConnections()) {
|
||||||
if (conn.state() != Connection::State::SHUT) {
|
if (conn.state() != Connection::State::SHUT) {
|
||||||
pdIter->connection_transmissibility_factor = conn.CF();
|
pdIter->connection_transmissibility_factor = conn.CF();
|
||||||
++pdIter;
|
++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>
|
template<typename TypeTag>
|
||||||
double
|
double
|
||||||
BlackoilWellModel<TypeTag>::
|
BlackoilWellModel<TypeTag>::
|
||||||
|
@ -2762,6 +2745,26 @@ namespace Opm {
|
||||||
ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX);
|
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 =
|
auto rescaleWellPI =
|
||||||
[this, timeStepIdx](const int well_index,
|
[this, timeStepIdx](const int well_index,
|
||||||
const double newWellPI) -> void
|
const double newWellPI) -> void
|
||||||
|
@ -2770,8 +2773,6 @@ namespace Opm {
|
||||||
|
|
||||||
auto& schedule = this->ebosSimulator_.vanguard().schedule(); // Mutable
|
auto& schedule = this->ebosSimulator_.vanguard().schedule(); // Mutable
|
||||||
schedule.applyWellProdIndexScaling(wname, timeStepIdx, newWellPI);
|
schedule.applyWellProdIndexScaling(wname, timeStepIdx, newWellPI);
|
||||||
|
|
||||||
this->updateEclWell(timeStepIdx, well_index);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Minimal well setup to compute PI/II values
|
// Minimal well setup to compute PI/II values
|
||||||
|
@ -2797,6 +2798,7 @@ namespace Opm {
|
||||||
for (auto wellID = 0*nw; wellID < nw; ++wellID) {
|
for (auto wellID = 0*nw; wellID < nw; ++wellID) {
|
||||||
if (hasWellPIEvent(wellID)) {
|
if (hasWellPIEvent(wellID)) {
|
||||||
rescaleWellPI(wellID, this->wellPI(wellID));
|
rescaleWellPI(wellID, this->wellPI(wellID));
|
||||||
|
updateEclWell(wellID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,6 +239,22 @@ namespace Opm
|
||||||
this->thp_[well_index] = 0;
|
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
|
virtual data::Wells
|
||||||
report(const PhaseUsage& pu,
|
report(const PhaseUsage& pu,
|
||||||
const int* globalCellIdxMap,
|
const int* globalCellIdxMap,
|
||||||
|
|
|
@ -66,6 +66,7 @@ namespace Opm
|
||||||
using BaseType :: numWells;
|
using BaseType :: numWells;
|
||||||
using BaseType :: numPhases;
|
using BaseType :: numPhases;
|
||||||
using BaseType :: resetConnectionTransFactors;
|
using BaseType :: resetConnectionTransFactors;
|
||||||
|
using BaseType :: updateStatus;
|
||||||
|
|
||||||
/// Allocate and initialize if wells is non-null. Also tries
|
/// Allocate and initialize if wells is non-null. Also tries
|
||||||
/// to give useful initial values to the bhp(), wellRates()
|
/// to give useful initial values to the bhp(), wellRates()
|
||||||
|
@ -166,8 +167,8 @@ namespace Opm
|
||||||
is_producer_[w] = wells_ecl[w].isProducer();
|
is_producer_[w] = wells_ecl[w].isProducer();
|
||||||
}
|
}
|
||||||
|
|
||||||
current_injection_controls_.resize(nw);
|
current_injection_controls_.resize(nw, Well::InjectorCMode::CMODE_UNDEFINED);
|
||||||
current_production_controls_.resize(nw);
|
current_production_controls_.resize(nw, Well::ProducerCMode::CMODE_UNDEFINED);
|
||||||
for (int w = 0; w < nw; ++w) {
|
for (int w = 0; w < nw; ++w) {
|
||||||
if (wells_ecl[w].isProducer()) {
|
if (wells_ecl[w].isProducer()) {
|
||||||
const auto controls = wells_ecl[w].productionControls(summary_state);
|
const auto controls = wells_ecl[w].productionControls(summary_state);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user