reading new tables for grid independent well specification

This commit is contained in:
Paul Egberts 2022-10-25 13:50:02 +02:00
parent 4ee3f9ed3e
commit 2da6dba9af
7 changed files with 237 additions and 1 deletions

View File

@ -731,11 +731,13 @@ namespace Opm
void handleWCONPROD (HandlerContext&);
void handleWECON (HandlerContext&);
void handleWEFAC (HandlerContext&);
void handleWELCOMPL (HandlerContext&);
void handleWELOPEN (HandlerContext&);
void handleWELPI (HandlerContext&);
void handleWELSEGS (HandlerContext&);
void handleWELSPECS (HandlerContext&);
void handleWELTARG (HandlerContext&);
void handleWELTRAJ (HandlerContext&);
void handleWFOAM (HandlerContext&);
void handleWGRUPCON (HandlerContext&);
void handleWHISTCTL (HandlerContext&);

View File

@ -88,6 +88,12 @@ namespace Opm {
const std::string& wname,
const KeywordLocation& location);
void loadWELCOMPL(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, const KeywordLocation& location);
void loadWELTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, const KeywordLocation& location);
using const_iterator = std::vector< Connection >::const_iterator;
void add(Connection);
std::size_t size() const;
bool empty() const;
@ -182,6 +188,12 @@ namespace Opm {
void orderTRACK();
void orderMSW();
void orderDEPTH();
Connection::Order m_ordering = Connection::Order::TRACK;
int headI, headJ;
std::vector< Connection > m_connections;
double x_coordinate;
};
std::optional<int>

View File

