diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimGridCollection.cpp index 598adac677..a3dd442710 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimGridCollection.cpp @@ -22,10 +22,14 @@ #include "RimEclipseView.h" #include "RimGridView.h" +#include "RigLocalGrid.h" #include "RigMainGrid.h" +#include "RigNestedHybridGridReconstructor.h" #include "cafPdmUiTreeOrdering.h" +#include + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -83,6 +87,33 @@ void RimGridInfo::setEclipseGridIndex( int index ) m_eclipseGridIndex = index; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridInfo::resetSimulatorGridIndices( int index ) +{ + m_eclipseGridIndex = index; + m_additionalGridIndices.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimGridInfo::addSimulatorGridIndex( int index ) +{ + m_additionalGridIndices.push_back( index ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimGridInfo::simulatorGridIndices() const +{ + std::vector indices = { m_eclipseGridIndex() }; + indices.insert( indices.end(), m_additionalGridIndices.begin(), m_additionalGridIndices.end() ); + return indices; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -318,7 +349,8 @@ std::vector RimGridCollection::indicesToVisibleGrids() const { if ( gridInfo->isActive() ) { - addIfValid( gridInfo->eclipseGridIndex() ); + for ( int index : gridInfo->simulatorGridIndices() ) + addIfValid( index ); } } } @@ -375,6 +407,8 @@ void RimGridCollection::syncFromMainEclipseGrid() auto allTemporaryGrids = m_temporaryLgrs->gridInfos(); auto allPersistentGrids = m_persistentLgrs->gridInfos(); + std::set groupedInfos; + size_t gridCount = mainGrid->gridCount(); for ( size_t i = 1; i < gridCount; i++ ) { @@ -399,18 +433,35 @@ void RimGridCollection::syncFromMainEclipseGrid() } else { - if ( m_persistentLgrs->containsGrid( gridName ) ) + // Reconstructed nested hybrid LGRs are grouped into one entry per refinement level + const auto* localGrid = dynamic_cast( grid ); + const bool isGrouped = localGrid && localGrid->isReconstructedGrid(); + const QString infoName = isGrouped ? RigNestedHybridGridReconstructor::levelGroupName( gridName ) : gridName; + + RimGridInfo* existing = nullptr; + for ( auto* info : m_persistentLgrs->gridInfos() ) + if ( info->name() == infoName ) existing = info; + + if ( existing ) { - removeGridInfo( gridName, allPersistentGrids ); + removeGridInfo( infoName, allPersistentGrids ); + if ( isGrouped ) + { + if ( groupedInfos.count( infoName ) ) + existing->addSimulatorGridIndex( (int)gridIndex ); + else + existing->resetSimulatorGridIndices( (int)gridIndex ); + } } else { - auto gridInfo = new RimGridInfo(); - gridInfo->setName( gridName ); - gridInfo->setEclipseGridIndex( (int)gridIndex ); - gridInfo->setUiIconFromResourceString( ":/LGR16x16.png" ); - m_persistentLgrs->addGridInfo( gridInfo ); + existing = new RimGridInfo(); + existing->setName( infoName ); + existing->setEclipseGridIndex( (int)gridIndex ); + existing->setUiIconFromResourceString( ":/LGR16x16.png" ); + m_persistentLgrs->addGridInfo( existing ); } + if ( isGrouped ) groupedInfos.insert( infoName ); } } diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCollection.h b/ApplicationLibCode/ProjectDataModel/RimGridCollection.h index b1096ef1e0..a9b915d857 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridCollection.h @@ -27,6 +27,8 @@ #include +#include + class RigMainGrid; //================================================================================================== @@ -47,6 +49,11 @@ public: QString name() const; int eclipseGridIndex() const; + // A grid info can represent several grids (e.g. all reconstructed LGRs of one nested hybrid level) + void resetSimulatorGridIndices( int index ); + void addSimulatorGridIndex( int index ); + std::vector simulatorGridIndices() const; + caf::PdmFieldHandle* objectToggleField() override; protected: @@ -58,6 +65,7 @@ private: caf::PdmField m_isActive; caf::PdmField m_gridName; caf::PdmField m_eclipseGridIndex; + std::vector m_additionalGridIndices; }; //================================================================================================== diff --git a/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.cpp b/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.cpp index 7fd4c00c90..b5efb86be7 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.cpp @@ -35,6 +35,8 @@ #include "RiaDefines.h" +#include + #include #include #include @@ -267,6 +269,16 @@ bool RigNestedHybridGridReconstructor::reconstruct( RigEclipseCaseData* caseData return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigNestedHybridGridReconstructor::levelGroupName( const QString& gridName ) +{ + static const QRegularExpression re( "^(LGR_NHG_L\\d+)(_\\d+)?$" ); + const auto match = re.match( gridName ); + return match.hasMatch() ? match.captured( 1 ) : gridName; +} + //-------------------------------------------------------------------------------------------------- /// Build one RigLocalGrid by appending contiguous cells/nodes to the global arrays, copying the real /// geometry from the scattered flat refined cells, hiding the originals, and linking every LGR cell diff --git a/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.h b/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.h index dd85c6a9bb..9900d223bd 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.h +++ b/ApplicationLibCode/ReservoirDataModel/RigNestedHybridGridReconstructor.h @@ -66,6 +66,9 @@ public: // Returns true if at least one refined region was reconstructed. static bool reconstruct( RigEclipseCaseData* caseData, const NestedHybridInput& input, QString* errorMessage = nullptr ); + // "LGR_NHG_L4_2" -> "LGR_NHG_L4". Names not matching the nested hybrid pattern are returned unchanged. + static QString levelGroupName( const QString& gridName ); + private: // Build one RigLocalGrid of the given IJK dimensions. boxToFlat maps each local cell to its // source flat cell (UNDEFINED for holes); boxToParent maps each local cell to the parent (coarse) diff --git a/ApplicationLibCode/UnitTests/RigNestedHybridGridReconstructor-Test.cpp b/ApplicationLibCode/UnitTests/RigNestedHybridGridReconstructor-Test.cpp index 5cb5b1ac8e..6f96464f28 100644 --- a/ApplicationLibCode/UnitTests/RigNestedHybridGridReconstructor-Test.cpp +++ b/ApplicationLibCode/UnitTests/RigNestedHybridGridReconstructor-Test.cpp @@ -375,6 +375,16 @@ TEST_F( RigNestedHybridGridReconstructorTest, LgrNamesAreConsistent ) EXPECT_GT( namesByLevel["LGR_NHG_L4"].size(), 1 ); } +//-------------------------------------------------------------------------------------------------- +/// Tree grouping: numbered component names collapse to their refinement level name. +//-------------------------------------------------------------------------------------------------- +TEST( RigNestedHybridGridReconstructorNameTest, LevelGroupName ) +{ + EXPECT_EQ( RigNestedHybridGridReconstructor::levelGroupName( "LGR_NHG_L4_12" ), QString( "LGR_NHG_L4" ) ); + EXPECT_EQ( RigNestedHybridGridReconstructor::levelGroupName( "LGR_NHG_L2" ), QString( "LGR_NHG_L2" ) ); + EXPECT_EQ( RigNestedHybridGridReconstructor::levelGroupName( "LGR1" ), QString( "LGR1" ) ); +} + //-------------------------------------------------------------------------------------------------- /// Results propagate to the reconstructed LGR cells: an active-cell-indexed STATIC result and the /// full-length REFINE input property (both loaded before reconstruction) must both carry, on an LGR