mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-11-21 08:54:08 -06:00
Merge pull request #1615 from GitPaean/using_events_for_well_states_2
detecting whether some well control events happens to a well
This commit is contained in:
commit
58eedf0d65
@ -172,7 +172,7 @@ namespace Opm {
|
||||
const double p = fs.pressure(FluidSystem::oilPhaseIdx).value();
|
||||
cellPressures[cellIdx] = p;
|
||||
}
|
||||
well_state_.init(wells(), cellPressures, &previous_well_state_, phase_usage_);
|
||||
well_state_.init(wells(), cellPressures, wells_ecl_, timeStepIdx, &previous_well_state_, phase_usage_);
|
||||
|
||||
// handling MS well related
|
||||
if (param_.use_multisegment_well_) { // if we use MultisegmentWell model
|
||||
@ -362,9 +362,9 @@ namespace Opm {
|
||||
|
||||
const int nw = wells->number_of_wells;
|
||||
if (nw > 0) {
|
||||
auto phaseUsage = phaseUsageFromDeck(eclState());
|
||||
size_t numCells = Opm::UgGridHelpers::numCells(grid());
|
||||
well_state_.resize(wells, numCells, phaseUsage); //Resize for restart step
|
||||
const auto phaseUsage = phaseUsageFromDeck(eclState());
|
||||
const size_t numCells = Opm::UgGridHelpers::numCells(grid());
|
||||
well_state_.resize(wells, numCells, phaseUsage); // Resize for restart step
|
||||
wellsToState(restartValues.wells, phaseUsage, well_state_);
|
||||
previous_well_state_ = well_state_;
|
||||
}
|
||||
@ -938,18 +938,19 @@ namespace Opm {
|
||||
WellControls* wc = well->wellControls();
|
||||
const int control = well_controls_get_current(wc);
|
||||
well_state_.currentControls()[w] = control;
|
||||
// TODO: for VFP control, the perf_densities are still zero here, investigate better
|
||||
// way to handle it later.
|
||||
well->updateWellStateWithTarget(well_state_);
|
||||
|
||||
// The wells are not considered to be newly added
|
||||
// for next time step
|
||||
if (well_state_.isNewWell(w) ) {
|
||||
well_state_.setNewWell(w, false);
|
||||
if (well_state_.effectiveEventsOccurred(w) ) {
|
||||
well->updateWellStateWithTarget(well_state_);
|
||||
}
|
||||
|
||||
// there is no new well control change input within a report step,
|
||||
// so next time step, the well does not consider to have effective events anymore
|
||||
if (well_state_.effectiveEventsOccurred(w) ) {
|
||||
well_state_.setEffectiveEventsOccurred(w, false);
|
||||
}
|
||||
} // end of for (int w = 0; w < nw; ++w)
|
||||
|
||||
|
||||
updatePrimaryVariables();
|
||||
}
|
||||
|
||||
|
||||
@ -1185,8 +1186,10 @@ namespace Opm {
|
||||
// it will not change the control mode, only update the targets
|
||||
wellCollection().updateWellTargets(well_state_.wellRates());
|
||||
|
||||
// TODO: we should only do the well is involved in the update group targets
|
||||
for (auto& well : well_container_) {
|
||||
well->updateWellStateWithTarget(well_state_);
|
||||
well->updatePrimaryVariables(well_state_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,8 +373,6 @@ namespace Opm
|
||||
|
||||
break;
|
||||
} // end of switch
|
||||
|
||||
updatePrimaryVariables(well_state);
|
||||
}
|
||||
|
||||
|
||||
|
@ -460,7 +460,7 @@ namespace Opm
|
||||
|
||||
const Wells* wells = wellsmanager.c_wells();
|
||||
size_t numCells = Opm::UgGridHelpers::numCells(grid);
|
||||
wellstate.resize(wells, numCells, phaseUsage ); //Resize for restart step
|
||||
wellstate.resize(wells, numCells, phaseUsage); //Resize for restart step
|
||||
auto restart_values = eclIO_->loadRestart(solution_keys, extra_keys);
|
||||
|
||||
solutionToSim( restart_values, phaseUsage, simulatorstate );
|
||||
|
@ -1222,8 +1222,6 @@ namespace Opm
|
||||
|
||||
break;
|
||||
} // end of switch
|
||||
|
||||
updatePrimaryVariables(well_state);
|
||||
}
|
||||
|
||||
|
||||
@ -1916,7 +1914,7 @@ namespace Opm
|
||||
} else {
|
||||
// the well has a THP related constraint
|
||||
// checking whether a well is newly added, it only happens at the beginning of the report step
|
||||
if ( !well_state.isNewWell(index_of_well_) ) {
|
||||
if ( !well_state.effectiveEventsOccurred(index_of_well_) ) {
|
||||
for (int p = 0; p < np; ++p) {
|
||||
// This is dangerous for new added well
|
||||
// since we are not handling the initialization correctly for now
|
||||
|
@ -438,6 +438,7 @@ namespace Opm
|
||||
|
||||
if (updated_control_index != old_control_index) { // || well_collection_->groupControlActive()) {
|
||||
updateWellStateWithTarget(well_state);
|
||||
updatePrimaryVariables(well_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,9 @@ namespace Opm
|
||||
/// Allocate and initialize if wells is non-null. Also tries
|
||||
/// to give useful initial values to the bhp(), wellRates()
|
||||
/// and perfPhaseRates() fields, depending on controls
|
||||
void init(const Wells* wells, const std::vector<double>& cellPressures, const WellStateFullyImplicitBlackoil* prevState, const PhaseUsage& pu)
|
||||
void init(const Wells* wells, const std::vector<double>& cellPressures,
|
||||
const std::vector<const Well*>& wells_ecl, const int report_step,
|
||||
const WellStateFullyImplicitBlackoil* prevState, const PhaseUsage& pu)
|
||||
{
|
||||
// call init on base class
|
||||
BaseType :: init(wells, cellPressures);
|
||||
@ -84,16 +86,38 @@ namespace Opm
|
||||
well_dissolved_gas_rates_.resize(nw, 0.0);
|
||||
well_vaporized_oil_rates_.resize(nw, 0.0);
|
||||
|
||||
is_new_well_.resize(nw, true);
|
||||
if (prevState && !prevState->wellMap().empty()) {
|
||||
const auto& end = prevState->wellMap().end();
|
||||
for (int w = 0; w < nw; ++w) {
|
||||
const auto& it = prevState->wellMap().find( wells->name[w]);
|
||||
if (it != end) {
|
||||
is_new_well_[w] = false;
|
||||
// checking whether some effective well control happens
|
||||
effective_events_occurred_.resize(nw, true);
|
||||
|
||||
// a hack to make the resize() function used in RESTART related work
|
||||
if (!wells_ecl.empty() ) {
|
||||
// At the moment, the following events are considered to be effective events
|
||||
// more events might join as effective events
|
||||
// PRODUCTION_UPDATE, INJECTION_UPDATE, WELL_STATUS_CHANGE
|
||||
// 16 + 32 + 128
|
||||
const uint64_t effective_events_mask = ScheduleEvents::WELL_STATUS_CHANGE
|
||||
+ ScheduleEvents::PRODUCTION_UPDATE
|
||||
+ ScheduleEvents::INJECTION_UPDATE;
|
||||
|
||||
for (int w = 0; w <nw; ++w) {
|
||||
const int nw_wells_ecl = wells_ecl.size();
|
||||
int index_well_ecl = 0;
|
||||
const std::string well_name(wells->name[w]);
|
||||
for (; index_well_ecl < nw_wells_ecl; ++index_well_ecl) {
|
||||
if (well_name == wells_ecl[index_well_ecl]->name()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// It should be able to find in wells_ecl.
|
||||
if (index_well_ecl == nw_wells_ecl) {
|
||||
OPM_THROW(std::logic_error, "Could not find well " << well_name << " in wells_ecl ");
|
||||
}
|
||||
|
||||
const Well* well_ecl = wells_ecl[index_well_ecl];
|
||||
effective_events_occurred_[w] = (well_ecl->hasEvent(effective_events_mask, report_step) );
|
||||
}
|
||||
}
|
||||
} // end of if (!well_ecl.empty() )
|
||||
|
||||
// Ensure that we start out with zero rates by default.
|
||||
perfphaserates_.clear();
|
||||
@ -117,17 +141,9 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize current_controls_.
|
||||
// The controls set in the Wells object are treated as defaults,
|
||||
// and also used for initial values.
|
||||
current_controls_.resize(nw);
|
||||
for (int w = 0; w < nw; ++w) {
|
||||
current_controls_[w] = well_controls_get_current(wells->ctrls[w]);
|
||||
}
|
||||
|
||||
perfRateSolvent_.clear();
|
||||
perfRateSolvent_.resize(nperf, 0.0);
|
||||
|
||||
productivity_index_.resize(nw * np, 0.0);
|
||||
|
||||
// intialize wells that have been there before
|
||||
@ -136,7 +152,7 @@ namespace Opm
|
||||
typedef typename WellMapType :: const_iterator const_iterator;
|
||||
const_iterator end = prevState->wellMap().end();
|
||||
for (int w = 0; w < nw; ++w) {
|
||||
std::string name( wells->name[ w ] );
|
||||
const std::string name( wells->name[ w ] );
|
||||
const_iterator it = prevState->wellMap().find( name );
|
||||
if( it != end )
|
||||
{
|
||||
@ -149,6 +165,16 @@ namespace Opm
|
||||
// thp
|
||||
thp()[ newIndex ] = prevState->thp()[ oldIndex ];
|
||||
|
||||
// if there is no effective control event happens to the well, we use the current_controls_ from prevState
|
||||
// otherwise, we use the control specified in the deck
|
||||
if (!effective_events_occurred_[w]) {
|
||||
current_controls_[ newIndex ] = prevState->currentControls()[ oldIndex ];
|
||||
// also change the one in the WellControls
|
||||
well_controls_set_current(wells->ctrls[w], current_controls_[ newIndex ]);
|
||||
} else {
|
||||
current_controls_[w] = well_controls_get_current(wells->ctrls[w]);
|
||||
}
|
||||
|
||||
// wellrates
|
||||
for( int i=0, idx=newIndex*np, oldidx=oldIndex*np; i<np; ++i, ++idx, ++oldidx )
|
||||
{
|
||||
@ -232,8 +258,9 @@ namespace Opm
|
||||
|
||||
void resize(const Wells* wells, size_t numCells, const PhaseUsage& pu)
|
||||
{
|
||||
std::vector<double> tmp(numCells, 0.0); // <- UGLY HACK to pass the size
|
||||
init(wells, tmp, nullptr, pu);
|
||||
const std::vector<double> tmp(numCells, 0.0); // <- UGLY HACK to pass the size
|
||||
const std::vector<const Well*> wells_ecl;
|
||||
init(wells, tmp, wells_ecl, 0, nullptr, pu);
|
||||
}
|
||||
|
||||
/// Allocate and initialize if wells is non-null. Also tries
|
||||
@ -296,8 +323,6 @@ namespace Opm
|
||||
current_controls_[w] = well_controls_get_current(wells->ctrls[w]);
|
||||
}
|
||||
|
||||
is_new_well_.resize(nw, true);
|
||||
|
||||
perfRateSolvent_.clear();
|
||||
perfRateSolvent_.resize(nperf, 0.0);
|
||||
|
||||
@ -312,9 +337,6 @@ namespace Opm
|
||||
const_iterator it = prevState.wellMap().find( name );
|
||||
if( it != end )
|
||||
{
|
||||
// this is not a new added well
|
||||
is_new_well_[w] = false;
|
||||
|
||||
const int oldIndex = (*it).second[ 0 ];
|
||||
const int newIndex = w;
|
||||
|
||||
@ -707,13 +729,13 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
bool isNewWell(const int w) const {
|
||||
return is_new_well_[w];
|
||||
bool effectiveEventsOccurred(const int w) const {
|
||||
return effective_events_occurred_[w];
|
||||
}
|
||||
|
||||
|
||||
void setNewWell(const int w, const bool is_new_well) {
|
||||
is_new_well_[w] = is_new_well;
|
||||
void setEffectiveEventsOccurred(const int w, const bool effective_events_occurred) {
|
||||
effective_events_occurred_[w] = effective_events_occurred;
|
||||
}
|
||||
|
||||
|
||||
@ -802,11 +824,10 @@ namespace Opm
|
||||
// should be zero for injection wells
|
||||
std::vector<double> well_vaporized_oil_rates_;
|
||||
|
||||
// marking whether the well is just added
|
||||
// for newly added well, the current initialized rates from WellState
|
||||
// will have very wrong compositions for production wells, will mostly cause
|
||||
// problem with VFP interpolation
|
||||
std::vector<bool> is_new_well_;
|
||||
// some events happens to the well, like this well is a new well
|
||||
// or new well control keywords happens
|
||||
// \Note: for now, only WCON* keywords, and well status change is considered
|
||||
std::vector<bool> effective_events_occurred_;
|
||||
|
||||
// MS well related
|
||||
// for StandardWell, the number of segments will be one
|
||||
|
Loading…
Reference in New Issue
Block a user