Merge pull request #2042 from joakim-hove/well-reperf
Changes to well reference depth
This commit is contained in:
commit
9fc6948e05
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user