mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 22:50:25 -05:00
#14429 Ignore mismatched cell visibility in grid cross plot
This commit is contained in:
1 parent
42aa580192
commit
800ab27370
3 files changed
+187
-2
No files matched your search
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "RigEclipseCrossPlotDataExtractor.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaQDateTimeTools.h"
|
||||
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
@@ -94,12 +95,23 @@ RigEclipseCrossPlotResult RigEclipseCrossPlotDataExtractor::extract( RigEclipseC
|
||||
timeStepsToInclude.insert( static_cast<size_t>( resultTimeStep ) );
|
||||
}
|
||||
|
||||
const size_t reservoirCellCount = xResultData->activeCellInfo()->reservoirCellCount();
|
||||
|
||||
for ( int timeStep : timeStepsToInclude )
|
||||
{
|
||||
const cvf::UByteArray* cellVisibility = nullptr;
|
||||
if ( timeStepCellVisibilityMap.count( timeStep ) )
|
||||
{
|
||||
cellVisibility = &timeStepCellVisibilityMap[timeStep];
|
||||
const cvf::UByteArray& visibilityForTimeStep = timeStepCellVisibilityMap[timeStep];
|
||||
if ( visibilityForTimeStep.size() == reservoirCellCount )
|
||||
{
|
||||
cellVisibility = &visibilityForTimeStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaLogging::warning(
|
||||
"Cell visibility size mismatch with reservoir cell count. Ignoring cell filter in grid cross plot." );
|
||||
}
|
||||
}
|
||||
|
||||
int xIndex = timeStep >= (int)xValuesForAllSteps.size() ? 0 : timeStep;
|
||||
@@ -118,7 +130,7 @@ RigEclipseCrossPlotResult RigEclipseCrossPlotDataExtractor::extract( RigEclipseC
|
||||
groupResultData->activeCellInfo() );
|
||||
}
|
||||
|
||||
for ( size_t globalCellIdx = 0; globalCellIdx < xResultData->activeCellInfo()->reservoirCellCount(); ++globalCellIdx )
|
||||
for ( size_t globalCellIdx = 0; globalCellIdx < reservoirCellCount; ++globalCellIdx )
|
||||
{
|
||||
if ( cellVisibility && !( *cellVisibility )[globalCellIdx] ) continue;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ set(SOURCE_UNITTEST_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseSummary-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigActiveCellInfo-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseCaseDataTools-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseCrossPlotDataExtractor-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultTools-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigMobilePoreVolumeResultCalculator-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigReservoir-Test.cpp
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2026- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseCrossPlotDataExtractor.h"
|
||||
#include "RigEclipseResultAddress.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigReservoirBuilder.h"
|
||||
|
||||
#include "cvfVector3.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct MockCase
|
||||
{
|
||||
std::unique_ptr<RimEclipseResultCase> resultCase;
|
||||
cvf::ref<RigEclipseCaseData> eclipseCase;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Build a regular ni x nj x nk box grid in memory (no file, no view)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
MockCase buildBoxGridCase( int ni, int nj, int nk )
|
||||
{
|
||||
RigReservoirBuilder builder;
|
||||
builder.setIJKCount( cvf::Vec3st( ni, nj, nk ) );
|
||||
builder.setWorldCoordinates( cvf::Vec3d( 0.0, 0.0, 0.0 ), cvf::Vec3d( ni, nj, -nk ) );
|
||||
|
||||
MockCase mockCase;
|
||||
mockCase.resultCase.reset( new RimEclipseResultCase );
|
||||
mockCase.eclipseCase = new RigEclipseCaseData( mockCase.resultCase.get() );
|
||||
|
||||
builder.createGridsAndCells( mockCase.eclipseCase.p() );
|
||||
mockCase.eclipseCase->mainGrid()->computeCachedData();
|
||||
|
||||
mockCase.resultCase->setReservoirData( mockCase.eclipseCase.p() );
|
||||
|
||||
return mockCase;
|
||||
}
|
||||
|
||||
void fillStaticResult( RigCaseCellResultsData* resultsData, const QString& resultName, size_t valueCount, double value )
|
||||
{
|
||||
resultsData->addStaticScalarResult( RiaDefines::ResultCatType::STATIC_NATIVE, resultName, false, valueCount );
|
||||
|
||||
const RigEclipseResultAddress resultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, resultName );
|
||||
std::vector<double>* resultVector = resultsData->modifiableCellScalarResult( resultAddress, 0 );
|
||||
ASSERT_NE( resultVector, nullptr );
|
||||
ASSERT_EQ( resultVector->size(), valueCount );
|
||||
|
||||
std::fill( resultVector->begin(), resultVector->end(), value );
|
||||
}
|
||||
|
||||
void setupResultDefinition( RimEclipseResultDefinition* resultDefinition, RimEclipseResultCase* resultCase, const QString& resultName )
|
||||
{
|
||||
resultDefinition->setEclipseCase( resultCase );
|
||||
resultDefinition->setPorosityModel( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
resultDefinition->setResultType( RiaDefines::ResultCatType::STATIC_NATIVE );
|
||||
resultDefinition->setResultVariable( resultName );
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// A cell visibility array not matching the reservoir cell count must be ignored.
|
||||
///
|
||||
/// RimEclipseView::calculateCurrentTotalCellVisibility() returns without resizing when the view has
|
||||
/// no main grid, leaving an empty array in the visibility map. Indexing that array crashed.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigEclipseCrossPlotDataExtractorTest, ExtractIgnoresEmptyCellVisibility )
|
||||
{
|
||||
MockCase mockCase = buildBoxGridCase( 10, 10, 5 );
|
||||
|
||||
RigCaseCellResultsData* resultsData = mockCase.eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
ASSERT_NE( resultsData, nullptr );
|
||||
ASSERT_NE( resultsData->activeCellInfo(), nullptr );
|
||||
|
||||
const size_t activeCellCount = resultsData->activeCellInfo()->reservoirActiveCellCount();
|
||||
ASSERT_EQ( activeCellCount, 500u );
|
||||
|
||||
fillStaticResult( resultsData, "XVALUES", activeCellCount, 1.0 );
|
||||
fillStaticResult( resultsData, "YVALUES", activeCellCount, 2.0 );
|
||||
|
||||
RimEclipseResultDefinition xAddress;
|
||||
RimEclipseResultDefinition yAddress;
|
||||
RimEclipseResultDefinition groupAddress;
|
||||
setupResultDefinition( &xAddress, mockCase.resultCase.get(), "XVALUES" );
|
||||
setupResultDefinition( &yAddress, mockCase.resultCase.get(), "YVALUES" );
|
||||
|
||||
// An empty visibility array is what a view without a main grid leaves behind.
|
||||
std::map<int, cvf::UByteArray> timeStepCellVisibilityMap;
|
||||
timeStepCellVisibilityMap[0] = cvf::UByteArray();
|
||||
|
||||
RigEclipseCrossPlotResult result = RigEclipseCrossPlotDataExtractor::extract( mockCase.eclipseCase.p(),
|
||||
0,
|
||||
xAddress,
|
||||
yAddress,
|
||||
RigGridCrossPlotCurveGrouping::NO_GROUPING,
|
||||
groupAddress,
|
||||
timeStepCellVisibilityMap );
|
||||
|
||||
// The filter must be ignored, so all active cells are included.
|
||||
EXPECT_EQ( result.xValues.size(), activeCellCount );
|
||||
EXPECT_EQ( result.yValues.size(), activeCellCount );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// A cell visibility array from a smaller grid must be ignored instead of read out of bounds.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigEclipseCrossPlotDataExtractorTest, ExtractIgnoresTooShortCellVisibility )
|
||||
{
|
||||
MockCase mockCase = buildBoxGridCase( 10, 10, 5 );
|
||||
|
||||
RigCaseCellResultsData* resultsData = mockCase.eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
ASSERT_NE( resultsData, nullptr );
|
||||
ASSERT_NE( resultsData->activeCellInfo(), nullptr );
|
||||
|
||||
const size_t activeCellCount = resultsData->activeCellInfo()->reservoirActiveCellCount();
|
||||
const size_t reservoirCellCount = resultsData->activeCellInfo()->reservoirCellCount();
|
||||
ASSERT_EQ( activeCellCount, 500u );
|
||||
|
||||
fillStaticResult( resultsData, "XVALUES", activeCellCount, 3.0 );
|
||||
fillStaticResult( resultsData, "YVALUES", activeCellCount, 4.0 );
|
||||
|
||||
RimEclipseResultDefinition xAddress;
|
||||
RimEclipseResultDefinition yAddress;
|
||||
RimEclipseResultDefinition groupAddress;
|
||||
setupResultDefinition( &xAddress, mockCase.resultCase.get(), "XVALUES" );
|
||||
setupResultDefinition( &yAddress, mockCase.resultCase.get(), "YVALUES" );
|
||||
|
||||
// Visibility computed for a smaller grid, as when the cell filter view refers to another case.
|
||||
std::map<int, cvf::UByteArray> timeStepCellVisibilityMap;
|
||||
cvf::UByteArray& cellVisibility = timeStepCellVisibilityMap[0];
|
||||
cellVisibility.resize( reservoirCellCount / 2 );
|
||||
cellVisibility.setAll( 1 );
|
||||
|
||||
RigEclipseCrossPlotResult result = RigEclipseCrossPlotDataExtractor::extract( mockCase.eclipseCase.p(),
|
||||
0,
|
||||
xAddress,
|
||||
yAddress,
|
||||
RigGridCrossPlotCurveGrouping::NO_GROUPING,
|
||||
groupAddress,
|
||||
timeStepCellVisibilityMap );
|
||||
|
||||
EXPECT_EQ( result.xValues.size(), activeCellCount );
|
||||
EXPECT_EQ( result.yValues.size(), activeCellCount );
|
||||
}
|
||||
Reference in new issue
Block a user