mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-27 05:37:21 -05:00
Refactor: move transformIjkToSectorCoordinates and add tests.
This commit is contained in:
@@ -516,8 +516,10 @@ std::expected<void, QString> RicExportEclipseSectorModelFeature::addBorderBounda
|
||||
// Transform border cell face coordinates to sector-relative coordinates
|
||||
for ( auto& face : borderCellFaces )
|
||||
{
|
||||
auto transformResult =
|
||||
transformIjkToSectorCoordinates( face.ijk, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResult = RigGridExportAdapter::transformIjkToSectorCoordinates( face.ijk,
|
||||
exportSettings.min(),
|
||||
exportSettings.max(),
|
||||
exportSettings.refinement() );
|
||||
|
||||
if ( !transformResult )
|
||||
{
|
||||
@@ -530,8 +532,8 @@ std::expected<void, QString> RicExportEclipseSectorModelFeature::addBorderBounda
|
||||
}
|
||||
|
||||
// Update the IJK coordinates to sector-relative (1-based Eclipse coordinates)
|
||||
// Note: transformIjkToSectorCoordinates returns 1-based coordinates, but we need to convert back to 0-based
|
||||
// for the BorderCellFace struct
|
||||
// Note: RigGridExportAdapter::transformIjkToSectorCoordinates returns 1-based coordinates, but we need to convert back to
|
||||
// 0-based for the BorderCellFace struct
|
||||
face.ijk = cvf::Vec3st( transformResult->x() - 1, transformResult->y() - 1, transformResult->z() - 1 );
|
||||
}
|
||||
|
||||
@@ -848,36 +850,6 @@ std::vector<RigSimWellData*>
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<cvf::Vec3st, QString> RicExportEclipseSectorModelFeature::transformIjkToSectorCoordinates( const cvf::Vec3st& originalIjk,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement )
|
||||
{
|
||||
// Check if original IJK is within the sector bounds
|
||||
if ( originalIjk.x() < min.x() || originalIjk.x() > max.x() || originalIjk.y() < min.y() || originalIjk.y() > max.y() ||
|
||||
originalIjk.z() < min.z() || originalIjk.z() > max.z() )
|
||||
{
|
||||
return std::unexpected( QString( "IJK coordinates (%1, %2, %3) are outside sector bounds [(%4, %5, %6), (%7, %8, %9)]" )
|
||||
.arg( originalIjk.x() )
|
||||
.arg( originalIjk.y() )
|
||||
.arg( originalIjk.z() )
|
||||
.arg( min.x() )
|
||||
.arg( min.y() )
|
||||
.arg( min.z() )
|
||||
.arg( max.x() )
|
||||
.arg( max.y() )
|
||||
.arg( max.z() ) );
|
||||
}
|
||||
|
||||
// Transform to sector-relative coordinates with refinement
|
||||
// Eclipse uses 1-based indexing, so we'll return 1-based coordinates
|
||||
cvf::Vec3st sectorIjk;
|
||||
sectorIjk.x() = ( originalIjk.x() - min.x() ) * refinement.x() + 1;
|
||||
sectorIjk.y() = ( originalIjk.y() - min.y() ) * refinement.y() + 1;
|
||||
sectorIjk.z() = ( originalIjk.z() - min.z() ) * refinement.z() + 1;
|
||||
|
||||
return sectorIjk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@@ -970,13 +942,17 @@ std::expected<Opm::DeckRecord, QString>
|
||||
|
||||
// Transform K1
|
||||
cvf::Vec3st origIjkK1( origI, origJ, origK1 );
|
||||
auto transformResultK1 =
|
||||
transformIjkToSectorCoordinates( origIjkK1, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResultK1 = RigGridExportAdapter::transformIjkToSectorCoordinates( origIjkK1,
|
||||
exportSettings.min(),
|
||||
exportSettings.max(),
|
||||
exportSettings.refinement() );
|
||||
|
||||
// Transform K2
|
||||
cvf::Vec3st origIjkK2( origI, origJ, origK2 );
|
||||
auto transformResultK2 =
|
||||
transformIjkToSectorCoordinates( origIjkK2, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResultK2 = RigGridExportAdapter::transformIjkToSectorCoordinates( origIjkK2,
|
||||
exportSettings.min(),
|
||||
exportSettings.max(),
|
||||
exportSettings.refinement() );
|
||||
|
||||
if ( !transformResultK1 )
|
||||
{
|
||||
@@ -1038,7 +1014,8 @@ std::expected<Opm::DeckRecord, QString>
|
||||
int origK = record.getItem( 2 ).get<int>( 0 ) - 1;
|
||||
|
||||
cvf::Vec3st origIjk( origI, origJ, origK );
|
||||
auto transformResult = transformIjkToSectorCoordinates( origIjk, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResult =
|
||||
RigGridExportAdapter::transformIjkToSectorCoordinates( origIjk, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
|
||||
if ( !transformResult )
|
||||
{
|
||||
@@ -1136,8 +1113,10 @@ std::expected<Opm::DeckRecord, QString>
|
||||
.arg( corner2.z() + 1 ) );
|
||||
}
|
||||
|
||||
auto transformResult1 = transformIjkToSectorCoordinates( corner1, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResult2 = transformIjkToSectorCoordinates( corner2, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResult1 =
|
||||
RigGridExportAdapter::transformIjkToSectorCoordinates( corner1, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
auto transformResult2 =
|
||||
RigGridExportAdapter::transformIjkToSectorCoordinates( corner2, exportSettings.min(), exportSettings.max(), exportSettings.refinement() );
|
||||
|
||||
if ( !transformResult1 )
|
||||
{
|
||||
|
||||
@@ -95,11 +95,6 @@ private:
|
||||
|
||||
static std::vector<RigSimWellData*> findIntersectingWells( RimEclipseCase* eclipseCase, const cvf::Vec3st& min, const cvf::Vec3st& max );
|
||||
|
||||
static std::expected<cvf::Vec3st, QString> transformIjkToSectorCoordinates( const cvf::Vec3st& originalIjk,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement );
|
||||
|
||||
static std::expected<Opm::DeckRecord, QString> processWelspecsRecord( const Opm::DeckRecord& record,
|
||||
const std::string& wellName,
|
||||
const RicExportEclipseSectorModelUi& exportSettings );
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include "cvfAssert.h"
|
||||
#include "cvfStructGrid.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Generate refined cell corners using trilinear interpolation within the original cell
|
||||
/// This ensures refined cells are strictly contained within the original cell bounds
|
||||
@@ -415,3 +417,38 @@ size_t RigGridExportAdapter::totalCells() const
|
||||
{
|
||||
return m_refinedNI * m_refinedNJ * m_refinedNK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Transform IJK coordinates from global grid space to sector-relative space with refinement
|
||||
/// Returns 1-based Eclipse coordinates
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<cvf::Vec3st, QString> RigGridExportAdapter::transformIjkToSectorCoordinates( const cvf::Vec3st& originalIjk,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement )
|
||||
{
|
||||
// Check if original IJK is within the sector bounds
|
||||
if ( originalIjk.x() < min.x() || originalIjk.x() > max.x() || originalIjk.y() < min.y() || originalIjk.y() > max.y() ||
|
||||
originalIjk.z() < min.z() || originalIjk.z() > max.z() )
|
||||
{
|
||||
return std::unexpected( QString( "IJK coordinates (%1, %2, %3) are outside sector bounds [(%4, %5, %6), (%7, %8, %9)]" )
|
||||
.arg( originalIjk.x() )
|
||||
.arg( originalIjk.y() )
|
||||
.arg( originalIjk.z() )
|
||||
.arg( min.x() )
|
||||
.arg( min.y() )
|
||||
.arg( min.z() )
|
||||
.arg( max.x() )
|
||||
.arg( max.y() )
|
||||
.arg( max.z() ) );
|
||||
}
|
||||
|
||||
// Transform to sector-relative coordinates with refinement
|
||||
// Eclipse uses 1-based indexing, so we'll return 1-based coordinates
|
||||
cvf::Vec3st sectorIjk;
|
||||
sectorIjk.x() = ( originalIjk.x() - min.x() ) * refinement.x() + 1;
|
||||
sectorIjk.y() = ( originalIjk.y() - min.y() ) * refinement.y() + 1;
|
||||
sectorIjk.z() = ( originalIjk.z() - min.z() ) * refinement.z() + 1;
|
||||
|
||||
return sectorIjk;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
#include "cvfVector3.h"
|
||||
|
||||
#include <array>
|
||||
#include <expected>
|
||||
|
||||
class RigEclipseCaseData;
|
||||
class RigMainGrid;
|
||||
class RigActiveCellInfo;
|
||||
class QString;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
@@ -84,6 +86,12 @@ public:
|
||||
cvf::Vec3st refinement() const;
|
||||
bool hasRefinement() const;
|
||||
|
||||
// Coordinate transformation utilities
|
||||
static std::expected<cvf::Vec3st, QString> transformIjkToSectorCoordinates( const cvf::Vec3st& originalIjk,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement );
|
||||
|
||||
private:
|
||||
// Internal methods to handle original vs refined cell access
|
||||
std::array<cvf::Vec3d, 8> getOriginalCellCorners( size_t origI, size_t origJ, size_t origK ) const;
|
||||
|
||||
@@ -663,3 +663,158 @@ TEST( RigGridExportAdapterTest, RefinedCellsContainOriginalCorners )
|
||||
EXPECT_TRUE( cornerFound[i] ) << "Original corner " << i << " was not found in any refined cell";
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test coordinate transformation without refinement (refinement = 1,1,1)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigGridExportAdapter, TransformIjkToSectorCoordinates_NoRefinement )
|
||||
{
|
||||
cvf::Vec3st min( 3, 3, 1 );
|
||||
cvf::Vec3st max( 10, 10, 5 );
|
||||
cvf::Vec3st refinement( 1, 1, 1 );
|
||||
|
||||
// Point at sector min should transform to (1,1,1)
|
||||
auto result1 = RigGridExportAdapter::transformIjkToSectorCoordinates( min, min, max, refinement );
|
||||
EXPECT_TRUE( result1.has_value() );
|
||||
EXPECT_EQ( cvf::Vec3st( 1, 1, 1 ), result1.value() );
|
||||
|
||||
// Point at sector max should transform correctly
|
||||
auto result2 = RigGridExportAdapter::transformIjkToSectorCoordinates( max, min, max, refinement );
|
||||
EXPECT_TRUE( result2.has_value() );
|
||||
EXPECT_EQ( cvf::Vec3st( 8, 8, 5 ), result2.value() ); // (10-3)*1+1 = 8
|
||||
|
||||
// Point in middle of sector
|
||||
cvf::Vec3st middle( 5, 5, 3 );
|
||||
auto result3 = RigGridExportAdapter::transformIjkToSectorCoordinates( middle, min, max, refinement );
|
||||
EXPECT_TRUE( result3.has_value() );
|
||||
EXPECT_EQ( cvf::Vec3st( 3, 3, 3 ), result3.value() ); // (5-3)*1+1 = 3
|
||||
|
||||
// Test different point
|
||||
cvf::Vec3st point( 7, 6, 2 );
|
||||
auto result4 = RigGridExportAdapter::transformIjkToSectorCoordinates( point, min, max, refinement );
|
||||
EXPECT_TRUE( result4.has_value() );
|
||||
EXPECT_EQ( cvf::Vec3st( 5, 4, 2 ), result4.value() ); // (7-3)*1+1=5, (6-3)*1+1=4, (2-1)*1+1=2
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test coordinate transformation with out-of-bounds detection
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigGridExportAdapter, TransformIjkToSectorCoordinates_OutOfBounds )
|
||||
{
|
||||
cvf::Vec3st min( 3, 3, 1 );
|
||||
cvf::Vec3st max( 10, 10, 5 );
|
||||
cvf::Vec3st refinement( 1, 1, 1 );
|
||||
|
||||
// Point before sector min (X too small)
|
||||
cvf::Vec3st point1( 2, 5, 3 );
|
||||
auto result1 = RigGridExportAdapter::transformIjkToSectorCoordinates( point1, min, max, refinement );
|
||||
EXPECT_FALSE( result1.has_value() );
|
||||
EXPECT_TRUE( result1.error().contains( "outside sector bounds" ) );
|
||||
|
||||
// Point after sector max (X too large)
|
||||
cvf::Vec3st point2( 11, 5, 3 );
|
||||
auto result2 = RigGridExportAdapter::transformIjkToSectorCoordinates( point2, min, max, refinement );
|
||||
EXPECT_FALSE( result2.has_value() );
|
||||
|
||||
// Point after sector max (Y too large)
|
||||
cvf::Vec3st point3( 5, 11, 3 );
|
||||
auto result3 = RigGridExportAdapter::transformIjkToSectorCoordinates( point3, min, max, refinement );
|
||||
EXPECT_FALSE( result3.has_value() );
|
||||
|
||||
// Point after sector max (Z too large)
|
||||
cvf::Vec3st point4( 5, 5, 6 );
|
||||
auto result4 = RigGridExportAdapter::transformIjkToSectorCoordinates( point4, min, max, refinement );
|
||||
EXPECT_FALSE( result4.has_value() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test box transformation with refinement = (1,1,1)
|
||||
/// For refinement = 1, box start and end should transform identically
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigGridExportAdapter, BoxTransformation_NoRefinement )
|
||||
{
|
||||
cvf::Vec3st sectorMin( 3, 3, 1 );
|
||||
cvf::Vec3st sectorMax( 10, 10, 5 );
|
||||
cvf::Vec3st refinement( 1, 1, 1 );
|
||||
|
||||
// Test box from (5,5,2) to (7,7,3) in global coordinates
|
||||
// Expected in sector coordinates: (3,3,2) to (5,5,3)
|
||||
cvf::Vec3st boxStart( 5, 5, 2 );
|
||||
cvf::Vec3st boxEnd( 7, 7, 3 );
|
||||
|
||||
auto startResult = RigGridExportAdapter::transformIjkToSectorCoordinates( boxStart, sectorMin, sectorMax, refinement );
|
||||
auto endResult = RigGridExportAdapter::transformIjkToSectorCoordinates( boxEnd, sectorMin, sectorMax, refinement );
|
||||
|
||||
EXPECT_TRUE( startResult.has_value() );
|
||||
EXPECT_TRUE( endResult.has_value() );
|
||||
|
||||
// Start: (5-3)*1+1 = 3 for each dimension
|
||||
EXPECT_EQ( cvf::Vec3st( 3, 3, 2 ), startResult.value() );
|
||||
|
||||
// End: (7-3)*1+1 = 5 for each dimension
|
||||
EXPECT_EQ( cvf::Vec3st( 5, 5, 3 ), endResult.value() );
|
||||
|
||||
// Verify box contains expected number of cells
|
||||
// In X: 5-3+1 = 3 cells (sector cells 3,4,5)
|
||||
// In Y: 5-3+1 = 3 cells
|
||||
// In Z: 3-2+1 = 2 cells
|
||||
size_t cellsX = endResult->x() - startResult->x() + 1;
|
||||
size_t cellsY = endResult->y() - startResult->y() + 1;
|
||||
size_t cellsZ = endResult->z() - startResult->z() + 1;
|
||||
|
||||
EXPECT_EQ( 3u, cellsX );
|
||||
EXPECT_EQ( 3u, cellsY );
|
||||
EXPECT_EQ( 2u, cellsZ );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test single-cell box transformation with refinement = (1,1,1)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigGridExportAdapter, SingleCellBox_NoRefinement )
|
||||
{
|
||||
cvf::Vec3st sectorMin( 3, 3, 1 );
|
||||
cvf::Vec3st sectorMax( 10, 10, 5 );
|
||||
cvf::Vec3st refinement( 1, 1, 1 );
|
||||
|
||||
// Single cell box at global position (5,5,2)
|
||||
cvf::Vec3st singleCell( 5, 5, 2 );
|
||||
|
||||
auto result = RigGridExportAdapter::transformIjkToSectorCoordinates( singleCell, sectorMin, sectorMax, refinement );
|
||||
|
||||
EXPECT_TRUE( result.has_value() );
|
||||
EXPECT_EQ( cvf::Vec3st( 3, 3, 2 ), result.value() );
|
||||
|
||||
// For a single-cell box, start and end are the same
|
||||
auto startResult = RigGridExportAdapter::transformIjkToSectorCoordinates( singleCell, sectorMin, sectorMax, refinement );
|
||||
auto endResult = RigGridExportAdapter::transformIjkToSectorCoordinates( singleCell, sectorMin, sectorMax, refinement );
|
||||
|
||||
EXPECT_EQ( startResult.value(), endResult.value() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test box at sector boundaries
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigGridExportAdapter, BoxAtSectorBoundaries_NoRefinement )
|
||||
{
|
||||
cvf::Vec3st sectorMin( 3, 3, 1 );
|
||||
cvf::Vec3st sectorMax( 10, 10, 5 );
|
||||
cvf::Vec3st refinement( 1, 1, 1 );
|
||||
|
||||
// Box spanning entire sector
|
||||
auto minResult = RigGridExportAdapter::transformIjkToSectorCoordinates( sectorMin, sectorMin, sectorMax, refinement );
|
||||
auto maxResult = RigGridExportAdapter::transformIjkToSectorCoordinates( sectorMax, sectorMin, sectorMax, refinement );
|
||||
|
||||
EXPECT_TRUE( minResult.has_value() );
|
||||
EXPECT_TRUE( maxResult.has_value() );
|
||||
|
||||
EXPECT_EQ( cvf::Vec3st( 1, 1, 1 ), minResult.value() );
|
||||
EXPECT_EQ( cvf::Vec3st( 8, 8, 5 ), maxResult.value() ); // (10-3)*1+1 = 8
|
||||
|
||||
// Verify sector dimensions
|
||||
size_t sectorSizeX = sectorMax.x() - sectorMin.x() + 1; // 10-3+1 = 8
|
||||
size_t sectorSizeY = sectorMax.y() - sectorMin.y() + 1; // 10-3+1 = 8
|
||||
size_t sectorSizeZ = sectorMax.z() - sectorMin.z() + 1; // 5-1+1 = 5
|
||||
|
||||
EXPECT_EQ( sectorSizeX, maxResult->x() );
|
||||
EXPECT_EQ( sectorSizeY, maxResult->y() );
|
||||
EXPECT_EQ( sectorSizeZ, maxResult->z() );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user