Skip to content

Commit d19bbc3

Browse files
committed
Fix incorrect sector export in refinement.
1 parent 16a93cf commit d19bbc3

File tree

2 files changed

+105
-15
lines changed

2 files changed

+105
-15
lines changed

ApplicationLibCode/FileInterface/RifEclipseInputFileTools.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ bool RifEclipseInputFileTools::exportKeywords( const QString& resul
406406
RigMainGrid* mainGrid = eclipseCase->mainGrid();
407407

408408
cvf::Vec3st max = maxIn;
409-
if ( max == cvf::Vec3st::UNDEFINED )
409+
if ( max.isUndefined() )
410410
{
411411
max = cvf::Vec3st( mainGrid->cellCountI() - 1, mainGrid->cellCountJ() - 1, mainGrid->cellCountK() - 1 );
412412
}
@@ -453,13 +453,16 @@ bool RifEclipseInputFileTools::exportKeywords( const QString& resul
453453
std::vector<double> filteredResults;
454454
filteredResults.reserve( resultValues.size() );
455455

456-
for ( size_t k = min.z() * refinement.z(); k <= max.z() * refinement.z(); ++k )
456+
cvf::Vec3st refinedMin( min.x() * refinement.x(), min.y() * refinement.y(), min.z() * refinement.z() );
457+
cvf::Vec3st refinedMax( ( max.x() + 1 ) * refinement.x(), ( max.y() + 1 ) * refinement.y(), ( max.z() + 1 ) * refinement.z() );
458+
459+
for ( size_t k = refinedMin.z(); k < refinedMax.z(); ++k )
457460
{
458461
size_t mainK = k / refinement.z();
459-
for ( size_t j = min.y() * refinement.y(); j <= max.y() * refinement.y(); ++j )
462+
for ( size_t j = refinedMin.y(); j < refinedMax.y(); ++j )
460463
{
461464
size_t mainJ = j / refinement.y();
462-
for ( size_t i = min.x() * refinement.x(); i <= max.x() * refinement.x(); ++i )
465+
for ( size_t i = refinedMin.x(); i < refinedMax.x(); ++i )
463466
{
464467
size_t mainI = i / refinement.x();
465468

ApplicationLibCode/UnitTests/RifEclipseInputFileTools-Test.cpp

Lines changed: 98 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "RiaTestDataDirectory.h"
44
#include "RifEclipseInputFileTools.h"
55
#include "RifEclipseInputPropertyLoader.h"
6+
#include "RigActiveCellInfo.h"
67
#include "RigCaseCellResultsData.h"
78
#include "RigEclipseCaseData.h"
89
#include "RigEclipseResultAddress.h"
@@ -664,22 +665,22 @@ TEST( RifEclipseInputFileToolsTest, ExportKeywordsWithRefinement )
664665
RigCaseCellResultsData* cellResultsData = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
665666
ASSERT_NE( nullptr, cellResultsData );
666667

667-
// Look specifically for PORO property
668+
// Look specifically for PORO property in the results system
668669
std::vector<QString> keywordsToExport;
669670
auto allResults = cellResultsData->existingResults();
670671
bool foundPoro = false;
671672

672673
for ( const auto& result : allResults )
673674
{
674-
if ( result.resultName() == "PORO" )
675+
if ( result.resultName() == "PORO" && result.resultCatType() == RiaDefines::ResultCatType::INPUT_PROPERTY )
675676
{
676677
keywordsToExport.push_back( result.resultName() );
677678
foundPoro = true;
678679
break;
679680
}
680681
}
681682

682-
ASSERT_TRUE( foundPoro ) << "PORO property not found in test data file";
683+
ASSERT_TRUE( foundPoro ) << "PORO property not found as INPUT_PROPERTY in result system";
683684

684685
QTemporaryDir tempDir;
685686
ASSERT_TRUE( tempDir.isValid() );
@@ -728,16 +729,102 @@ TEST( RifEclipseInputFileToolsTest, ExportKeywordsWithRefinement )
728729
EXPECT_EQ( originalGrid->cellCountJ() * refinement.y(), refinedGrid->cellCountJ() ) << "Refined J dimension incorrect";
729730
EXPECT_EQ( originalGrid->cellCountK() * refinement.z(), refinedGrid->cellCountK() ) << "Refined K dimension incorrect";
730731

731-
// Try to import the exported keywords back into the refined grid case
732-
// This test is expected to FAIL due to a bug in the export function:
733-
// The export outputs values for active cells only, but the refined grid has more total cells
732+
// Import the exported keywords back into the refined grid case
734733
auto propertyMap = RifEclipseInputPropertyLoader::readProperties( exportFileName, refinedEclipseCase.get() );
735734

736-
// This test documents the bug: the export should create the same number of values as refined cells
737-
// Currently it exports 25830 values but refined grid has 27048 cells
738-
EXPECT_FALSE( propertyMap.empty() ) << "BUG: Should have imported properties but export doesn't match refined grid cell count";
739-
EXPECT_TRUE( propertyMap.find( "PORO" ) != propertyMap.end() )
740-
<< "BUG: Should have imported PORO property but cell count mismatch prevents import";
735+
// Verify the import was successful
736+
EXPECT_FALSE( propertyMap.empty() ) << "Should have imported properties successfully";
737+
EXPECT_TRUE( propertyMap.find( "PORO" ) != propertyMap.end() ) << "Should have imported PORO property";
738+
739+
// Get the imported PORO data from both original and refined cases
740+
RigCaseCellResultsData* originalResultsData = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
741+
RigCaseCellResultsData* refinedResultsData = refinedEclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
742+
743+
RigEclipseResultAddress poroAddress( RiaDefines::ResultCatType::INPUT_PROPERTY, "PORO" );
744+
745+
// Ensure both datasets are loaded
746+
bool originalLoaded = originalResultsData->ensureKnownResultLoaded( poroAddress );
747+
bool refinedLoaded = refinedResultsData->ensureKnownResultLoaded( poroAddress );
748+
749+
ASSERT_TRUE( originalLoaded ) << "Original PORO data should be available after loading properties";
750+
ASSERT_TRUE( refinedLoaded ) << "Refined PORO data should be loaded after import";
751+
752+
auto originalPoroValues = originalResultsData->cellScalarResults( poroAddress );
753+
auto refinedPoroValues = refinedResultsData->cellScalarResults( poroAddress );
754+
755+
ASSERT_FALSE( originalPoroValues.empty() ) << "Original PORO values should not be empty";
756+
ASSERT_FALSE( refinedPoroValues.empty() ) << "Refined PORO values should not be empty";
757+
ASSERT_FALSE( originalPoroValues[0].empty() ) << "Original PORO values first time step should not be empty";
758+
ASSERT_FALSE( refinedPoroValues[0].empty() ) << "Refined PORO values first time step should not be empty";
759+
760+
const auto& originalData = originalPoroValues[0];
761+
const auto& refinedData = refinedPoroValues[0];
762+
763+
// Verify refined data has the expected size
764+
EXPECT_EQ( refinedGrid->cellCount(), refinedData.size() ) << "Refined PORO data size should match refined cell count";
765+
766+
// Find an active cell to test the refinement mapping principle
767+
auto findActiveCell = []( RigMainGrid* originalGrid, RigCaseCellResultsData* originalResultsData, const std::vector<double>& originalData )
768+
{
769+
// Search for an active cell to test with
770+
for ( size_t k = 0; k < originalGrid->cellCountK(); ++k )
771+
{
772+
for ( size_t j = 0; j < originalGrid->cellCountJ(); ++j )
773+
{
774+
for ( size_t i = 0; i < originalGrid->cellCountI(); ++i )
775+
{
776+
size_t originalCellIndex = originalGrid->cellIndexFromIJK( i, j, k );
777+
size_t originalResultIndex = originalResultsData->activeCellInfo()->cellResultIndex( originalCellIndex );
778+
779+
if ( originalResultIndex != cvf::UNDEFINED_SIZE_T && originalResultIndex < originalData.size() )
780+
{
781+
return cvf::Vec3st( i, j, k );
782+
}
783+
}
784+
}
785+
}
786+
787+
return cvf::Vec3st::UNDEFINED;
788+
};
789+
790+
cvf::Vec3st testCell = findActiveCell( originalGrid, originalResultsData, originalData );
791+
ASSERT_FALSE( testCell.isUndefined() ) << "Should find at least one active cell with PORO data to test refinement mapping";
792+
793+
size_t originalCellIndex = originalGrid->cellIndexFromIJK( testCell.x(), testCell.y(), testCell.z() );
794+
size_t originalResultIndex = originalResultsData->activeCellInfo()->cellResultIndex( originalCellIndex );
795+
double originalPoroValue = originalData[originalResultIndex];
796+
797+
// Check all 4 refined cells (2x2x1) that correspond to this original cell
798+
int matchingCells = 0;
799+
for ( size_t refK = 0; refK < refinement.z(); ++refK )
800+
{
801+
for ( size_t refJ = 0; refJ < refinement.y(); ++refJ )
802+
{
803+
for ( size_t refI = 0; refI < refinement.x(); ++refI )
804+
{
805+
size_t refinedI = testCell.x() * refinement.x() + refI;
806+
size_t refinedJ = testCell.y() * refinement.y() + refJ;
807+
size_t refinedK = testCell.z() * refinement.z() + refK;
808+
809+
size_t refinedCellIndex = refinedGrid->cellIndexFromIJK( refinedI, refinedJ, refinedK );
810+
if ( refinedCellIndex < refinedData.size() )
811+
{
812+
double refinedPoroValue = refinedData[refinedCellIndex];
813+
814+
EXPECT_NEAR( originalPoroValue, refinedPoroValue, 1e-6 )
815+
<< "Refined cell (" << refinedI << "," << refinedJ << "," << refinedK << ") should match original cell ("
816+
<< testCell.x() << "," << testCell.y() << "," << testCell.z() << ") PORO value";
817+
818+
if ( std::abs( originalPoroValue - refinedPoroValue ) < 1e-6 )
819+
{
820+
matchingCells++;
821+
}
822+
}
823+
}
824+
}
825+
}
826+
827+
EXPECT_EQ( 4, matchingCells ) << "All 4 refined cells should match the original cell value for cell";
741828
}
742829

743830
//--------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)