diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp b/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp index 99f533d51a..7ad81db451 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp @@ -421,9 +421,9 @@ size_t RigGridExportAdapter::totalCells() const //-------------------------------------------------------------------------------------------------- /// Transform IJK coordinates from global grid space to sector-relative space with refinement -/// Returns 1-based Eclipse coordinates +/// Returns 0-based coordinates //-------------------------------------------------------------------------------------------------- -std::expected RigGridExportAdapter::transformIjkToSectorCoordinates( const caf::VecIjk0& originalIjk, +std::expected RigGridExportAdapter::transformIjkToSectorCoordinates( const caf::VecIjk0& ijk, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement, @@ -431,48 +431,37 @@ std::expected RigGridExportAdapter::transformIjkToSectorC bool isBoxMaxCoordinate ) { // 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() ) + if ( ijk.x() < min.x() || ijk.x() > max.x() || ijk.y() < min.y() || ijk.y() > max.y() || ijk.z() < min.z() || ijk.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() ) ); + return std::unexpected( QString( "IJK coordinates (%1) are outside sector bounds [(%2), (%3)]" ) + .arg( QString::fromStdString( ijk.toString() ) ) + .arg( QString::fromStdString( min.toString() ) ) + .arg( QString::fromStdString( max.toString() ) ) ); } // Transform to sector-relative coordinates with refinement - // Eclipse uses 1-based indexing, so we'll return 1-based coordinates - size_t sectorI, sectorJ, sectorK; - + // Returns 0-based coordinates if ( applyRefinementCentering ) { // Center the coordinate in the refined cell block (for point coordinates like WELSPECS) - sectorI = ( originalIjk.x() - min.x() ) * refinement.x() + ( refinement.x() + 1 ) / 2; - sectorJ = ( originalIjk.y() - min.y() ) * refinement.y() + ( refinement.y() + 1 ) / 2; - sectorK = ( originalIjk.z() - min.z() ) * refinement.z() + ( refinement.z() + 1 ) / 2; + return caf::VecIjk0( ( ijk.x() - min.x() ) * refinement.x() + ( refinement.x() + 1 ) / 2 - 1, + ( ijk.y() - min.y() ) * refinement.y() + ( refinement.y() + 1 ) / 2 - 1, + ( ijk.z() - min.z() ) * refinement.z() + ( refinement.z() + 1 ) / 2 - 1 ); } else if ( isBoxMaxCoordinate ) { // Box maximum coordinate: map to end of last refined cell // For a cell at index i (0-based), after refinement it becomes cells [i*r, i*r+r-1] - // So the max index of a box [min, max] becomes: (max-sector_min+1)*r (1-based) - sectorI = ( originalIjk.x() - min.x() + 1 ) * refinement.x(); - sectorJ = ( originalIjk.y() - min.y() + 1 ) * refinement.y(); - sectorK = ( originalIjk.z() - min.z() + 1 ) * refinement.z(); + // So the max index of a box [min, max] becomes: (max-sector_min+1)*r - 1 (0-based) + return caf::VecIjk0( ( ijk.x() - min.x() + 1 ) * refinement.x() - 1, + ( ijk.y() - min.y() + 1 ) * refinement.y() - 1, + ( ijk.z() - min.z() + 1 ) * refinement.z() - 1 ); } else { // Box minimum coordinate: map to start of first refined cell - sectorI = ( originalIjk.x() - min.x() ) * refinement.x() + 1; - sectorJ = ( originalIjk.y() - min.y() ) * refinement.y() + 1; - sectorK = ( originalIjk.z() - min.z() ) * refinement.z() + 1; + return caf::VecIjk0( ( ijk.x() - min.x() ) * refinement.x(), + ( ijk.y() - min.y() ) * refinement.y(), + ( ijk.z() - min.z() ) * refinement.z() ); } - - return caf::VecIjk1( sectorI, sectorJ, sectorK ); } diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.h b/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.h index 5953dc6713..448f7fb804 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.h +++ b/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.h @@ -89,7 +89,7 @@ public: bool hasRefinement() const; // Coordinate transformation utilities - static std::expected transformIjkToSectorCoordinates( const caf::VecIjk0& originalIjk, + static std::expected transformIjkToSectorCoordinates( const caf::VecIjk0& originalIjk, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement, diff --git a/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp b/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp index d916b06a4e..83649cba54 100644 --- a/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp +++ b/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp @@ -753,10 +753,10 @@ std::expected RigSimulationInputTool::processCompdatRe } using C = Opm::ParserKeywords::COMPDAT; - items.push_back( RifOpmDeckTools::item( C::I::itemName, static_cast( transformResultK1->x() ) ) ); - items.push_back( RifOpmDeckTools::item( C::J::itemName, static_cast( transformResultK1->y() ) ) ); - items.push_back( RifOpmDeckTools::item( C::K1::itemName, static_cast( transformResultK1->z() ) ) ); - items.push_back( RifOpmDeckTools::item( C::K2::itemName, static_cast( transformResultK2->z() ) ) ); + items.push_back( RifOpmDeckTools::item( C::I::itemName, static_cast( transformResultK1->toOneBased().x() ) ) ); + items.push_back( RifOpmDeckTools::item( C::J::itemName, static_cast( transformResultK1->toOneBased().y() ) ) ); + items.push_back( RifOpmDeckTools::item( C::K1::itemName, static_cast( transformResultK1->toOneBased().z() ) ) ); + items.push_back( RifOpmDeckTools::item( C::K2::itemName, static_cast( transformResultK2->toOneBased().z() ) ) ); // Copy remaining items for ( size_t i = 5; i < record.size(); ++i ) @@ -809,9 +809,9 @@ std::expected RigSimulationInputTool::processCompsegsR } // Add transformed I, J, K - items.push_back( RifOpmDeckTools::item( "I", static_cast( transformResult->x() ) ) ); - items.push_back( RifOpmDeckTools::item( "J", static_cast( transformResult->y() ) ) ); - items.push_back( RifOpmDeckTools::item( "K", static_cast( transformResult->z() ) ) ); + items.push_back( RifOpmDeckTools::item( "I", static_cast( transformResult->toOneBased().x() ) ) ); + items.push_back( RifOpmDeckTools::item( "J", static_cast( transformResult->toOneBased().y() ) ) ); + items.push_back( RifOpmDeckTools::item( "K", static_cast( transformResult->toOneBased().z() ) ) ); // Copy remaining items for ( size_t i = 3; i < record.size(); ++i ) @@ -913,10 +913,8 @@ std::expected RigSimulationInputTool::transformBoxTo } // Return bounding box with 0-based sector-relative coordinates - return RigBoundingBoxIjk( cvf::Vec3st( transformResult1->x() - 1, transformResult1->y() - 1, transformResult1->z() - 1 ), - cvf::Vec3st( transformResult2->x() - 1, transformResult2->y() - 1, transformResult2->z() - 1 ) ); + return RigBoundingBoxIjk( *transformResult1, *transformResult2 ); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/UnitTests/RigGridExportAdapter-Test.cpp b/ApplicationLibCode/UnitTests/RigGridExportAdapter-Test.cpp index c49ec621e1..a5815daa9a 100644 --- a/ApplicationLibCode/UnitTests/RigGridExportAdapter-Test.cpp +++ b/ApplicationLibCode/UnitTests/RigGridExportAdapter-Test.cpp @@ -672,27 +672,27 @@ TEST( RigGridExportAdapter, TransformIjkToSectorCoordinates_NoRefinement ) caf::VecIjk0 max( 10, 10, 5 ); cvf::Vec3st refinement( 1, 1, 1 ); - // Point at sector min should transform to (1,1,1) + // Point at sector min should transform to (0,0,0) auto result1 = RigGridExportAdapter::transformIjkToSectorCoordinates( min, min, max, refinement ); EXPECT_TRUE( result1.has_value() ); - EXPECT_EQ( caf::VecIjk1( 1, 1, 1 ), result1.value() ); + EXPECT_EQ( caf::VecIjk0( 0, 0, 0 ), result1.value() ); // Point at sector max should transform correctly auto result2 = RigGridExportAdapter::transformIjkToSectorCoordinates( max, min, max, refinement ); EXPECT_TRUE( result2.has_value() ); - EXPECT_EQ( caf::VecIjk1( 8, 8, 5 ), result2.value() ); // (10-3)*1+1 = 8 + EXPECT_EQ( caf::VecIjk0( 7, 7, 4 ), result2.value() ); // (10-3)*1 = 7 // Point in middle of sector caf::VecIjk0 middle( 5, 5, 3 ); auto result3 = RigGridExportAdapter::transformIjkToSectorCoordinates( middle, min, max, refinement ); EXPECT_TRUE( result3.has_value() ); - EXPECT_EQ( caf::VecIjk1( 3, 3, 3 ), result3.value() ); // (5-3)*1+1 = 3 + EXPECT_EQ( caf::VecIjk0( 2, 2, 2 ), result3.value() ); // (5-3)*1 = 2 // Test different point caf::VecIjk0 point( 7, 6, 2 ); auto result4 = RigGridExportAdapter::transformIjkToSectorCoordinates( point, min, max, refinement ); EXPECT_TRUE( result4.has_value() ); - EXPECT_EQ( caf::VecIjk1( 5, 4, 2 ), result4.value() ); // (7-3)*1+1=5, (6-3)*1+1=4, (2-1)*1+1=2 + EXPECT_EQ( caf::VecIjk0( 4, 3, 1 ), result4.value() ); // (7-3)*1=4, (6-3)*1=3, (2-1)*1=1 } //-------------------------------------------------------------------------------------------------- @@ -747,11 +747,11 @@ TEST( RigGridExportAdapter, BoxTransformation_NoRefinement ) EXPECT_TRUE( startResult.has_value() ); EXPECT_TRUE( endResult.has_value() ); - // Start: (5-3)*1+1 = 3 for each dimension - EXPECT_EQ( caf::VecIjk1( 3, 3, 2 ), startResult.value() ); + // Start: (5-3)*1 = 2 for each dimension + EXPECT_EQ( caf::VecIjk0( 2, 2, 1 ), startResult.value() ); - // End: (7-3)*1+1 = 5 for each dimension - EXPECT_EQ( caf::VecIjk1( 5, 5, 3 ), endResult.value() ); + // End: (7-3)*1 = 4 for each dimension + EXPECT_EQ( caf::VecIjk0( 4, 4, 2 ), endResult.value() ); // Verify box contains expected number of cells // In X: 5-3+1 = 3 cells (sector cells 3,4,5) @@ -781,7 +781,7 @@ TEST( RigGridExportAdapter, SingleCellBox_NoRefinement ) auto result = RigGridExportAdapter::transformIjkToSectorCoordinates( singleCell, sectorMin, sectorMax, refinement ); EXPECT_TRUE( result.has_value() ); - EXPECT_EQ( caf::VecIjk1( 3, 3, 2 ), result.value() ); + EXPECT_EQ( caf::VecIjk0( 2, 2, 1 ), result.value() ); // For a single-cell box, start and end are the same auto startResult = RigGridExportAdapter::transformIjkToSectorCoordinates( singleCell, sectorMin, sectorMax, refinement ); @@ -806,15 +806,16 @@ TEST( RigGridExportAdapter, BoxAtSectorBoundaries_NoRefinement ) EXPECT_TRUE( minResult.has_value() ); EXPECT_TRUE( maxResult.has_value() ); - EXPECT_EQ( caf::VecIjk1( 1, 1, 1 ), minResult.value() ); - EXPECT_EQ( caf::VecIjk1( 8, 8, 5 ), maxResult.value() ); // (10-3)*1+1 = 8 + EXPECT_EQ( caf::VecIjk0( 0, 0, 0 ), minResult.value() ); + EXPECT_EQ( caf::VecIjk0( 7, 7, 4 ), maxResult.value() ); // (10-3)*1 = 7 // 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() ); + // maxResult is 0-based, so max index = size - 1 + EXPECT_EQ( sectorSizeX - 1, maxResult->x() ); + EXPECT_EQ( sectorSizeY - 1, maxResult->y() ); + EXPECT_EQ( sectorSizeZ - 1, maxResult->z() ); }