Add support for COMPLUMP in WECON and WTEST

This commit is contained in:
Tor Harald Sandve
2018-06-28 13:28:30 +02:00
parent 0f4038342d
commit 834f680587
4 changed files with 80 additions and 45 deletions

View File

@@ -191,7 +191,7 @@ namespace Opm {
well_container.reserve(wellsForTesting.size()); well_container.reserve(wellsForTesting.size());
for (auto& testWell : wellsForTesting) { for (auto& testWell : wellsForTesting) {
const std::string msg = std::string("well ") + testWell.first + std::string(" will be tested"); const std::string msg = std::string("well ") + testWell.first + std::string(" is tested");
OpmLog::info(msg); OpmLog::info(msg);
// finding the location of the well in wells_ecl // finding the location of the well in wells_ecl
@@ -225,8 +225,6 @@ namespace Opm {
const int well_cell_top = wells()->well_cells[wells()->well_connpos[wellidx]]; const int well_cell_top = wells()->well_cells[wells()->well_connpos[wellidx]];
const int pvtreg = pvt_region_idx_[well_cell_top]; const int pvtreg = pvt_region_idx_[well_cell_top];
//WellInterface<TypeTag> well(well_ecl, timeStepIdx, wells(), param_, *rateConverter_, pvtreg, numComponents() );
if ( !well_ecl->isMultiSegment(timeStepIdx) || !param_.use_multisegment_well_) { if ( !well_ecl->isMultiSegment(timeStepIdx) || !param_.use_multisegment_well_) {
well_container.emplace_back(new StandardWell<TypeTag>(well_ecl, timeStepIdx, wells(), well_container.emplace_back(new StandardWell<TypeTag>(well_ecl, timeStepIdx, wells(),
param_, *rateConverter_, pvtreg, numComponents() ) ); param_, *rateConverter_, pvtreg, numComponents() ) );
@@ -238,25 +236,37 @@ namespace Opm {
for (auto& well : well_container) { for (auto& well : well_container) {
WellTestState wellTestStateForTheWellTest; WellTestState wellTestStateForTheWellTest;
WellState wellStateCopy = well_state_;
well->init(&phase_usage_, depth_, gravity_, number_of_cells_); well->init(&phase_usage_, depth_, gravity_, number_of_cells_);
const std::string well_name = well->name(); const std::string well_name = well->name();
const WellNode& well_node = wellCollection().findWellNode(well_name); const WellNode& well_node = wellCollection().findWellNode(well_name);
const double well_efficiency_factor = well_node.getAccumulativeEfficiencyFactor(); const double well_efficiency_factor = well_node.getAccumulativeEfficiencyFactor();
well->setWellEfficiencyFactor(well_efficiency_factor); well->setWellEfficiencyFactor(well_efficiency_factor);
well->setVFPProperties(vfp_properties_.get()); well->setVFPProperties(vfp_properties_.get());
well->updatePrimaryVariables(well_state_); well->updatePrimaryVariables(wellStateCopy);
well->initPrimaryVariablesEvaluation(); well->initPrimaryVariablesEvaluation();
well->solveWellEq(ebosSimulator_, well_state_, /*dt (not relevant for well test) =*/ 1.0, B_avg, terminal_output_);
well->updateListEconLimited(well_state_, simulationTime, wellTestStateForTheWellTest); bool testWell = true;
while (testWell) {
size_t numberOfClosedCompletions = wellTestStateForTheWellTest.sizeCompletions();
well->solveWellEq(ebosSimulator_, wellStateCopy, /*dt (not relevant for well test) =*/ 1.0, B_avg, terminal_output_);
well->updateListEconLimited(wellStateCopy, simulationTime, wellTestStateForTheWellTest, /*writeMessageToOPMLog=*/ false);
well->closeWellsAndCompletions(wellTestStateForTheWellTest);
// test completions individually.
if (numberOfClosedCompletions == wellTestStateForTheWellTest.sizeCompletions())
testWell = false;
}
// update wellTestState if the well test succeeds // update wellTestState if the well test succeeds
if (!wellTestStateForTheWellTest.hasWell(well->name(), WellTestConfig::Reason::ECONOMIC)) { if (!wellTestStateForTheWellTest.hasWell(well->name(), WellTestConfig::Reason::ECONOMIC)) {
wellTestState_.openWell(well->name()); wellTestState_.openWell(well->name());
const std::string msg = std::string("well ") + well->name() + std::string(" is re-opened"); const std::string msg = std::string("well ") + well->name() + std::string(" is re-opened");
OpmLog::info(msg); OpmLog::info(msg);
// also reopen completions // also reopen completions
for (int completionIdx = 0; completionIdx <well->numberOfCompletions(); ++completionIdx) { for (auto& completion : well->wellEcl()->getCompletions(timeStepIdx)) {
if (!wellTestStateForTheWellTest.hasCompletion(well->name(), completionIdx)) if (!wellTestStateForTheWellTest.hasCompletion(well->name(), completion.first))
wellTestState_.dropCompletion(well->name(), completionIdx); wellTestState_.dropCompletion(well->name(), completion.first);
} }
} }
} }
@@ -748,7 +758,7 @@ namespace Opm {
updateListEconLimited(const double& simulationTime, WellTestState& wellTestState) const updateListEconLimited(const double& simulationTime, WellTestState& wellTestState) const
{ {
for (const auto& well : well_container_) { for (const auto& well : well_container_) {
well->updateListEconLimited(well_state_, simulationTime, wellTestState); well->updateListEconLimited(well_state_, simulationTime, wellTestState, /*writeMessageToOPMLog=*/ true);
} }
} }

View File

@@ -1570,7 +1570,6 @@ namespace Opm
for ( int compIdx = 0; compIdx < num_components_; ++compIdx ) for ( int compIdx = 0; compIdx < num_components_; ++compIdx )
{ {
report.converged = report.converged && (well_flux_residual[compIdx] < tol_wells) && control_eq_converged; report.converged = report.converged && (well_flux_residual[compIdx] < tol_wells) && control_eq_converged;
//std::cout << name() << " " << well_flux_residual[compIdx] << std::endl;
} }
} else { // abnormal values found and no need to check the convergence } else { // abnormal values found and no need to check the convergence
report.converged = false; report.converged = false;

View File

@@ -179,7 +179,8 @@ namespace Opm
void updateListEconLimited(const WellState& well_state, void updateListEconLimited(const WellState& well_state,
const double& simulationTime, const double& simulationTime,
WellTestState& wellTestState) const; WellTestState& wellTestState,
const bool& writeMessageToOPMLog) const;
void setWellEfficiencyFactor(const double efficiency_factor); void setWellEfficiencyFactor(const double efficiency_factor);
@@ -228,8 +229,7 @@ namespace Opm
void closeWellsAndCompletions(WellTestState& wellTestState); void closeWellsAndCompletions(WellTestState& wellTestState);
#warning currently just return number of connections const Well* wellEcl() const { return well_ecl_;}
int numberOfCompletions(){ return number_of_perforations_;}
protected: protected:
@@ -348,6 +348,7 @@ namespace Opm
double scalingFactor(const int comp_idx) const; double scalingFactor(const int comp_idx) const;
int numberOfCompletions() const { return well_ecl_->getCompletions(current_step_).size();}
}; };

View File

@@ -103,7 +103,6 @@ namespace Opm
saturation_table_number_.begin() ); saturation_table_number_.begin() );
} }
well_efficiency_factor_ = 1.0; well_efficiency_factor_ = 1.0;
} }
@@ -538,24 +537,34 @@ namespace Opm
water_cut_perf[perf] = 0.; water_cut_perf[perf] = 0.;
} }
} }
const auto& completions = well_ecl_->getCompletions(current_step_);
const auto& connections = well_ecl_->getConnections(current_step_);
last_connection = (perf_number == 1); int complnumIdx = 0;
if (last_connection) { std::vector<double> water_cut_in_completions(numberOfCompletions(), 0.0);
worst_offending_connection = 0; for (const auto& completion : completions) {
violation_extent = water_cut_perf[0] / max_water_cut_limit; int complnum = completion.first;
return std::make_tuple(water_cut_limit_violated, last_connection, worst_offending_connection, violation_extent); for (int perf = 0; perf < perf_number; ++perf) {
if (complnum == connections.get ( perf ).complnum) {
water_cut_in_completions[complnumIdx] += water_cut_perf[perf];
}
}
complnumIdx++;
} }
last_connection = false;
double max_water_cut_perf = 0.; double max_water_cut_perf = 0.;
for (int perf = 0; perf < perf_number; ++perf) { complnumIdx = 0;
if (water_cut_perf[perf] > max_water_cut_perf) { for (const auto& completion : completions) {
worst_offending_connection = perf; if (water_cut_in_completions[complnumIdx] > max_water_cut_perf) {
max_water_cut_perf = water_cut_perf[perf]; worst_offending_connection = completion.first;
max_water_cut_perf = water_cut_in_completions[complnumIdx];
} }
complnumIdx++;
} }
assert(max_water_cut_perf != 0.); assert(max_water_cut_limit != 0.);
assert((worst_offending_connection >= 0) && (worst_offending_connection < perf_number));
violation_extent = max_water_cut_perf / max_water_cut_limit; violation_extent = max_water_cut_perf / max_water_cut_limit;
} }
@@ -629,7 +638,8 @@ namespace Opm
WellInterface<TypeTag>:: WellInterface<TypeTag>::
updateListEconLimited(const WellState& well_state, updateListEconLimited(const WellState& well_state,
const double& simulationTime, const double& simulationTime,
WellTestState& wellTestState) const WellTestState& wellTestState,
const bool& writeMessageToOPMLog) const
{ {
// economic limits only apply for production wells. // economic limits only apply for production wells.
if (wellType() != PRODUCER) { if (wellType() != PRODUCER) {
@@ -672,12 +682,14 @@ namespace Opm
} }
wellTestState.addClosedWell(well_name, WellTestConfig::Reason::ECONOMIC, simulationTime); wellTestState.addClosedWell(well_name, WellTestConfig::Reason::ECONOMIC, simulationTime);
if (well_ecl_->getAutomaticShutIn()) { if (writeMessageToOPMLog) {
const std::string msg = std::string("well ") + well_name + std::string(" will be shut due to rate economic limit"); if (well_ecl_->getAutomaticShutIn()) {
OpmLog::info(msg); const std::string msg = std::string("well ") + well_name + std::string(" will be shut due to rate economic limit");
} else { OpmLog::info(msg);
const std::string msg = std::string("well ") + well_name + std::string(" will be stopped due to rate economic limit"); } else {
OpmLog::info(msg); const std::string msg = std::string("well ") + well_name + std::string(" will be stopped due to rate economic limit");
OpmLog::info(msg);
}
} }
// the well is closed, not need to check other limits // the well is closed, not need to check other limits
return; return;
@@ -699,23 +711,30 @@ namespace Opm
{ {
const int worst_offending_connection = std::get<2>(ratio_check_return); const int worst_offending_connection = std::get<2>(ratio_check_return);
assert((worst_offending_connection >= 0) && (worst_offending_connection < number_of_perforations_));
#warning map to completions
wellTestState.addClosedCompletion(well_name, worst_offending_connection, simulationTime); wellTestState.addClosedCompletion(well_name, worst_offending_connection, simulationTime);
const std::string msg = std::string("Connection ") + std::to_string(worst_offending_connection) + std::string(" for well ") if (writeMessageToOPMLog) {
+ well_name + std::string(" will be closed due to economic limit"); if (worst_offending_connection < 0) {
OpmLog::info(msg); const std::string msg = std::string("Connection ") + std::to_string(- worst_offending_connection) + std::string(" for well ")
+ well_name + std::string(" will be closed due to economic limit");
OpmLog::info(msg);
} else {
const std::string msg = std::string("Completion ") + std::to_string(worst_offending_connection) + std::string(" for well ")
+ well_name + std::string(" will be closed due to economic limit");
OpmLog::info(msg);
}
}
bool allCompletionsClosed = true; bool allCompletionsClosed = true;
for (int perf = 0; perf < number_of_perforations_ ; ++perf) { const auto& connections = well_ecl_->getConnections(current_step_);
if (!wellTestState.hasCompletion(name(), perf)) { for (const auto& connection : connections) {
if (!wellTestState.hasCompletion(name(), connection.complnum)) {
allCompletionsClosed = false; allCompletionsClosed = false;
} }
} }
if (allCompletionsClosed) { if (allCompletionsClosed) {
wellTestState.addClosedWell(well_name, WellTestConfig::Reason::ECONOMIC, simulationTime); wellTestState.addClosedWell(well_name, WellTestConfig::Reason::ECONOMIC, simulationTime);
if (writeMessageToOPMLog) {
if (well_ecl_->getAutomaticShutIn()) { if (well_ecl_->getAutomaticShutIn()) {
const std::string msg = well_name + std::string(" will be shut due to last compleation closed"); const std::string msg = well_name + std::string(" will be shut due to last compleation closed");
OpmLog::info(msg); OpmLog::info(msg);
@@ -723,12 +742,14 @@ namespace Opm
const std::string msg = well_name + std::string(" will be stopped due to last compleation closed"); const std::string msg = well_name + std::string(" will be stopped due to last compleation closed");
OpmLog::info(msg); OpmLog::info(msg);
} }
}
} }
break; break;
} }
case WellEcon::WELL: case WellEcon::WELL:
{ {
wellTestState.addClosedWell(well_name, WellTestConfig::Reason::ECONOMIC, 0); wellTestState.addClosedWell(well_name, WellTestConfig::Reason::ECONOMIC, 0);
if (writeMessageToOPMLog) {
if (well_ecl_->getAutomaticShutIn()) { if (well_ecl_->getAutomaticShutIn()) {
// tell the controll that the well is closed // tell the controll that the well is closed
const std::string msg = well_name + std::string(" will be shut due to ratio economic limit"); const std::string msg = well_name + std::string(" will be shut due to ratio economic limit");
@@ -737,6 +758,7 @@ namespace Opm
const std::string msg = well_name + std::string(" will be stopped due to ratio economic limit"); const std::string msg = well_name + std::string(" will be stopped due to ratio economic limit");
OpmLog::info(msg); OpmLog::info(msg);
} }
}
break; break;
} }
case WellEcon::NONE: case WellEcon::NONE:
@@ -895,10 +917,13 @@ namespace Opm
well_controls_stop_well(wellControls()); well_controls_stop_well(wellControls());
} }
for (int perf = 0; perf < number_of_perforations_ ; ++perf) { const auto& connections = well_ecl_->getConnections(current_step_);
if (wellTestState.hasCompletion(name(), perf)) { int perfIdx = 0;
well_index_[perf] = 0.0; for (const auto& connection : connections) {
if (wellTestState.hasCompletion(name(), connection.complnum)) {
well_index_[perfIdx] = 0.0;
} }
perfIdx++;
} }
} }