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:
Atgeirr Flø Rasmussen 2018-11-13 07:42:19 +01:00 committed by GitHub
commit 58eedf0d65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 52 deletions

View File

@ -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_);
}
}
}

View File

@ -373,8 +373,6 @@ namespace Opm
break;
} // end of switch
updatePrimaryVariables(well_state);
}

View File

@ -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 );

View File

@ -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

View File

@ -438,6 +438,7 @@ namespace Opm
if (updated_control_index != old_control_index) { // || well_collection_->groupControlActive()) {
updateWellStateWithTarget(well_state);
updatePrimaryVariables(well_state);
}
}

View File

@ -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