mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Update Well Topology if Triggered From ACTIONX
This commit adds a new flag data member,
wellStructureChangedDynamically_
to the generic black-oil well model. This flag captures the
well_structure_changed
value from the 'SimulatorUpdate' structure in the updateEclWells()
member function. Then, in BlackoilWellModel::beginTimeStep(), we
key a well structure update off this flag when set. This, in turn,
enables creating or opening wells as a result of an ACTIONX block
updating the structure in the middle of a report step.
This commit is contained in:
@@ -188,21 +188,24 @@ void EclActionHandler::applySimulatorUpdate(const int report_step,
|
|||||||
const SimulatorUpdate& sim_update,
|
const SimulatorUpdate& sim_update,
|
||||||
bool& commit_wellstate,
|
bool& commit_wellstate,
|
||||||
const TransFunc& updateTrans)
|
const TransFunc& updateTrans)
|
||||||
{
|
{
|
||||||
OPM_TIMEBLOCK(applySimulatorUpdate);
|
OPM_TIMEBLOCK(applySimulatorUpdate);
|
||||||
this->wellModel_.updateEclWells(report_step, sim_update.affected_wells, summaryState_);
|
|
||||||
if (!sim_update.affected_wells.empty())
|
|
||||||
commit_wellstate = true;
|
|
||||||
|
|
||||||
if (sim_update.tran_update) {
|
this->wellModel_.updateEclWells(report_step, sim_update, this->summaryState_);
|
||||||
const auto& keywords = schedule_[report_step].geo_keywords();
|
|
||||||
ecl_state_.apply_schedule_keywords( keywords );
|
|
||||||
eclBroadcast(comm_, ecl_state_.getTransMult() );
|
|
||||||
|
|
||||||
// re-compute transmissibility
|
if (!sim_update.affected_wells.empty()) {
|
||||||
updateTrans(true);
|
commit_wellstate = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (sim_update.tran_update) {
|
||||||
|
const auto& keywords = schedule_[report_step].geo_keywords();
|
||||||
|
ecl_state_.apply_schedule_keywords( keywords );
|
||||||
|
eclBroadcast(comm_, ecl_state_.getTransMult() );
|
||||||
|
|
||||||
|
// re-compute transmissibility
|
||||||
|
updateTrans(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, double>
|
std::unordered_map<std::string, double>
|
||||||
EclActionHandler::fetchWellPI(const int reportStep,
|
EclActionHandler::fetchWellPI(const int reportStep,
|
||||||
|
|||||||
@@ -32,6 +32,9 @@
|
|||||||
#include <opm/output/eclipse/RestartValue.hpp>
|
#include <opm/output/eclipse/RestartValue.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||||
|
#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/Action/SimulatorUpdate.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||||
@@ -42,7 +45,7 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
#include <opm/simulators/utils/DeferredLogger.hpp>
|
#include <opm/simulators/utils/DeferredLogger.hpp>
|
||||||
@@ -669,10 +672,10 @@ checkGroupHigherConstraints(const Group& group,
|
|||||||
void
|
void
|
||||||
BlackoilWellModelGeneric::
|
BlackoilWellModelGeneric::
|
||||||
updateEclWells(const int timeStepIdx,
|
updateEclWells(const int timeStepIdx,
|
||||||
const std::unordered_set<std::string>& wells,
|
const SimulatorUpdate& sim_update,
|
||||||
const SummaryState& st)
|
const SummaryState& st)
|
||||||
{
|
{
|
||||||
for (const auto& wname : wells) {
|
for (const auto& wname : sim_update.affected_wells) {
|
||||||
auto well_iter = std::find_if(this->wells_ecl_.begin(), this->wells_ecl_.end(),
|
auto well_iter = std::find_if(this->wells_ecl_.begin(), this->wells_ecl_.end(),
|
||||||
[&wname] (const auto& well) -> bool
|
[&wname] (const auto& well) -> bool
|
||||||
{
|
{
|
||||||
@@ -683,25 +686,36 @@ updateEclWells(const int timeStepIdx,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto well_index = std::distance(this->wells_ecl_.begin(), well_iter);
|
const 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];
|
this->schedule_.getWell(wname, timeStepIdx);
|
||||||
auto pdIter = pd.begin();
|
|
||||||
for (const auto& conn : well.getConnections()) {
|
auto& pd = this->well_perf_data_[well_index];
|
||||||
if (conn.state() != Connection::State::SHUT) {
|
|
||||||
pdIter->connection_transmissibility_factor = conn.CF();
|
{
|
||||||
++pdIter;
|
auto pdIter = pd.begin();
|
||||||
|
|
||||||
|
for (const auto& conn : well.getConnections()) {
|
||||||
|
if (conn.state() != Connection::State::SHUT) {
|
||||||
|
pdIter->connection_transmissibility_factor = conn.CF();
|
||||||
|
++pdIter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto& ws = this->wellState().well(well_index);
|
|
||||||
|
|
||||||
ws.updateStatus( well.getStatus() );
|
{
|
||||||
ws.reset_connection_factors(pd);
|
auto& ws = this->wellState().well(well_index);
|
||||||
ws.update_targets(well, st);
|
|
||||||
|
ws.updateStatus(well.getStatus());
|
||||||
|
ws.reset_connection_factors(pd);
|
||||||
|
ws.update_targets(well, st);
|
||||||
|
}
|
||||||
|
|
||||||
this->prod_index_calc_[well_index].reInit(well);
|
this->prod_index_calc_[well_index].reInit(well);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->wellStructureChangedDynamically_ = sim_update.well_structure_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
|
|||||||
@@ -54,14 +54,15 @@
|
|||||||
namespace Opm {
|
namespace Opm {
|
||||||
class DeferredLogger;
|
class DeferredLogger;
|
||||||
class EclipseState;
|
class EclipseState;
|
||||||
|
class GasLiftGroupInfo;
|
||||||
class GasLiftSingleWellGeneric;
|
class GasLiftSingleWellGeneric;
|
||||||
class GasLiftWellState;
|
class GasLiftWellState;
|
||||||
class GasLiftGroupInfo;
|
|
||||||
class Group;
|
class Group;
|
||||||
class GuideRateConfig;
|
class GuideRateConfig;
|
||||||
class ParallelWellInfo;
|
class ParallelWellInfo;
|
||||||
class RestartValue;
|
class RestartValue;
|
||||||
class Schedule;
|
class Schedule;
|
||||||
|
struct SimulatorUpdate;
|
||||||
class SummaryConfig;
|
class SummaryConfig;
|
||||||
class VFPProperties;
|
class VFPProperties;
|
||||||
class WellInterfaceGeneric;
|
class WellInterfaceGeneric;
|
||||||
@@ -152,7 +153,7 @@ public:
|
|||||||
double wellPI(const std::string& well_name) const;
|
double wellPI(const std::string& well_name) const;
|
||||||
|
|
||||||
void updateEclWells(const int timeStepIdx,
|
void updateEclWells(const int timeStepIdx,
|
||||||
const std::unordered_set<std::string>& wells,
|
const SimulatorUpdate& sim_update,
|
||||||
const SummaryState& st);
|
const SummaryState& st);
|
||||||
|
|
||||||
void initFromRestartFile(const RestartValue& restartValues,
|
void initFromRestartFile(const RestartValue& restartValues,
|
||||||
@@ -579,6 +580,8 @@ protected:
|
|||||||
|
|
||||||
double last_glift_opt_time_ = -1.0;
|
double last_glift_opt_time_ = -1.0;
|
||||||
|
|
||||||
|
bool wellStructureChangedDynamically_{false};
|
||||||
|
|
||||||
std::map<std::string, std::string> switched_prod_groups_;
|
std::map<std::string, std::string> switched_prod_groups_;
|
||||||
std::map<std::pair<std::string, Opm::Phase>, std::string> switched_inj_groups_;
|
std::map<std::pair<std::string, Opm::Phase>, std::string> switched_inj_groups_;
|
||||||
|
|
||||||
|
|||||||
@@ -272,6 +272,8 @@ namespace Opm {
|
|||||||
// Store the current well and group states in order to recover in
|
// Store the current well and group states in order to recover in
|
||||||
// the case of failed iterations
|
// the case of failed iterations
|
||||||
this->commitWGState();
|
this->commitWGState();
|
||||||
|
|
||||||
|
this->wellStructureChangedDynamically_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -371,16 +373,46 @@ namespace Opm {
|
|||||||
beginTimeStep()
|
beginTimeStep()
|
||||||
{
|
{
|
||||||
OPM_TIMEBLOCK(beginTimeStep);
|
OPM_TIMEBLOCK(beginTimeStep);
|
||||||
updateAverageFormationFactor();
|
|
||||||
|
this->updateAverageFormationFactor();
|
||||||
|
|
||||||
DeferredLogger local_deferredLogger;
|
DeferredLogger local_deferredLogger;
|
||||||
switched_prod_groups_.clear();
|
|
||||||
switched_inj_groups_.clear();
|
this->switched_prod_groups_.clear();
|
||||||
|
this->switched_inj_groups_.clear();
|
||||||
|
|
||||||
|
if (this->wellStructureChangedDynamically_) {
|
||||||
|
// Something altered the well structure/topology. Possibly
|
||||||
|
// WELSPECS/COMPDAT and/or WELOPEN run from an ACTIONX block.
|
||||||
|
// Reconstruct the local wells to account for the new well
|
||||||
|
// structure.
|
||||||
|
const auto reportStepIdx =
|
||||||
|
this->ebosSimulator_.episodeIndex();
|
||||||
|
|
||||||
|
// Disable WELPI scaling when well structure is updated in the
|
||||||
|
// middle of a report step.
|
||||||
|
const auto enableWellPIScaling = false;
|
||||||
|
|
||||||
|
this->initializeLocalWellStructure(reportStepIdx, enableWellPIScaling);
|
||||||
|
this->initializeGroupStructure(reportStepIdx);
|
||||||
|
|
||||||
|
this->commitWGState();
|
||||||
|
|
||||||
|
// Reset topology flag to signal that we've handled this
|
||||||
|
// structure change. That way we don't end up here in
|
||||||
|
// subsequent calls to beginTimeStep() unless there's a new
|
||||||
|
// dynamic change to the well structure during a report step.
|
||||||
|
this->wellStructureChangedDynamically_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
this->resetWGState();
|
this->resetWGState();
|
||||||
|
|
||||||
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
const int reportStepIdx = ebosSimulator_.episodeIndex();
|
||||||
updateAndCommunicateGroupData(reportStepIdx,
|
updateAndCommunicateGroupData(reportStepIdx,
|
||||||
ebosSimulator_.model().newtonMethod().numIterations());
|
ebosSimulator_.model().newtonMethod().numIterations());
|
||||||
|
|
||||||
this->wellState().gliftTimeStepInit();
|
this->wellState().gliftTimeStepInit();
|
||||||
|
|
||||||
const double simulationTime = ebosSimulator_.time();
|
const double simulationTime = ebosSimulator_.time();
|
||||||
OPM_BEGIN_PARALLEL_TRY_CATCH();
|
OPM_BEGIN_PARALLEL_TRY_CATCH();
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user