Merge pull request #2042 from joakim-hove/well-reperf

Changes to well reference depth
This commit is contained in:
Bård Skaflestad 2020-10-23 16:49:08 +02:00 committed by GitHub
commit 9fc6948e05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 153 additions and 27 deletions

View File

@ -376,7 +376,7 @@ namespace Opm
int headI, int headI,
int headJ, int headJ,
Phase preferredPhase, Phase preferredPhase,
double refDepth, const std::optional<double>& refDepth,
double drainageRadius, double drainageRadius,
bool allowCrossFlow, bool allowCrossFlow,
bool automaticShutIn, bool automaticShutIn,

View File

@ -463,7 +463,7 @@ public:
std::size_t insert_index, std::size_t insert_index,
int headI, int headI,
int headJ, int headJ,
double ref_depth, const std::optional<double>& ref_depth,
const WellType& wtype_arg, const WellType& wtype_arg,
ProducerCMode whistctl_cmode, ProducerCMode whistctl_cmode,
Connection::Order ordering, Connection::Order ordering,
@ -552,7 +552,8 @@ public:
bool updateCrossFlow(bool allow_cross_flow); bool updateCrossFlow(bool allow_cross_flow);
bool updatePVTTable(int pvt_table); bool updatePVTTable(int pvt_table);
bool updateHead(int I, int J); bool updateHead(int I, int J);
bool updateRefDepth(double ref_dpeth); void updateRefDepth();
bool updateRefDepth(const std::optional<double>& ref_dpeth);
bool updateDrainageRadius(double drainage_radius); bool updateDrainageRadius(double drainage_radius);
void updateSegments(std::shared_ptr<WellSegments> segments_arg); void updateSegments(std::shared_ptr<WellSegments> segments_arg);
bool updateConnections(std::shared_ptr<WellConnections> connections); bool updateConnections(std::shared_ptr<WellConnections> connections);
@ -651,7 +652,7 @@ private:
std::size_t insert_index; std::size_t insert_index;
int headI; int headI;
int headJ; int headJ;
double ref_depth; std::optional<double> ref_depth;
double drainage_radius; double drainage_radius;
bool allow_cross_flow; bool allow_cross_flow;
bool automatic_shutin; bool automatic_shutin;

View File

