From 4cf6a260837ffb275e1a30955446013e9c2711f6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 3 Nov 2024 13:38:03 +0100 Subject: [PATCH] Improve draw performance for active cell grid * Show timing for geoBuilder.generateSurface() * Check state of element vector result before geometry is created * Improve performance for isFaceVisible Avoid calling costly function cell() when possible Remove check on fault geometry as this does not affect the visualization * Performance: Avoid traversal of all cells when computing visibility When we have an active cell grid, we can skip checking for inactive and invalid state. Use the list of active grid cells when looping through cells. --- .../ModelVisualization/RivGridPartMgr.cpp | 31 +++++++++++++++++++ .../RivReservoirViewPartMgr.cpp | 22 +++++++++++++ .../ProjectDataModel/RimEclipseView.cpp | 23 ++++++++------ .../ReservoirDataModel/RigActiveCellGrid.cpp | 16 ++++++++++ .../ReservoirDataModel/RigActiveCellGrid.h | 2 ++ .../ReservoirDataModel/RigGridBase.cpp | 25 +++++---------- 6 files changed, 92 insertions(+), 27 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp index 935d35d4bc..cbad222ab4 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp @@ -20,6 +20,7 @@ #include "RivGridPartMgr.h" +#include "RiaLogging.h" #include "RiaPreferences.h" #include "RiaRegressionTestRunner.h" @@ -66,6 +67,32 @@ #include "cvfTransform.h" #include "cvfUniform.h" +namespace caf +{ +template <> +void caf::AppEnum::setUp() +{ + addItem( RivCellSetEnum::OVERRIDDEN_CELL_VISIBILITY, "OVERRIDDEN_CELL_VISIBILITY", "OVERRIDDEN_CELL_VISIBILITY" ); + addItem( RivCellSetEnum::ALL_CELLS, "ALL_CELLS", "ALL_CELLS" ); + addItem( RivCellSetEnum::ACTIVE, "ACTIVE", "ACTIVE" ); + addItem( RivCellSetEnum::ALL_WELL_CELLS, "ALL_WELL_CELLS", "ALL_WELL_CELLS" ); + addItem( RivCellSetEnum::VISIBLE_WELL_CELLS, "VISIBLE_WELL_CELLS", "VISIBLE_WELL_CELLS" ); + addItem( RivCellSetEnum::VISIBLE_WELL_FENCE_CELLS, "VISIBLE_WELL_FENCE_CELLS", "VISIBLE_WELL_FENCE_CELLS" ); + addItem( RivCellSetEnum::INACTIVE, "INACTIVE", "INACTIVE" ); + addItem( RivCellSetEnum::RANGE_FILTERED, "RANGE_FILTERED", "RANGE_FILTERED" ); + addItem( RivCellSetEnum::RANGE_FILTERED_INACTIVE, "RANGE_FILTERED_INACTIVE", "RANGE_FILTERED_INACTIVE" ); + addItem( RivCellSetEnum::RANGE_FILTERED_WELL_CELLS, "RANGE_FILTERED_WELL_CELLS", "RANGE_FILTERED_WELL_CELLS" ); + addItem( RivCellSetEnum::VISIBLE_WELL_CELLS_OUTSIDE_RANGE_FILTER, + "VISIBLE_WELL_CELLS_OUTSIDE_RANGE_FILTER", + "VISIBLE_WELL_CELLS_OUTSIDE_RANGE_FILTER" ); + addItem( RivCellSetEnum::VISIBLE_WELL_FENCE_CELLS_OUTSIDE_RANGE_FILTER, + "VISIBLE_WELL_FENCE_CELLS_OUTSIDE_RANGE_FILTER", + "VISIBLE_WELL_FENCE_CELLS_OUTSIDE_RANGE_FILTER" ); + addItem( RivCellSetEnum::PROPERTY_FILTERED, "PROPERTY_FILTERED", "PROPERTY_FILTERED" ); + addItem( RivCellSetEnum::PROPERTY_FILTERED_WELL_CELLS, "PROPERTY_FILTERED_WELL_CELLS", "PROPERTY_FILTERED_WELL_CELLS" ); +} +} // namespace caf + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -117,7 +144,11 @@ void RivGridPartMgr::generatePartGeometry( cvf::StructGridGeometryGenerator& geo // Surface geometry { + auto text = caf::AppEnum::text( m_cellSetType ); + RiaLogging::resetTimer( "Compute surface for " + text ); cvf::ref geo = geoBuilder.generateSurface(); + RiaLogging::logTimeElapsed( "" ); + if ( geo.notNull() ) { geo->computeNormals(); diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 5e39ce8166..718ce426d6 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -20,6 +20,7 @@ #include "RivReservoirViewPartMgr.h" +#include "RigActiveCellGrid.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" #include "RigCaseToCaseCellMapper.h" @@ -601,6 +602,27 @@ void RivReservoirViewPartMgr::computeNativeVisibility( cvf::UByteArray* cellVisibility->resize( grid->cellCount() ); + if ( auto activeGrid = dynamic_cast( grid ) ) + { + auto reservoirIndices = activeGrid->activeReservoirCellIndices(); +#pragma omp parallel for + for ( int i = 0; i < static_cast( reservoirIndices.size() ); i++ ) + { + size_t cellIndex = reservoirIndices[i]; + + if ( ( !activeCellsIsVisible ) || ( *cellIsInWellStatuses )[cellIndex] ) + { + ( *cellVisibility )[cellIndex] = false; + } + else + { + ( *cellVisibility )[cellIndex] = true; + } + } + + return; + } + #pragma omp parallel for for ( int cellIndex = 0; cellIndex < static_cast( grid->cellCount() ); cellIndex++ ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 5ec6ff1489..6a9f632724 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -1139,19 +1139,22 @@ void RimEclipseView::appendElementVectorResultToModel() cvf::String name = "ElementVectorModelMod"; RimEclipseView::removeModelByName( frameScene, name ); - cvf::ref frameParts = new cvf::ModelBasicList; - frameParts->setName( name ); + if ( m_elementVectorResult->showResult() ) + { + cvf::ref frameParts = new cvf::ModelBasicList; + frameParts->setName( name ); - m_reservoirGridPartManager->appendElementVectorResultDynamicGeometryPartsToModel( frameParts.p(), - PROPERTY_FILTERED, - m_currentTimeStep ); + m_reservoirGridPartManager->appendElementVectorResultDynamicGeometryPartsToModel( frameParts.p(), + PROPERTY_FILTERED, + m_currentTimeStep ); - // TODO: should this be ACTIVE? - m_reservoirGridPartManager->appendElementVectorResultDynamicGeometryPartsToModel( frameParts.p(), - PROPERTY_FILTERED_WELL_CELLS, - m_currentTimeStep ); + // TODO: should this be ACTIVE? + m_reservoirGridPartManager->appendElementVectorResultDynamicGeometryPartsToModel( frameParts.p(), + PROPERTY_FILTERED_WELL_CELLS, + m_currentTimeStep ); - frameScene->addModel( frameParts.p() ); + frameScene->addModel( frameParts.p() ); + } } } } diff --git a/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.cpp b/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.cpp index 7eb4054962..6f98891cf0 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.cpp @@ -109,6 +109,22 @@ size_t RigActiveCellGrid::totalActiveCellCount() const return m_totalActiveCellCount; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigActiveCellGrid::activeReservoirCellIndices() const +{ + std::vector indices; + indices.reserve( m_nativeCells.size() ); + + for ( const auto& [index, cell] : m_nativeCells ) + { + indices.emplace_back( index ); + } + + return indices; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.h b/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.h index 142b47e822..c7e1225033 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.h +++ b/ApplicationLibCode/ReservoirDataModel/RigActiveCellGrid.h @@ -34,6 +34,8 @@ public: size_t totalCellCount() const override; size_t totalActiveCellCount() const; + std::vector activeReservoirCellIndices() const; + protected: // only for use by file readers! friend class RifReaderOpmCommonActive; std::map& nativeCells(); diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp index 8b87d9ccd9..1adbb1716b 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp @@ -535,7 +535,7 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible( size_t CVF_TIGHT_ASSERT( m_grid ); size_t cellIndex = m_grid->cellIndexFromIJK( i, j, k ); - if ( m_grid->cell( cellIndex ).subGrid() ) + if ( m_grid->mainGrid()->gridCount() > 1 && m_grid->cell( cellIndex ).subGrid() ) { // Do not show any faces in the place where a LGR is present return false; @@ -552,27 +552,18 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible( size_t size_t neighborCellIndex = m_grid->cellIndexFromIJK( ni, nj, nk ); - // Do show the faces in the boarder between this grid and a possible LGR. Some of the LGR cells - // might not be visible. - if ( m_grid->cell( neighborCellIndex ).subGrid() ) - { - return true; - } - - // Do not show cell geometry if a fault is present to avoid z fighting between surfaces - // It will always be a better solution to avoid geometry creation instead of part priority and polygon offset - size_t nativeResvCellIndex = m_grid->reservoirCellIndex( cellIndex ); - const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace( nativeResvCellIndex, face ); - if ( fault ) - { - return false; - } - // If the neighbour cell is invisible, we need to draw the face if ( ( cellVisibility != nullptr ) && !( *cellVisibility )[neighborCellIndex] ) { return true; } + // Do show the faces in the boarder between this grid and a possible LGR. Some of the LGR cells + // might not be visible. + if ( m_grid->mainGrid()->gridCount() > 1 && m_grid->cell( neighborCellIndex ).subGrid() ) + { + return true; + } + return false; }