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 headJ,
|
||||
Phase preferredPhase,
|
||||
double refDepth,
|
||||
const std::optional<double>& refDepth,
|
||||
double drainageRadius,
|
||||
bool allowCrossFlow,
|
||||
bool automaticShutIn,
|
||||
|
@ -463,7 +463,7 @@ public:
|
||||
std::size_t insert_index,
|
||||
int headI,
|
||||
int headJ,
|
||||
double ref_depth,
|
||||
const std::optional<double>& ref_depth,
|
||||
const WellType& wtype_arg,
|
||||
ProducerCMode whistctl_cmode,
|
||||
Connection::Order ordering,
|
||||
@ -552,7 +552,8 @@ public:
|
||||
bool updateCrossFlow(bool allow_cross_flow);
|
||||
bool updatePVTTable(int pvt_table);
|
||||
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);
|
||||
void updateSegments(std::shared_ptr<WellSegments> segments_arg);
|
||||
bool updateConnections(std::shared_ptr<WellConnections> connections);
|
||||
@ -651,7 +652,7 @@ private:
|
||||
std::size_t insert_index;
|
||||
int headI;
|
||||
int headJ;
|
||||
double ref_depth;
|
||||
std::optional<double> ref_depth;
|
||||
double drainage_radius;
|
||||
bool allow_cross_flow;
|
||||
bool automatic_shutin;
|
||||
|
@ -143,6 +143,7 @@ namespace {
|
||||
}
|
||||
|
||||
void Schedule::handleCOMPDAT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
std::unordered_set<std::string> wells;
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
||||
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 connections = std::shared_ptr<WellConnections>( new WellConnections( well2->getConnections()));
|
||||
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);
|
||||
|
||||
wells.insert( name );
|
||||
}
|
||||
this->addWellGroupEvent(name, 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&) {
|
||||
@ -1200,18 +1211,19 @@ namespace {
|
||||
const auto& refDepthItem = record.getItem<ParserKeywords::WELSPECS::REF_DEPTH>();
|
||||
int pvt_table = record.getItem<ParserKeywords::WELSPECS::P_TABLE>().get<int>(0);
|
||||
double drainageRadius = record.getItem<ParserKeywords::WELSPECS::D_RADIUS>().getSIDouble(0);
|
||||
double refDepth = refDepthItem.hasValue(0)
|
||||
? refDepthItem.getSIDouble(0)
|
||||
: -1.0;
|
||||
std::optional<double> ref_depth;
|
||||
if (refDepthItem.hasValue(0))
|
||||
ref_depth = refDepthItem.getSIDouble(0);
|
||||
{
|
||||
bool update = false;
|
||||
auto well2 = std::shared_ptr<Well>(new Well( this->getWell(wellName, handlerContext.currentStep)));
|
||||
update = well2->updateHead(headI, headJ);
|
||||
update |= well2->updateRefDepth(refDepth);
|
||||
update = well2->updateHead(headI, headJ);
|
||||
update |= well2->updateRefDepth(ref_depth);
|
||||
update |= well2->updateDrainageRadius(drainageRadius);
|
||||
update |= well2->updatePVTTable(pvt_table);
|
||||
|
||||
if (update) {
|
||||
well2->updateRefDepth();
|
||||
this->updateWell(std::move(well2), handlerContext.currentStep);
|
||||
this->addWellGroupEvent(wellName, ScheduleEvents::WELL_WELSPECS_UPDATE, handlerContext.currentStep);
|
||||
}
|
||||
|
@ -799,9 +799,9 @@ private:
|
||||
}
|
||||
}
|
||||
const auto& refDepthItem = record.getItem("REF_DEPTH");
|
||||
double refDepth = refDepthItem.hasValue( 0 )
|
||||
? refDepthItem.getSIDouble( 0 )
|
||||
: -1.0;
|
||||
std::optional<double> ref_depth;
|
||||
if (refDepthItem.hasValue( 0 ))
|
||||
ref_depth = refDepthItem.getSIDouble( 0 );
|
||||
|
||||
double drainageRadius = record.getItem( "D_RADIUS" ).getSIDouble(0);
|
||||
|
||||
@ -825,7 +825,7 @@ private:
|
||||
headI,
|
||||
headJ,
|
||||
preferredPhase,
|
||||
refDepth,
|
||||
ref_depth,
|
||||
drainageRadius,
|
||||
allowCrossFlow,
|
||||
automaticShutIn,
|
||||
@ -854,7 +854,7 @@ private:
|
||||
int headI,
|
||||
int headJ,
|
||||
Phase preferredPhase,
|
||||
double refDepth,
|
||||
const std::optional<double>& ref_depth,
|
||||
double drainageRadius,
|
||||
bool allowCrossFlow,
|
||||
bool automaticShutIn,
|
||||
@ -869,7 +869,7 @@ private:
|
||||
timeStep,
|
||||
0,
|
||||
headI, headJ,
|
||||
refDepth,
|
||||
ref_depth,
|
||||
WellType(preferredPhase),
|
||||
this->global_whistctl_mode[timeStep],
|
||||
wellConnectionOrder,
|
||||
|
@ -309,7 +309,7 @@ Well::Well(const std::string& wname_arg,
|
||||
std::size_t insert_index_arg,
|
||||
int headI_arg,
|
||||
int headJ_arg,
|
||||
double ref_depth_arg,
|
||||
const std::optional<double>& ref_depth_arg,
|
||||
const WellType& wtype_arg,
|
||||
ProducerCMode whistctl_cmode,
|
||||
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) {
|
||||
this->ref_depth = ref_depth_arg;
|
||||
return true;
|
||||
@ -798,16 +798,21 @@ bool Well::getAllowCrossFlow() const {
|
||||
}
|
||||
|
||||
double Well::getRefDepth() const {
|
||||
if( this->ref_depth >= 0.0 )
|
||||
return this->ref_depth;
|
||||
if (!this->ref_depth.has_value())
|
||||
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
|
||||
if( this->connections->empty() ) {
|
||||
throw std::invalid_argument( "No completions defined for well: "
|
||||
+ name()
|
||||
void Well::updateRefDepth() {
|
||||
if( !this->ref_depth ) {
|
||||
// ref depth was defaulted and we get the depth of the first completion
|
||||
|
||||
if( this->connections->empty() )
|
||||
throw std::invalid_argument( "No completions defined for well: "
|
||||
+ name()
|
||||
+ ". 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(),
|
||||
"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