mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 06:38:13 -05:00
Sector export: Split COMPSEGS MD interval in the direction the well travels through the refined cell
This commit is contained in:
1 parent
b84eea5cb1
commit
2a8cd7856b
3 files changed
+175
-9
No files matched your search
@@ -64,6 +64,7 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include <set>
|
||||
@@ -1508,6 +1509,15 @@ RigSimulationInputTool::ConnectionCellPropertiesProvider RigSimulationInputTool:
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigSimulationInputTool::ConnectionKey::operator<( const ConnectionKey& other ) const
|
||||
{
|
||||
return std::make_tuple( wellName, ijk.x(), ijk.y(), ijk.z() ) <
|
||||
std::make_tuple( other.wellName, other.ijk.x(), other.ijk.y(), other.ijk.z() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1535,7 +1545,7 @@ RigSimulationInputTool::ConnectionDirectionMap RigSimulationInputTool::connectio
|
||||
const auto dim = compdatPenetrationDimension( record );
|
||||
for ( int k = k1; k <= k2; ++k )
|
||||
{
|
||||
directions[{ wellName, static_cast<size_t>( i ), static_cast<size_t>( j ), static_cast<size_t>( k ) }] = dim;
|
||||
directions[{ wellName, caf::VecIjk0( i, j, k ) }] = dim;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1543,6 +1553,77 @@ RigSimulationInputTool::ConnectionDirectionMap RigSimulationInputTool::connectio
|
||||
return directions;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Cells where the well travels towards decreasing index along the connection penetration direction,
|
||||
/// determined from the neighbouring COMPSEGS cells on the same branch sorted by measured depth
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigSimulationInputTool::ConnectionKeySet RigSimulationInputTool::reversedSegmentCells( const std::vector<Opm::DeckKeyword>& compsegsKeywords,
|
||||
const ConnectionDirectionMap& directions )
|
||||
{
|
||||
struct SegmentCell
|
||||
{
|
||||
double startMd = 0.0;
|
||||
caf::VecIjk0 ijk;
|
||||
};
|
||||
|
||||
ConnectionKeySet reversed;
|
||||
|
||||
for ( const auto& keyword : compsegsKeywords )
|
||||
{
|
||||
if ( keyword.size() < 2 ) continue;
|
||||
|
||||
const auto& wellItem = keyword.getRecord( 0 ).getItem( 0 );
|
||||
if ( !wellItem.hasValue( 0 ) || wellItem.getType() != Opm::type_tag::string ) continue;
|
||||
const auto wellName = wellItem.get<std::string>( 0 );
|
||||
|
||||
std::map<int, std::vector<SegmentCell>> cellsPerBranch;
|
||||
for ( size_t r = 1; r < keyword.size(); ++r )
|
||||
{
|
||||
const auto& record = keyword.getRecord( r );
|
||||
if ( record.size() < 6 ) continue;
|
||||
if ( !record.getItem( 0 ).hasValue( 0 ) || !record.getItem( 1 ).hasValue( 0 ) || !record.getItem( 2 ).hasValue( 0 ) ) continue;
|
||||
if ( !record.getItem( 4 ).hasValue( 0 ) ) continue;
|
||||
|
||||
const int i = record.getItem( 0 ).get<int>( 0 ) - 1;
|
||||
const int j = record.getItem( 1 ).get<int>( 0 ) - 1;
|
||||
const int k = record.getItem( 2 ).get<int>( 0 ) - 1;
|
||||
if ( i < 0 || j < 0 || k < 0 ) continue;
|
||||
|
||||
const int branch = record.getItem( 3 ).hasValue( 0 ) ? record.getItem( 3 ).get<int>( 0 ) : 0;
|
||||
cellsPerBranch[branch].push_back( { record.getItem( 4 ).get<double>( 0 ), caf::VecIjk0( i, j, k ) } );
|
||||
}
|
||||
|
||||
for ( auto& [branch, cells] : cellsPerBranch )
|
||||
{
|
||||
std::stable_sort( cells.begin(), cells.end(), []( const SegmentCell& a, const SegmentCell& b ) { return a.startMd < b.startMd; } );
|
||||
|
||||
for ( size_t c = 0; c < cells.size(); ++c )
|
||||
{
|
||||
const auto& ijk = cells[c].ijk;
|
||||
const auto key = ConnectionKey{ wellName, ijk };
|
||||
|
||||
auto dim = RigRefinement::DimK;
|
||||
if ( auto it = directions.find( key ); it != directions.end() ) dim = it->second;
|
||||
|
||||
// Prefer the next cell along the well, fall back to the previous cell
|
||||
std::optional<bool> isReversed;
|
||||
if ( c + 1 < cells.size() && cells[c + 1].ijk[dim] != ijk[dim] )
|
||||
{
|
||||
isReversed = cells[c + 1].ijk[dim] < ijk[dim];
|
||||
}
|
||||
else if ( c > 0 && cells[c - 1].ijk[dim] != ijk[dim] )
|
||||
{
|
||||
isReversed = ijk[dim] < cells[c - 1].ijk[dim];
|
||||
}
|
||||
|
||||
if ( isReversed.value_or( false ) ) reversed.insert( key );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reversed;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1757,7 +1838,8 @@ std::expected<std::vector<Opm::DeckRecord>, QString> RigSimulationInputTool::pro
|
||||
const std::string& wellName,
|
||||
bool isWellNameRecord,
|
||||
const RigSimulationInputSettings& settings,
|
||||
const ConnectionDirectionMap& directions )
|
||||
const ConnectionDirectionMap& directions,
|
||||
const ConnectionKeySet& reversedCells )
|
||||
{
|
||||
// COMPSEGS format: first record is well name, subsequent records are segment data
|
||||
// Well name record: just copy as-is
|
||||
@@ -1788,7 +1870,7 @@ std::expected<std::vector<Opm::DeckRecord>, QString> RigSimulationInputTool::pro
|
||||
}
|
||||
|
||||
auto dim = RigRefinement::DimK;
|
||||
if ( auto it = directions.find( { wellName, origIjk.x(), origIjk.y(), origIjk.z() } ); it != directions.end() )
|
||||
if ( auto it = directions.find( { wellName, origIjk } ); it != directions.end() )
|
||||
{
|
||||
dim = it->second;
|
||||
}
|
||||
@@ -1804,6 +1886,12 @@ std::expected<std::vector<Opm::DeckRecord>, QString> RigSimulationInputTool::pro
|
||||
if ( hasMdInterval && !isCellRange )
|
||||
{
|
||||
subcells = allSubcells( refinement, dim, sectorIndex );
|
||||
|
||||
// Assign the MD interval in the order the well travels through the sub-cells
|
||||
if ( reversedCells.contains( { wellName, origIjk } ) )
|
||||
{
|
||||
std::reverse( subcells.begin(), subcells.end() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2588,7 +2676,8 @@ std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords
|
||||
"WTEMP", "WTEST", "WTRACER", "WSEGVALV", "WSEGAICD", "WSEGSICD" };
|
||||
|
||||
// Collect connection directions from the original COMPDAT before it is transformed, used to split COMPSEGS
|
||||
const auto directions = connectionDirections( deckFile.findAllKeywords( "COMPDAT" ) );
|
||||
const auto directions = connectionDirections( deckFile.findAllKeywords( "COMPDAT" ) );
|
||||
const auto reversedCells = reversedSegmentCells( deckFile.findAllKeywords( "COMPSEGS" ), directions );
|
||||
|
||||
const auto cellProperties = connectionCellPropertiesProvider( eclipseCase );
|
||||
|
||||
@@ -2685,7 +2774,7 @@ std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords
|
||||
}
|
||||
else if ( keywordName == "COMPSEGS" )
|
||||
{
|
||||
auto result = processCompsegsRecord( record, wellName, isWellNameRecord, settings, directions );
|
||||
auto result = processCompsegsRecord( record, wellName, isWellNameRecord, settings, directions, reversedCells );
|
||||
if ( result )
|
||||
{
|
||||
for ( auto& rec : result.value() )
|
||||
|
||||
@@ -105,11 +105,24 @@ public:
|
||||
static std::expected<Opm::DeckRecord, QString>
|
||||
processAqunumRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const RigRefinement& refinement );
|
||||
|
||||
// Penetration direction of well connections, keyed on (well name, original 0-based I, J, K)
|
||||
using ConnectionDirectionMap = std::map<std::tuple<std::string, size_t, size_t, size_t>, RigRefinement::Dimension>;
|
||||
// Penetration direction of well connections, keyed on (well name, original 0-based IJK)
|
||||
struct ConnectionKey
|
||||
{
|
||||
std::string wellName;
|
||||
caf::VecIjk0 ijk;
|
||||
|
||||
bool operator<( const ConnectionKey& other ) const;
|
||||
};
|
||||
using ConnectionKeySet = std::set<ConnectionKey>;
|
||||
using ConnectionDirectionMap = std::map<ConnectionKey, RigRefinement::Dimension>;
|
||||
|
||||
static ConnectionDirectionMap connectionDirections( const std::vector<Opm::DeckKeyword>& compdatKeywords );
|
||||
|
||||
// Segment cells (well name, original 0-based IJK) where the well travels towards decreasing index along the
|
||||
// connection penetration direction, derived from neighbouring COMPSEGS cells on the same branch ordered by MD
|
||||
static ConnectionKeySet reversedSegmentCells( const std::vector<Opm::DeckKeyword>& compsegsKeywords,
|
||||
const ConnectionDirectionMap& directions );
|
||||
|
||||
// Size and permeability of an original grid cell, ordered I/X, J/Y, K/Z
|
||||
struct ConnectionCellProperties
|
||||
{
|
||||
@@ -130,12 +143,13 @@ public:
|
||||
const ConnectionCellPropertiesProvider& cellProperties = {} );
|
||||
|
||||
// Segment records are split into one record per sub-cell along the connection penetration direction,
|
||||
// with the MD interval divided by the sub-cell length fractions
|
||||
// with the MD interval divided by the sub-cell length fractions in the order the well travels through them
|
||||
static std::expected<std::vector<Opm::DeckRecord>, QString> processCompsegsRecord( const Opm::DeckRecord& record,
|
||||
const std::string& wellName,
|
||||
bool isWellNameRecord,
|
||||
const RigSimulationInputSettings& settings,
|
||||
const ConnectionDirectionMap& directions );
|
||||
const ConnectionDirectionMap& directions,
|
||||
const ConnectionKeySet& reversedCells = {} );
|
||||
|
||||
static std::vector<int> createRefinedVisibility( const RigGridExportAdapter& gridAdapter );
|
||||
|
||||
|
||||
Reference in new issue
Block a user