@ -179,6 +179,83 @@ namespace {
}
}
void Schedule::handleWELTRAJ(HandlerContext& handlerContext) {
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 );
for (const auto& name : wellnames) {
auto well2 = this->snapshots.back().wells.get(name);
auto connections = std::shared_ptr<WellConnections>( new WellConnections( well2.getConnections()));
connections->loadWELTRAJ(record, handlerContext.grid, name, handlerContext.keyword.location());
//what to do here? need here something like updateTrajectory
//maybe new method WellConnection::addTrajectory?
if (well2.updateConnections(connections, handlerContext.grid)) {
this->snapshots.back().wells.update( well2 );
wells.insert( name );
}
if (connections->empty() && well2.getConnections().empty()) {
const auto& location = handlerContext.keyword.location();
auto msg = fmt::format("Problem with COMPDAT/{}\n"
"In {} line {}\n"
"Well {} is not connected to grid - will remain SHUT", name, location.filename, location.lineno, name);
OpmLog::warning(msg);
}
this->snapshots.back().wellgroup_events().addEvent( name, ScheduleEvents::COMPLETION_CHANGE);
}
}
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
// 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) {
// auto& well = this->snapshots.back().wells.get( wname );
// well.updateRefDepth();
// this->snapshots.back().wells.update( std::move(well));
// }
}
void Schedule::handleWELCOMPL(HandlerContext& handlerContext) {
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 );
for (const auto& name : wellnames) {
auto well2 = this->snapshots.back().wells.get(name);
auto connections = std::shared_ptr<WellConnections>( new WellConnections( well2.getConnections()));
connections->loadWELCOMPL(record, handlerContext.grid, name, handlerContext.keyword.location());
// if (well2.updateConnections(connections, handlerContext.grid)) {
// this->snapshots.back().wells.update( well2 );
// wells.insert( name );
// }
// if (connections->empty() && well2.getConnections().empty()) {
// const auto& location = handlerContext.keyword.location();
// auto msg = fmt::format("Problem with COMPDAT/{}\n"
// "In {} line {}\n"
// "Well {} is not connected to grid - will remain SHUT", name, location.filename, location.lineno, name);
// OpmLog::warning(msg);
// }
// this->snapshots.back().wellgroup_events().addEvent( name, ScheduleEvents::COMPLETION_CHANGE);
}
}
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
// 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) {
// auto& well = this->snapshots.back().wells.get( wname );
// well.updateRefDepth();
// this->snapshots.back().wells.update( std::move(well));
// }
}
void Schedule::handleCOMPLUMP(HandlerContext& handlerContext) {
for (const auto& record : handlerContext.keyword) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
@ -2298,11 +2375,13 @@ Well{0} entered with disallowed 'FIELD' parent group:
{ "WCONPROD", &Schedule::handleWCONPROD },
{ "WECON" , &Schedule::handleWECON },
{ "WEFAC" , &Schedule::handleWEFAC },
{ "WELCOMPL", &Schedule::handleWELCOMPL },
{ "WELOPEN" , &Schedule::handleWELOPEN },
{ "WELPI" , &Schedule::handleWELPI },
{ "WELSEGS" , &Schedule::handleWELSEGS },
{ "WELSPECS", &Schedule::handleWELSPECS },
{ "WELTARG" , &Schedule::handleWELTARG },
{ "WELTRAJ" , &Schedule::handleWELTRAJ },
{ "WFOAM" , &Schedule::handleWFOAM },
{ "WGRUPCON", &Schedule::handleWGRUPCON },
{ "WHISTCTL", &Schedule::handleWHISTCTL },

View File

@ -1,4 +1,4 @@
/*
/*addConnectioncell
Copyright 2013 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
@ -46,6 +46,18 @@
#include <vector>
#include <stddef.h>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/common/utility/ActiveGridCells.hpp>
#include <opm/input/eclipse/Units/Units.hpp>
#include <opm/io/eclipse/rst/connection.hpp>
#include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
#include <opm/input/eclipse/Schedule/VFPInjTable.hpp> //testing
#include <fmt/format.h>
@ -441,6 +453,55 @@ namespace Opm {
}
}
}
void WellConnections::loadWELCOMPL(const DeckRecord& record,
const ScheduleGrid& grid,
const std::string& wname,
const KeywordLocation& location) {
const std::string& completionNamePattern = record.getItem("COMPLETION").getTrimmedString(0);
//Connection::State state = Connection::StateFromString( record.getItem("STATE").getTrimmedString(0) );
//based on the data of wellCOMPL and trajectory data the ijk coordinates should be derived here.
//unclear how to get trajectory data in this method
const auto& ahdepth_upper = record.getItem("AHDEPTH_UPPER");
const auto& ahdepth_lower = record.getItem("AHDEPTH_LOWER");
const auto& diameterItem = record.getItem("DIAMETER");
double skin_factor = record.getItem("SKIN").getSIDouble(0);
double rw;
if (diameterItem.hasValue(0))
rw = 0.50 * diameterItem.getSIDouble(0);
else
// The Eclipse100 manual does not specify a default value for the wellbore
// diameter, but the Opm codebase has traditionally implemented a default
// value of one foot. The same default value is used by Eclipse300.
rw = 0.5*unit::feet;
//const auto& test = grid.cells;
}
void WellConnections::loadWELTRAJ(const DeckRecord& record,
const ScheduleGrid& grid,
const std::string& wname,
const KeywordLocation& location) {
//const std::string& completionNamePattern = record.getItem("COMPLETION").getTrimmedString(0);
//Connection::State state = Connection::StateFromString( record.getItem("STATE").getTrimmedString(0) );
////should we use loadWELTRAJ we may assume (?) that only once a trajectory is created?
//(1) how to store data read in here????
//(2) how to get info from here to loadWELCOMPL???????
this->x_coordinate = record.getItem("X").getSIDouble(0);
const auto& y_coordinate = record.getItem("Y");
const int I = 8;
const int J = 8;
const int K = 2;
const CompletedCells::Cell& cell = grid.get_cell(I, J, K);
}
std::size_t WellConnections::size() const {
return m_connections.size();

View File

@ -0,0 +1,43 @@
{
"name": "WELCOMPL",
"sections": [
"SCHEDULE"
],
"items": [
{
"item": 1,
"name": "WELL",
"value_type": "STRING"
},
{
"item": 2,
"name": "COMPLETION",
"value_type": "STRING"
},
{
"item": 3,
"name": "AHDEPTH_UPPER",
"value_type": "DOUBLE",
"dimension": "Length"
},
{
"item": 4,
"name": "AHDEPTH_LOWER",
"value_type": "DOUBLE",
"dimension": "Length"
},
{
"item": 5,
"name": "DIAMETER",
"value_type": "DOUBLE",
"dimension": "Length"
},
{
"item": 6,
"name": "SKIN",
"value_type": "DOUBLE",
"dimension": "1"
}
]
}

View File

@ -0,0 +1,37 @@
{
"name": "WELTRAJ",
"sections": [
"SCHEDULE"
],
"items": [
{
"item": 1,
"name": "WELL",
"value_type": "STRING"
},
{
"item": 2,
"name": "X",
"value_type": "DOUBLE",
"dimension": "Length"
},
{
"item": 3,
"name": "Y",
"value_type": "DOUBLE",
"dimension": "Length"
},
{
"item": 4,
"name": "TVDEPTH",
"value_type": "DOUBLE",
"dimension": "Length"
},
{
"item": 5,
"name": "AHDEPTH",
"value_type": "DOUBLE",
"dimension": "Length"
}
]
}

View File

@ -1135,6 +1135,8 @@ set( keywords
900_OPM/T/TLPMIXPA
900_OPM/V/VAPWAT
900_OPM/W/WATJT
900_OPM/W/WELTRAJ
900_OPM/W/WELCOMPL
900_OPM/W/WMICP
900_OPM/W/WPMITAB
900_OPM/W/WSKPTAB)