@ -143,6 +143,7 @@ namespace {
} }
void Schedule::handleCOMPDAT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { void Schedule::handleCOMPDAT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
std::unordered_set<std::string> wells;
for (const auto& record : handlerContext.keyword) { for (const auto& record : handlerContext.keyword) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0); const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
auto wellnames = this->wellNames(wellNamePattern, handlerContext.currentStep); auto wellnames = this->wellNames(wellNamePattern, handlerContext.currentStep);
@ -153,14 +154,24 @@ namespace {
auto well2 = std::shared_ptr<Well>(new Well( this->getWell(name, handlerContext.currentStep))); auto well2 = std::shared_ptr<Well>(new Well( this->getWell(name, handlerContext.currentStep)));
auto connections = std::shared_ptr<WellConnections>( new WellConnections( well2->getConnections())); auto connections = std::shared_ptr<WellConnections>( new WellConnections( well2->getConnections()));
connections->loadCOMPDAT(record, handlerContext.grid, handlerContext.fieldPropsManager); connections->loadCOMPDAT(record, handlerContext.grid, handlerContext.fieldPropsManager);
if (well2->updateConnections(connections, handlerContext.grid, handlerContext.fieldPropsManager.get_int("PVTNUM"))) {
if (well2->updateConnections(connections, handlerContext.grid, handlerContext.fieldPropsManager.get_int("PVTNUM")))
this->updateWell(std::move(well2), handlerContext.currentStep); this->updateWell(std::move(well2), handlerContext.currentStep);
wells.insert( name );
}
this->addWellGroupEvent(name, ScheduleEvents::COMPLETION_CHANGE, handlerContext.currentStep); this->addWellGroupEvent(name, ScheduleEvents::COMPLETION_CHANGE, handlerContext.currentStep);
} }
} }
m_events.addEvent(ScheduleEvents::COMPLETION_CHANGE, handlerContext.currentStep); m_events.addEvent(ScheduleEvents::COMPLETION_CHANGE, handlerContext.currentStep);
// In the case the wells reference depth has been defaulted in the
// WELSPECS keyword we need to force a calculation of the wells
// reference depth exactly when the COMPDAT keyword has been completely
// processed.
for (const auto& wname : wells) {
const auto& dynamic_state = this->wells_static.at(wname);
auto& well_ptr = dynamic_state.get(handlerContext.currentStep);
well_ptr->updateRefDepth();
}
} }
void Schedule::handleCOMPLUMP(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { void Schedule::handleCOMPLUMP(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
@ -1200,18 +1211,19 @@ namespace {
const auto& refDepthItem = record.getItem<ParserKeywords::WELSPECS::REF_DEPTH>(); const auto& refDepthItem = record.getItem<ParserKeywords::WELSPECS::REF_DEPTH>();
int pvt_table = record.getItem<ParserKeywords::WELSPECS::P_TABLE>().get<int>(0); int pvt_table = record.getItem<ParserKeywords::WELSPECS::P_TABLE>().get<int>(0);
double drainageRadius = record.getItem<ParserKeywords::WELSPECS::D_RADIUS>().getSIDouble(0); double drainageRadius = record.getItem<ParserKeywords::WELSPECS::D_RADIUS>().getSIDouble(0);
double refDepth = refDepthItem.hasValue(0) std::optional<double> ref_depth;
? refDepthItem.getSIDouble(0) if (refDepthItem.hasValue(0))
: -1.0; ref_depth = refDepthItem.getSIDouble(0);
{ {
bool update = false; bool update = false;
auto well2 = std::shared_ptr<Well>(new Well( this->getWell(wellName, handlerContext.currentStep))); auto well2 = std::shared_ptr<Well>(new Well( this->getWell(wellName, handlerContext.currentStep)));
update = well2->updateHead(headI, headJ); update = well2->updateHead(headI, headJ);
update |= well2->updateRefDepth(refDepth); update |= well2->updateRefDepth(ref_depth);
update |= well2->updateDrainageRadius(drainageRadius); update |= well2->updateDrainageRadius(drainageRadius);
update |= well2->updatePVTTable(pvt_table); update |= well2->updatePVTTable(pvt_table);
if (update) { if (update) {
well2->updateRefDepth();
this->updateWell(std::move(well2), handlerContext.currentStep); this->updateWell(std::move(well2), handlerContext.currentStep);
this->addWellGroupEvent(wellName, ScheduleEvents::WELL_WELSPECS_UPDATE, handlerContext.currentStep); this->addWellGroupEvent(wellName, ScheduleEvents::WELL_WELSPECS_UPDATE, handlerContext.currentStep);
} }

View File

@ -799,9 +799,9 @@ private:
} }
} }
const auto& refDepthItem = record.getItem("REF_DEPTH"); const auto& refDepthItem = record.getItem("REF_DEPTH");
double refDepth = refDepthItem.hasValue( 0 ) std::optional<double> ref_depth;
? refDepthItem.getSIDouble( 0 ) if (refDepthItem.hasValue( 0 ))
: -1.0; ref_depth = refDepthItem.getSIDouble( 0 );
double drainageRadius = record.getItem( "D_RADIUS" ).getSIDouble(0); double drainageRadius = record.getItem( "D_RADIUS" ).getSIDouble(0);
@ -825,7 +825,7 @@ private:
headI, headI,
headJ, headJ,
preferredPhase, preferredPhase,
refDepth, ref_depth,
drainageRadius, drainageRadius,
allowCrossFlow, allowCrossFlow,
automaticShutIn, automaticShutIn,
@ -854,7 +854,7 @@ private:
int headI, int headI,
int headJ, int headJ,
Phase preferredPhase, Phase preferredPhase,
double refDepth, const std::optional<double>& ref_depth,
double drainageRadius, double drainageRadius,
bool allowCrossFlow, bool allowCrossFlow,
bool automaticShutIn, bool automaticShutIn,
@ -869,7 +869,7 @@ private:
timeStep, timeStep,
0, 0,
headI, headJ, headI, headJ,
refDepth, ref_depth,
WellType(preferredPhase), WellType(preferredPhase),
this->global_whistctl_mode[timeStep], this->global_whistctl_mode[timeStep],
wellConnectionOrder, wellConnectionOrder,

View File

@ -309,7 +309,7 @@ Well::Well(const std::string& wname_arg,
std::size_t insert_index_arg, std::size_t insert_index_arg,
int headI_arg, int headI_arg,
int headJ_arg, int headJ_arg,
double ref_depth_arg, const std::optional<double>& ref_depth_arg,
const WellType& wtype_arg, const WellType& wtype_arg,
ProducerCMode whistctl_cmode, ProducerCMode whistctl_cmode,
Connection::Order ordering_arg, Connection::Order ordering_arg,
@ -638,7 +638,7 @@ bool Well::updateStatus(Status well_state, bool update_connections) {
} }
bool Well::updateRefDepth(double ref_depth_arg) { bool Well::updateRefDepth(const std::optional<double>& ref_depth_arg) {
if (this->ref_depth != ref_depth_arg) { if (this->ref_depth != ref_depth_arg) {
this->ref_depth = ref_depth_arg; this->ref_depth = ref_depth_arg;
return true; return true;
@ -798,16 +798,21 @@ bool Well::getAllowCrossFlow() const {
} }
double Well::getRefDepth() const { double Well::getRefDepth() const {
if( this->ref_depth >= 0.0 ) if (!this->ref_depth.has_value())
return this->ref_depth; throw std::logic_error(fmt::format("Well: {} - tried to access not initialized well reference depth", this->name()));
return *this->ref_depth;
}
// ref depth was defaulted and we get the depth of the first completion void Well::updateRefDepth() {
if( this->connections->empty() ) { if( !this->ref_depth ) {
throw std::invalid_argument( "No completions defined for well: " // ref depth was defaulted and we get the depth of the first completion
+ name()
if( this->connections->empty() )
throw std::invalid_argument( "No completions defined for well: "
+ name()
+ ". Can not infer reference depth" ); + ". Can not infer reference depth" );
this->ref_depth = this->connections->get(0).depth();
} }
return this->connections->get(0).depth();
} }

View File

@ -1354,3 +1354,111 @@ END
BOOST_CHECK_MESSAGE(wellP.getConnections() == wellQ.getConnections(), BOOST_CHECK_MESSAGE(wellP.getConnections() == wellQ.getConnections(),
"P and Q must have same WellConnections VALUE"); "P and Q must have same WellConnections VALUE");
} }
BOOST_AUTO_TEST_CASE(REPERF) {
const auto deck = Parser{}.parseString(R"(RUNSPEC
START
7 OCT 2020 /
DIMENS
10 10 4 /
GRID
DXV
10*100.0 /
DYV
10*100.0 /
DZV
4*10.0 /
DEPTHZ
121*2000.0 /
PERMX
400*100.0 /
PERMY
400*100.0 /
PERMZ
400*10.0 /
PORO
400*0.3 /
SCHEDULE
WELSPECS
'W1' 'G' 1 1 1* 'OIL' 2* 'STOP' 4* /
/
COMPDAT
'W1' 1 1 4 4 'OPEN' 1* 34.720 0.216 3095.832 2* 'Y' 12.828 /
'W1' 1 1 3 3 'OPEN' 1* 34.720 0.216 3095.832 2* 'Y' 12.828 /
/
-- W0
TSTEP
1 /
COMPDAT
'W1' 1 1 2 2 'OPEN' 1* 25.620 0.216 2086.842 2* 'Y' 8.486 /
/
-- W1
TSTEP
1 /
WELSPECS
'W1' 'G' 1 1 2005 'LIQ' /
/
-- W2
TSTEP
1 /
WELSPECS
'W1' 'G' 1 1 1* 'LIQ' /
/
-- W3
TSTEP
1 /
COMPDAT
'W1' 1 1 1 1 'OPEN' 1* 25.620 0.216 2086.842 2* 'Y' 8.486 /
/
-- W4
TSTEP
1 /
WELSPECS
'W1' 'G' 1 1 1* 'LIQ' /
/
-- W5
END
)");
const auto es = EclipseState{ deck };
const auto& grid = es.getInputGrid();
const auto sched = Schedule{ deck, es };
const auto& w0 = sched.getWell("W1", 0);
const auto& w1 = sched.getWell("W1", 1);
const auto& w2 = sched.getWell("W1", 2);
const auto& w3 = sched.getWell("W1", 3);
const auto& w4 = sched.getWell("W1", 4);
const auto& w5 = sched.getWell("W1", 5);
BOOST_CHECK_EQUAL(w0.getRefDepth(), grid.getCellDepth(0,0,2));
BOOST_CHECK_EQUAL(w1.getRefDepth(), w0.getRefDepth());
BOOST_CHECK_EQUAL(w2.getRefDepth(), 2005 );
BOOST_CHECK_EQUAL(w3.getRefDepth(), grid.getCellDepth(0,0,1));
BOOST_CHECK_EQUAL(w4.getRefDepth(), w3.getRefDepth());
BOOST_CHECK_EQUAL(w5.getRefDepth(), grid.getCellDepth(0,0,0));
}